mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
crashfix + optimiziation
Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
parent
c0f128bcb3
commit
ce505a9bb3
10 changed files with 300 additions and 106 deletions
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "optimizer.hpp"
|
||||
|
||||
#include <osg/Version>
|
||||
#include <osg/Transform>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
@ -587,17 +588,36 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Node& node)
|
|||
traverse(node);
|
||||
}
|
||||
|
||||
bool needvbo(const osg::Geometry* geom)
|
||||
{
|
||||
#if OSG_MIN_VERSION_REQUIRED(3,5,6)
|
||||
return true;
|
||||
#else
|
||||
return geom->getUseVertexBufferObjects();
|
||||
#endif
|
||||
}
|
||||
|
||||
osg::Array* cloneArray(osg::Array* array, osg::VertexBufferObject*& vbo, const osg::Geometry* geom)
|
||||
{
|
||||
array = osg::clone(array, osg::CopyOp::DEEP_COPY_ALL);
|
||||
if (!vbo && needvbo(geom))
|
||||
vbo = new osg::VertexBufferObject;
|
||||
if (vbo)
|
||||
array->setVertexBufferObject(vbo);
|
||||
return array;
|
||||
}
|
||||
|
||||
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Drawable& drawable)
|
||||
{
|
||||
osg::Geometry *geometry = drawable.asGeometry();
|
||||
if((geometry) && (isOperationPermissibleForObject(&drawable)))
|
||||
{
|
||||
osg::VertexBufferObject* vbo = nullptr;
|
||||
if(geometry->getVertexArray() && geometry->getVertexArray()->referenceCount() > 1) {
|
||||
geometry->setVertexArray(dynamic_cast<osg::Array*>(geometry->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ALL)));
|
||||
geometry->setVertexArray(cloneArray(geometry->getVertexArray(), vbo, geometry));
|
||||
}
|
||||
if(geometry->getNormalArray() && geometry->getNormalArray()->referenceCount() > 1) {
|
||||
geometry->setNormalArray(dynamic_cast<osg::Array*>(geometry->getNormalArray()->clone(osg::CopyOp::DEEP_COPY_ALL)));
|
||||
geometry->setNormalArray(cloneArray(geometry->getNormalArray(), vbo, geometry));
|
||||
}
|
||||
}
|
||||
_drawableSet.insert(&drawable);
|
||||
|
@ -1110,14 +1130,30 @@ void Optimizer::MergeGeometryVisitor::apply(osg::Group &group)
|
|||
popStateSet();
|
||||
}
|
||||
|
||||
osg::PrimitiveSet* clonePrimitive(osg::PrimitiveSet* ps)
|
||||
osg::PrimitiveSet* clonePrimitive(osg::PrimitiveSet* ps, osg::ElementBufferObject*& ebo, const osg::Geometry* geom)
|
||||
{
|
||||
if (ps->referenceCount() <= 1)
|
||||
return ps;
|
||||
ps = dynamic_cast<osg::PrimitiveSet*>(ps->clone(osg::CopyOp::DEEP_COPY_ALL));
|
||||
ps = osg::clone(ps, osg::CopyOp::DEEP_COPY_ALL);
|
||||
|
||||
osg::DrawElements* drawElements = ps->getDrawElements();
|
||||
if (!drawElements) return ps;
|
||||
|
||||
if (!ebo && needvbo(geom))
|
||||
ebo = new osg::ElementBufferObject;
|
||||
if (ebo)
|
||||
drawElements->setElementBufferObject(ebo);
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
bool containsSharedPrimitives(const osg::Geometry* geom)
|
||||
{
|
||||
for (unsigned int i=0; i<geom->getNumPrimitiveSets(); ++i)
|
||||
if (geom->getPrimitiveSet(i)->referenceCount() > 1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
||||
{
|
||||
if (!isOperationPermissibleForObject(&group)) return false;
|
||||
|
@ -1305,6 +1341,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
if (!drawable)
|
||||
continue;
|
||||
osg::Geometry* geom = drawable->asGeometry();
|
||||
osg::ElementBufferObject* ebo = nullptr;
|
||||
if (geom)
|
||||
{
|
||||
osg::Geometry::PrimitiveSetList& primitives = geom->getPrimitiveSetList();
|
||||
|
@ -1317,12 +1354,12 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
{
|
||||
if (prim->getNumIndices()==3)
|
||||
{
|
||||
prim = clonePrimitive(prim); (*itr) = prim;
|
||||
prim = clonePrimitive(prim, ebo, geom); (*itr) = prim;
|
||||
prim->setMode(osg::PrimitiveSet::TRIANGLES);
|
||||
}
|
||||
else if (prim->getNumIndices()==4)
|
||||
{
|
||||
prim = clonePrimitive(prim); (*itr) = prim;
|
||||
prim = clonePrimitive(prim, ebo, geom); (*itr) = prim;
|
||||
prim->setMode(osg::PrimitiveSet::QUADS);
|
||||
}
|
||||
}
|
||||
|
@ -1337,6 +1374,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
if (!drawable)
|
||||
continue;
|
||||
osg::Geometry* geom = drawable->asGeometry();
|
||||
osg::ElementBufferObject* ebo = nullptr;
|
||||
if (geom)
|
||||
{
|
||||
if (geom->getNumPrimitiveSets()>0 &&
|
||||
|
@ -1379,7 +1417,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
|
||||
if (combine)
|
||||
{
|
||||
lhs = clonePrimitive(lhs);
|
||||
lhs = clonePrimitive(lhs, ebo, geom);
|
||||
primitives[lhsNo] = lhs;
|
||||
|
||||
switch(lhs->getType())
|
||||
|
@ -1499,6 +1537,12 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (doneCombine && !geom->containsSharedArrays() && !containsSharedPrimitives(geom))
|
||||
{
|
||||
// prefer to use vbo for merged geometries as vbo uses less memory than display lists.
|
||||
geom->setUseVertexBufferObjects(true);
|
||||
geom->setUseDisplayList(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1578,16 +1622,14 @@ class MergeArrayVisitor : public osg::ArrayVisitor
|
|||
|
||||
bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs)
|
||||
{
|
||||
if (lhs.containsSharedArrays())
|
||||
lhs.duplicateSharedArrays();
|
||||
|
||||
MergeArrayVisitor merger;
|
||||
|
||||
osg::VertexBufferObject* vbo = nullptr;
|
||||
unsigned int base = 0;
|
||||
if (lhs.getVertexArray() && rhs.getVertexArray())
|
||||
{
|
||||
|
||||
base = lhs.getVertexArray()->getNumElements();
|
||||
if (lhs.getVertexArray()->referenceCount() > 1)
|
||||
lhs.setVertexArray(cloneArray(lhs.getVertexArray(), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getVertexArray(),rhs.getVertexArray()))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: vertex array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1602,6 +1644,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
|
||||
if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalArray()->getBinding()!=osg::Array::BIND_OVERALL)
|
||||
{
|
||||
if (lhs.getNormalArray()->referenceCount() > 1)
|
||||
lhs.setNormalArray(cloneArray(lhs.getNormalArray(), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getNormalArray(),rhs.getNormalArray()))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: normal array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1615,6 +1659,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
|
||||
if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorArray()->getBinding()!=osg::Array::BIND_OVERALL)
|
||||
{
|
||||
if (lhs.getColorArray()->referenceCount() > 1)
|
||||
lhs.setColorArray(cloneArray(lhs.getColorArray(), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getColorArray(),rhs.getColorArray()))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: color array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1627,6 +1673,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
|
||||
if (lhs.getSecondaryColorArray() && rhs.getSecondaryColorArray() && lhs.getSecondaryColorArray()->getBinding()!=osg::Array::BIND_OVERALL)
|
||||
{
|
||||
if (lhs.getSecondaryColorArray()->referenceCount() > 1)
|
||||
lhs.setSecondaryColorArray(cloneArray(lhs.getSecondaryColorArray(), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getSecondaryColorArray(),rhs.getSecondaryColorArray()))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: secondary color array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1639,6 +1687,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
|
||||
if (lhs.getFogCoordArray() && rhs.getFogCoordArray() && lhs.getFogCoordArray()->getBinding()!=osg::Array::BIND_OVERALL)
|
||||
{
|
||||
if (lhs.getFogCoordArray()->referenceCount() > 1)
|
||||
lhs.setFogCoordArray(cloneArray(lhs.getFogCoordArray(), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getFogCoordArray(),rhs.getFogCoordArray()))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: fog coord array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1653,6 +1703,9 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
unsigned int unit;
|
||||
for(unit=0;unit<lhs.getNumTexCoordArrays();++unit)
|
||||
{
|
||||
if (!lhs.getTexCoordArray(unit)) continue;
|
||||
if (lhs.getTexCoordArray(unit)->referenceCount() > 1)
|
||||
lhs.setTexCoordArray(unit, cloneArray(lhs.getTexCoordArray(unit), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getTexCoordArray(unit),rhs.getTexCoordArray(unit)))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: tex coord array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1661,6 +1714,9 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
|
||||
for(unit=0;unit<lhs.getNumVertexAttribArrays();++unit)
|
||||
{
|
||||
if (!lhs.getVertexAttribArray(unit)) continue;
|
||||
if (lhs.getVertexAttribArray(unit)->referenceCount() > 1)
|
||||
lhs.setVertexAttribArray(unit, cloneArray(lhs.getVertexAttribArray(unit), vbo, &lhs));
|
||||
if (!merger.merge(lhs.getVertexAttribArray(unit),rhs.getVertexAttribArray(unit)))
|
||||
{
|
||||
OSG_DEBUG << "MergeGeometry: vertex attrib array not merged. Some data may be lost." <<std::endl;
|
||||
|
@ -1668,6 +1724,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
}
|
||||
|
||||
// shift the indices of the incoming primitives to account for the pre existing geometry.
|
||||
osg::ElementBufferObject* ebo = nullptr;
|
||||
osg::Geometry::PrimitiveSetList::iterator primItr;
|
||||
for(primItr=rhs.getPrimitiveSetList().begin(); primItr!=rhs.getPrimitiveSetList().end(); ++primItr)
|
||||
{
|
||||
|
@ -1689,6 +1746,11 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
{
|
||||
// must promote to a DrawElementsUInt
|
||||
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt(primitive->getMode());
|
||||
if (needvbo(&lhs))
|
||||
{
|
||||
if (!ebo) ebo = new osg::ElementBufferObject;
|
||||
new_primitive->setElementBufferObject(ebo);
|
||||
}
|
||||
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
|
@ -1696,13 +1758,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
{
|
||||
// must promote to a DrawElementsUShort
|
||||
osg::DrawElementsUShort* new_primitive = new osg::DrawElementsUShort(primitive->getMode());
|
||||
if (needvbo(&lhs))
|
||||
{
|
||||
if (!ebo) ebo = new osg::ElementBufferObject;
|
||||
new_primitive->setElementBufferObject(ebo);
|
||||
}
|
||||
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*primItr) = clonePrimitive(primitive);
|
||||
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
|
||||
(*primItr)->offsetIndices(base);
|
||||
}
|
||||
}
|
||||
|
@ -1722,13 +1789,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
{
|
||||
// must promote to a DrawElementsUInt
|
||||
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt(primitive->getMode());
|
||||
if (needvbo(&lhs))
|
||||
{
|
||||
if (!ebo) ebo = new osg::ElementBufferObject;
|
||||
new_primitive->setElementBufferObject(ebo);
|
||||
}
|
||||
std::copy(primitiveUShort->begin(),primitiveUShort->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*primItr) = clonePrimitive(primitive);
|
||||
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
|
||||
(*primItr)->offsetIndices(base);
|
||||
}
|
||||
}
|
||||
|
@ -1738,7 +1810,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||
case(osg::PrimitiveSet::DrawArrayLengthsPrimitiveType):
|
||||
case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType):
|
||||
default:
|
||||
(*primItr) = clonePrimitive(primitive);
|
||||
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
|
||||
(*primItr)->offsetIndices(base);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue