Some scene graph optimizations
When loading terrain, use DrawElementsUShort where possible. Don't chunk unconnected triangles in the terrain into seperate Geometry sets; make the sets as big as possible.
This commit is contained in:
@@ -54,6 +54,44 @@ struct SGVertNormTex {
|
|||||||
SGVec2f texCoord;
|
SGVec2f texCoord;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Use a DrawElementsUShort if there are few enough vertices,
|
||||||
|
// otherwise fallback to DrawElementsUInt. Hide the differences
|
||||||
|
// between the two from the rest of the code.
|
||||||
|
//
|
||||||
|
// We don't bother with DrawElementsUByte because that is generally
|
||||||
|
// not an advantage on modern hardware.
|
||||||
|
class DrawElementsFacade {
|
||||||
|
public:
|
||||||
|
DrawElementsFacade(unsigned numVerts) :
|
||||||
|
_ushortElements(0), _uintElements(0)
|
||||||
|
{
|
||||||
|
if (numVerts > 65535)
|
||||||
|
_uintElements
|
||||||
|
= new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
|
||||||
|
else
|
||||||
|
_ushortElements
|
||||||
|
= new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(unsigned val)
|
||||||
|
{
|
||||||
|
if (_uintElements)
|
||||||
|
_uintElements->push_back(val);
|
||||||
|
else
|
||||||
|
_ushortElements->push_back(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::DrawElements* getDrawElements()
|
||||||
|
{
|
||||||
|
if (_uintElements)
|
||||||
|
return _uintElements;
|
||||||
|
return _ushortElements;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
osg::DrawElementsUShort* _ushortElements;
|
||||||
|
osg::DrawElementsUInt* _uintElements;
|
||||||
|
};
|
||||||
|
|
||||||
class SGTexturedTriangleBin : public SGTriangleBin<SGVertNormTex> {
|
class SGTexturedTriangleBin : public SGTriangleBin<SGVertNormTex> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -123,9 +161,8 @@ public:
|
|||||||
|
|
||||||
const unsigned invalid = ~unsigned(0);
|
const unsigned invalid = ~unsigned(0);
|
||||||
std::vector<unsigned> indexMap(getNumVertices(), invalid);
|
std::vector<unsigned> indexMap(getNumVertices(), invalid);
|
||||||
|
|
||||||
osg::DrawElementsUInt* drawElements;
|
DrawElementsFacade deFacade(vertices->size());
|
||||||
drawElements = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
|
|
||||||
for (index_type i = 0; i < triangles.size(); ++i) {
|
for (index_type i = 0; i < triangles.size(); ++i) {
|
||||||
triangle_ref triangle = triangles[i];
|
triangle_ref triangle = triangles[i];
|
||||||
if (indexMap[triangle[0]] == invalid) {
|
if (indexMap[triangle[0]] == invalid) {
|
||||||
@@ -134,7 +171,7 @@ public:
|
|||||||
normals->push_back(getVertex(triangle[0]).normal.osg());
|
normals->push_back(getVertex(triangle[0]).normal.osg());
|
||||||
texCoords->push_back(getVertex(triangle[0]).texCoord.osg());
|
texCoords->push_back(getVertex(triangle[0]).texCoord.osg());
|
||||||
}
|
}
|
||||||
drawElements->push_back(indexMap[triangle[0]]);
|
deFacade.push_back(indexMap[triangle[0]]);
|
||||||
|
|
||||||
if (indexMap[triangle[1]] == invalid) {
|
if (indexMap[triangle[1]] == invalid) {
|
||||||
indexMap[triangle[1]] = vertices->size();
|
indexMap[triangle[1]] = vertices->size();
|
||||||
@@ -142,7 +179,7 @@ public:
|
|||||||
normals->push_back(getVertex(triangle[1]).normal.osg());
|
normals->push_back(getVertex(triangle[1]).normal.osg());
|
||||||
texCoords->push_back(getVertex(triangle[1]).texCoord.osg());
|
texCoords->push_back(getVertex(triangle[1]).texCoord.osg());
|
||||||
}
|
}
|
||||||
drawElements->push_back(indexMap[triangle[1]]);
|
deFacade.push_back(indexMap[triangle[1]]);
|
||||||
|
|
||||||
if (indexMap[triangle[2]] == invalid) {
|
if (indexMap[triangle[2]] == invalid) {
|
||||||
indexMap[triangle[2]] = vertices->size();
|
indexMap[triangle[2]] = vertices->size();
|
||||||
@@ -150,9 +187,9 @@ public:
|
|||||||
normals->push_back(getVertex(triangle[2]).normal.osg());
|
normals->push_back(getVertex(triangle[2]).normal.osg());
|
||||||
texCoords->push_back(getVertex(triangle[2]).texCoord.osg());
|
texCoords->push_back(getVertex(triangle[2]).texCoord.osg());
|
||||||
}
|
}
|
||||||
drawElements->push_back(indexMap[triangle[2]]);
|
deFacade.push_back(indexMap[triangle[2]]);
|
||||||
}
|
}
|
||||||
geometry->addPrimitiveSet(drawElements);
|
geometry->addPrimitiveSet(deFacade.getDrawElements());
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,7 +360,12 @@ struct SGTileGeometryBin {
|
|||||||
osg::Geode* geode = new osg::Geode;
|
osg::Geode* geode = new osg::Geode;
|
||||||
SGMaterialTriangleMap::const_iterator i;
|
SGMaterialTriangleMap::const_iterator i;
|
||||||
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
|
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
|
||||||
#define CHUNCKED
|
// CHUNCKED (sic) here splits up unconnected triangles parts of
|
||||||
|
// the mesh into different Geometry sets, presumably for better
|
||||||
|
// culling. I (timoore) believe it is more performant to build
|
||||||
|
// the biggest indexed sets possible at the expense of tight
|
||||||
|
// culling.
|
||||||
|
//#define CHUNCKED
|
||||||
#ifdef CHUNCKED
|
#ifdef CHUNCKED
|
||||||
SGMaterial *mat = matlib->find(i->first);
|
SGMaterial *mat = matlib->find(i->first);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user