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

@ -1,15 +1,14 @@
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta content="text/html; charset=iso-8859-1"
http-equiv="Content-Type">
<meta
content="Mozilla/4.77 [en] (X11; U; Linux 2.4.3-20mdk i686) [Netscape]"
name="GENERATOR">
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="GENERATOR"
content="Mozilla/4.77 [en] (X11; U; Linux 2.4.3-20mdk i686) [Netscape]">
<title>Introduction to the OpenSceneGraph</title>
</head>
<body bgcolor="#ffffff">
<img border="0" src="images/OpenSceneGraphBanner_Distribution.jpg">
<img src="images/OpenSceneGraphBanner_Distribution.jpg" border="0">
<table>
<tbody>
<tr>
@ -202,26 +201,23 @@ be found at Vterrain.org and TerrainEngine.com, both of which integrate
with the OpenSceneGraph.
<p></p>
<li><b><i>Productivity</i></b> </li>
<p>
The core scene graph provides encapsulate the majority of OpenGL
<p>The core scene graph provides encapsulate the majority of OpenGL
functionality including latest extensions, provides rending
optimizations
such as culling and sorting, and a whole set of add on libraries which
make
it possible to develop high peformance graphics applications very
rapidly. The application developer is freed to concentrate on content
and how that content is controlled rather than low level coding.
</p>
<p>
Combining lessons learned from established scene graphs like Performer
and how that content is controlled rather than low level coding. </p>
<p>Combining lessons learned from established scene graphs like
Performer
and Open Inventor, with modern software engineering methods like Design
Patterns, along with a great deal of feedback early on in the
development cycle, it has been possible to design a library that is
clean and extensible. This has made it easy for users to adopt to the
OpenSceneGraph and to integrate it with their own applications.
</p>
<p>
For reading and writing databases an the database library (osgDB) adds
OpenSceneGraph and to integrate it with their own applications. </p>
<p>For reading and writing databases an the database library (osgDB)
adds
support for a wide
variety of database formats via a extensible dynamic plugin mechansim -
the distribution now includes 33
@ -235,33 +231,30 @@ native .osg ASCII format.
Image loaders include .rgb, .gif, .jpg, .png, .tiff, .pic, .bmp, .dds
(include compressed mip mapped imagery), .tga and qucktime (under OSX).
A whole set of high quality, anti-aliased fonts can also be loaded via
the freetype plugin.
</p>
<p>
The scene graph also has a set of <i>Node Kits</i> which are seperate
the freetype plugin. </p>
<p>The scene graph also has a set of <i>Node Kits</i> which are
seperate
libraries,
that can be compiled in with your applications or loaded in at runtime,
which add support for particle systems (osgParticle),
high quality anti-aliased text (osgText) and navigational light points
(osgSim). </p>
<p>
The community has also developed a number of additional <i>Node Kits</i>
<p>The community has also developed a number of additional <i>Node
Kits</i>
such as <a href="http://osgnv.sourceforge.net/">osgNV</a> (which
includes support for NVidia's vertex, fragment, combiner etc extension
and NVidia's Cg shader language.), <a
href="http://www.terrainengine.com">Demeter</a> (CLOD terrain +
integration with OSG). <a href="http://osgcal.sourceforge.net">osgCal</a>
(which integrates <a href="http://cal3d.sourceforge.net//">Cal3D</a>
and the OSG), <a
href="http://www.cs.umu.se/kurser/TDBD12/HT02/lab/osgVortex/">osgVortex</a>
and the OSG), <a href="http://www.vrlab.umu.se/research/osgvortex">osgVortex</a>
(which integrates the <a href="http://www.cm-labs.com/">CM-Labs Vortex</a>
physics enginer with OSG)
and a whole set libraries that integrating the leading Windowing API's
Links can be found in the bazaar sections on the <a
href="http://www.openscenegraph.org/download/">download</a> page of
OpenSceneGraph webiste. </p>
<p>
The project has also been integrated with <a
<p>The project has also been integrated with <a
href="http://www.vrjuggler.org/">VR Juggler</a> and <a
href="http://http://vess.ist.ucf.edu/">Vess</a> virtual realilty the
frameworks, with others in developments. </p>

View File

@ -138,19 +138,19 @@ make1DSineTexture( int texSize )
///////////////////////////////////////////////////////////////////////////
static osg::Node* createGlobe()
{
osg::Geode* geode = new osg::Geode();
osg::StateSet* stateset = geode->getOrCreateStateSet();
osg::Texture2D* texture = new osg::Texture2D;
texture->setImage( osgDB::readImageFile("Images/land_shallow_topo_2048.jpg") );
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 2.0f)));
return geode;
}
// static osg::Node* createGlobe()
// {
// osg::Geode* geode = new osg::Geode();
// osg::StateSet* stateset = geode->getOrCreateStateSet();
//
// osg::Texture2D* texture = new osg::Texture2D;
// texture->setImage( osgDB::readImageFile("Images/land_shallow_topo_2048.jpg") );
// stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
//
// geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 2.0f)));
//
// return geode;
// }
///////////////////////////////////////////////////////////////////////////
// OpenGL Shading Language source code for the "microshader" example,

View File

@ -73,6 +73,9 @@ class SG_EXPORT Array : public Object
virtual void accept(unsigned int index,ValueVisitor&) = 0;
virtual void accept(unsigned int index,ConstValueVisitor&) const = 0;
/** return -1 if lhs element is less than rhs element, 0 is equal, 1 if lhs element is greater than rhs element.*/
virtual int compare(unsigned int lhs,unsigned int rhs) const = 0;
Type getType() const { return _arrayType; }
GLint getDataSize() const { return _dataSize; }
GLenum getDataType() const { return _dataType; }
@ -122,6 +125,15 @@ class TemplateArray : public Array, public std::vector<T>
virtual void accept(unsigned int index,ValueVisitor& vv) { vv.apply( (*this)[index] ); }
virtual void accept(unsigned int index,ConstValueVisitor& vv) const { vv.apply( (*this)[index] );}
virtual int compare(unsigned int lhs,unsigned int rhs) const
{
const T& elem_lhs = (*this)[lhs];
const T& elem_rhs = (*this)[rhs];
if (elem_lhs<elem_rhs) return -1;
if (elem_rhs<elem_lhs) return 1;
return 0;
}
virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; }
virtual unsigned int getTotalDataSize() const { return size()*sizeof(T); }
virtual unsigned int getNumElements() const { return size(); }
@ -184,6 +196,15 @@ class TemplateIndexArray : public IndexArray, public std::vector<T>
virtual void accept(unsigned int index,ValueVisitor& vv) { vv.apply( (*this)[index] ); }
virtual void accept(unsigned int index,ConstValueVisitor& vv) const { vv.apply( (*this)[index] );}
virtual int compare(unsigned int lhs,unsigned int rhs) const
{
const T& elem_lhs = (*this)[lhs];
const T& elem_rhs = (*this)[rhs];
if (elem_lhs<elem_rhs) return -1;
if (elem_rhs<elem_lhs) return 1;
return 0;
}
virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; }
virtual unsigned int getTotalDataSize() const { return size()*sizeof(T); }
virtual unsigned int getNumElements() const { return size(); }

View File

