#include <osg/StateSet>
#include <osg/Switch>
+#include <boost/foreach.hpp>
+
#include <simgear/debug/logstream.hxx>
#include <simgear/io/sg_binobj.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_random.h>
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/model/SGOffsetTransform.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
-#include <simgear/threads/SGThread.hxx>
-#include <simgear/threads/SGGuard.hxx>
+#include <simgear/scene/util/QuadTreeBuilder.hxx>
#include "SGTexturedTriangleBin.hxx"
#include "SGLightBin.hxx"
+#include "SGModelBin.hxx"
+#include "TreeBin.hxx"
#include "SGDirectionalLightBin.hxx"
+#include "GroundLightManager.hxx"
+
+#include "userdata.hxx"
#include "pt_lights.hxx"
+using namespace simgear;
+
typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
typedef std::list<SGLightBin> SGLightListBin;
typedef std::list<SGDirectionalLightBin> SGDirectionalLightListBin;
SGMaterialTriangleMap materialTriangleMap;
SGLightBin tileLights;
SGLightBin randomTileLights;
+ SGTreeBinList randomForest;
SGDirectionalLightBin runwayLights;
SGDirectionalLightBin taxiLights;
SGDirectionalLightListBin vasiLights;
SGDirectionalLightListBin rabitLights;
SGLightListBin odalLights;
SGDirectionalLightListBin reilLights;
+ SGMatModelBin randomModels;
static SGVec4f
getMaterialLightColor(const SGMaterial* material)
for (unsigned grp = 0; grp < obj.get_pts_v().size(); ++grp) {
std::string materialName = obj.get_pt_materials()[grp];
- SGMaterial* material = matlib->find(materialName);
+ SGMaterial* material = 0;
+ if (matlib)
+ material = matlib->find(materialName);
SGVec4f color = getMaterialLightColor(material);
-
+
if (3 <= materialName.size() && materialName.substr(0, 3) != "RWY") {
// Just plain lights. Not something for the runway.
addPointGeometry(tileLights, obj.get_wgs84_nodes(), color,
if (materialTriangleMap.empty())
return 0;
- osg::Geode* geode = new osg::Geode;
+ EffectGeode* eg = 0;
+ osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : 0);
+ //osg::Geode* geode = new osg::Geode;
SGMaterialTriangleMap::const_iterator i;
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
-#define CHUNCKED
-#ifdef CHUNCKED
- SGMaterial *mat = matlib->find(i->first);
-
- std::list<SGTexturedTriangleBin::TriangleVector> connectSets;
- i->second.getConnectedSets(connectSets);
-
- std::list<SGTexturedTriangleBin::TriangleVector>::iterator j;
- for (j = connectSets.begin(); j != connectSets.end(); ++j) {
- osg::Geometry* geometry = i->second.buildGeometry(*j);
- if (mat)
- geometry->setStateSet(mat->get_state());
- geode->addDrawable(geometry);
- }
-#else
osg::Geometry* geometry = i->second.buildGeometry();
- SGMaterial *mat = matlib->find(i->first);
+ SGMaterial *mat = 0;
+ if (matlib)
+ mat = matlib->find(i->first);
+ eg = new EffectGeode;
if (mat)
- geometry->setStateSet(mat->get_state());
- geode->addDrawable(geometry);
-#endif
+ eg->setEffect(mat->get_effect());
+ eg->addDrawable(geometry);
+ eg->runGenerators(geometry); // Generate extra data needed by effect
+ if (group)
+ group->addChild(eg);
}
- return geode;
+ if (group)
+ return group;
+ else
+ return eg;
}
void computeRandomSurfaceLights(SGMaterialLib* matlib)
{
- SGMaterialTriangleMap::const_iterator i;
+ SGMaterialTriangleMap::iterator i;
+
+ // generate a repeatable random seed
+ mt seed;
+ mt_init(&seed, unsigned(123));
+
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
SGMaterial *mat = matlib->find(i->first);
if (!mat)
coverage = 10000;
}
- // generate a repeatable random seed
- sg_srandom(unsigned(coverage));
-
std::vector<SGVec3f> randomPoints;
i->second.addRandomSurfacePoints(coverage, 3, randomPoints);
std::vector<SGVec3f>::iterator j;
for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
- float zombie = sg_random();
+ float zombie = mt_rand(&seed);
// factor = sg_random() ^ 2, range = 0 .. 1 concentrated towards 0
- float factor = sg_random();
+ float factor = mt_rand(&seed);
factor *= factor;
float bright = 1;
}
}
- bool insertBinObj(const SGBinObject& obj, SGMaterialLib* matlib)
+ void computeRandomForest(SGMaterialLib* matlib)
{
- if (!insertPtGeometry(obj, matlib))
- return false;
- if (!insertSurfaceGeometry(obj, matlib))
- return false;
- return true;
- }
-};
-
+ SGMaterialTriangleMap::iterator i;
-class SGTileUpdateCallback : public osg::NodeCallback {
-public:
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- assert(dynamic_cast<osg::Switch*>(node));
- assert(dynamic_cast<SGUpdateVisitor*>(nv));
+ // generate a repeatable random seed
+ mt seed;
+ mt_init(&seed, unsigned(586));
- osg::Switch* lightSwitch = static_cast<osg::Switch*>(node);
- SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
+ for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
+ SGMaterial *mat = matlib->find(i->first);
+ if (!mat)
+ continue;
- // The current sun angle in degree
- float sun_angle = updateVisitor->getSunAngleDeg();
+ float wood_coverage = mat->get_wood_coverage();
+ if (wood_coverage <= 0)
+ continue;
+
+ // Attributes that don't vary by tree but do vary by material
+ bool found = false;
+ TreeBin* bin = NULL;
+
+ BOOST_FOREACH(bin, randomForest)
+ {
+ if ((bin->texture == mat->get_tree_texture() ) &&
+ (bin->texture_varieties == mat->get_tree_varieties()) &&
+ (bin->range == mat->get_tree_range() ) &&
+ (bin->width == mat->get_tree_width() ) &&
+ (bin->height == mat->get_tree_height() ) ) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ bin = new TreeBin();
+ bin->texture = mat->get_tree_texture();
+ SG_LOG(SG_INPUT, SG_DEBUG, "Tree texture " << bin->texture);
+ bin->range = mat->get_tree_range();
+ bin->width = mat->get_tree_width();
+ bin->height = mat->get_tree_height();
+ bin->texture_varieties = mat->get_tree_varieties();
+ randomForest.push_back(bin);
+ }
- // vasi is always on
- lightSwitch->setValue(0, true);
- if (sun_angle > 85 || updateVisitor->getVisibility() < 5000) {
- // runway and taxi
- lightSwitch->setValue(1, true);
- lightSwitch->setValue(2, true);
- } else {
- // runway and taxi
- lightSwitch->setValue(1, false);
- lightSwitch->setValue(2, false);
+ std::vector<SGVec3f> randomPoints;
+ i->second.addRandomTreePoints(wood_coverage,
+ mat->get_tree_density(),
+ mat->get_wood_size(),
+ randomPoints);
+
+ std::vector<SGVec3f>::iterator k;
+ for (k = randomPoints.begin(); k != randomPoints.end(); ++k) {
+ bin->insert(*k);
+ }
}
-
- // ground lights
- if ( sun_angle > 95 )
- lightSwitch->setValue(5, true);
- else
- lightSwitch->setValue(5, false);
- if ( sun_angle > 92 )
- lightSwitch->setValue(4, true);
- else
- lightSwitch->setValue(4, false);
- if ( sun_angle > 89 )
- lightSwitch->setValue(3, true);
- else
- lightSwitch->setValue(3, false);
-
- traverse(node, nv);
}
-};
-class SGRunwayLightFogUpdateCallback : public osg::StateAttribute::Callback {
-public:
- virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+ void computeRandomObjects(SGMaterialLib* matlib)
{
- assert(dynamic_cast<SGUpdateVisitor*>(nv));
- assert(dynamic_cast<osg::Fog*>(sa));
- SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
- osg::Fog* fog = static_cast<osg::Fog*>(sa);
- fog->setMode(osg::Fog::EXP2);
- fog->setColor(updateVisitor->getFogColor().osg());
- fog->setDensity(updateVisitor->getRunwayFogExp2Density());
+ SGMaterialTriangleMap::iterator i;
+
+ // generate a repeatable random seed
+ mt seed;
+ mt_init(&seed, unsigned(123));
+
+ for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
+ SGMaterial *mat = matlib->find(i->first);
+ if (!mat)
+ continue;
+
+ int group_count = mat->get_object_group_count();
+
+ if (group_count > 0)
+ {
+ for (int j = 0; j < group_count; j++)
+ {
+ SGMatModelGroup *object_group = mat->get_object_group(j);
+ int nObjects = object_group->get_object_count();
+
+ if (nObjects > 0)
+ {
+ // For each of the random models in the group, determine an appropriate
+ // number of random placements and insert them.
+ for (int k = 0; k < nObjects; k++) {
+ SGMatModel * object = object_group->get_object(k);
+
+ std::vector<SGVec3f> randomPoints;
+
+ i->second.addRandomPoints(object->get_coverage_m2(), randomPoints);
+ std::vector<SGVec3f>::iterator l;
+ for (l = randomPoints.begin(); l != randomPoints.end(); ++l) {
+ randomModels.insert(*l, object, (int)object->get_randomized_range_m(&seed));
+ }
+ }
+ }
+ }
+ }
+ }
}
-};
-class SGTaxiLightFogUpdateCallback : public osg::StateAttribute::Callback {
-public:
- virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+ bool insertBinObj(const SGBinObject& obj, SGMaterialLib* matlib)
{
- assert(dynamic_cast<SGUpdateVisitor*>(nv));
- assert(dynamic_cast<osg::Fog*>(sa));
- SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
- osg::Fog* fog = static_cast<osg::Fog*>(sa);
- fog->setMode(osg::Fog::EXP2);
- fog->setColor(updateVisitor->getFogColor().osg());
- fog->setDensity(updateVisitor->getTaxiFogExp2Density());
+ if (!insertPtGeometry(obj, matlib))
+ return false;
+ if (!insertSurfaceGeometry(obj, matlib))
+ return false;
+ return true;
}
};
-class SGGroundLightFogUpdateCallback : public osg::StateAttribute::Callback {
-public:
- virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
- {
- assert(dynamic_cast<SGUpdateVisitor*>(nv));
- assert(dynamic_cast<osg::Fog*>(sa));
- SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
- osg::Fog* fog = static_cast<osg::Fog*>(sa);
- fog->setMode(osg::Fog::EXP2);
- fog->setColor(updateVisitor->getFogColor().osg());
- fog->setDensity(updateVisitor->getGroundLightsFogExp2Density());
- }
+typedef std::pair<osg::Node*, int> ModelLOD;
+struct MakeQuadLeaf {
+ osg::LOD* operator() () const { return new osg::LOD; }
+};
+struct AddModelLOD {
+ void operator() (osg::LOD* leaf, ModelLOD& mlod) const
+ {
+ leaf->addChild(mlod.first, 0, mlod.second);
+ }
+};
+struct GetModelLODCoord {
+ GetModelLODCoord() {}
+ GetModelLODCoord(const GetModelLODCoord& rhs)
+ {}
+ osg::Vec3 operator() (const ModelLOD& mlod) const
+ {
+ return mlod.first->getBound().center();
+ }
};
+typedef QuadTreeBuilder<osg::LOD*, ModelLOD, MakeQuadLeaf, AddModelLOD,
+ GetModelLODCoord> RandomObjectsQuadtree;
+
osg::Node*
-SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation)
{
- SGBinObject obj;
- if (!obj.read_bin(path))
+ SGBinObject tile;
+ if (!tile.read_bin(path))
return false;
+ SGVec3d center = tile.get_gbs_center();
+ SGGeod geodPos = SGGeod::fromCart(center);
+ SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
+
+ // rotate the tiles so that the bounding boxes get nearly axis aligned.
+ // this will help the collision tree's bounding boxes a bit ...
+ std::vector<SGVec3d> nodes = tile.get_wgs84_nodes();
+ for (unsigned i = 0; i < nodes.size(); ++i)
+ nodes[i] = hlOr.transform(nodes[i]);
+ tile.set_wgs84_nodes(nodes);
+
+ SGQuatf hlOrf(hlOr[0], hlOr[1], hlOr[2], hlOr[3]);
+ std::vector<SGVec3f> normals = tile.get_normals();
+ for (unsigned i = 0; i < normals.size(); ++i)
+ normals[i] = hlOrf.transform(normals[i]);
+ tile.set_normals(normals);
+
SGTileGeometryBin tileGeometryBin;
- if (!tileGeometryBin.insertBinObj(obj, matlib))
+ if (!tileGeometryBin.insertBinObj(tile, matlib))
return false;
- SGVec3d center = obj.get_gbs_center2();
- SGGeod geodPos = SGGeod::fromCart(center);
- SGQuatd hlOr = SGQuatd::fromLonLat(geodPos);
- SGVec3f up = toVec3f(hlOr.backTransform(SGVec3d(0, 0, -1)));
-
- osg::Group* vasiLights = new osg::Group;
- vasiLights->setCullCallback(new SGPointSpriteLightCullCallback(osg::Vec3(1, 0.0001, 0.000001), 6));
- osg::StateSet* stateSet = vasiLights->getOrCreateStateSet();
- osg::Fog* fog = new osg::Fog;
- fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Group* rwyLights = new osg::Group;
- rwyLights->setCullCallback(new SGPointSpriteLightCullCallback);
- stateSet = rwyLights->getOrCreateStateSet();
- fog = new osg::Fog;
- fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Group* taxiLights = new osg::Group;
- taxiLights->setCullCallback(new SGPointSpriteLightCullCallback);
- stateSet = taxiLights->getOrCreateStateSet();
- fog = new osg::Fog;
- fog->setUpdateCallback(new SGTaxiLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Group* groundLights0 = new osg::Group;
- stateSet = groundLights0->getOrCreateStateSet();
- fog = new osg::Fog;
- fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Group* groundLights1 = new osg::Group;
- stateSet = groundLights1->getOrCreateStateSet();
- fog = new osg::Fog;
- fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Group* groundLights2 = new osg::Group;
- stateSet = groundLights2->getOrCreateStateSet();
- fog = new osg::Fog;
- fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
- stateSet->setAttribute(fog);
-
- osg::Switch* lightSwitch = new osg::Switch;
- lightSwitch->setUpdateCallback(new SGTileUpdateCallback);
- lightSwitch->addChild(vasiLights, true);
- lightSwitch->addChild(rwyLights, true);
- lightSwitch->addChild(taxiLights, true);
- lightSwitch->addChild(groundLights0, true);
- lightSwitch->addChild(groundLights1, true);
- lightSwitch->addChild(groundLights2, true);
-
- osg::Group* lightGroup = new SGOffsetTransform(0.94);
- lightGroup->addChild(lightSwitch);
-
- osg::LOD* lightLOD = new osg::LOD;
- lightLOD->addChild(lightGroup, 0, 30000);
- unsigned nodeMask = ~0u;
- nodeMask &= ~SG_NODEMASK_CASTSHADOW_BIT;
- nodeMask &= ~SG_NODEMASK_RECIEVESHADOW_BIT;
- nodeMask &= ~SG_NODEMASK_PICK_BIT;
- nodeMask &= ~SG_NODEMASK_TERRAIN_BIT;
- lightLOD->setNodeMask(nodeMask);
+ SGVec3f up(0, 0, 1);
+ GroundLightManager* lightManager = GroundLightManager::instance();
+ osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
+ osg::ref_ptr<osg::Group> randomObjects;
+ osg::ref_ptr<osg::Group> forestNode;
osg::Group* terrainGroup = new osg::Group;
+
osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
if (node)
terrainGroup->addChild(node);
- if (calc_lights) {
- // FIXME: ugly, has a side effect
- tileGeometryBin.computeRandomSurfaceLights(matlib);
-
- osg::Geode* geode = new osg::Geode;
- groundLights0->addChild(geode);
- geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
-
- groundLights0->addChild(geode);
- geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
+ if (use_random_objects || use_random_vegetation) {
+ if (use_random_objects) {
+ if (matlib)
+ tileGeometryBin.computeRandomObjects(matlib);
+
+ if (tileGeometryBin.randomModels.getNumModels() > 0) {
+ // Generate a repeatable random seed
+ mt seed;
+ mt_init(&seed, unsigned(123));
+
+ std::vector<ModelLOD> models;
+ for (unsigned int i = 0;
+ i < tileGeometryBin.randomModels.getNumModels(); i++) {
+ SGMatModelBin::MatModel obj
+ = tileGeometryBin.randomModels.getMatModel(i);
+ osg::Node* node = sgGetRandomModel(obj.model, seed);
+
+ // Create a matrix to place the object in the correct
+ // location, and then apply the rotation matrix created
+ // above, with an additional random heading rotation if appropriate.
+ osg::Matrix transformMat;
+ transformMat = osg::Matrix::translate(toOsg(obj.position));
+ if (obj.model->get_heading_type() == SGMatModel::HEADING_RANDOM) {
+ // Rotate the object around the z axis.
+ double hdg = mt_rand(&seed) * M_PI * 2;
+ transformMat.preMult(osg::Matrix::rotate(hdg,
+ osg::Vec3d(0.0, 0.0, 1.0)));
+ }
+ osg::MatrixTransform* position =
+ new osg::MatrixTransform(transformMat);
+ position->addChild(node);
+ models.push_back(ModelLOD(position, obj.lod));
+ }
+ RandomObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
+ quadtree.buildQuadTree(models.begin(), models.end());
+ randomObjects = quadtree.getRoot();
+ randomObjects->setName("random objects");
+ }
+ }
- geode = new osg::Geode;
- groundLights1->addChild(geode);
- geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
+ if (use_random_vegetation && matlib) {
+ // Now add some random forest.
+ tileGeometryBin.computeRandomForest(matlib);
+
+ if (tileGeometryBin.randomForest.size() > 0) {
+ forestNode = createForest(tileGeometryBin.randomForest, osg::Matrix::identity());
+ forestNode->setName("Random trees");
+ }
+ }
+ }
- geode = new osg::Geode;
- groundLights2->addChild(geode);
- geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
+ if (calc_lights) {
+ // FIXME: ugly, has a side effect
+ if (matlib)
+ tileGeometryBin.computeRandomSurfaceLights(matlib);
+
+ if (tileGeometryBin.tileLights.getNumLights() > 0
+ || tileGeometryBin.randomTileLights.getNumLights() > 0) {
+ osg::Group* groundLights0 = new osg::Group;
+ groundLights0->setStateSet(lightManager->getGroundLightStateSet());
+ groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
+ groundLights0->addChild(geode);
+ lightGroup->addChild(groundLights0);
+ }
+ if (tileGeometryBin.randomTileLights.getNumLights() > 0) {
+ osg::Group* groundLights1 = new osg::Group;
+ groundLights1->setStateSet(lightManager->getGroundLightStateSet());
+ groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
+ osg::Group* groundLights2 = new osg::Group;
+ groundLights2->setStateSet(lightManager->getGroundLightStateSet());
+ groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
+ groundLights1->addChild(geode);
+ lightGroup->addChild(groundLights1);
+ geode = new osg::Geode;
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
+ groundLights2->addChild(geode);
+ lightGroup->addChild(groundLights2);
+ }
}
- {
+ if (!tileGeometryBin.vasiLights.empty()) {
+ EffectGeode* vasiGeode = new EffectGeode;
+ Effect* vasiEffect
+ = getLightEffect(6, osg::Vec3(1, 0.0001, 0.000001), 1, 6, true);
+ vasiGeode->setEffect(vasiEffect);
SGVec4f red(1, 0, 0, 1);
- SGMaterial* mat = matlib->find("RWY_RED_LIGHTS");
+ SGMaterial* mat = 0;
+ if (matlib)
+ mat = matlib->find("RWY_RED_LIGHTS");
if (mat)
red = mat->get_light_color();
SGVec4f white(1, 1, 1, 1);
- mat = matlib->find("RWY_WHITE_LIGHTS");
+ mat = 0;
+ if (matlib)
+ mat = matlib->find("RWY_WHITE_LIGHTS");
if (mat)
white = mat->get_light_color();
- osg::Geode* geode;
- geode = new osg::Geode;
- vasiLights->addChild(geode);
SGDirectionalLightListBin::const_iterator i;
for (i = tileGeometryBin.vasiLights.begin();
i != tileGeometryBin.vasiLights.end(); ++i) {
- geode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
+ vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
}
-
- geode = new osg::Geode;
- rwyLights->addChild(geode);
- geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.runwayLights));
+ vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
+ lightGroup->addChild(vasiGeode);
+ }
+ Effect* runwayEffect = 0;
+ if (tileGeometryBin.runwayLights.getNumLights() > 0
+ || !tileGeometryBin.rabitLights.empty()
+ || !tileGeometryBin.reilLights.empty()
+ || !tileGeometryBin.odalLights.empty()
+ || tileGeometryBin.taxiLights.getNumLights() > 0)
+ runwayEffect = getLightEffect(4, osg::Vec3(1, 0.001, 0.0002), 1, 4, true);
+ if (tileGeometryBin.runwayLights.getNumLights() > 0
+ || !tileGeometryBin.rabitLights.empty()
+ || !tileGeometryBin.reilLights.empty()
+ || !tileGeometryBin.odalLights.empty()) {
+ osg::Group* rwyLights = new osg::Group;
+ rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
+ rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
+ if (tileGeometryBin.runwayLights.getNumLights() != 0) {
+ EffectGeode* geode = new EffectGeode;
+ geode->setEffect(runwayEffect);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin
+ .runwayLights));
+ rwyLights->addChild(geode);
+ }
+ SGDirectionalLightListBin::const_iterator i;
for (i = tileGeometryBin.rabitLights.begin();
i != tileGeometryBin.rabitLights.end(); ++i) {
rwyLights->addChild(SGLightFactory::getSequenced(*i));
i != tileGeometryBin.reilLights.end(); ++i) {
rwyLights->addChild(SGLightFactory::getSequenced(*i));
}
-
SGLightListBin::const_iterator j;
for (j = tileGeometryBin.odalLights.begin();
j != tileGeometryBin.odalLights.end(); ++j) {
rwyLights->addChild(SGLightFactory::getOdal(*j));
}
+ lightGroup->addChild(rwyLights);
+ }
- geode = new osg::Geode;
- taxiLights->addChild(geode);
+ if (tileGeometryBin.taxiLights.getNumLights() > 0) {
+ osg::Group* taxiLights = new osg::Group;
+ taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
+ taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
+ EffectGeode* geode = new EffectGeode;
+ geode->setEffect(runwayEffect);
geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.taxiLights));
+ taxiLights->addChild(geode);
+ lightGroup->addChild(taxiLights);
}
// The toplevel transform for that tile.
osg::MatrixTransform* transform = new osg::MatrixTransform;
transform->setName(path);
- transform->setMatrix(osg::Matrix::translate(center.osg()));
+ transform->setMatrix(osg::Matrix::rotate(toOsg(hlOr))*
+ osg::Matrix::translate(toOsg(center)));
transform->addChild(terrainGroup);
- transform->addChild(lightLOD);
-
+ if (lightGroup->getNumChildren() > 0) {
+ osg::LOD* lightLOD = new osg::LOD;
+ lightLOD->addChild(lightGroup.get(), 0, 30000);
+ // VASI is always on, so doesn't use light bits.
+ lightLOD->setNodeMask(LIGHTS_BITS | MODEL_BIT);
+ transform->addChild(lightLOD);
+ }
+
+ if (randomObjects.valid() || forestNode.valid()) {
+
+ // Add a LoD node, so we don't try to display anything when the tile center
+ // is more than 20km away.
+ osg::LOD* objectLOD = new osg::LOD;
+
+ if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000);
+ if (forestNode.valid()) objectLOD->addChild(forestNode.get(), 0, 20000);
+
+ unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECIEVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT;
+ objectLOD->setNodeMask(nodeMask);
+ transform->addChild(objectLOD);
+ }
+
return transform;
}