X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Ftgdb%2FTreeBin.cxx;h=a530ba32d3216489a8d703f055fcdcb069c5a1e7;hb=7e7ce2f38e87d6244e05730fa4382da088bb25f1;hp=b4219f33be85a70a8bd1d9a31be0d69887e5f1af;hpb=dc63ddb010408e716c2b31de26dade1476850e46;p=simgear.git diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index b4219f33..a530ba32 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -20,9 +20,12 @@ */ #include +#include #include #include +#include + #include #include #include @@ -64,8 +67,17 @@ using namespace osg; namespace simgear { +// memoize geometry +typedef boost::tuple ForestTuple; +typedef std::map > OrthQuadMap; + osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matrix& rotate) { + static OrthQuadMap orthQuadMap; + OrthQuadMap::iterator giter + = orthQuadMap.find(ForestTuple(w, h, varieties)); + if (giter != orthQuadMap.end()) + return giter->second.get(); //const osg::Vec3& pos = osg::Vec3(0.0f,0.0f,0.0f), // set up the coords @@ -123,6 +135,7 @@ osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matri // No color for now; that's used to pass the position. geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,8)); + orthQuadMap.insert(std::make_pair(ForestTuple(w, h, varieties), geom)); return geom; } @@ -136,14 +149,12 @@ osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matri " 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" - " vec3 N = normalize(gl_NormalMatrix * gl_Normal);\n" - " vec3 diffuse = gl_FrontMaterial.diffuse.rgb * max(0.0, dot(N, gl_LightSource[0].position.xyz));\n" - " vec3 backDiffuse = gl_FrontMaterial.diffuse.rgb * max(0.0, dot(-N, gl_LightSource[0].position.xyz));\n" - " 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" - " float fogCoord = abs(ecPosition.z);\n" + " float n = dot(normalize(gl_LightSource[0].position.xyz), normalize(-ecPosition));\n" + " vec3 diffuse = gl_FrontMaterial.diffuse.rgb * max(0.1, n);\n" + " 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 = gl_FrontColor;\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" "}\n"; @@ -201,26 +212,41 @@ struct AddTreesLeafObject struct GetTreeCoord { - GetTreeCoord(const Matrix& transform) : _transform(transform) {} - GetTreeCoord(const GetTreeCoord& rhs) : _transform(rhs._transform) {} Vec3 operator() (const TreeBin::Tree& tree) const { - return tree.position.osg() * _transform; + return tree.position.osg(); } - Matrix _transform; }; typedef QuadTreeBuilder ShaderGeometryQuadtree; } +struct TreeTransformer +{ + TreeTransformer(Matrix& mat_) : mat(mat_) {} + TreeBin::Tree operator()(const TreeBin::Tree& tree) const + { + const Vec3& pos = tree.position.osg(); + return TreeBin::Tree(SGVec3f(pos * mat), tree.texture_index, + tree.scale); + } + Matrix mat; +}; + +// This actually returns a MatrixTransform node. If we rotate the whole +// forest into the local Z-up coordinate system we can reuse the +// primitive tree geometry for all the forests of the same type. + osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) { + Matrix transInv = Matrix::inverse(transform); + static Matrix ident; // Set up some shared structures. osg::Geometry* shared_geometry = createOrthQuads(forest.width, forest.height, forest.texture_varieties, - transform); + ident); ref_ptr group; @@ -256,9 +282,9 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) // Don´t track vertex color material->setColorMode(Material::OFF); material->setAmbient(Material::FRONT_AND_BACK, - Vec4(.8f, .8f, .8f, 1.0f)); + Vec4(1.0f, 1.0f, 1.0f, 1.0f)); material->setDiffuse(Material::FRONT_AND_BACK, - Vec4(.2f, .2f, .2f, 1.0f)); + Vec4(1.0f, 1.0f, 1.0f, 1.0f)); } stateset->setAttributeAndModes(alphaFunc.get()); stateset->setAttribute(program.get()); @@ -273,17 +299,28 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform) } // Now, create a quadtree for the forest. { - ShaderGeometryQuadtree quadtree(GetTreeCoord(Matrix::inverse(transform)), + ShaderGeometryQuadtree quadtree(GetTreeCoord(), AddTreesLeafObject(), SG_TREE_QUAD_TREE_DEPTH, MakeTreesLeaf(forest.range, shared_geometry, forest.texture_varieties)); - quadtree.buildQuadTree(forest._trees.begin(), forest._trees.end()); + // Transform tree positions from the "geocentric" positions we + // get from the scenery polys into the local Z-up coordinate + // system. + std::vector rotatedTrees; + rotatedTrees.reserve(forest._trees.size()); + std::transform(forest._trees.begin(), forest._trees.end(), + std::back_inserter(rotatedTrees), + TreeTransformer(transInv)); + quadtree.buildQuadTree(rotatedTrees.begin(), rotatedTrees.end()); group = quadtree.getRoot(); } - group->setStateSet(stateset); - return group.release(); + MatrixTransform* mt = new MatrixTransform(transform); + for (int i = 0; i < group->getNumChildren(); ++i) + mt->addChild(group->getChild(i)); + mt->setStateSet(stateset); + return mt; } }