Added conversion to osg::GeoSet::converToGeometry() utility to help the

migration to and testing of the new osg::Geometry class.
This commit is contained in:
Robert Osfield
2002-06-23 21:43:46 +00:00
parent bbc129e5c6
commit f2e215bf44
10 changed files with 1022 additions and 88 deletions

View File

@@ -12,6 +12,10 @@
namespace osg {
// forward declare so that we don't need to include the header.
class Geometry;
/** Encapsulates OpenGL drawing primitives, geometry and
optional binding of normal, color and texture coordinates. Used
for representing the visible objects in the scene. State attributes
@@ -334,6 +338,9 @@ class SG_EXPORT GeoSet : public Drawable
virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf);
/** convinience function for converting GeoSet's to equivilant Geometry nodes.*/
Geometry* convertToGeometry();
protected:

View File

@@ -88,8 +88,18 @@ class TemplateArray : public AttributeArray, public std::vector<T>
TemplateArray() : AttributeArray(ARRAYTYPE,DataSize,DataType) {}
TemplateArray(const TemplateArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : AttributeArray(ta,copyop), std::vector<T>(ta) {}
TemplateArray(const TemplateArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
AttributeArray(ta,copyop),
std::vector<T>(ta) {}
TemplateArray(unsigned int no,T* ptr) :
AttributeArray(ARRAYTYPE,DataSize,DataType),
std::vector<T>(ptr,ptr+no) {}
TemplateArray(T* first,T* last) :
AttributeArray(ARRAYTYPE,DataSize,DataType),
std::vector<T>(first,last) {}
virtual Object* cloneType() const { return osgNew TemplateArray(); }
virtual Object* clone(const CopyOp& copyop) const { return osgNew TemplateArray(*this,copyop); }
virtual const char* libraryName() const { return "osg"; }
@@ -115,7 +125,7 @@ typedef TemplateArray<Vec4,Vec4ArrayType,4,GL_FLOAT> Vec4Ar
enum PrimitiveType
{
PrimitivePrimitiveType = 0,
DrawArrayPrimitiveType = 1,
DrawArraysPrimitiveType = 1,
UByteDrawElementsPrimitiveType = 2,
UShortDrawElementsPrimitiveType = 3,
UIntDrawElementsPrimitiveType = 4,
@@ -124,7 +134,7 @@ enum PrimitiveType
static char* s_PrimitiveNames[] =
{
"Primitive", // 0
"DrawArray", // 1
"DrawArrays", // 1
"UByteDrawElements", // 2
"UShortDrawElements", // 3
"UIntDrawElements" // 4
@@ -164,31 +174,31 @@ class Primitive : public Object
PrimitiveType _primitiveType;
};
class DrawArray : public Primitive
class DrawArrays : public Primitive
{
public:
DrawArray():
Primitive(DrawArrayPrimitiveType)
DrawArrays():
Primitive(DrawArraysPrimitiveType)
{}
DrawArray(GLenum mode, GLint first, GLsizei count):
Primitive(DrawArrayPrimitiveType),
DrawArrays(GLenum mode, GLint first, GLsizei count):
Primitive(DrawArraysPrimitiveType),
_mode(mode),
_first(first),
_count(count) {}
DrawArray(const DrawArray& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Primitive(da,copyop),
_mode(da._mode),
_first(da._first),
_count(da._count) {}
virtual Object* cloneType() const { return osgNew DrawArray(); }
virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawArray(*this,copyop); }
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawArray*>(obj)!=NULL; }
virtual Object* cloneType() const { return osgNew DrawArrays(); }
virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawArrays(*this,copyop); }
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawArrays*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
virtual const char* className() const { return "DrawArray"; }
virtual const char* className() const { return "DrawArrays"; }
virtual void draw() const
{
@@ -200,15 +210,33 @@ class DrawArray : public Primitive
GLsizei _count;
};
template<typename T, int PRIMTYPE, int DataType>
template<typename T, PrimitiveType PRIMTYPE, int DataType>
class DrawElements : public Primitive, public std::vector<T>
{
public:
DrawElements():Primitive(PRIMTYPE),_dataType(_dataType) {}
DrawElements(GLenum mode=0):
Primitive(PRIMTYPE),
_mode(mode),
_dataType(DataType) {}
DrawElements(const DrawElements& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Primitive(array,copyop) {}
Primitive(array,copyop),
std::vector<T>(array),
_mode(array._mode),
_dataType(array._dataType) {}
DrawElements(GLenum mode,unsigned int no,T* ptr) :
Primitive(PRIMTYPE),
std::vector<T>(ptr,ptr+no),
_mode(mode),
_dataType(DataType) {}
DrawElements(GLenum mode, T* first,T* last) :
Primitive(PRIMTYPE),
std::vector<T>(first,last),
_mode(mode),
_dataType(DataType) {}
virtual Object* cloneType() const { return osgNew DrawElements(); }
virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawElements(*this,copyop); }
@@ -252,10 +280,10 @@ class SG_EXPORT Geometry : public Drawable
enum AttributeBinding
{
OFF=0,
OVERALL,
PER_PRIMITIVE,
PER_VERTEX,
BIND_OFF=0,
BIND_OVERALL,
BIND_PER_PRIMITIVE,
BIND_PER_VERTEX,
};
void setVertexArray(Vec3Array* array) { _vertexArray = array; }
@@ -266,7 +294,7 @@ class SG_EXPORT Geometry : public Drawable
void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; }
AttributeBinding getNormalBinding() const { return _normalBinding; }
void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=OFF; }
void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; }
Vec3Array* getNormalArray() { return _normalArray.get(); }
const Vec3Array* getNormalArray() const { return _normalArray.get(); }
@@ -274,7 +302,7 @@ class SG_EXPORT Geometry : public Drawable
void setColorBinding(AttributeBinding ab) { _colorBinding = ab; }
AttributeBinding getColorBinding() const { return _colorBinding; }
void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=OFF; }
void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; }
AttributeArray* getColorArray() { return _colorArray.get(); }
const AttributeArray* getColorArray() const { return _colorArray.get(); }
@@ -292,7 +320,7 @@ class SG_EXPORT Geometry : public Drawable
PrimitiveList& getPrimitiveList() { return _primitives; }
const PrimitiveList& getPrimitiveList() const { return _primitives; }
void addPrimtive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); }
void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); }

