00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <simgear_config.h>
00027 #endif
00028
00029 #include "obj.hxx"
00030
00031 #include <simgear/compiler.h>
00032
00033 #include <osg/Fog>
00034 #include <osg/Geode>
00035 #include <osg/Geometry>
00036 #include <osg/Group>
00037 #include <osg/LOD>
00038 #include <osg/MatrixTransform>
00039 #include <osg/Point>
00040 #include <osg/StateSet>
00041 #include <osg/Switch>
00042
00043 #include <simgear/debug/logstream.hxx>
00044 #include <simgear/io/sg_binobj.hxx>
00045 #include <simgear/math/sg_geodesy.hxx>
00046 #include <simgear/math/sg_random.h>
00047 #include <simgear/scene/material/Effect.hxx>
00048 #include <simgear/scene/material/EffectGeode.hxx>
00049 #include <simgear/scene/material/mat.hxx>
00050 #include <simgear/scene/material/matlib.hxx>
00051 #include <simgear/scene/model/SGOffsetTransform.hxx>
00052 #include <simgear/scene/util/SGUpdateVisitor.hxx>
00053 #include <simgear/scene/util/SGNodeMasks.hxx>
00054 #include <simgear/scene/util/QuadTreeBuilder.hxx>
00055
00056 #include "SGTexturedTriangleBin.hxx"
00057 #include "SGLightBin.hxx"
00058 #include "SGModelBin.hxx"
00059 #include "TreeBin.hxx"
00060 #include "SGDirectionalLightBin.hxx"
00061 #include "GroundLightManager.hxx"
00062
00063
00064 #include "userdata.hxx"
00065 #include "pt_lights.hxx"
00066
00067 using namespace simgear;
00068
00069 typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
00070 typedef std::list<SGLightBin> SGLightListBin;
00071 typedef std::list<SGDirectionalLightBin> SGDirectionalLightListBin;
00072
00073 struct SGTileGeometryBin {
00074 SGMaterialTriangleMap materialTriangleMap;
00075 SGLightBin tileLights;
00076 SGLightBin randomTileLights;
00077 TreeBin randomForest;
00078 SGDirectionalLightBin runwayLights;
00079 SGDirectionalLightBin taxiLights;
00080 SGDirectionalLightListBin vasiLights;
00081 SGDirectionalLightListBin rabitLights;
00082 SGLightListBin odalLights;
00083 SGDirectionalLightListBin reilLights;
00084 SGMatModelBin randomModels;
00085
00086 static SGVec4f
00087 getMaterialLightColor(const SGMaterial* material)
00088 {
00089 if (!material)
00090 return SGVec4f(1, 1, 1, 0.8);
00091 return material->get_light_color();
00092 }
00093
00094 static void
00095 addPointGeometry(SGLightBin& lights,
00096 const std::vector<SGVec3d>& vertices,
00097 const SGVec4f& color,
00098 const int_list& pts_v)
00099 {
00100 for (unsigned i = 0; i < pts_v.size(); ++i)
00101 lights.insert(toVec3f(vertices[pts_v[i]]), color);
00102 }
00103
00104 static void
00105 addPointGeometry(SGDirectionalLightBin& lights,
00106 const std::vector<SGVec3d>& vertices,
00107 const std::vector<SGVec3f>& normals,
00108 const SGVec4f& color,
00109 const int_list& pts_v,
00110 const int_list& pts_n)
00111 {
00112
00113
00114 if (pts_v.size() == pts_n.size()) {
00115 for (unsigned i = 0; i < pts_v.size(); ++i)
00116 lights.insert(toVec3f(vertices[pts_v[i]]), normals[pts_n[i]], color);
00117 } else {
00118 for (unsigned i = 0; i < pts_v.size(); ++i)
00119 lights.insert(toVec3f(vertices[pts_v[i]]), normals[pts_v[i]], color);
00120 }
00121 }
00122
00123 bool
00124 insertPtGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
00125 {
00126 if (obj.get_pts_v().size() != obj.get_pts_n().size()) {
00127 SG_LOG(SG_TERRAIN, SG_ALERT,
00128 "Group list sizes for points do not match!");
00129 return false;
00130 }
00131
00132 for (unsigned grp = 0; grp < obj.get_pts_v().size(); ++grp) {
00133 std::string materialName = obj.get_pt_materials()[grp];
00134 SGMaterial* material = 0;
00135 if (matlib)
00136 material = matlib->find(materialName);
00137 SGVec4f color = getMaterialLightColor(material);
00138
00139 if (3 <= materialName.size() && materialName.substr(0, 3) != "RWY") {
00140
00141 addPointGeometry(tileLights, obj.get_wgs84_nodes(), color,
00142 obj.get_pts_v()[grp]);
00143 } else if (materialName == "RWY_BLUE_TAXIWAY_LIGHTS"
00144 || materialName == "RWY_GREEN_TAXIWAY_LIGHTS") {
00145 addPointGeometry(taxiLights, obj.get_wgs84_nodes(), obj.get_normals(),
00146 color, obj.get_pts_v()[grp], obj.get_pts_n()[grp]);
00147 } else if (materialName == "RWY_VASI_LIGHTS") {
00148 vasiLights.push_back(SGDirectionalLightBin());
00149 addPointGeometry(vasiLights.back(), obj.get_wgs84_nodes(),
00150 obj.get_normals(), color, obj.get_pts_v()[grp],
00151 obj.get_pts_n()[grp]);
00152 } else if (materialName == "RWY_SEQUENCED_LIGHTS") {
00153 rabitLights.push_back(SGDirectionalLightBin());
00154 addPointGeometry(rabitLights.back(), obj.get_wgs84_nodes(),
00155 obj.get_normals(), color, obj.get_pts_v()[grp],
00156 obj.get_pts_n()[grp]);
00157 } else if (materialName == "RWY_ODALS_LIGHTS") {
00158 odalLights.push_back(SGLightBin());
00159 addPointGeometry(odalLights.back(), obj.get_wgs84_nodes(),
00160 color, obj.get_pts_v()[grp]);
00161 } else if (materialName == "RWY_REIL_LIGHTS") {
00162 reilLights.push_back(SGDirectionalLightBin());
00163 addPointGeometry(reilLights.back(), obj.get_wgs84_nodes(),
00164 obj.get_normals(), color, obj.get_pts_v()[grp],
00165 obj.get_pts_n()[grp]);
00166 } else {
00167
00168 addPointGeometry(runwayLights, obj.get_wgs84_nodes(),
00169 obj.get_normals(), color, obj.get_pts_v()[grp],
00170 obj.get_pts_n()[grp]);
00171 }
00172 }
00173
00174 return true;
00175 }
00176
00177
00178 static SGVec2f
00179 getTexCoord(const std::vector<SGVec2f>& texCoords, const int_list& tc,
00180 const SGVec2f& tcScale, unsigned i)
00181 {
00182 if (tc.empty())
00183 return tcScale;
00184 else if (tc.size() == 1)
00185 return mult(texCoords[tc[0]], tcScale);
00186 else
00187 return mult(texCoords[tc[i]], tcScale);
00188 }
00189
00190 static void
00191 addTriangleGeometry(SGTexturedTriangleBin& triangles,
00192 const std::vector<SGVec3d>& vertices,
00193 const std::vector<SGVec3f>& normals,
00194 const std::vector<SGVec2f>& texCoords,
00195 const int_list& tris_v,
00196 const int_list& tris_n,
00197 const int_list& tris_tc,
00198 const SGVec2f& tcScale)
00199 {
00200 if (tris_v.size() != tris_n.size()) {
00201
00202
00203
00204 addTriangleGeometry(triangles, vertices, normals, texCoords,
00205 tris_v, tris_v, tris_tc, tcScale);
00206 return;
00207 }
00208
00209 for (unsigned i = 2; i < tris_v.size(); i += 3) {
00210 SGVertNormTex v0;
00211 v0.vertex = toVec3f(vertices[tris_v[i-2]]);
00212 v0.normal = normals[tris_n[i-2]];
00213 v0.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-2);
00214 SGVertNormTex v1;
00215 v1.vertex = toVec3f(vertices[tris_v[i-1]]);
00216 v1.normal = normals[tris_n[i-1]];
00217 v1.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-1);
00218 SGVertNormTex v2;
00219 v2.vertex = toVec3f(vertices[tris_v[i]]);
00220 v2.normal = normals[tris_n[i]];
00221 v2.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i);
00222 triangles.insert(v0, v1, v2);
00223 }
00224 }
00225
00226 static void
00227 addStripGeometry(SGTexturedTriangleBin& triangles,
00228 const std::vector<SGVec3d>& vertices,
00229 const std::vector<SGVec3f>& normals,
00230 const std::vector<SGVec2f>& texCoords,
00231 const int_list& strips_v,
00232 const int_list& strips_n,
00233 const int_list& strips_tc,
00234 const SGVec2f& tcScale)
00235 {
00236 if (strips_v.size() != strips_n.size()) {
00237
00238
00239
00240 addStripGeometry(triangles, vertices, normals, texCoords,
00241 strips_v, strips_v, strips_tc, tcScale);
00242 return;
00243 }
00244
00245 for (unsigned i = 2; i < strips_v.size(); ++i) {
00246 SGVertNormTex v0;
00247 v0.vertex = toVec3f(vertices[strips_v[i-2]]);
00248 v0.normal = normals[strips_n[i-2]];
00249 v0.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-2);
00250 SGVertNormTex v1;
00251 v1.vertex = toVec3f(vertices[strips_v[i-1]]);
00252 v1.normal = normals[strips_n[i-1]];
00253 v1.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-1);
00254 SGVertNormTex v2;
00255 v2.vertex = toVec3f(vertices[strips_v[i]]);
00256 v2.normal = normals[strips_n[i]];
00257 v2.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i);
00258 if (i%2)
00259 triangles.insert(v1, v0, v2);
00260 else
00261 triangles.insert(v0, v1, v2);
00262 }
00263 }
00264
00265 static void
00266 addFanGeometry(SGTexturedTriangleBin& triangles,
00267 const std::vector<SGVec3d>& vertices,
00268 const std::vector<SGVec3f>& normals,
00269 const std::vector<SGVec2f>& texCoords,
00270 const int_list& fans_v,
00271 const int_list& fans_n,
00272 const int_list& fans_tc,
00273 const SGVec2f& tcScale)
00274 {
00275 if (fans_v.size() != fans_n.size()) {
00276
00277
00278
00279 addFanGeometry(triangles, vertices, normals, texCoords,
00280 fans_v, fans_v, fans_tc, tcScale);
00281 return;
00282 }
00283
00284 SGVertNormTex v0;
00285 v0.vertex = toVec3f(vertices[fans_v[0]]);
00286 v0.normal = normals[fans_n[0]];
00287 v0.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 0);
00288 SGVertNormTex v1;
00289 v1.vertex = toVec3f(vertices[fans_v[1]]);
00290 v1.normal = normals[fans_n[1]];
00291 v1.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 1);
00292 for (unsigned i = 2; i < fans_v.size(); ++i) {
00293 SGVertNormTex v2;
00294 v2.vertex = toVec3f(vertices[fans_v[i]]);
00295 v2.normal = normals[fans_n[i]];
00296 v2.texCoord = getTexCoord(texCoords, fans_tc, tcScale, i);
00297 triangles.insert(v0, v1, v2);
00298 v1 = v2;
00299 }
00300 }
00301
00302 SGVec2f getTexCoordScale(const std::string& name, SGMaterialLib* matlib)
00303 {
00304 if (!matlib)
00305 return SGVec2f(1, 1);
00306 SGMaterial* material = matlib->find(name);
00307 if (!material)
00308 return SGVec2f(1, 1);
00309
00310 return material->get_tex_coord_scale();
00311 }
00312
00313 bool
00314 insertSurfaceGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
00315 {
00316 if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
00317 obj.get_tris_tc().size() < obj.get_tris_v().size()) {
00318 SG_LOG(SG_TERRAIN, SG_ALERT,
00319 "Group list sizes for triangles do not match!");
00320 return false;
00321 }
00322
00323 for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
00324 std::string materialName = obj.get_tri_materials()[grp];
00325 SGVec2f tcScale = getTexCoordScale(materialName, matlib);
00326 addTriangleGeometry(materialTriangleMap[materialName],
00327 obj.get_wgs84_nodes(), obj.get_normals(),
00328 obj.get_texcoords(), obj.get_tris_v()[grp],
00329 obj.get_tris_n()[grp], obj.get_tris_tc()[grp],
00330 tcScale);
00331 }
00332
00333 if (obj.get_strips_n().size() < obj.get_strips_v().size() ||
00334 obj.get_strips_tc().size() < obj.get_strips_v().size()) {
00335 SG_LOG(SG_TERRAIN, SG_ALERT,
00336 "Group list sizes for strips do not match!");
00337 return false;
00338 }
00339 for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
00340 std::string materialName = obj.get_strip_materials()[grp];
00341 SGVec2f tcScale = getTexCoordScale(materialName, matlib);
00342 addStripGeometry(materialTriangleMap[materialName],
00343 obj.get_wgs84_nodes(), obj.get_normals(),
00344 obj.get_texcoords(), obj.get_strips_v()[grp],
00345 obj.get_strips_n()[grp], obj.get_strips_tc()[grp],
00346 tcScale);
00347 }
00348
00349 if (obj.get_fans_n().size() < obj.get_fans_v().size() ||
00350 obj.get_fans_tc().size() < obj.get_fans_v().size()) {
00351 SG_LOG(SG_TERRAIN, SG_ALERT,
00352 "Group list sizes for fans do not match!");
00353 return false;
00354 }
00355 for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
00356 std::string materialName = obj.get_fan_materials()[grp];
00357 SGVec2f tcScale = getTexCoordScale(materialName, matlib);
00358 addFanGeometry(materialTriangleMap[materialName],
00359 obj.get_wgs84_nodes(), obj.get_normals(),
00360 obj.get_texcoords(), obj.get_fans_v()[grp],
00361 obj.get_fans_n()[grp], obj.get_fans_tc()[grp],
00362 tcScale);
00363 }
00364 return true;
00365 }
00366
00367 osg::Node* getSurfaceGeometry(SGMaterialLib* matlib) const
00368 {
00369 if (materialTriangleMap.empty())
00370 return 0;
00371
00372 EffectGeode* eg = 0;
00373 osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : 0);
00374
00375 SGMaterialTriangleMap::const_iterator i;
00376 for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
00377 osg::Geometry* geometry = i->second.buildGeometry();
00378 SGMaterial *mat = 0;
00379 if (matlib)
00380 mat = matlib->find(i->first);
00381 eg = new EffectGeode;
00382 if (mat)
00383 eg->setEffect(mat->get_effect());
00384 eg->addDrawable(geometry);
00385 if (group)
00386 group->addChild(eg);
00387 }
00388 if (group)
00389 return group;
00390 else
00391 return eg;
00392 }
00393
00394 void computeRandomSurfaceLights(SGMaterialLib* matlib)
00395 {
00396 SGMaterialTriangleMap::iterator i;
00397
00398
00399 mt seed;
00400 mt_init(&seed, unsigned(123));
00401
00402 for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
00403 SGMaterial *mat = matlib->find(i->first);
00404 if (!mat)
00405 continue;
00406
00407 float coverage = mat->get_light_coverage();
00408 if (coverage <= 0)
00409 continue;
00410 if (coverage < 10000.0) {
00411 SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
00412 << coverage << ", pushing up to 10000");
00413 coverage = 10000;
00414 }
00415
00416 std::vector<SGVec3f> randomPoints;
00417 i->second.addRandomSurfacePoints(coverage, 3, randomPoints);
00418 std::vector<SGVec3f>::iterator j;
00419 for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
00420 float zombie = mt_rand(&seed);
00421
00422 float factor = mt_rand(&seed);
00423 factor *= factor;
00424
00425 float bright = 1;
00426 SGVec4f color;
00427 if ( zombie > 0.5 ) {
00428
00429 color = SGVec4f(0.9f, 0.9f, 0.3f, bright - factor * 0.2f);
00430 } else if (zombie > 0.15f) {
00431
00432 color = SGVec4f(0.9, 0.9f, 0.8f, bright - factor * 0.2f);
00433 } else if (zombie > 0.05f) {
00434
00435 color = SGVec4f(0.9f, 0.6f, 0.2f, bright - factor * 0.2f);
00436 } else {
00437
00438 color = SGVec4f(0.9f, 0.2f, 0.2f, bright - factor * 0.2f);
00439 }
00440 randomTileLights.insert(*j, color);
00441 }
00442 }
00443 }
00444
00445 void computeRandomForest(SGMaterialLib* matlib)
00446 {
00447 SGMaterialTriangleMap::iterator i;
00448
00449
00450 mt seed;
00451 mt_init(&seed, unsigned(586));
00452
00453 for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
00454 SGMaterial *mat = matlib->find(i->first);
00455 if (!mat)
00456 continue;
00457
00458 float wood_coverage = mat->get_wood_coverage();
00459 if (wood_coverage <= 0)
00460 continue;
00461
00462
00463 randomForest.texture = mat->get_tree_texture();
00464 randomForest.range = mat->get_tree_range();
00465 randomForest.width = mat->get_tree_width();
00466 randomForest.height = mat->get_tree_height();
00467 randomForest.texture_varieties = mat->get_tree_varieties();
00468
00469 std::vector<SGVec3f> randomPoints;
00470 i->second.addRandomTreePoints(wood_coverage,
00471 mat->get_tree_density(),
00472 mat->get_wood_size(),
00473 randomPoints);
00474
00475 std::vector<SGVec3f>::iterator j;
00476 for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
00477 randomForest.insert(*j);
00478 }
00479 }
00480 }
00481
00482 void computeRandomObjects(SGMaterialLib* matlib)
00483 {
00484 SGMaterialTriangleMap::iterator i;
00485
00486
00487 mt seed;
00488 mt_init(&seed, unsigned(123));
00489
00490 for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
00491 SGMaterial *mat = matlib->find(i->first);
00492 if (!mat)
00493 continue;
00494
00495 int group_count = mat->get_object_group_count();
00496
00497 if (group_count > 0)
00498 {
00499 for (int j = 0; j < group_count; j++)
00500 {
00501 SGMatModelGroup *object_group = mat->get_object_group(j);
00502 int nObjects = object_group->get_object_count();
00503
00504 if (nObjects > 0)
00505 {
00506
00507
00508 for (int k = 0; k < nObjects; k++) {
00509 SGMatModel * object = object_group->get_object(k);
00510
00511 std::vector<SGVec3f> randomPoints;
00512
00513 i->second.addRandomPoints(object->get_coverage_m2(), randomPoints);
00514 std::vector<SGVec3f>::iterator l;
00515 for (l = randomPoints.begin(); l != randomPoints.end(); ++l) {
00516 randomModels.insert(*l, object, (int)object->get_randomized_range_m(&seed));
00517 }
00518 }
00519 }
00520 }
00521 }
00522 }
00523 }
00524
00525 bool insertBinObj(const SGBinObject& obj, SGMaterialLib* matlib)
00526 {
00527 if (!insertPtGeometry(obj, matlib))
00528 return false;
00529 if (!insertSurfaceGeometry(obj, matlib))
00530 return false;
00531 return true;
00532 }
00533 };
00534
00535 typedef std::pair<osg::Node*, int> ModelLOD;
00536 struct MakeQuadLeaf {
00537 osg::LOD* operator() () const { return new osg::LOD; }
00538 };
00539 struct AddModelLOD {
00540 void operator() (osg::LOD* leaf, ModelLOD& mlod) const
00541 {
00542 leaf->addChild(mlod.first, 0, mlod.second);
00543 }
00544 };
00545 struct GetModelLODCoord {
00546 GetModelLODCoord() {}
00547 GetModelLODCoord(const GetModelLODCoord& rhs)
00548 {}
00549 osg::Vec3 operator() (const ModelLOD& mlod) const
00550 {
00551 return mlod.first->getBound().center();
00552 }
00553 };
00554
00555 typedef QuadTreeBuilder<osg::LOD*, ModelLOD, MakeQuadLeaf, AddModelLOD,
00556 GetModelLODCoord> RandomObjectsQuadtree;
00557
00558 osg::Node*
00559 SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation)
00560 {
00561 SGBinObject tile;
00562 if (!tile.read_bin(path))
00563 return false;
00564
00565 SGVec3d center = tile.get_gbs_center2();
00566 SGGeod geodPos = SGGeod::fromCart(center);
00567 SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
00568
00569
00570
00571 std::vector<SGVec3d> nodes = tile.get_wgs84_nodes();
00572 for (unsigned i = 0; i < nodes.size(); ++i)
00573 nodes[i] = hlOr.transform(nodes[i]);
00574 tile.set_wgs84_nodes(nodes);
00575
00576 SGQuatf hlOrf(hlOr[0], hlOr[1], hlOr[2], hlOr[3]);
00577 std::vector<SGVec3f> normals = tile.get_normals();
00578 for (unsigned i = 0; i < normals.size(); ++i)
00579 normals[i] = hlOrf.transform(normals[i]);
00580 tile.set_normals(normals);
00581
00582 SGTileGeometryBin tileGeometryBin;
00583 if (!tileGeometryBin.insertBinObj(tile, matlib))
00584 return false;
00585
00586 SGVec3f up(0, 0, 1);
00587 GroundLightManager* lightManager = GroundLightManager::instance();
00588
00589 osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
00590 osg::ref_ptr<osg::Group> randomObjects;
00591 osg::ref_ptr<osg::Group> randomForest;
00592 osg::Group* terrainGroup = new osg::Group;
00593
00594 osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
00595 if (node)
00596 terrainGroup->addChild(node);
00597
00598 if (use_random_objects || use_random_vegetation) {
00599 if (use_random_objects) {
00600 if (matlib)
00601 tileGeometryBin.computeRandomObjects(matlib);
00602
00603 if (tileGeometryBin.randomModels.getNumModels() > 0) {
00604
00605 mt seed;
00606 mt_init(&seed, unsigned(123));
00607
00608 std::vector<ModelLOD> models;
00609 for (unsigned int i = 0;
00610 i < tileGeometryBin.randomModels.getNumModels(); i++) {
00611 SGMatModelBin::MatModel obj
00612 = tileGeometryBin.randomModels.getMatModel(i);
00613 osg::Node* node = sgGetRandomModel(obj.model);
00614
00615
00616
00617
00618 osg::Matrix transformMat;
00619 transformMat = osg::Matrix::translate(toOsg(obj.position));
00620 if (obj.model->get_heading_type() == SGMatModel::HEADING_RANDOM) {
00621
00622 double hdg = mt_rand(&seed) * M_PI * 2;
00623 transformMat.preMult(osg::Matrix::rotate(hdg,
00624 osg::Vec3d(0.0, 0.0, 1.0)));
00625 }
00626 osg::MatrixTransform* position =
00627 new osg::MatrixTransform(transformMat);
00628 position->addChild(node);
00629 models.push_back(ModelLOD(position, obj.lod));
00630 }
00631 RandomObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
00632 quadtree.buildQuadTree(models.begin(), models.end());
00633 randomObjects = quadtree.getRoot();
00634 randomObjects->setName("random objects");
00635 }
00636 }
00637
00638 if (use_random_vegetation && matlib) {
00639
00640 tileGeometryBin.computeRandomForest(matlib);
00641
00642 if (tileGeometryBin.randomForest.getNumTrees() > 0) {
00643 randomForest = createForest(tileGeometryBin.randomForest,
00644 osg::Matrix::identity());
00645 randomForest->setName("random trees");
00646 }
00647 }
00648 }
00649
00650 if (calc_lights) {
00651
00652 if (matlib)
00653 tileGeometryBin.computeRandomSurfaceLights(matlib);
00654
00655 if (tileGeometryBin.tileLights.getNumLights() > 0
00656 || tileGeometryBin.randomTileLights.getNumLights() > 0) {
00657 osg::Group* groundLights0 = new osg::Group;
00658 groundLights0->setStateSet(lightManager->getGroundLightStateSet());
00659 groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
00660 osg::Geode* geode = new osg::Geode;
00661 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
00662 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
00663 groundLights0->addChild(geode);
00664 lightGroup->addChild(groundLights0);
00665 }
00666 if (tileGeometryBin.randomTileLights.getNumLights() > 0) {
00667 osg::Group* groundLights1 = new osg::Group;
00668 groundLights1->setStateSet(lightManager->getGroundLightStateSet());
00669 groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
00670 osg::Group* groundLights2 = new osg::Group;
00671 groundLights2->setStateSet(lightManager->getGroundLightStateSet());
00672 groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
00673 osg::Geode* geode = new osg::Geode;
00674 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
00675 groundLights1->addChild(geode);
00676 lightGroup->addChild(groundLights1);
00677 geode = new osg::Geode;
00678 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
00679 groundLights2->addChild(geode);
00680 lightGroup->addChild(groundLights2);
00681 }
00682 }
00683
00684 if (!tileGeometryBin.vasiLights.empty()) {
00685 EffectGeode* vasiGeode = new EffectGeode;
00686 Effect* vasiEffect
00687 = getLightEffect(6, osg::Vec3(1, 0.0001, 0.000001), 1, 6, true);
00688 vasiGeode->setEffect(vasiEffect);
00689 SGVec4f red(1, 0, 0, 1);
00690 SGMaterial* mat = 0;
00691 if (matlib)
00692 mat = matlib->find("RWY_RED_LIGHTS");
00693 if (mat)
00694 red = mat->get_light_color();
00695 SGVec4f white(1, 1, 1, 1);
00696 mat = 0;
00697 if (matlib)
00698 mat = matlib->find("RWY_WHITE_LIGHTS");
00699 if (mat)
00700 white = mat->get_light_color();
00701 SGDirectionalLightListBin::const_iterator i;
00702 for (i = tileGeometryBin.vasiLights.begin();
00703 i != tileGeometryBin.vasiLights.end(); ++i) {
00704 vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
00705 }
00706 vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
00707 lightGroup->addChild(vasiGeode);
00708 }
00709 Effect* runwayEffect = 0;
00710 if (tileGeometryBin.runwayLights.getNumLights() > 0
00711 || !tileGeometryBin.rabitLights.empty()
00712 || !tileGeometryBin.reilLights.empty()
00713 || !tileGeometryBin.odalLights.empty()
00714 || tileGeometryBin.taxiLights.getNumLights() > 0)
00715 runwayEffect = getLightEffect(4, osg::Vec3(1, 0.001, 0.0002), 1, 4, true);
00716 if (tileGeometryBin.runwayLights.getNumLights() > 0
00717 || !tileGeometryBin.rabitLights.empty()
00718 || !tileGeometryBin.reilLights.empty()
00719 || !tileGeometryBin.odalLights.empty()) {
00720 osg::Group* rwyLights = new osg::Group;
00721 rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
00722 rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
00723 if (tileGeometryBin.runwayLights.getNumLights() != 0) {
00724 EffectGeode* geode = new EffectGeode;
00725 geode->setEffect(runwayEffect);
00726 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin
00727 .runwayLights));
00728 rwyLights->addChild(geode);
00729 }
00730 SGDirectionalLightListBin::const_iterator i;
00731 for (i = tileGeometryBin.rabitLights.begin();
00732 i != tileGeometryBin.rabitLights.end(); ++i) {
00733 rwyLights->addChild(SGLightFactory::getSequenced(*i));
00734 }
00735 for (i = tileGeometryBin.reilLights.begin();
00736 i != tileGeometryBin.reilLights.end(); ++i) {
00737 rwyLights->addChild(SGLightFactory::getSequenced(*i));
00738 }
00739 SGLightListBin::const_iterator j;
00740 for (j = tileGeometryBin.odalLights.begin();
00741 j != tileGeometryBin.odalLights.end(); ++j) {
00742 rwyLights->addChild(SGLightFactory::getOdal(*j));
00743 }
00744 lightGroup->addChild(rwyLights);
00745 }
00746
00747 if (tileGeometryBin.taxiLights.getNumLights() > 0) {
00748 osg::Group* taxiLights = new osg::Group;
00749 taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
00750 taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
00751 EffectGeode* geode = new EffectGeode;
00752 geode->setEffect(runwayEffect);
00753 geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.taxiLights));
00754 taxiLights->addChild(geode);
00755 lightGroup->addChild(taxiLights);
00756 }
00757
00758
00759 osg::MatrixTransform* transform = new osg::MatrixTransform;
00760 transform->setName(path);
00761 transform->setMatrix(osg::Matrix::rotate(toOsg(hlOr))*
00762 osg::Matrix::translate(toOsg(center)));
00763 transform->addChild(terrainGroup);
00764 if (lightGroup->getNumChildren() > 0) {
00765 osg::LOD* lightLOD = new osg::LOD;
00766 lightLOD->addChild(lightGroup.get(), 0, 30000);
00767
00768 lightLOD->setNodeMask(LIGHTS_BITS | MODEL_BIT);
00769 transform->addChild(lightLOD);
00770 }
00771
00772 if (randomObjects.valid() || randomForest.valid()) {
00773
00774
00775
00776 osg::LOD* objectLOD = new osg::LOD;
00777
00778 if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000);
00779 if (randomForest.valid()) objectLOD->addChild(randomForest.get(), 0, 20000);
00780
00781 unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECIEVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT;
00782 objectLOD->setNodeMask(nodeMask);
00783 transform->addChild(objectLOD);
00784 }
00785
00786 return transform;
00787 }