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:
parent
cdb6f9a1df
commit
db66abd6d6
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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(); }
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.*/
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user