View File

@@ -274,7 +274,7 @@ class SG_EXPORT Texture : public StateAttribute
{
// pad out handle list if required.
if (_handleList.size()<=contextID)
_handleList.resize(contextID,0);
_handleList.resize(contextID+1,0);
// get the globj for the current contextID.
return _handleList[contextID];

View File

@@ -95,6 +95,12 @@ class ref_ptr
inline const T* get() const { return _ptr; }
/** take control over the object pointed to by ref_ptr, unreference but do not delete even if ref count goes to 0,
* return the pointer to the object.
* Note, do not use this unless you are 100% sure your code handles the deletion of the object correctly, and
* only use when absolutely required.*/
inline T* take() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp;}
private:
T* _ptr;
};

View File

@@ -42,7 +42,19 @@ class OSGUTIL_EXPORT Optimizer
virtual void optimize(osg::Node* node, unsigned int options = ALL_OPTIMIZATIONS);
/** ConvertGeoSetsToGeometryVisitor all the old GeoSet Drawables to the new Geometry Drawables.*/
class OSGUTIL_EXPORT ConvertGeoSetsToGeometryVisitor : public osg::NodeVisitor
{
public:
ConvertGeoSetsToGeometryVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Geode& geode);
virtual void apply(osg::Node& node) { traverse(node); }
};
/** Flatten Static Trasform nodes by applying their transform to the
* geometry on the leaves of the scene graph, then removing the
* now redundent transforms.*/
@@ -133,6 +145,113 @@ class OSGUTIL_EXPORT Optimizer
};
/** Remove the lowest static transforms in the scene.*/
class OSGUTIL_EXPORT RemoveLowestStaticTransformsVisitor : public osg::NodeVisitor
{
public:
RemoveLowestStaticTransformsVisitor(bool ignoreDynamicTransforms=true):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_ignoreDynamicTransforms(ignoreDynamicTransforms) {}
virtual void apply(osg::Geode& geode);
virtual void apply(osg::Billboard& billboard);
virtual void apply(osg::LOD& lod);
virtual void apply(osg::Transform& transform);
bool removeTransforms();
typedef std::vector<osg::Transform*> TransformStack;
typedef std::vector<osg::Matrix> MatrixStack;
protected:
struct TransformStruct
{
typedef std::set<osg::Object*> ObjectSet;
TransformStruct():_containsTransform(false),_canBeApplied(true) {}
void add(osg::Object* obj) { _objectSet.insert(obj); }
bool _containsTransform;
bool _canBeApplied;
ObjectSet _objectSet;
};
struct ObjectStruct
{
typedef std::set<osg::Transform*> TransformSet;
ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {}
void add(osg::Transform* transform,osg::Matrix& matrix)
{
_transformSet.insert(transform);
if (!_matrixSet)
{
_matrixSet = true;
_moreThanOneMatrixRequired = false;
_matrix = matrix;
}
else if (_matrix!=matrix)
{
_moreThanOneMatrixRequired = true;
}
}
bool _canBeApplied;
bool _matrixSet;
bool _moreThanOneMatrixRequired;
osg::Matrix _matrix;
TransformSet _transformSet;
};
typedef std::map<osg::Transform*,TransformStruct> TransformMap;
typedef std::map<osg::Object*,ObjectStruct> ObjectMap;
void disableObject(osg::Object* object)
{
disableObject(_objectMap.find(object));
}
void disableObject(ObjectMap::iterator itr);
void disableTransform(osg::Transform* transform);
void doTransform(osg::Object* obj,osg::Matrix& matrix);
bool _ignoreDynamicTransforms;
MatrixStack _matrixStack;
TransformStack _transformStack;
TransformMap _transformMap;
ObjectMap _objectMap;
};
/** Remove rendundent nodes, such as groups with one single child.*/
class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor
{
public:
typedef std::set<osg::Node*> NodeList;
NodeList _redundentNodeList;
RemoveEmptyNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Geode& geode);
virtual void apply(osg::Group& group);
void removeEmptyNodes();
};
/** Remove rendundent nodes, such as groups with one single child.*/
class OSGUTIL_EXPORT RemoveRedundentNodesVisitor : public osg::NodeVisitor
{
@@ -142,8 +261,9 @@ class OSGUTIL_EXPORT Optimizer
NodeList _redundentNodeList;
RemoveRedundentNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Group& group);
virtual void apply(osg::Transform& transform);
void removeRedundentNodes();

