Implemented duplicate removal code into TriStripVisitor and added an

extra pass to doing tri stripping in the osgUtil::Optimzer.

Added validity checks into osg::TexEnvCombine to catch eronous enumarant values.

Improved the efficient of CullingSet's handling of new transforms.

Added a copy shared subgraphs and subdivision code into osgUtil::Optimizer.
This commit is contained in:
Robert Osfield
2003-12-03 21:45:32 +00:00
parent cdb6f9a1df
commit db66abd6d6
14 changed files with 985 additions and 112 deletions

View File

@@ -358,6 +358,23 @@ class DrawFogCoord : public osg::ConstValueVisitor
const Drawable::Extensions * _extensions;
};
Geometry::ArrayData::ArrayData(const ArrayData& data,const CopyOp& copyop):
array(data.array.valid()?dynamic_cast<osg::Array*>(data.array->clone(copyop)):0),
indices(data.indices.valid()?dynamic_cast<osg::IndexArray*>(data.indices->clone(copyop)):0),
binding(data.binding),
normalize(data.normalize),
offset(data.offset)
{
}
Geometry::Vec3ArrayData::Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop):
array(data.array.valid()?dynamic_cast<osg::Vec3Array*>(data.array->clone(copyop)):0),
indices(data.indices.valid()?dynamic_cast<osg::IndexArray*>(data.indices->clone(copyop)):0),
binding(data.binding),
normalize(data.normalize),
offset(data.offset)
{
}
Geometry::Geometry()
{
@@ -367,11 +384,11 @@ Geometry::Geometry()
Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
Drawable(geometry,copyop),
_vertexData(geometry._vertexData),
_normalData(geometry._normalData),
_colorData(geometry._colorData),
_secondaryColorData(geometry._secondaryColorData),
_fogCoordData(geometry._fogCoordData),
_vertexData(geometry._vertexData,copyop),
_normalData(geometry._normalData,copyop),
_colorData(geometry._colorData,copyop),
_secondaryColorData(geometry._secondaryColorData,copyop),
_fogCoordData(geometry._fogCoordData,copyop),
_fastPath(geometry._fastPath),
_fastPathHint(geometry._fastPathHint)
{

View File

@@ -12,6 +12,7 @@
*/
#include <osg/GLExtensions>
#include <osg/TexEnvCombine>
#include <osg/Notify>
using namespace osg;
@@ -100,3 +101,42 @@ void TexEnvCombine::apply(State&) const
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
void TexEnvCombine::setCombine_RGB(GLint cm) { _combine_RGB = cm; }
void TexEnvCombine::setCombine_Alpha(GLint cm) { _combine_Alpha = cm; }
void TexEnvCombine::setSource0_RGB(GLint sp) { _source0_RGB = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setSource1_RGB(GLint sp) { _source1_RGB = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setSource2_RGB(GLint sp) { _source2_RGB = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setSource0_Alpha(GLint sp) { _source0_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setSource1_Alpha(GLint sp) { _source1_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setSource2_Alpha(GLint sp) { _source2_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void TexEnvCombine::setOperand0_RGB(GLint op) { _operand0_RGB = op; }
void TexEnvCombine::setOperand1_RGB(GLint op) { _operand1_RGB = op; }
void TexEnvCombine::setOperand2_RGB(GLint op) { _operand2_RGB = op; }
static GLint Valid_Operand_Alpha(GLint op, const char* functionName)
{
if (op==TexEnvCombine::SRC_ALPHA || op==TexEnvCombine::ONE_MINUS_SRC_ALPHA) return op;
notify(WARN)<<"Warning:: TexEnvCombine::"<<functionName<<"("<<op<<") invalid parameter value,"<<std::endl<<
" must be SRC_ALPHA or ONE_MINUS_SRC_ALPHA, resetting to SRC_ALPHA."<<std::endl;
return TexEnvCombine::SRC_ALPHA;
}
void TexEnvCombine::setOperand0_Alpha(GLint op)
{
_operand0_Alpha = Valid_Operand_Alpha(op,"setOperand0_Alpha");
}
void TexEnvCombine::setOperand1_Alpha(GLint op)
{
_operand1_Alpha = Valid_Operand_Alpha(op,"setOperand1_Alpha");
}
void TexEnvCombine::setOperand2_Alpha(GLint op)
{
_operand2_Alpha = Valid_Operand_Alpha(op,"setOperand2_Alpha");
}
void TexEnvCombine::setScale_RGB(float scale) { _scale_RGB = scale; }
void TexEnvCombine::setScale_Alpha(float scale) { _scale_Alpha = scale; }

View File

@@ -25,6 +25,7 @@
#include <osg/Switch>
#include <osgUtil/TransformAttributeFunctor>
#include <osgUtil/TriStripVisitor>
#include <typeinfo>
#include <algorithm>
@@ -48,19 +49,101 @@ static bool isNodeEmpty(const osg::Node& node)
return true;
}
void Optimizer::optimize(osg::Node* node)
{
unsigned int options = 0;
const char* env = getenv("OSG_OPTIMIZER");
if (env)
{
std::string str(env);
if(str.find("!DEFAULT")!=std::string::npos) options ^= DEFAULT_OPTIMIZATIONS;
else if(str.find("DEFAULT")!=std::string::npos) options |= DEFAULT_OPTIMIZATIONS;
if(str.find("!FLATTEN_STATIC_TRANSFORMS")!=std::string::npos) options ^= FLATTEN_STATIC_TRANSFORMS;
else if(str.find("FLATTEN_STATIC_TRANSFORMS")!=std::string::npos) options |= FLATTEN_STATIC_TRANSFORMS;
if(str.find("!REMOVE_REDUNDANT_NODES")!=std::string::npos) options ^= REMOVE_REDUNDANT_NODES;
else if(str.find("REMOVE_REDUNDANT_NODES")!=std::string::npos) options |= REMOVE_REDUNDANT_NODES;
if(str.find("!COMBINE_ADJACENT_LODS")!=std::string::npos) options ^= COMBINE_ADJACENT_LODS;
else if(str.find("COMBINE_ADJACENT_LODS")!=std::string::npos) options |= COMBINE_ADJACENT_LODS;
if(str.find("!SHARE_DUPLICATE_STATE")!=std::string::npos) options ^= SHARE_DUPLICATE_STATE;
else if(str.find("SHARE_DUPLICATE_STATE")!=std::string::npos) options |= SHARE_DUPLICATE_STATE;
if(str.find("!MERGE_GEOMETRY")!=std::string::npos) options ^= MERGE_GEOMETRY;
else if(str.find("MERGE_GEOMETRY")!=std::string::npos) options |= MERGE_GEOMETRY;
if(str.find("!SPATIALIZE_GROUPS")!=std::string::npos) options ^= SPATIALIZE_GROUPS;
else if(str.find("SPATIALIZE_GROUPS")!=std::string::npos) options |= SPATIALIZE_GROUPS;
if(str.find("!COPY_SHARED_NODES")!=std::string::npos) options ^= COPY_SHARED_NODES;
else if(str.find("COPY_SHARED_NODES")!=std::string::npos) options |= COPY_SHARED_NODES;
if(str.find("!TRISTRIP_GEOMETRY")!=std::string::npos) options ^= TRISTRIP_GEOMETRY;
else if(str.find("TRISTRIP_GEOMETRY")!=std::string::npos) options |= TRISTRIP_GEOMETRY;
}
else
{
options = DEFAULT_OPTIMIZATIONS;
}
optimize(node,options);
}
void Optimizer::optimize(osg::Node* node, unsigned int options)
{
if (options & COMBINE_ADJACENT_LODS)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing COMBINE_ADJACENT_LODS"<<std::endl;
CombineLODsVisitor clv;
node->accept(clv);
clv.combineLODs();
}
if (options & SHARE_DUPLICATE_STATE)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SHARE_DUPLICATE_STATE"<<std::endl;
StateVisitor osv;
node->accept(osv);
osv.optimize();
}
if (options & CHECK_GEOMETRY)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing CHECK_GEOMETRY"<<std::endl;
CheckGeometryVisitor mgv;
node->accept(mgv);
}
if (options & MERGE_GEOMETRY)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing MERGE_GEOMETRY"<<std::endl;
MergeGeometryVisitor mgv;
node->accept(mgv);
}
if (options & COPY_SHARED_NODES)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing COPY_SHARED_NODES"<<std::endl;
CopySharedSubgraphsVisitor cssv;
node->accept(cssv);
cssv.copySharedNodes();
}
if (options & FLATTEN_STATIC_TRANSFORMS)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing FLATTEN_STATIC_TRANSFORMS"<<std::endl;
int i=0;
bool result = false;
@@ -78,6 +161,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
if (options & REMOVE_REDUNDANT_NODES)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing REMOVE_REDUNDANT_NODES"<<std::endl;
RemoveEmptyNodesVisitor renv;
node->accept(renv);
@@ -89,33 +173,22 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
}
if (options & SHARE_DUPLICATE_STATE)
{
StateVisitor osv;
node->accept(osv);
osv.optimize();
}
if (options & CHECK_GEOMETRY)
{
CheckGeometryVisitor mgv;
node->accept(mgv);
}
if (options & MERGE_GEOMETRY)
{
MergeGeometryVisitor mgv;
node->accept(mgv);
}
if (options & SPATIALIZE_GROUPS)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SPATIALIZE_GROUPS"<<std::endl;
SpatializeGroupsVisitor sv;
node->accept(sv);
sv.divide();
}
if (options & TRISTRIP_GEOMETRY)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing TRISTRIP_GEOMETRY"<<std::endl;
TriStripVisitor tsv;
node->accept(tsv);
tsv.stripify();
}
}
@@ -1532,6 +1605,7 @@ bool Optimizer::MergeGeometryVisitor::mergePrimitive(osg::DrawElementsUInt& lhs,
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// Spatialize the scene to accelerate culling
@@ -1718,3 +1792,41 @@ bool Optimizer::SpatializeGroupsVisitor::divide(osg::Group* group, unsigned int
return (numChildrenOnEntry<group->getNumChildren());
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// Spatialize the scene to accelerate culling
//
void Optimizer::CopySharedSubgraphsVisitor::apply(osg::Node& node)
{
if (node.getNumParents()>1)
{
_sharedNodeList.insert(&node);
}
traverse(node);
}
void Optimizer::CopySharedSubgraphsVisitor::copySharedNodes()
{
std::cout<<"Shared node "<<_sharedNodeList.size()<<std::endl;
for(SharedNodeList::iterator itr=_sharedNodeList.begin();
itr!=_sharedNodeList.end();
++itr)
{
std::cout<<" No parents "<<(*itr)->getNumParents()<<std::endl;
osg::Node* node = *itr;
for(unsigned int i=node->getNumParents()-1;i>0;--i)
{
// create a clone.
osg::ref_ptr<osg::Object> new_object = node->clone(osg::CopyOp::DEEP_COPY_NODES |
osg::CopyOp::DEEP_COPY_DRAWABLES);
// cast it to node.
osg::Node* new_node = dynamic_cast<osg::Node*>(new_object.get());
// replace the node by new_new
if (new_node) node->getParent(i)->replaceChild(node,new_node);
}
}
}

View File

@@ -14,6 +14,7 @@
#include <osg/TriangleFunctor>
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>
#include <stdio.h>
#include <algorithm>
@@ -23,6 +24,484 @@
using namespace osg;
using namespace osgUtil;
typedef std::vector<unsigned int> IndexList;
class WriteValue : public osg::ConstValueVisitor
{
public:
WriteValue(std::ostream& o):_o(o) {}
std::ostream& _o;
virtual void apply(const GLbyte& v) { _o << v; }
virtual void apply(const GLshort& v) { _o << v; }
virtual void apply(const GLint& v) { _o << v; }
virtual void apply(const GLushort& v) { _o << v; }
virtual void apply(const GLubyte& v) { _o << v; }
virtual void apply(const GLuint& v) { _o << v; }
virtual void apply(const GLfloat& v) { _o << v; }
virtual void apply(const UByte4& v) { _o << v; }
virtual void apply(const Vec2& v) { _o << v; }
virtual void apply(const Vec3& v) { _o << v; }
virtual void apply(const Vec4& v) { _o << v; }
};
struct VertexAttribComparitor
{
VertexAttribComparitor(osg::Geometry& geometry)
{
add(geometry.getVertexArray(),osg::Geometry::BIND_PER_VERTEX);
add(geometry.getNormalArray(),geometry.getNormalBinding());
add(geometry.getColorArray(),geometry.getColorBinding());
add(geometry.getSecondaryColorArray(),geometry.getSecondaryColorBinding());
add(geometry.getFogCoordArray(),geometry.getFogCoordBinding());
unsigned int i;
for(i=0;i<geometry.getNumTexCoordArrays();++i)
{
add(geometry.getTexCoordArray(i),osg::Geometry::BIND_PER_VERTEX);
}
for(i=0;i<geometry.getNumVertexAttribArrays();++i)
{
add(geometry.getVertexAttribArray(i),geometry.getVertexAttribBinding(i));
}
}
void add(osg::Array* array, osg::Geometry::AttributeBinding binding)
{
if (binding==osg::Geometry::BIND_PER_VERTEX && array)
_arrayList.push_back(array);
}
typedef std::vector<osg::Array*> ArrayList;
ArrayList _arrayList;
bool operator() (unsigned int lhs, unsigned int rhs) const
{
for(ArrayList::const_iterator itr=_arrayList.begin();
itr!=_arrayList.end();
++itr)
{
int compare = (*itr)->compare(lhs,rhs);
if (compare==-1) return true;
if (compare==1) return false;
}
return false;
}
int compare(unsigned int lhs, unsigned int rhs)
{
for(ArrayList::iterator itr=_arrayList.begin();
itr!=_arrayList.end();
++itr)
{
int compare = (*itr)->compare(lhs,rhs);
if (compare==-1) return -1;
if (compare==1) return 1;
}
//
// WriteValue wv(std::cout);
//
// std::cout<<"Values equal"<<std::endl;
// for(ArrayList::iterator itr=_arrayList.begin();
// itr!=_arrayList.end();
// ++itr)
// {
// std::cout<<" lhs["<<lhs<<"]="; (*itr)->accept(lhs,wv);
// std::cout<<" rhs["<<rhs<<"]="; (*itr)->accept(rhs,wv);
// std::cout<<std::endl;
// }
return 0;
}
void accept(osg::ArrayVisitor& av)
{
for(ArrayList::iterator itr=_arrayList.begin();
itr!=_arrayList.end();
++itr)
{
(*itr)->accept(av);
}
}
};
class RemapArray : public osg::ArrayVisitor
{
public:
RemapArray(const IndexList& remapping):_remapping(remapping) {}
const IndexList& _remapping;
template<class T>
inline void remap(T& array)
{
for(unsigned int i=0;i<_remapping.size();++i)
{
if (i!=_remapping[i])
{
array[i] = array[_remapping[i]];
}
}
array.erase(array.begin()+_remapping.size(),array.end());
}
virtual void apply(osg::Array&) {}
virtual void apply(osg::ByteArray& array) { remap(array); }
virtual void apply(osg::ShortArray& array) { remap(array); }
virtual void apply(osg::IntArray& array) { remap(array); }
virtual void apply(osg::UByteArray& array) { remap(array); }
virtual void apply(osg::UShortArray& array) { remap(array); }
virtual void apply(osg::UIntArray& array) { remap(array); }
virtual void apply(osg::UByte4Array& array) { remap(array); }
virtual void apply(osg::FloatArray& array) { remap(array); }
virtual void apply(osg::Vec2Array& array) { remap(array); }
virtual void apply(osg::Vec3Array& array) { remap(array); }
virtual void apply(osg::Vec4Array& array) { remap(array); }
};
class TriangleIndexFunctor : public osg::Drawable::PrimitiveFunctor
{
public:
IndexList _remapIndices;
triangle_stripper::tri_stripper::indices _in_indices;
inline void triangle(unsigned int p1, unsigned int p2, unsigned int p3)
{
if (_remapIndices.empty())
{
_in_indices.push_back(p1);
_in_indices.push_back(p2);
_in_indices.push_back(p3);
}
else
{
_in_indices.push_back(_remapIndices[p1]);
_in_indices.push_back(_remapIndices[p2]);
_in_indices.push_back(_remapIndices[p3]);
}
}
virtual void setVertexArray(unsigned int,const Vec2*)
{
notify(WARN)<<"TriangleIndexFunctor does not support Vec2* vertex arrays"<<std::endl;
}
virtual void setVertexArray(unsigned int ,const Vec3* )
{
notify(WARN)<<"TriangleIndexFunctor does not support Vec4* vertex arrays"<<std::endl;
}
virtual void setVertexArray(unsigned int,const Vec4* )
{
notify(WARN)<<"TriangleIndexFunctor does not support Vec4* vertex arrays"<<std::endl;
}
virtual void begin(GLenum )
{
notify(WARN)<<"TriangleIndexFunctor::begin(GLenum mode) not implemented"<<std::endl;
}
virtual void vertex(const Vec2& )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(const Vec2& vert) not implemented"<<std::endl;
}
virtual void vertex(const Vec3& )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(const Vec3& vert) not implemented"<<std::endl;
}
virtual void vertex(const Vec4& )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(const Vec4& vert) not implemented"<<std::endl;
}
virtual void vertex(float ,float )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(float x,float y) not implemented"<<std::endl;
}
virtual void vertex(float ,float ,float )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(float x,float y,float z) not implemented"<<std::endl;
}
virtual void vertex(float ,float ,float ,float )
{
notify(WARN)<<"TriangleIndexFunctor::vertex(float x,float y,float z,float w) not implemented"<<std::endl;
}
virtual void end()
{
notify(WARN)<<"TriangleIndexFunctor::end() not implemented"<<std::endl;
}
virtual void drawArrays(GLenum mode,GLint first,GLsizei count)
{
switch(mode)
{
case(GL_TRIANGLES):
{
unsigned int pos=first;
for(GLsizei i=2;i<count;i+=3,pos+=3)
{
triangle(pos,pos+1,pos+2);
}
break;
}
case(GL_TRIANGLE_STRIP):
{
unsigned int pos=first;
for(GLsizei i=2;i<count;++i,++pos)
{
if ((i%2)) triangle(pos,pos+2,pos+1);
else triangle(pos,pos+1,pos+2);
}
break;
}
case(GL_QUADS):
{
unsigned int pos=first;
for(GLsizei i=3;i<count;i+=4,pos+=4)
{
triangle(pos,pos+1,pos+2);
triangle(pos,pos+2,pos+3);
}
break;
}
case(GL_QUAD_STRIP):
{
unsigned int pos=first;
for(GLsizei i=3;i<count;i+=2,pos+=2)
{
triangle(pos,pos+1,pos+2);
triangle(pos+1,pos+3,pos+2);
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
unsigned int pos=first+1;
for(GLsizei i=2;i<count;++i,++pos)
{
triangle(first,pos,pos+1);
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices)
{
if (indices==0 || count==0) return;
typedef const GLubyte* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
triangle(*iptr,*(iptr+1),*(iptr+2));
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) triangle(*(iptr),*(iptr+2),*(iptr+1));
else triangle(*(iptr),*(iptr+1),*(iptr+2));
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr),*(iptr+2),*(iptr+3));
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr+1),*(iptr+3),*(iptr+2));
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
unsigned int first = *iptr;
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
triangle(first,*(iptr),*(iptr+1));
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices)
{
if (indices==0 || count==0) return;
typedef const GLushort* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
triangle(*iptr,*(iptr+1),*(iptr+2));
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) triangle(*(iptr),*(iptr+2),*(iptr+1));
else triangle(*(iptr),*(iptr+1),*(iptr+2));
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr),*(iptr+2),*(iptr+3));
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr+1),*(iptr+3),*(iptr+2));
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
unsigned int first = *iptr;
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
triangle(first,*(iptr),*(iptr+1));
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices)
{
if (indices==0 || count==0) return;
typedef const GLuint* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
triangle(*iptr,*(iptr+1),*(iptr+2));
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) triangle(*(iptr),*(iptr+2),*(iptr+1));
else triangle(*(iptr),*(iptr+1),*(iptr+2));
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr),*(iptr+2),*(iptr+3));
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
triangle(*(iptr),*(iptr+1),*(iptr+2));
triangle(*(iptr+1),*(iptr+3),*(iptr+2));
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
unsigned int first = *iptr;
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
triangle(first,*(iptr),*(iptr+1));
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
};
// triangle functor.
struct TriangleAcumulatorFunctor
{
@@ -32,7 +511,7 @@ struct TriangleAcumulatorFunctor
TriangleAcumulatorFunctor() : _vbase(0) {}
void setCoords( const Vec3* vbase ) { _vbase = vbase; }
void setCoords( const Vec3* vbase ) { _vbase = vbase; std::cout<<"set coords"<<std::endl;}
inline void operator() ( const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, bool treatVertexDataAsTemporary )
{
@@ -96,7 +575,110 @@ void TriStripVisitor::stripify(Geometry& geom)
if (!numSurfacePrimitives) return;
TriangleFunctor<TriangleAcumulatorFunctor> taf;
// compute duplicate vertices
typedef std::vector<unsigned int> IndexList;
unsigned int numVertices = geom.getVertexArray()->getNumElements();
IndexList indices(numVertices);
unsigned int i,j;
for(i=0;i<numVertices;++i)
{
indices[i] = i;
}
VertexAttribComparitor arrayComparitor(geom);
std::sort(indices.begin(),indices.end(),arrayComparitor);
unsigned int lastUnique = 0;
unsigned int numUnique = 1;
unsigned int numDuplicate = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(indices[lastUnique],indices[i])==0)
{
//std::cout<<" found duplicate "<<indices[lastUnique]<<" and "<<indices[i]<<std::endl;
++numDuplicate;
}
else
{
//std::cout<<" unique "<<indices[i]<<std::endl;
lastUnique = i;
++numUnique;
}
}
// std::cout<<" Number of duplicates "<<numDuplicate<<std::endl;
// std::cout<<" Number of unique "<<numUnique<<std::endl;
// std::cout<<" Total number of vertices required "<<numUnique<<" vs original "<<numVertices<<std::endl;
// std::cout<<" % size "<<(float)numUnique/(float)numVertices*100.0f<<std::endl;
IndexList remapDuplicatesToOrignals(numVertices);
lastUnique = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(indices[lastUnique],indices[i])!=0)
{
// found a new vertex entry, so previous run of duplicates needs
// to be put together.
unsigned int min_index = indices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index,indices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[indices[j]]=min_index;
}
lastUnique = i;
}
}
unsigned int min_index = indices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index,indices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[indices[j]]=min_index;
}
// copy the arrays.
IndexList finalMapping(numVertices);
IndexList copyMapping;
copyMapping.reserve(numUnique);
unsigned int currentIndex=0;
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]==i)
{
finalMapping[i] = currentIndex;
copyMapping.push_back(i);
currentIndex++;
}
}
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]!=i)
{
finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]];
}
}
for(i=0;i<finalMapping.size();++i)
{
//std::cout<<" finalMapping["<<i<<"] = "<<finalMapping[i]<<std::endl;
}
RemapArray ra(copyMapping);
arrayComparitor.accept(ra);
TriangleIndexFunctor taf;
//taf._remapIndices.swap(remapDuplicatesToOrignals);
taf._remapIndices.swap(finalMapping);
Geometry::PrimitiveSetList new_primitives;
new_primitives.reserve(primitives.size());
@@ -122,11 +704,11 @@ void TriStripVisitor::stripify(Geometry& geom)
}
}
if (!taf.in_indices.empty())
if (!taf._in_indices.empty())
{
int in_numVertices = -1;
for(triangle_stripper::tri_stripper::indices::iterator itr=taf.in_indices.begin();
itr!=taf.in_indices.end();
for(triangle_stripper::tri_stripper::indices::iterator itr=taf._in_indices.begin();
itr!=taf._in_indices.end();
++itr)
{
if ((int)*itr>in_numVertices) in_numVertices=*itr;
@@ -135,7 +717,7 @@ void TriStripVisitor::stripify(Geometry& geom)
// so increment to give to the corrent number of verticies.
++in_numVertices;
triangle_stripper::tri_stripper stripifier(taf.in_indices);
triangle_stripper::tri_stripper stripifier(taf._in_indices);
stripifier.SetCacheSize(_cacheSize);
stripifier.SetMinStripSize(_minStripSize);
@@ -170,17 +752,42 @@ void TriStripVisitor::stripify(Geometry& geom)
new_primitives.push_back(elements);
}
}
geom.setPrimitiveSetList(new_primitives);
#if 0
// debugging code for indentifying the tri-strips.
osg::Vec4Array* colors = new osg::Vec4Array(new_primitives.size());
for(i=0;i<colors->size();++i)
{
(*colors)[i].set(((float)rand()/(float)RAND_MAX),
((float)rand()/(float)RAND_MAX),
((float)rand()/(float)RAND_MAX),
1.0f);
}
geom.setColorArray(colors);
geom.setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
#endif
}
}
void TriStripVisitor::stripify()
{
for(GeometryList::iterator itr=_geometryList.begin();
itr!=_geometryList.end();
++itr)
{
stripify(*(*itr));
// osgUtil::SmoothingVisitor sv;
// sv.smooth(*(*itr));
}
}
void TriStripVisitor::apply(Geode& geode)
{
for(unsigned int i = 0; i < geode.getNumDrawables(); ++i )
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
if (geom) stripify(*geom);
if (geom) _geometryList.insert(geom);
}
}