@ -81,12 +81,14 @@ class SG_EXPORT CullingSet : public Referenced
inline void set(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector)
{
_mask = cs._mask;
_frustum = cs._frustum;
_occluderList = cs._occluderList;
_pixelSizeVector = pixelSizeVector;
_smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
_frustum.transformProvidingInverse(matrix);
//_frustum = cs._frustum;
//_frustum.transformProvidingInverse(matrix);
_frustum.setAndTransformProvidingInverse(cs._frustum,matrix);
for(OccluderList::iterator itr=_occluderList.begin();
itr!=_occluderList.end();

View File

@ -58,6 +58,8 @@ class SG_EXPORT Geometry : public Drawable
normalize(GL_FALSE),
offset(0) {}
ArrayData(const ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
ArrayData(Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(0),
@ -96,6 +98,8 @@ class SG_EXPORT Geometry : public Drawable
normalize(GL_FALSE),
offset(0) {}
Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
Vec3ArrayData(Vec3Array* a, AttributeBinding b, GLboolean n = GL_FALSE):
array(a),
indices(0),
@ -357,24 +361,15 @@ class SG_EXPORT Geometry : public Drawable
PrimitiveSetList _primitives;
ArrayData _vertexData;
Vec3ArrayData _normalData;
ArrayData _colorData;
ArrayData _secondaryColorData;
ArrayData _fogCoordData;
ArrayList _texCoordList;
ArrayList _vertexAttribList;
mutable bool _fastPath;
bool _fastPathHint;
ref_ptr<Geometry> _internalOptimizedGeometry;

View File

@ -77,7 +77,7 @@ class SG_EXPORT Multisample : public StateAttribute
return 0; // passed all the above comparison macro's, must be equal.
}
virtual void getAssociatedModes(std::vector<GLMode>& modes) const {}
virtual void getAssociatedModes(std::vector<GLMode>& /*modes*/) const {}
void setSampleCoverage(float coverage, bool invert)
{

View File

@ -69,8 +69,56 @@ class SG_EXPORT Polytope
setupMask();
}
inline void setAndTransformProvidingInverse(const Polytope& pt, const osg::Matrix& matrix)
{
_referenceVertexList = pt._referenceVertexList;
unsigned int resultMask = pt._maskStack.back();
if (resultMask==0)
{
_maskStack.back() = 0;
_resultMask = 0;
_planeList.clear();
return;
}
ClippingMask selector_mask = 0x1;
unsigned int numActivePlanes = 0;
// count number active planes.
PlaneList::const_iterator itr;
for(itr=pt._planeList.begin();
itr!=pt._planeList.end();
++itr)
{
if (resultMask&selector_mask) ++numActivePlanes;
selector_mask <<= 1;
}
_planeList.resize(numActivePlanes);
_resultMask = 0;
selector_mask = 0x1;
unsigned int index = 0;
for(itr=pt._planeList.begin();
itr!=pt._planeList.end();
++itr)
{
if (resultMask&selector_mask)
{
_planeList[index] = *itr;
_planeList[index++].transformProvidingInverse(matrix);
_resultMask = (_resultMask<<1) | 1;
}
selector_mask <<= 1;
}
_maskStack.back() = _resultMask;
}
inline void set(const PlaneList& pl) { _planeList = pl; setupMask(); }
inline void add(const osg::Plane& pl) { _planeList.push_back(pl); setupMask(); }
/** flip/reverse the orientation of all the planes.*/

View File

@ -134,8 +134,8 @@ class SG_EXPORT TexEnvCombine : public StateAttribute
DOT3_RGBA = GL_DOT3_RGBA_ARB
};
void setCombine_RGB(GLint cm) { _combine_RGB = cm; }
void setCombine_Alpha(GLint cm) { _combine_Alpha = cm; }
void setCombine_RGB(GLint cm);
void setCombine_Alpha(GLint cm);
GLint getCombine_RGB() const { return _combine_RGB; }
GLint getCombine_Alpha() const { return _combine_Alpha; }
@ -156,13 +156,13 @@ class SG_EXPORT TexEnvCombine : public StateAttribute
TEXTURE7 = GL_TEXTURE0+7
};
void setSource0_RGB(GLint sp) { _source0_RGB = sp; computeNeedoForTexEnvCombiners(); }
void setSource1_RGB(GLint sp) { _source1_RGB = sp; computeNeedoForTexEnvCombiners(); }
void setSource2_RGB(GLint sp) { _source2_RGB = sp; computeNeedoForTexEnvCombiners(); }
void setSource0_RGB(GLint sp);
void setSource1_RGB(GLint sp);
void setSource2_RGB(GLint sp);
void setSource0_Alpha(GLint sp) { _source0_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void setSource1_Alpha(GLint sp) { _source1_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void setSource2_Alpha(GLint sp) { _source2_Alpha = sp; computeNeedoForTexEnvCombiners(); }
void setSource0_Alpha(GLint sp);
void setSource1_Alpha(GLint sp);
void setSource2_Alpha(GLint sp);
GLint getSource0_RGB() const { return _source0_RGB; }
GLint getSource1_RGB() const { return _source1_RGB; }
@ -180,13 +180,13 @@ class SG_EXPORT TexEnvCombine : public StateAttribute
ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA
};
void setOperand0_RGB(GLint op) { _operand0_RGB = op; }
void setOperand1_RGB(GLint op) { _operand1_RGB = op; }
void setOperand2_RGB(GLint op) { _operand2_RGB = op; }
void setOperand0_RGB(GLint op);
void setOperand1_RGB(GLint op);
void setOperand2_RGB(GLint op);
void setOperand0_Alpha(GLint op) { _operand0_Alpha = op; }
void setOperand1_Alpha(GLint op) { _operand1_Alpha = op; }
void setOperand2_Alpha(GLint op) { _operand2_Alpha = op; }
void setOperand0_Alpha(GLint op);
void setOperand1_Alpha(GLint op);
void setOperand2_Alpha(GLint op);
GLint getOperand0_RGB() const { return _operand0_RGB; }
GLint getOperand1_RGB() const { return _operand1_RGB; }
@ -197,8 +197,8 @@ class SG_EXPORT TexEnvCombine : public StateAttribute
GLint getOperand2_Alpha() const { return _operand2_Alpha; }
void setScale_RGB(float scale) { _scale_RGB = scale; }
void setScale_Alpha(float scale) { _scale_Alpha = scale; }
void setScale_RGB(float scale);
void setScale_Alpha(float scale);
float getScale_RGB() const { return _scale_RGB; }
float getScale_Alpha() const { return _scale_Alpha; }

View File

@ -38,25 +38,39 @@ class OSGUTIL_EXPORT Optimizer
enum OptimizationOptions
{
FLATTEN_STATIC_TRANSFORMS = 0x1,
REMOVE_REDUNDANT_NODES = 0x2,
COMBINE_ADJACENT_LODS = 0x4,
SHARE_DUPLICATE_STATE = 0x8,
MERGE_GEOMETRY = 0x10,
CHECK_GEOMETRY = 0x20,
SPATIALIZE_GROUPS = 0x40,
FLATTEN_STATIC_TRANSFORMS = 0x001,
REMOVE_REDUNDANT_NODES = 0x002,
COMBINE_ADJACENT_LODS = 0x004,
SHARE_DUPLICATE_STATE = 0x008,
MERGE_GEOMETRY = 0x010,
CHECK_GEOMETRY = 0x020,
SPATIALIZE_GROUPS = 0x040,
COPY_SHARED_NODES = 0x080,
TRISTRIP_GEOMETRY = 0x100,
DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
REMOVE_REDUNDANT_NODES |
COMBINE_ADJACENT_LODS |
SHARE_DUPLICATE_STATE |
MERGE_GEOMETRY |
CHECK_GEOMETRY,
ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
REMOVE_REDUNDANT_NODES |
COMBINE_ADJACENT_LODS |
SHARE_DUPLICATE_STATE |
MERGE_GEOMETRY |
CHECK_GEOMETRY |
SPATIALIZE_GROUPS
SPATIALIZE_GROUPS |
COPY_SHARED_NODES |
TRISTRIP_GEOMETRY
};
/** traverse the node and its subgraph with a series of optimization
* visitors, specificied by the OptizationOptions.*/
virtual void optimize(osg::Node* node, unsigned int options = ALL_OPTIMIZATIONS);
void optimize(osg::Node* node);
/** traverse the node and its subgraph with a series of optimization
* visitors, specificied by the OptizationOptions.*/
virtual void optimize(osg::Node* node, unsigned int options);
@ -233,6 +247,22 @@ class OSGUTIL_EXPORT Optimizer
GroupsToDivideList _groupsToDivideList;
};
/** Copy any shared subgraphs, enabling flattening of static transforms.*/
class OSGUTIL_EXPORT CopySharedSubgraphsVisitor : public osg::NodeVisitor
{
public:
CopySharedSubgraphsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Node& node);
void copySharedNodes();
typedef std::set<osg::Node*> SharedNodeList;
SharedNodeList _sharedNodeList;
};
};
}

View File

@ -20,6 +20,8 @@
#include <osgUtil/Export>
#include <set>
namespace osgUtil {
/** A tri stripping visitor for converting Geometry surface primitives into tri strips.
@ -42,7 +44,10 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor
*/
void stripify(osg::Geometry& drawable);
/// apply stripify method to all geode geometry.
/** Stripfy the accumulated list of Geometry drawables.*/
void stripify();
/// accumulate the Geometry drawables to stripify
virtual void apply(osg::Geode& geode);
inline void setCacheSize( unsigned int size )
@ -77,8 +82,11 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor
private:
typedef std::set<osg::Geometry*> GeometryList;
unsigned int _cacheSize;
unsigned int _minStripSize;
GeometryList _geometryList;
};
}

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