From 8cbe9f1bd0b2fb48480ecd03e817930e8d5a126e Mon Sep 17 00:00:00 2001 From: timoore Date: Thu, 7 Feb 2008 23:00:23 +0000 Subject: [PATCH] Second trees patch from Stuart Buchanan Adds random variation of tree texture maps --- simgear/scene/material/mat.cxx | 13 ++-- simgear/scene/material/mat.hxx | 20 +++-- simgear/scene/material/matmodel.cxx | 3 - simgear/scene/tgdb/SGReaderWriterBTG.cxx | 5 +- .../scene/tgdb/SGReaderWriterBTGOptions.hxx | 15 +++- simgear/scene/tgdb/ShaderGeometry.cxx | 40 ++++++---- simgear/scene/tgdb/ShaderGeometry.hxx | 15 +++- simgear/scene/tgdb/TreeBin.cxx | 62 +++++++++------- simgear/scene/tgdb/TreeBin.hxx | 32 ++++---- simgear/scene/tgdb/obj.cxx | 73 +++++++++++-------- simgear/scene/tgdb/obj.hxx | 2 +- 11 files changed, 170 insertions(+), 110 deletions(-) diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 4257ae2a..6dde0c51 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -145,6 +145,11 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props tree_height = props->getDoubleValue("tree-height-m", 0.0); tree_width = props->getDoubleValue("tree-width-m", 0.0); tree_range = props->getDoubleValue("tree-range-m", 0.0); + tree_varieties = props->getIntValue("tree-varieties", 1); + + SGPath tpath( fg_root ); + tpath.append(props->getStringValue("tree-texture")); + tree_texture = tpath.str(); // surface values for use with ground reactions solid = props->getBoolValue("solid", true); @@ -181,14 +186,6 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props for (unsigned int i = 0; i < object_group_nodes.size(); i++) object_groups.push_back(new SGMatModelGroup(object_group_nodes[i])); - vector tree_texture_nodes = - ((SGPropertyNode *)props)->getChildren("tree-texture"); - for (unsigned int i = 0; i < tree_texture_nodes.size(); i++) { - SGPath tpath( fg_root ); - tpath.append(tree_texture_nodes[i]->getStringValue()); - tree_textures.push_back(tpath.str()); - } - // read glyph table for taxi-/runway-signs vector glyph_nodes = props->getChildren("glyph"); for (unsigned int i = 0; i < glyph_nodes.size(); i++) { diff --git a/simgear/scene/material/mat.hxx b/simgear/scene/material/mat.hxx index 38cc7c95..96a33a3a 100644 --- a/simgear/scene/material/mat.hxx +++ b/simgear/scene/material/mat.hxx @@ -177,11 +177,18 @@ public: inline double get_tree_range () const { return tree_range; } /** - * Get the list of textures to use for trees in the forest + * Get the number of tree varieties available * - * @return the vector of forest textures to use. + * @return the number of different trees defined in the texture strip */ - inline vector get_tree_textures () const { return tree_textures; } + inline int get_tree_varieties () const { return tree_varieties; } + + /** + * Get the texture strip to use for trees + * + * @return the texture to use for trees. + */ + inline string get_tree_texture () const { return tree_texture; } /** * Return if the surface material is solid, if it is not solid, a fluid @@ -309,6 +316,9 @@ private: // Width of the tree double tree_width; + // Number of varieties of tree texture + int tree_varieties; + // True if the material is solid, false if it is a fluid bool solid; @@ -336,8 +346,8 @@ private: // taxiway-/runway-sign texture elements map > glyphs; - // The list of forest textures, used when creating trees - vector tree_textures; + // Tree texture, typically a strip of applicable tree textures + string tree_texture; //////////////////////////////////////////////////////////////////// // Internal constructors and methods. diff --git a/simgear/scene/material/matmodel.cxx b/simgear/scene/material/matmodel.cxx index 7af83c75..70850edc 100644 --- a/simgear/scene/material/matmodel.cxx +++ b/simgear/scene/material/matmodel.cxx @@ -263,7 +263,4 @@ SGMatModelGroup::get_object (int index) const return _objects[index]; } - - - // end of matmodel.cxx diff --git a/simgear/scene/tgdb/SGReaderWriterBTG.cxx b/simgear/scene/tgdb/SGReaderWriterBTG.cxx index 828ab039..9c35ce6a 100644 --- a/simgear/scene/tgdb/SGReaderWriterBTG.cxx +++ b/simgear/scene/tgdb/SGReaderWriterBTG.cxx @@ -54,15 +54,18 @@ SGReaderWriterBTG::readNode(const std::string& fileName, SGMaterialLib* matlib = 0; bool calcLights = false; bool useRandomObjects = false; + bool useRandomVegetation = false; const SGReaderWriterBTGOptions* btgOptions = dynamic_cast(options); if (btgOptions) { matlib = btgOptions->getMatlib(); calcLights = btgOptions->getCalcLights(); useRandomObjects = btgOptions->getUseRandomObjects(); + useRandomVegetation = btgOptions->getUseRandomVegetation(); } osg::Node* result = SGLoadBTG(fileName, matlib, calcLights, - useRandomObjects); + useRandomObjects, + useRandomVegetation); if (result) return result; else diff --git a/simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx b/simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx index 91a7c2ad..86174bf2 100644 --- a/simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx +++ b/simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx @@ -24,14 +24,17 @@ public: SGReaderWriterBTGOptions() {} SGReaderWriterBTGOptions(const std::string& str): osgDB::ReaderWriter::Options(str), - _matlib(0), _calcLights(false), _useRandomObjects(false) + _matlib(0), _calcLights(false), + _useRandomObjects(false), + _useRandomVegetation(false) {} SGReaderWriterBTGOptions(const SGReaderWriterBTGOptions& options, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osgDB::ReaderWriter::Options(options, copyop), _matlib(options._matlib), _calcLights(options._calcLights), - _useRandomObjects(options._useRandomObjects) + _useRandomObjects(options._useRandomObjects), + _useRandomVegetation(options._useRandomVegetation) { } SGMaterialLib* getMatlib() const { return _matlib; } @@ -39,15 +42,21 @@ public: bool getCalcLights() const { return _calcLights; } void setCalcLights(bool calcLights) { _calcLights = calcLights; } bool getUseRandomObjects() const { return _useRandomObjects; } + bool getUseRandomVegetation() const { return _useRandomVegetation; } void setUseRandomObjects(bool useRandomObjects) { _useRandomObjects = useRandomObjects; } + void setUseRandomVegetation(bool useRandomVegetation) + { + _useRandomVegetation = useRandomVegetation; + } + protected: virtual ~SGReaderWriterBTGOptions() {} SGMaterialLib* _matlib; bool _calcLights; bool _useRandomObjects; - + bool _useRandomVegetation; }; #endif diff --git a/simgear/scene/tgdb/ShaderGeometry.cxx b/simgear/scene/tgdb/ShaderGeometry.cxx index 7fdf657f..8691f3d0 100644 --- a/simgear/scene/tgdb/ShaderGeometry.cxx +++ b/simgear/scene/tgdb/ShaderGeometry.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include "ShaderGeometry.hxx" @@ -32,10 +33,13 @@ namespace simgear { void ShaderGeometry::drawImplementation(RenderInfo& renderInfo) const { - for(PositionSizeList::const_iterator itr = _trees.begin(); - itr != _trees.end(); - ++itr) { - glColor4fv(itr->ptr()); + osg::State& state = *renderInfo.getState(); + const Extensions* extensions = getExtensions(state.getContextID(),true); + + for(TreeBin::TreeList::const_iterator t = _trees.begin(); t != _trees.end(); ++t) + { + extensions->glVertexAttrib1f(1, (float) t->texture_index/varieties); + glColor4f(t->position.x(), t->position.y(), t->position.z(), t->scale); _geometry->draw(renderInfo); } } @@ -44,13 +48,13 @@ BoundingBox ShaderGeometry::computeBound() const { BoundingBox geom_box = _geometry->getBound(); BoundingBox bb; - for(PositionSizeList::const_iterator itr = _trees.begin(); + for(TreeBin::TreeList::const_iterator itr = _trees.begin(); itr != _trees.end(); ++itr) { - bb.expandBy(geom_box.corner(0)*(*itr)[3] + - Vec3((*itr)[0], (*itr)[1], (*itr)[2])); - bb.expandBy(geom_box.corner(7)*(*itr)[3] + - Vec3((*itr)[0], (*itr)[1], (*itr)[2])); + bb.expandBy(geom_box.corner(0)*itr->scale + + osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() )); + bb.expandBy(geom_box.corner(7)*itr->scale + + osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() )); } return bb; } @@ -64,7 +68,7 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr) if ((fr[0].matchWord("geometry"))) { ++fr; iteratorAdvanced = true; - Drawable* drawable = fr.readDrawable(); + osg::Drawable* drawable = fr.readDrawable(); if (drawable) { geom._geometry = drawable; } @@ -78,11 +82,15 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr) iteratorAdvanced = true; // skip { while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) { - Vec4 v; + SGVec3f v; + int t; + float s; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) - && fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) { + && fr[2].getFloat(v.z()) && fr[3].getInt(t) && fr[4].getFloat(s)) { fr += 4; - geom._trees.push_back(v); + //SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z()); + //TreeBin::Tree tree = new TreeBin::Tree(v, t, s); + geom._trees.push_back(TreeBin::Tree(v, t, s)); } else { ++fr; } @@ -100,12 +108,12 @@ bool ShaderGeometry_writeLocalData(const Object& obj, Output& fw) fw.indent() << "instances " << geom._trees.size() << std::endl; fw.indent() << "{" << std::endl; fw.moveIn(); - for (ShaderGeometry::PositionSizeList::const_iterator iter + for (TreeBin::TreeList::const_iterator iter = geom._trees.begin(); iter != geom._trees.end(); ++iter) { - fw.indent() << iter->x() << " " << iter->y() << " " << iter->z() << " " - << iter->w() << std::endl; + fw.indent() << iter->position.x() << " " << iter->position.y() << " " << iter->position.z() << " " + << iter->texture_index << " " << iter->scale << std::endl; } fw.moveOut(); fw.indent() << "}" << std::endl; diff --git a/simgear/scene/tgdb/ShaderGeometry.hxx b/simgear/scene/tgdb/ShaderGeometry.hxx index 99f2c1e0..9814af28 100644 --- a/simgear/scene/tgdb/ShaderGeometry.hxx +++ b/simgear/scene/tgdb/ShaderGeometry.hxx @@ -32,6 +32,8 @@ #include #include +#include "TreeBin.hxx" + namespace simgear { @@ -42,6 +44,12 @@ class ShaderGeometry : public osg::Drawable { setUseDisplayList(false); } + + ShaderGeometry(int v) : + varieties(v) + { + setUseDisplayList(false); + } /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ ShaderGeometry(const ShaderGeometry& ShaderGeometry,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): @@ -60,14 +68,15 @@ class ShaderGeometry : public osg::Drawable _geometry = geometry; } - void addTree(const osg::Vec3& position, float scale) + void addTree(TreeBin::Tree tree) { - _trees.push_back(osg::Vec4(position, scale)); + _trees.push_back(tree); } osg::ref_ptr _geometry; - PositionSizeList _trees; + TreeBin::TreeList _trees; + int varieties; protected: diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index a9777444..431e31aa 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -64,7 +64,7 @@ using namespace osg; namespace simgear { -osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate) +osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matrix& rotate) { //const osg::Vec3& pos = osg::Vec3(0.0f,0.0f,0.0f), @@ -87,14 +87,19 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate) v[6].set( cw,0.0f,h); v[7].set(-cw,0.0f,h); + // The texture coordinate range is not the + // entire coordinate space - as the texture + // has a number of different trees on it. + float tx = 1.0f/varieties; + t[0].set(0.0f,0.0f); - t[1].set(1.0f,0.0f); - t[2].set(1.0f,1.0f); + t[1].set( tx,0.0f); + t[2].set( tx,1.0f); t[3].set(0.0f,1.0f); t[4].set(0.0f,0.0f); - t[5].set(1.0f,0.0f); - t[6].set(1.0f,1.0f); + t[5].set( tx,0.0f); + t[6].set( tx,1.0f); t[7].set(0.0f,1.0f); // For now the normal is normal to the quad. If we want to get @@ -122,10 +127,13 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate) } static char vertexShaderSource[] = + "varying vec2 texcoord;\n" "varying float fogFactor;\n" + "attribute float textureIndex;\n" "\n" "void main(void)\n" "{\n" + " texcoord = gl_MultiTexCoord0.st + vec2(textureIndex, 0.0);\n" " vec3 position = gl_Vertex.xyz * gl_Color.w + gl_Color.xyz;\n" " gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n" " vec3 ecPosition = vec3(gl_ModelViewMatrix * vec4(position, 1.0));\n" @@ -135,7 +143,7 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate) " vec4 ambientColor = gl_FrontLightModelProduct.sceneColor + gl_LightSource[0].ambient * gl_FrontMaterial.ambient;\n" " gl_FrontColor = ambientColor + gl_LightSource[0].diffuse * vec4(diffuse, 1.0);\n" " gl_BackColor = ambientColor + gl_LightSource[0].diffuse * vec4(backDiffuse, 1.0)\n;" - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" +// " gl_TexCoord[0] = gl_MultiTexCoord0;\n" " float fogCoord = abs(ecPosition.z);\n" " fogFactor = exp( -gl_Fog.density * gl_Fog.density * fogCoord * fogCoord);\n" " fogFactor = clamp(fogFactor, 0.0, 1.0);\n" @@ -143,13 +151,14 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate) static char fragmentShaderSource[] = "uniform sampler2D baseTexture; \n" -// "varying vec3 N;\n" + "varying vec2 texcoord;\n" +// "varying vec3 N;\n" // "varying vec3 v;\n" "varying float fogFactor;\n" "\n" "void main(void) \n" "{ \n" - " vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n" + " vec4 base = texture2D( baseTexture, texcoord);\n" " vec4 finalColor = base * gl_Color;\n" " gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );\n" @@ -164,22 +173,23 @@ namespace { struct MakeTreesLeaf { - MakeTreesLeaf(float range, Geometry* geometry) : - _range(range), _geometry(geometry) + MakeTreesLeaf(float range, Geometry* geometry, int varieties) : + _range(range), _geometry(geometry), _varieties(varieties) {} MakeTreesLeaf(const MakeTreesLeaf& rhs) : - _range(rhs._range), _geometry(rhs._geometry) {} + _range(rhs._range), _geometry(rhs._geometry), _varieties(rhs._varieties) {} LOD* operator() () const { LOD* result = new LOD; Geode* geode = new Geode; - ShaderGeometry* sg = new ShaderGeometry; + ShaderGeometry* sg = new ShaderGeometry(_varieties); sg->setGeometry(_geometry); geode->addDrawable(sg); result->addChild(geode, 0, _range); return result; } float _range; + int _varieties; Geometry* _geometry; }; @@ -190,7 +200,7 @@ struct AddTreesLeafObject Geode* geode = static_cast(lod->getChild(0)); ShaderGeometry* sg = static_cast(geode->getDrawable(0)); - sg->addTree(tree.position.osg(), tree.height); + sg->addTree(tree); } }; @@ -212,22 +222,20 @@ typedef QuadTreeBuilder group; osg::StateSet* stateset = 0; - StateSetMap::iterator iter = treeTextureMap.find(firstTree.texture); + StateSetMap::iterator iter = treeTextureMap.find(forest.texture); if (iter == treeTextureMap.end()) { osg::Texture2D *tex = new osg::Texture2D; tex->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP ); tex->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP ); - tex->setImage(osgDB::readImageFile(firstTree.texture)); + tex->setImage(osgDB::readImageFile(forest.texture)); static ref_ptr alphaFunc; static ref_ptr program; @@ -244,6 +252,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) baseTextureSampler = new osg::Uniform("baseTexture", 0); Shader* vertex_shader = new Shader(Shader::VERTEX, vertexShaderSource); program->addShader(vertex_shader); + program->addBindAttribLocation("textureIndex", 1); + Shader* fragment_shader = new Shader(Shader::FRAGMENT, fragmentShaderSource); program->addShader(fragment_shader); @@ -260,9 +270,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) stateset->addUniform(baseTextureSampler.get()); stateset->setMode(GL_VERTEX_PROGRAM_TWO_SIDE, StateAttribute::ON); stateset->setAttribute(material.get()); - // XXX This should really come from a material definition - // instead of being hard-coded. - treeTextureMap.insert(StateSetMap::value_type(firstTree.texture, + + treeTextureMap.insert(StateSetMap::value_type(forest.texture, stateset)); } else { stateset = iter->second.get(); @@ -272,8 +281,9 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) ShaderGeometryQuadtree quadtree(GetTreeCoord(Matrix::inverse(transform)), AddTreesLeafObject(), SG_TREE_QUAD_TREE_DEPTH, - MakeTreesLeaf(firstTree.range, - shared_geometry)); + MakeTreesLeaf(forest.range, + shared_geometry, + forest.texture_varieties)); quadtree.buildQuadTree(forest._trees.begin(), forest._trees.end()); group = quadtree.getRoot(); } diff --git a/simgear/scene/tgdb/TreeBin.hxx b/simgear/scene/tgdb/TreeBin.hxx index da94313e..3c797028 100644 --- a/simgear/scene/tgdb/TreeBin.hxx +++ b/simgear/scene/tgdb/TreeBin.hxx @@ -23,33 +23,39 @@ #define TREE_BIN_HXX #include +#include #include #include #include -#include +#include namespace simgear { class TreeBin { public: - struct Tree { - Tree(const SGVec3f& p, string t, float h, float w, double r) : - position(p), texture(t), height(h), width(w), range(r) - { } - SGVec3f position; - string texture; - float height; - float width; - double range; - }; + struct Tree { + Tree(const SGVec3f& p, int t, float s) : + position(p), texture_index(t), scale(s) + { } + SGVec3f position; + int texture_index; + float scale; + }; + typedef std::vector TreeList; + int texture_varieties; + double range; + float height; + float width; + std::string texture; + void insert(const Tree& t) { _trees.push_back(t); } - void insert(const SGVec3f& p, string t, float h, float w, double r) - { insert(Tree(p, t, h, w, r)); } + void insert(const SGVec3f& p, int t, float s) + { insert(Tree(p, t, s)); } unsigned getNumTrees() const { return _trees.size(); } diff --git a/simgear/scene/tgdb/obj.cxx b/simgear/scene/tgdb/obj.cxx index d319ec4c..06ec24fc 100644 --- a/simgear/scene/tgdb/obj.cxx +++ b/simgear/scene/tgdb/obj.cxx @@ -133,7 +133,7 @@ struct SGTileGeometryBin { std::string materialName = obj.get_pt_materials()[grp]; SGMaterial* 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, @@ -454,11 +454,11 @@ struct SGTileGeometryBin { void computeRandomForest(SGMaterialLib* matlib) { SGMaterialTriangleMap::iterator i; - + // generate a repeatable random seed mt seed; mt_init(&seed, unsigned(586)); - + for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) { SGMaterial *mat = matlib->find(i->first); if (!mat) @@ -467,24 +467,32 @@ struct SGTileGeometryBin { float coverage = mat->get_tree_coverage(); if (coverage <= 0) continue; - - vector textures = mat->get_tree_textures(); - + + // Attributes that don't vary by tree + randomForest.texture = mat->get_tree_texture(); + randomForest.range = mat->get_tree_range(); + randomForest.width = mat->get_tree_width(); + randomForest.height = mat->get_tree_height(); + randomForest.texture_varieties = mat->get_tree_varieties(); + std::vector randomPoints; i->second.addRandomSurfacePoints(coverage, 0, randomPoints); std::vector::iterator j; - for (j = randomPoints.begin(); j != randomPoints.end(); ++j) { - int k = (int)(mt_rand(&seed) * textures.size()); - if (k == textures.size()) k--; - randomForest.insert(*j, textures[k], mat->get_tree_height(), mat->get_tree_width(), mat->get_tree_range()); + for (j = randomPoints.begin(); j != randomPoints.end(); ++j) { + + // Apply a random scaling factor and texture index. + float scale = (mt_rand(&seed) + mt_rand(&seed)) / 2.0f + 0.5f; + int v = (int) (mt_rand(&seed) * mat->get_tree_varieties()); + if (v == mat->get_tree_varieties()) v--; + randomForest.insert(*j, v, scale); } } } - + void computeRandomObjects(SGMaterialLib* matlib) { SGMaterialTriangleMap::iterator i; - + // generate a repeatable random seed mt seed; mt_init(&seed, unsigned(123)); @@ -493,23 +501,23 @@ struct SGTileGeometryBin { 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 randomPoints; i->second.addRandomPoints(object->get_coverage_m2(), randomPoints); @@ -559,7 +567,7 @@ typedef QuadTreeBuilder 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 tile; if (!tile.read_bin(path)) @@ -579,13 +587,13 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool osg::ref_ptr randomObjects; osg::ref_ptr randomForest; osg::Group* terrainGroup = new osg::Group; - + osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib); if (node) terrainGroup->addChild(node); - + if (use_random_objects) { - + // Simple matrix for used for flipping models that have been oriented // with the center of the tile but upside down. static const osg::Matrix flip(1, 0, 0, 0, @@ -618,7 +626,7 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool // heading rotation if appropriate. osg::Matrix mPos = osg::Matrix::translate(obj.position.osg()); osg::MatrixTransform* 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; @@ -631,7 +639,7 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool position = new osg::MatrixTransform(mAtt * mPos); } - position->addChild(node); + position->addChild(node); models.push_back(ModelLOD(position, obj.lod)); } RandomObjectsQuadtree quadtree((GetModelLODCoord(world2Tile)), @@ -640,13 +648,16 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool randomObjects = quadtree.getRoot(); randomObjects->setName("random objects"); } - - // Now add some random forest. - tileGeometryBin.computeRandomForest(matlib); - - if (tileGeometryBin.randomForest.getNumTrees() > 0) { - randomForest = createForest(tileGeometryBin.randomForest, mAtt); - randomForest->setName("random trees"); + + if (use_random_vegetation) + { + // Now add some random forest. + tileGeometryBin.computeRandomForest(matlib); + + if (tileGeometryBin.randomForest.getNumTrees() > 0) { + randomForest = createForest(tileGeometryBin.randomForest, mAtt); + randomForest->setName("random trees"); + } } } diff --git a/simgear/scene/tgdb/obj.hxx b/simgear/scene/tgdb/obj.hxx index f0c31300..f35e2b36 100644 --- a/simgear/scene/tgdb/obj.hxx +++ b/simgear/scene/tgdb/obj.hxx @@ -56,6 +56,6 @@ inline bool SGGenTile( const std::string&, const SGBucket& b, } 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); #endif // _SG_OBJ_HXX -- 2.39.5