Allow OSG to recalculate terrain normals.

This commit is contained in:
James.Hester
2020-04-22 18:39:23 +10:00
committed by James Turner
parent 27907c5e6f
commit 259c1314de
4 changed files with 36 additions and 20 deletions

View File

@@ -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()

View File

@@ -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<osgUtil::TangentSpaceGenerator> 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
}
}
}

View File

@@ -348,7 +348,7 @@ public:
}
}
void addRandomPoints(double coverage,
void addRandomPoints(double coverage,
double spacing,
osg::Texture2D* object_mask,
std::vector<std::pair<SGVec3f, float> >& 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
{

View File

@@ -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);
}