From 259c1314de6ef0cd0d5bbf859c1684808ff7d5f3 Mon Sep 17 00:00:00 2001 From: "James.Hester" Date: Wed, 22 Apr 2020 18:39:23 +1000 Subject: [PATCH] Allow OSG to recalculate terrain normals. --- CMakeLists.txt | 3 +++ simgear/scene/material/EffectGeode.cxx | 27 +++++++++++--------- simgear/scene/tgdb/SGTexturedTriangleBin.hxx | 16 +++++++----- simgear/scene/tgdb/SGTileGeometryBin.hxx | 10 ++++++-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6e1923a..80ad1194 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,9 @@ if(COMMAND cmake_policy) if(POLICY CMP0093) cmake_policy(SET CMP0093 NEW) + endif() + if(POLICY CMP0072) + cmake_policy(SET CMP0072 NEW) endif() endif() diff --git a/simgear/scene/material/EffectGeode.cxx b/simgear/scene/material/EffectGeode.cxx index c2967639..b4c1feeb 100644 --- a/simgear/scene/material/EffectGeode.cxx +++ b/simgear/scene/material/EffectGeode.cxx @@ -72,37 +72,40 @@ void EffectGeode::releaseGLObjects(osg::State* state) const // Generates tangent space vectors or other data from geom, as defined by effect void EffectGeode::runGenerators(osg::Geometry *geometry) { - if(geometry && _effect.valid()) { + if(geometry && _effect.valid()) { // Generate tangent vectors for the geometry osg::ref_ptr tsg = new osgUtil::TangentSpaceGenerator; - + tsg->generate(geometry,0); // Generating only tangent vector should be enough // since the binormal is a cross product of normal and tangent // This saves a bit of memory & memory bandwidth! int n = _effect->getGenerator(Effect::TANGENT); - tsg->generate(geometry, 0); // 0 is normal_unit, but I have no idea what that is! - if (n != -1 && !geometry->getVertexAttribArray(n)) + if (n != -1 && !geometry->getVertexAttribArray(n)) { #if OSG_MIN_VERSION_REQUIRED(3,1,8) - geometry->setVertexAttribArray(n, tsg->getTangentArray(), osg::Array::BIND_PER_VERTEX); + geometry->setVertexAttribArray(n, tsg->getTangentArray(), osg::Array::BIND_PER_VERTEX); #else - geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getTangentArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); + geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getTangentArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); #endif - + } n = _effect->getGenerator(Effect::BINORMAL); if (n != -1 && !geometry->getVertexAttribArray(n)) #if OSG_MIN_VERSION_REQUIRED(3,1,8) - geometry->setVertexAttribArray(n, tsg->getBinormalArray(), osg::Array::BIND_PER_VERTEX); + geometry->setVertexAttribArray(n, tsg->getBinormalArray(), osg::Array::BIND_PER_VERTEX); #else - geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getBinormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); + geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getBinormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); #endif n = _effect->getGenerator(Effect::NORMAL); - if (n != -1 && !geometry->getVertexAttribArray(n)) + if (n != -1 && !geometry->getVertexAttribArray(n)) { + // Provide the tsg-generated normals to the geometry + Vec4Array * new_normals = tsg->getNormalArray(); + geometry->setNormalArray(new_normals,osg::Array::BIND_PER_VERTEX); #if OSG_MIN_VERSION_REQUIRED(3,1,8) - geometry->setVertexAttribArray(n, tsg->getNormalArray(), osg::Array::BIND_PER_VERTEX); + geometry->setVertexAttribArray(n, new_normals, osg::Array::BIND_PER_VERTEX); #else - geometry->setVertexAttribData(n, osg::Geometry::ArrayData(tsg->getNormalArray(), osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); + geometry->setVertexAttribData(n, osg::Geometry::ArrayData(new_normals, osg::Geometry::BIND_PER_VERTEX,GL_FALSE)); #endif + } } } diff --git a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx index 8f5cc314..0f0ff84b 100644 --- a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx +++ b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx @@ -348,7 +348,7 @@ public: } } - void addRandomPoints(double coverage, + void addRandomPoints(double coverage, double spacing, osg::Texture2D* object_mask, std::vector >& points) @@ -421,7 +421,9 @@ public: } } - osg::Geometry* buildGeometry(const TriangleVector& triangles, bool useVBOs) const + // If include_norms is true, normals from the input vertices are added to the geometry. If false, + // they should be generated during geometry initialisation. + osg::Geometry* buildGeometry(const TriangleVector& triangles, bool useVBOs, bool include_norms) const { // Do not build anything if there is nothing in here ... if (empty() || triangles.empty()) @@ -444,8 +446,10 @@ public: geometry->setDataVariance(osg::Object::STATIC); geometry->setVertexArray(vertices); - geometry->setNormalArray(normals); - geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + if (include_norms) { + geometry->setNormalArray(normals); + geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + } geometry->setColorArray(colors); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); if ( has_sec_tcs ) { @@ -499,8 +503,8 @@ public: return geometry; } - osg::Geometry* buildGeometry(bool useVBOs) const - { return buildGeometry(getTriangles(), useVBOs); } + osg::Geometry* buildGeometry(bool useVBOs, bool include_norms) const + { return buildGeometry(getTriangles(), useVBOs, include_norms); } int getTextureIndex() const { diff --git a/simgear/scene/tgdb/SGTileGeometryBin.hxx b/simgear/scene/tgdb/SGTileGeometryBin.hxx index 409ded6c..2c8aa9ae 100644 --- a/simgear/scene/tgdb/SGTileGeometryBin.hxx +++ b/simgear/scene/tgdb/SGTileGeometryBin.hxx @@ -275,7 +275,6 @@ public: //osg::Geode* geode = new osg::Geode; SGMaterialTriangleMap::const_iterator i; for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) { - osg::Geometry* geometry = i->second.buildGeometry(useVBOs); SGMaterial *mat = NULL; if (matcache) { mat = matcache->find(i->first); @@ -288,8 +287,15 @@ public: } else { eg->setMaterial(NULL); } - eg->addDrawable(geometry); + // If effect requests normal generation, we do not include terragear + // normals in the geometry + bool include_normals = true; + int n = eg->getEffect()->getGenerator(Effect::NORMAL); + if (n != -1) + include_normals = false; + osg::Geometry* geometry = i->second.buildGeometry(useVBOs, include_normals); eg->runGenerators(geometry); // Generate extra data needed by effect + eg->addDrawable(geometry); if (group) { group->addChild(eg); }