+
+ // Generate all the random forest, objects and buildings for the tile
+ osg::LOD* generateRandomTileObjects()
+ {
+ SGMaterialLib* matlib;
+ bool use_random_objects = false;
+ bool use_random_vegetation = false;
+ bool use_random_buildings = false;
+ float vegetation_density = 1.0f;
+ float building_density = 1.0f;
+
+ osg::ref_ptr<osg::Group> randomObjects;
+ osg::ref_ptr<osg::Group> forestNode;
+ osg::ref_ptr<osg::Group> buildingNode;
+
+ if (_options) {
+ matlib = _options->getMaterialLib();
+ SGPropertyNode* propertyNode = _options->getPropertyNode().get();
+ if (propertyNode) {
+ use_random_objects
+ = propertyNode->getBoolValue("/sim/rendering/random-objects",
+ use_random_objects);
+ use_random_vegetation
+ = propertyNode->getBoolValue("/sim/rendering/random-vegetation",
+ use_random_vegetation);
+ vegetation_density
+ = propertyNode->getFloatValue("/sim/rendering/vegetation-density",
+ vegetation_density);
+ use_random_buildings
+ = propertyNode->getBoolValue("/sim/rendering/random-buildings",
+ use_random_buildings);
+ building_density
+ = propertyNode->getFloatValue("/sim/rendering/building-density",
+ building_density);
+ }
+ }
+
+
+
+ if (matlib && (use_random_objects || use_random_buildings)) {
+ _tileGeometryBin->computeRandomObjectsAndBuildings(matlib,
+ building_density,
+ use_random_objects,
+ use_random_buildings);
+ }
+
+
+ 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);
+
+ SGPropertyNode* root = _options->getPropertyNode()->getRootNode();
+ osg::Node* node = obj.model->get_random_model(root, &seed);
+
+ // Create a matrix to place the object in the correct
+ // location, and then apply the rotation matrix created
+ // above, with an additional random (or taken from
+ // the object mask) 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)));
+ }
+
+ if (obj.model->get_heading_type() == SGMatModel::HEADING_MASK) {
+ // Rotate the object around the z axis.
+ double hdg = - obj.rotation * 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->setName("positionRandomModel");
+ 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");
+ }
+
+ if (! _tileGeometryBin->randomBuildings.empty()) {
+ buildingNode = createRandomBuildings(_tileGeometryBin->randomBuildings, osg::Matrix::identity(),
+ _options);
+ buildingNode->setName("Random buildings");
+ _tileGeometryBin->randomBuildings.clear();
+ }
+
+ if (use_random_vegetation && matlib) {
+ // Now add some random forest.
+ _tileGeometryBin->computeRandomForest(matlib, vegetation_density);
+
+ if (! _tileGeometryBin->randomForest.empty()) {
+ forestNode = createForest(_tileGeometryBin->randomForest, osg::Matrix::identity(),
+ _options);
+ forestNode->setName("Random trees");
+ }
+ }
+
+ osg::LOD* objectLOD = NULL;
+
+ if (randomObjects.valid() || forestNode.valid() || buildingNode.valid()) {
+ objectLOD = new osg::LOD;
+
+ if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000);
+ if (forestNode.valid()) objectLOD->addChild(forestNode.get(), 0, 20000);
+ if (buildingNode.valid()) objectLOD->addChild(buildingNode.get(), 0, 20000);
+
+ unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECEIVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT;
+ objectLOD->setNodeMask(nodeMask);
+ }
+
+ return objectLOD;