View File

@@ -13,7 +13,7 @@
#include <osg/Math>
// ----------------------------------------------------------------------
// Global variables - this is basically the stuff which will be animated
// Global variables - this is basically the stuff wh ich will be animated
// ----------------------------------------------------------------------
@@ -186,12 +186,12 @@ osg::Geode* createGeometryCube()
// set up the primitives
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,0,4));
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,4,4));
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,8,4));
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,12,4));
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,16,4));
cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,20,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,0,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,4,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,8,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,12,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,16,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,20,4));
// set up coords.
@@ -244,7 +244,7 @@ osg::Geode* createGeometryCube()
(*cubeNormals)[5].set(0.0f,-1.0f,0.0f);
cube->setNormalArray( cubeNormals );
cube->setNormalBinding( osg::Geometry::PER_PRIMITIVE );
cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
// ---------------------------------------
// Set up a StateSet to make the cube red

View File

@@ -9,6 +9,9 @@
#include <osg/Notify>
#include <osg/Statistics>
#include <osg/Geometry>
#include <osg/ShadeModel>
//#include <osg/mem_ptr>
using namespace osg;
@@ -975,3 +978,367 @@ bool GeoSet::getStats(Statistics &stat)
stat.addNumPrims(type, nprimlens, numprimtypes, primverts);
return true;
}
Geometry* GeoSet::convertToGeometry()
{
set_fast_path();
computeNumVerts();
ref_ptr<Geometry> geom = osgNew Geometry;
geom->setStateSet(getStateSet());
if (_flat_shaded_skip)
{
// will need to add flat shading to primitive.
StateSet* stateset = geom->getStateSet();
if (!stateset)
{
stateset = osgNew StateSet;
geom->setStateSet(stateset);
}
ShadeModel* shademodel = dynamic_cast<ShadeModel*>(stateset->getAttribute(StateAttribute::SHADEMODEL));
if (!shademodel)
{
shademodel = osgNew osg::ShadeModel;
stateset->setAttribute(shademodel,StateAttribute::OVERRIDE);
}
shademodel->setMode( ShadeModel::FLAT );
}
switch(_normal_binding)
{
case(BIND_OFF):
geom->setNormalBinding(Geometry::BIND_OFF);
break;
case(BIND_OVERALL):
geom->setNormalBinding(Geometry::BIND_OVERALL);
break;
case(BIND_PERPRIM):
geom->setNormalBinding(Geometry::BIND_PER_PRIMITIVE);
break;
case(BIND_PERVERTEX):
geom->setNormalBinding(Geometry::BIND_PER_VERTEX);
break;
default:
geom->setNormalBinding(Geometry::BIND_OFF);
break;
}
switch(_color_binding)
{
case(BIND_OFF):
geom->setColorBinding(Geometry::BIND_OFF);
break;
case(BIND_OVERALL):
geom->setColorBinding(Geometry::BIND_OVERALL);
break;
case(BIND_PERPRIM):
geom->setColorBinding(Geometry::BIND_PER_PRIMITIVE);
break;
case(BIND_PERVERTEX):
geom->setColorBinding(Geometry::BIND_PER_VERTEX);
break;
default:
geom->setColorBinding(Geometry::BIND_OFF);
break;
}
if (_fast_path)
{
// will easily convert into a Geometry.
if (_coords) geom->setVertexArray(osgNew Vec3Array(_numcoords,_coords));
if (_normals) geom->setNormalArray(osgNew Vec3Array(_numnormals,_normals));
if (_colors) geom->setColorArray(osgNew Vec4Array(_numcolors,_colors));
if (_tcoords) geom->setTexCoordArray(0,osgNew Vec2Array(_numtcoords,_tcoords));
if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP,
// TRIANGLE_FAN, QUAD_STRIP, POLYGONS
{
int index = 0;
if( _primLengths == (int *)0 )
{
return 0;
}
for( int i = 0; i < _numprims; i++ )
{
if( _cindex.valid() )
{
UShortDrawElements* n = new UShortDrawElements;
geom->addPrimitive(n);
if (_cindex._is_ushort)
geom->addPrimitive(osgNew UShortDrawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] ));
else
geom->addPrimitive(osgNew UIntDrawElements( (GLenum)_oglprimtype, _primLengths[i], &_cindex._ptr._uint[index] ));
}
else
geom->addPrimitive(osgNew DrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] ));
index += _primLengths[i];
}
}
else // POINTS, LINES, TRIANGLES, QUADS
{
if( _cindex.valid())
{
if (_cindex._is_ushort)
geom->addPrimitive(osgNew UShortDrawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._ushort ));
else
geom->addPrimitive(osgNew UIntDrawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._uint ));
}
else
geom->addPrimitive(new DrawArrays( (GLenum)_oglprimtype, 0, _numcoords ));
}
}
else if( _needprimlen )
{
// slow path, and needing handling of primlen array.
//
// LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP,
// TRIANGLE_FAN, QUAD_STRIP, POLYGONS
// FLAT_LINE_STRIP, FLAT_TRIANGLE_STRIP, FLAT_TRIANGLE_FAN
int i, j;
int index = 0;
int ai = 0;
int ci = 0;
int ni = 0;
int ti = 0;
if( _primLengths == (int *)0 )
{
return 0;
}
Vec3Array* coords = osgNew Vec3Array;
Vec3Array* normals = 0;
Vec4Array* colors = 0;
Vec2Array* texcoords = 0;
if (_colors) colors = osgNew Vec4Array;
if (_normals) normals = osgNew Vec3Array;
if (_tcoords) texcoords = osgNew Vec2Array;
geom->setVertexArray(coords);
geom->setColorArray(colors);
geom->setNormalArray(normals);
geom->setTexCoordArray(0,texcoords);
if (_color_binding == BIND_OVERALL)
{
if( _colindex.valid() )
colors->push_back( _colors[_colindex[0]] );
else
colors->push_back( _colors[0] );
}
if (_normal_binding == BIND_OVERALL)
{
if( _nindex.valid() )
normals->push_back( _normals[0] );
else
normals->push_back( _normals[0] );
}
for( i = 0; i < _numprims; i++ )
{
if (_color_binding == BIND_PERPRIM && colors)
{
if( _colindex.valid() )
colors->push_back( _colors[_colindex[ci++]] );
else
colors->push_back( _colors[ci++] );
}
if (_normal_binding == BIND_PERPRIM && normals)
{
if( _nindex.valid() )
normals->push_back( _normals[_nindex[ni++]] );
else
normals->push_back( _normals[ni++] );
}
unsigned int first = coords->size();
unsigned int count = 0;
for( j = 0; j < _primLengths[i]; j++ )
{
if( j >= _flat_shaded_skip )
{
if( _color_binding == BIND_PERVERTEX && colors)
{
if( (_colindex.valid()) )
colors->push_back( _colors[_colindex[ci++]] );
else
colors->push_back( _colors[ci++] );
}
if( _normal_binding == BIND_PERVERTEX && normals)
{
if(_nindex.valid())
normals->push_back( _normals[_nindex[ni++]] );
else
normals->push_back( _normals[ni++] );
}
}
else
{
// note don't increment ci & ni as we want to make multiple copies it when in _flat_shaded_skip
if( _color_binding == BIND_PERVERTEX && colors)
{
if( (_colindex.valid()) )
colors->push_back( _colors[_colindex[ci]] );
else
colors->push_back( _colors[ci] );
}
if( _normal_binding == BIND_PERVERTEX && normals )
{
if(_nindex.valid())
normals->push_back( _normals[_nindex[ni]] );
else
normals->push_back( _normals[ni] );
}
}
if( _texture_binding == BIND_PERVERTEX && texcoords)
{
if( _tindex.valid() )
texcoords->push_back( _tcoords[_tindex[ti++]] );
else
texcoords->push_back( _tcoords[ti++] );
}
if( _cindex.valid() )
coords->push_back( _coords[_cindex[ai++]] );
else
coords->push_back( _coords[ai++] );
++count;
}
geom->addPrimitive(osgNew DrawArrays(_oglprimtype,first,count));
index += _primLengths[i];
}
}
else
{
Vec3Array* coords = osgNew Vec3Array;
Vec3Array* normals = 0;
Vec4Array* colors = 0;
Vec2Array* texcoords = 0;
if (_colors) colors = osgNew Vec4Array;
if (_normals) normals = osgNew Vec3Array;
if (_tcoords) texcoords = osgNew Vec2Array;
geom->setVertexArray(coords);
geom->setColorArray(colors);
geom->setNormalArray(normals);
geom->setTexCoordArray(0,texcoords);
if (_color_binding == BIND_OVERALL)
{
if( _colindex.valid() )
colors->push_back( _colors[_colindex[0]] );
else
colors->push_back( _colors[0] );
}
if (_normal_binding == BIND_OVERALL)
{
if( _nindex.valid() )
normals->push_back( _normals[_nindex[0]] );
else
normals->push_back( _normals[0] );
}
for(int i = 0; i < _numprims; i++ )
{
if (_color_binding == BIND_PERPRIM && colors)
{
if( _colindex.valid() )
colors->push_back( _colors[_colindex[i]] );
else
colors->push_back( _colors[i] );
}
if (_normal_binding == BIND_PERPRIM && normals)
{
if( _nindex.valid() )
normals->push_back( _normals[_nindex[i]] );
else
normals->push_back( _normals[i] );
}
unsigned int first = coords->size();
unsigned int count = 0;
for(int j = 0; j < _primlength; j++ )
{
if( _color_binding == BIND_PERVERTEX && colors)
{
if( (_colindex.valid()) )
colors->push_back( _colors[_colindex[i*_primlength+j]] );
else
colors->push_back( _colors[i*_primlength+j] );
}
if( _normal_binding == BIND_PERVERTEX && normals )
{
if(_nindex.valid())
normals->push_back( _normals[_nindex[i*_primlength+j]] );
else
normals->push_back( _normals[i*_primlength+j] );
}
if( _texture_binding == BIND_PERVERTEX && texcoords)
{
if( _tindex.valid() )
texcoords->push_back( _tcoords[_tindex[i*_primlength+j]] );
else
texcoords->push_back( _tcoords[i*_primlength+j] );
}
if( _cindex.valid() )
coords->push_back( _coords[_cindex[i*_primlength+j]] );
else
coords->push_back( _coords[i*_primlength+j] );
++count;
}
geom->addPrimitive(osgNew DrawArrays(_oglprimtype,first,count));
}
}
return geom.take();
}

