+ if (use_random_vegetation) {
+ // Now add some random forest.
+ tileGeometryBin.computeRandomForest(matlib);
+
+ if (tileGeometryBin.randomForest.getNumTrees() > 0) {
+ randomForest = createForest(tileGeometryBin.randomForest,
+ osg::Matrix::identity());
+ randomForest->setName("random trees");
+ }
+ }
+ }
+
+ if (calc_lights) {
+ // FIXME: ugly, has a side effect
+ 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()) {
+ osg::Geode* vasiGeode = new osg::Geode;
+ SGVec4f red(1, 0, 0, 1);
+ SGMaterial* 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");
+ if (mat)
+ white = mat->get_light_color();
+
+ SGDirectionalLightListBin::const_iterator i;
+ for (i = tileGeometryBin.vasiLights.begin();
+ i != tileGeometryBin.vasiLights.end(); ++i) {
+ vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
+ }
+ vasiGeode->setCullCallback(new SGPointSpriteLightCullCallback(osg::Vec3(1, 0.0001, 0.000001), 6));
+ vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
+ lightGroup->addChild(vasiGeode);
+ }
+
+ if (tileGeometryBin.runwayLights.getNumLights() > 0
+ || !tileGeometryBin.rabitLights.empty()
+ || !tileGeometryBin.reilLights.empty()
+ || !tileGeometryBin.odalLights.empty()) {
+ osg::Group* rwyLights = new osg::Group;
+ rwyLights->setCullCallback(new SGPointSpriteLightCullCallback);
+ rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
+ rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
+ if (tileGeometryBin.runwayLights.getNumLights() != 0) {
+ osg::Geode* geode = new osg::Geode;
+ 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));
+ }
+ for (i = tileGeometryBin.reilLights.begin();
+ 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);
+ }
+
+ if (tileGeometryBin.taxiLights.getNumLights() > 0) {
+ osg::Group* taxiLights = new osg::Group;
+ taxiLights->setCullCallback(new SGPointSpriteLightCullCallback);
+ taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
+ taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
+ osg::Geode* geode = new osg::Geode;
+ 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::rotate(hlOr.osg())*
+ osg::Matrix::translate(center.osg()));
+ transform->addChild(terrainGroup);
+ 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() || randomForest.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 (randomForest.valid()) objectLOD->addChild(randomForest.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;