View File

@@ -4,8 +4,8 @@ using namespace osg;
Geometry::Geometry()
{
_normalBinding = OFF;
_colorBinding = OFF;
_normalBinding = BIND_OFF;
_colorBinding = BIND_OFF;
}
Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
@@ -70,17 +70,17 @@ void Geometry::drawImmediateMode(State& /*state*/)
switch (_normalBinding)
{
case(OFF):
case(BIND_OFF):
glDisableClientState( GL_NORMAL_ARRAY );
break;
case(OVERALL):
case(BIND_OVERALL):
glDisableClientState( GL_NORMAL_ARRAY );
if (normalPointer) glNormal3fv(reinterpret_cast<const GLfloat*>(normalPointer));
break;
case(BIND_PER_PRIMITIVE):
glDisableClientState( GL_NORMAL_ARRAY );
break;
case(PER_PRIMITIVE):
glDisableClientState( GL_NORMAL_ARRAY );
break;
case(PER_VERTEX):
case(BIND_PER_VERTEX):
glEnableClientState( GL_NORMAL_ARRAY );
if (normalPointer) glNormalPointer(GL_FLOAT,0,normalPointer);
break;
@@ -121,10 +121,10 @@ void Geometry::drawImmediateMode(State& /*state*/)
switch (_colorBinding)
{
case(OFF):
case(BIND_OFF):
glDisableClientState( GL_COLOR_ARRAY );
break;
case(OVERALL):
case(BIND_OVERALL):
glDisableClientState( GL_COLOR_ARRAY );
if (colorPointer)
{
@@ -142,10 +142,10 @@ void Geometry::drawImmediateMode(State& /*state*/)
}
}
break;
case(PER_PRIMITIVE):
case(BIND_PER_PRIMITIVE):
glDisableClientState( GL_COLOR_ARRAY );
break;
case(PER_VERTEX):
case(BIND_PER_VERTEX):
glEnableClientState( GL_COLOR_ARRAY );
if (colorPointer) glColorPointer(_colorArray->dataSize(),_colorArray->dataType(),0,colorPointer);
}
@@ -156,12 +156,12 @@ void Geometry::drawImmediateMode(State& /*state*/)
itr!=_primitives.end();
++itr)
{
if (_normalBinding==PER_PRIMITIVE)
if (_normalBinding==BIND_PER_PRIMITIVE)
{
glNormal3fv((const GLfloat *)normalPointer++);
}
if (_colorBinding==PER_PRIMITIVE)
if (_colorBinding==BIND_PER_PRIMITIVE)
{
switch(colorType)
{

View File

@@ -4,6 +4,8 @@
#include <osg/LOD>
#include <osg/Impostor>
#include <osg/Billboard>
#include <osg/Geometry>
#include <osg/GeoSet>
#include <osg/Notify>
#include <typeinfo>
@@ -18,6 +20,7 @@ using namespace osgUtil;
void Optimizer::optimize(osg::Node* node, unsigned int options)
{
if (options & COMBINE_ADJACENT_LODS)
{
CombineLODsVisitor clv;
@@ -30,15 +33,42 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
FlattenStaticTransformsVisitor fstv;
node->accept(fstv);
fstv.removeTransforms();
// the following RemoveLowestStaticTransformVisitor doesn't yet work
// properly, will need further work.... Robert Osfield, June 2002.
// int i=0;
// bool result = false;
// do
// {
// cout << "************ RemoveLowestStaticTransformsVisitor "<<i<<endl;
// RemoveLowestStaticTransformsVisitor fstv;
// node->accept(fstv);
// result = fstv.removeTransforms();
// ++i;
// } while (result);
}
if (options & REMOVE_REDUNDENT_NODES)
{
RemoveEmptyNodesVisitor renv;
node->accept(renv);
renv.removeEmptyNodes();
RemoveRedundentNodesVisitor rrnv;
node->accept(rrnv);
rrnv.removeRedundentNodes();
}
// // convert the old style GeoSet to Geometry
// ConvertGeoSetsToGeometryVisitor cgtg;
// node->accept(cgtg);
if (options & SHARE_DUPLICATE_STATE)
{
#if (defined(_MSC_VER) && _MSC_VER<1300 && !defined(_STLPORT_VERSION))
@@ -50,6 +80,9 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
#endif
}
}
class TransformFunctor : public osg::Drawable::AttributeFunctor
@@ -94,6 +127,34 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor
};
////////////////////////////////////////////////////////////////////////////
// Convert GeoSet To Geometry Visitor.
////////////////////////////////////////////////////////////////////////////
void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode)
{
for(int i=0;i<geode.getNumDrawables();++i)
{
osg::GeoSet* geoset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (geoset)
{
osg::Geometry* geom = geoset->convertToGeometry();
if (geom)
{
std::cout<<"Successfully converted GeoSet to Geometry"<<std::endl;
geode.replaceDrawable(geoset,geom);
}
else
{
std::cout<<"*** Failed to convert GeoSet to Geometry"<<std::endl;
}
}
}
}
////////////////////////////////////////////////////////////////////////////
// Optimize State Visitor
////////////////////////////////////////////////////////////////////////////
@@ -153,7 +214,6 @@ void Optimizer::StateVisitor::optimize()
{
osg::notify(osg::INFO) << "Num of StateSet="<<_statesets.size()<< std::endl;
{
// create map from state attributes to stateset which contain them.
typedef std::set<osg::StateSet*> StateSetList;
@@ -335,13 +395,18 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
}
else
{
osg::ref_ptr<osg::Matrix> matrix = osgNew osg::Matrix;
osg::ref_ptr<osg::Matrix> matrix;
if (_matrixStack.empty())
{
matrix = osgNew osg::Matrix;
}
else
{
matrix = osgNew osg::Matrix(_matrixStack.back());
}
transform.getLocalToWorldMatrix(*matrix,this);
if (!_matrixStack.empty())
{
matrix->postMult(_matrixStack.back());
}
_matrixStack.push_back(*matrix);
_transformStack.push_back(&transform);
@@ -523,8 +588,6 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
{
if (titr->second._canBeApplied)
{
osg::ref_ptr<osg::Transform> transform = titr->first;
osg::ref_ptr<osg::Group> group = osgNew osg::Group;
group->setDataVariance(osg::Object::STATIC);
@@ -548,6 +611,342 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
_matrixStack.clear();
}
////////////////////////////////////////////////////////////////////////////
// Flatten static transforms
////////////////////////////////////////////////////////////////////////////
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode)
{
osg::Transform* transform = NULL;
if (!_transformStack.back()) transform = _transformStack.back();
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(transform,matrix);
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Billboard& billboard)
{
if (!_matrixStack.empty())
{
// register ourselves with the objectMap.
_objectMap[&billboard].add(_transformStack.back(),_matrixStack.back());
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::LOD& lod)
{
if (!_matrixStack.empty())
{
// register ourselves with the objectMap.
_objectMap[&lod].add(_transformStack.back(),_matrixStack.back());
}
traverse(lod);
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Transform& transform)
{
if (_ignoreDynamicTransforms && transform.getDataVariance()==osg::Object::DYNAMIC)
{
// simple traverse the children as if this Transform didn't exist.
traverse(transform);
}
else
{
if (!_matrixStack.empty())
{
_transformMap[&transform]._containsTransform=false;
}
osg::Matrix matrix;
transform.getLocalToWorldMatrix(matrix,this);
_matrixStack.push_back(matrix);
_transformStack.push_back(&transform);
// simple traverse the children as if this Transform didn't exist.
traverse(transform);
_transformStack.pop_back();
_matrixStack.pop_back();
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::doTransform(osg::Object* obj,osg::Matrix& matrix)
{
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(obj);
if (drawable)
{
TransformFunctor tf(matrix);
drawable->applyAttributeOperation(tf);
drawable->dirtyBound();
return;
}
osg::LOD* lod = dynamic_cast<osg::LOD*>(obj);
if (lod)
{
osg::Matrix matrix_no_trans = matrix;
matrix_no_trans.setTrans(0.0f,0.0f,0.0f);
osg::Vec3 v111(1.0f,1.0f,1.0f);
osg::Vec3 new_v111 = v111*matrix_no_trans;
float ratio = new_v111.length()/v111.length();
// move center point.
lod->setCenter(lod->getCenter()*matrix);
// adjust ranges to new scale.
for(unsigned int i=0;i<lod->getNumRanges();++i)
{
lod->setRange(i,lod->getRange(i)*ratio);
}
lod->dirtyBound();
return;
}
osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(obj);
if (billboard)
{
osg::Matrix matrix_no_trans = matrix;
matrix_no_trans.setTrans(0.0f,0.0f,0.0f);
TransformFunctor tf(matrix_no_trans);
osg::Vec3 axis = osg::Matrix::transform3x3(tf._im,billboard->getAxis());
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
}
billboard->dirtyBound();
return;
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::disableObject(ObjectMap::iterator itr)
{
if (itr==_objectMap.end())
{
// Euston we have a problem..
osg::notify(osg::WARN)<<"Warning: internal error Optimizer::RemoveLowestStaticTransformsVisitor::disableObject()"<<std::endl;
return;
}
if (itr->second._canBeApplied)
{
// we havn't been disabled yet so we need to disable,
itr->second._canBeApplied = false;
// and then inform everybody we have been disabled.
for(ObjectStruct::TransformSet::iterator titr = itr->second._transformSet.begin();
titr != itr->second._transformSet.end();
++titr)
{
disableTransform(*titr);
}
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform(osg::Transform* transform)
{
TransformMap::iterator itr=_transformMap.find(transform);
if (itr==_transformMap.end())
{
// Euston we have a problem..
osg::notify(osg::WARN)<<"Warning: internal error Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform()"<<std::endl;
return;
}
if (itr->second._canBeApplied)
{
// we havn't been disabled yet so we need to disable,
itr->second._canBeApplied = false;
// and then inform everybody we have been disabled.
for(TransformStruct::ObjectSet::iterator oitr = itr->second._objectSet.begin();
oitr != itr->second._objectSet.end();
++oitr)
{
disableObject(*oitr);
}
}
}
bool Optimizer::RemoveLowestStaticTransformsVisitor::removeTransforms()
{
// create the TransformMap from the ObjectMap
ObjectMap::iterator oitr;
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
osg::Object* object = oitr->first;
ObjectStruct& os = oitr->second;
for(ObjectStruct::TransformSet::iterator titr = os._transformSet.begin();
titr != os._transformSet.end();
++titr)
{
_transformMap[*titr].add(object);
}
}
for(TransformMap::iterator titr=_transformMap.begin();
titr!=_transformMap.end();
++titr)
{
TransformStruct& ts = titr->second;
if (ts._containsTransform)
{
disableTransform(titr->first);
}
}
// disable all the objects which have more than one matrix associated
// with them, and then disable all transforms which have an object associated
// them that can't be applied, and then disable all objects which have
// disabled transforms associated, recursing until all disabled
// associativity.
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
ObjectStruct& os = oitr->second;
if (os._canBeApplied)
{
if (os._moreThanOneMatrixRequired)
{
disableObject(oitr);
}
}
}
// transform the objects that can be applied.
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
osg::Object* object = oitr->first;
ObjectStruct& os = oitr->second;
if (os._canBeApplied)
{
doTransform(object,os._matrix);
}
}
bool transformsRemoved = false;
// clean up the transforms.
for(TransformMap::iterator titr=_transformMap.begin();
titr!=_transformMap.end();
++titr)
{
if (titr->second._canBeApplied && titr->first)
{
osg::ref_ptr<osg::Transform> transform = titr->first;
osg::ref_ptr<osg::Group> group = osgNew osg::Group;
group->setDataVariance(osg::Object::STATIC);
for(unsigned int i=0;i<transform->getNumChildren();++i)
{
for(unsigned int j=0;j<transform->getNumParents();++j)
{
group->addChild(transform->getChild(i));
}
}
for(int i2=transform->getNumParents()-1;i2>=0;--i2)
{
transform->getParent(i2)->replaceChild(transform.get(),group.get());
}
transformsRemoved = true;
}
}
_objectMap.clear();
_transformMap.clear();
_transformStack.clear();
_matrixStack.clear();
return transformsRemoved;
}
////////////////////////////////////////////////////////////////////////////
// RemoveEmptyNodes.
////////////////////////////////////////////////////////////////////////////
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Geode& geode)
{
if (geode.getNumParents()>0)
{
if (geode.getNumDrawables()==0) _redundentNodeList.insert(&geode);
}
}
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group)
{
if (group.getNumParents()>0)
{
if (group.getNumChildren()==0)
{
_redundentNodeList.insert(&group);
}
}
traverse(group);
}
void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes()
{
NodeList newEmptyGroups;
// keep iterator through until scene graph is cleaned of empty nodes.
while (!_redundentNodeList.empty())
{
for(NodeList::iterator itr=_redundentNodeList.begin();
itr!=_redundentNodeList.end();
++itr)
{
osg::Node* nodeToRemove = (*itr);
// take a copy of parents list since subsequent removes will modify the original one.
osg::Node::ParentList parents = nodeToRemove->getParents();
for(osg::Node::ParentList::iterator pitr=parents.begin();
pitr!=parents.end();
++pitr)
{
(*pitr)->removeChild(nodeToRemove);
if ((*pitr)->getNumChildren()==0) newEmptyGroups.insert(*pitr);
}
}
_redundentNodeList.clear();
_redundentNodeList.swap(newEmptyGroups);
}
}
////////////////////////////////////////////////////////////////////////////
// RemoveRedundentNodes.
@@ -555,24 +954,42 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Group& group)
{
if (typeid(group)==typeid(osg::Group))
if (group.getNumParents()>0)
{
if (group.getNumParents()>0 && group.getNumChildren()<=1)
if (group.getNumChildren()==1 && typeid(group)==typeid(osg::Group))
{
if (!group.getUserData() &&
!group.getAppCallback() &&
!group.getStateSet() &&
group.getNodeMask()==0xffffffff)
if (group.getNumParents()>0 && group.getNumChildren()<=1)
{
_redundentNodeList.insert(&group);
if (!group.getUserData() &&
!group.getAppCallback() &&
!group.getStateSet() &&
group.getNodeMask()==0xffffffff)
{
_redundentNodeList.insert(&group);
}
}
}
}
traverse(group);
}
void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Transform& transform)
{
if (transform.getNumParents()>0)
{
static osg::Matrix identity;
if (transform.getMatrix()==identity && transform.getDataVariance()==osg::Object::STATIC)
{
_redundentNodeList.insert(&transform);
}
}
traverse(transform);
}
void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
for(NodeList::iterator itr=_redundentNodeList.begin();
itr!=_redundentNodeList.end();
++itr)
@@ -582,17 +999,8 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
// take a copy of parents list since subsequent removes will modify the original one.
osg::Node::ParentList parents = group->getParents();
if (group->getNumChildren()==0)
{
for(osg::Node::ParentList::iterator pitr=parents.begin();
pitr!=parents.end();
++pitr)
{
(*pitr)->removeChild(group.get());
}
}
else if (group->getNumChildren()==1)
if (group->getNumChildren()==1)
{
osg::Node* child = group->getChild(0);
for(osg::Node::ParentList::iterator pitr=parents.begin();
@@ -601,14 +1009,13 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
(*pitr)->replaceChild(group.get(),child);
}
}
else // (group->getNumChildren()>1)
{
osg::notify(osg::WARN)<<"Warning: Optimizer::RemoveRedundentNodesVisitor has incorrectly assigned Group to remove."<<std::endl;
osg::notify(osg::WARN)<<" Safely ignoring remove operation for this group."<<std::endl;
}
}
else
{
std::cout<<"failed dynamic_cast"<<endl;
}
}
_redundentNodeList.clear();
@@ -616,7 +1023,6 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
////////////////////////////////////////////////////////////////////////////
// combine LOD's.
////////////////////////////////////////////////////////////////////////////

View File

@@ -48,20 +48,20 @@ void Tesselator::tesselate(osg::Vec3* coords,int numIndices, int* indices,InputB
{
init();
_coordVec.reserve(numIndices);
if (ibd==COUNTER_CLOCK_WISE)
{
if (ibd==COUNTER_CLOCK_WISE)
{
for(int i=0;i<numIndices;++i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
else
else
{
for(int i=numIndices-1;i>=0;--i)
{
for(int i=numIndices-1;i>=0;--i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
}
do_it();
}