Various fixes to the flt loader, and knock on changes to the osgUtil::Optimizer

to better support removal of seperate osg::Geometry instances where they
share the same state and bindings.
This commit is contained in:
Robert Osfield
2002-07-18 00:53:03 +00:00
parent 735b9d2318
commit 09bdb10af5
15 changed files with 609 additions and 230 deletions

View File

@@ -170,7 +170,7 @@ class InsertCallbacksVisitor : public osg::NodeVisitor
//If you wish to control the culling of drawables
//then use a drawable cullback...
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
geode.getDrawable(i)->setAppCallback(new DrawableAppCallback());
geode.getDrawable(i)->setCullCallback(new DrawableCullCallback());

View File

@@ -1,4 +1,5 @@
#include <osg/Geometry>
#include <osg/Notify>
using namespace osg;
@@ -40,12 +41,18 @@ Array* Geometry::getTexCoordArray(unsigned int unit)
else return 0;
}
const Array* Geometry::getTexCoordArray(unsigned int unit) const
{
if (unit<_texCoordList.size()) return _texCoordList[unit].get();
else return 0;
}
void Geometry::drawImmediateMode(State& state)
{
if (!_vertexArray.valid()) return;
// set up the vertex arrays.
state.setVertexPointer(3,GL_FLOAT,0,_vertexArray->dataPointer());
state.setVertexPointer(3,GL_FLOAT,0,_vertexArray->getDataPointer());
// set up texture coordinates.
unsigned int i;
@@ -53,7 +60,7 @@ void Geometry::drawImmediateMode(State& state)
{
Array* array = _texCoordList[i].get();
if (array)
state.setTexCoordPointer(i,array->dataSize(),array->dataType(),0,array->dataPointer());
state.setTexCoordPointer(i,array->getDataSize(),array->getDataType(),0,array->getDataPointer());
else
state.disableTexCoordPointer(i);
}
@@ -96,19 +103,19 @@ void Geometry::drawImmediateMode(State& state)
{
case(Array::UByte4ArrayType):
{
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->dataPointer());
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
colorStride = 4;
break;
}
case(Array::Vec3ArrayType):
{
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->dataPointer());
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
colorStride = 12;
break;
}
case(Array::Vec4ArrayType):
{
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->dataPointer());
colorPointer = reinterpret_cast<const unsigned char*>(_colorArray->getDataPointer());
colorStride = 16;
break;
}
@@ -146,7 +153,7 @@ void Geometry::drawImmediateMode(State& state)
state.disableColorPointer();
break;
case(BIND_PER_VERTEX):
if (colorPointer) state.setColorPointer(_colorArray->dataSize(),_colorArray->dataType(),0,colorPointer);
if (colorPointer) state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,colorPointer);
else state.disableColorPointer();
}
@@ -255,3 +262,148 @@ const bool Geometry::computeBound() const
return _bbox.valid();
}
bool Geometry::verifyBindings() const
{
switch(_normalBinding)
{
case(BIND_OFF):
if (_normalArray.valid() && _normalArray->getNumElements()>0) return false;
break;
case(BIND_OVERALL):
if (!_normalArray.valid()) return false;
if (_normalArray->getNumElements()!=1) return false;
break;
case(BIND_PER_PRIMITIVE):
if (!_normalArray.valid()) return false;
if (_normalArray->getNumElements()!=_primitives.size()) return false;
break;
case(BIND_PER_VERTEX):
if (_vertexArray.valid())
{
if (!_normalArray.valid()) return false;
if (_normalArray->getNumElements()!=_vertexArray->getNumElements()) return false;
}
else if (_normalArray.valid() && _normalArray->getNumElements()>0) return false;
break;
}
switch(_colorBinding)
{
case(BIND_OFF):
if (_colorArray.valid() && _colorArray->getNumElements()>0) return false;
break;
case(BIND_OVERALL):
if (!_colorArray.valid()) return false;
if (_colorArray->getNumElements()!=1) return false;
break;
case(BIND_PER_PRIMITIVE):
if (!_colorArray.valid()) return false;
if (_colorArray->getNumElements()!=_primitives.size()) return false;
break;
case(BIND_PER_VERTEX):
if (_vertexArray.valid())
{
if (!_colorArray.valid()) return false;
if (_colorArray->getNumElements()!=_vertexArray->getNumElements()) return false;
}
else if (_colorArray.valid() && _colorArray->getNumElements()>0) return false;
break;
}
for(TexCoordArrayList::const_iterator itr=_texCoordList.begin();
itr!=_texCoordList.end();
++itr)
{
const Array* array = itr->get();
if (_vertexArray.valid())
{
if (array && array->getNumElements()!=_vertexArray->getNumElements()) return false;
}
else if (array && array->getNumElements()>0) return false;
}
return true;
}
void Geometry::computeCorrectBindingsAndArraySizes()
{
if (verifyBindings()) return;
if (!_vertexArray.valid() || _vertexArray->empty())
{
// no vertex array so switch everything off.
_vertexArray = 0;
_colorArray = 0;
_colorBinding = BIND_OFF;
_normalArray = 0;
_normalBinding = BIND_OFF;
_texCoordList.clear();
notify(INFO)<<"Info: remove redundent attribute arrays from empty osg::Geometry"<<std::endl;
return;
}
switch(_normalBinding)
{
case(BIND_OFF):
if (_normalArray.valid()) _normalArray = 0;
break;
case(BIND_OVERALL):
if (!_normalArray.valid())
{
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()==0)
{
_normalArray = 0;
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()>1)
{
// trim the array down to 1 element long.
_normalArray->erase(_normalArray->begin()+1,_normalArray->end());
}
break;
case(BIND_PER_PRIMITIVE):
if (!_normalArray.valid())
{
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()<_primitives.size())
{
_normalArray = 0;
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()>_primitives.size())
{
// trim the array down to size of the number of primitives.
_normalArray->erase(_normalArray->begin()+_primitives.size(),_normalArray->end());
}
break;
case(BIND_PER_VERTEX):
if (!_normalArray.valid())
{
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()<_vertexArray->getNumElements())
{
_normalArray = 0;
_normalBinding = BIND_OFF;
}
else if (_normalArray->getNumElements()>_vertexArray->getNumElements())
{
// trim the array down to size of the number of primitives.
_normalArray->erase(_normalArray->begin()+_vertexArray->getNumElements(),_normalArray->end());
}
break;
}
// TODO colours and tex coords.
}

View File

@@ -48,6 +48,16 @@ void DrawElementsUByte::applyPrimitiveOperation(Drawable::PrimitiveFunctor& func
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUByte::offsetIndices(int offset)
{
for(iterator itr=begin();
itr!=end();
++itr)
{
*itr += offset;
}
}
void DrawElementsUShort::draw() const
{
@@ -59,6 +69,15 @@ void DrawElementsUShort::applyPrimitiveOperation(Drawable::PrimitiveFunctor& fun
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUShort::offsetIndices(int offset)
{
for(iterator itr=begin();
itr!=end();
++itr)
{
*itr += offset;
}
}
void DrawElementsUInt::draw() const
@@ -70,3 +89,13 @@ void DrawElementsUInt::applyPrimitiveOperation(Drawable::PrimitiveFunctor& funct
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUInt::offsetIndices(int offset)
{
for(iterator itr=begin();
itr!=end();
++itr)
{
*itr += offset;
}
}

View File

@@ -49,39 +49,39 @@ void DynGeoSet::append(DynGeoSet* source)
{
APPEND_DynGeoSet_List(_primLenList)
APPEND_DynGeoSet_List(_coordList)
APPEND_DynGeoSet_List(_normalList)
APPEND_DynGeoSet_List(_colorList)
APPEND_DynGeoSet_List(_tcoordList)
if (_normal_binding==osg::Geometry::BIND_PER_VERTEX || _normal_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_normalList)
if (_color_binding==osg::Geometry::BIND_PER_VERTEX || _color_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_colorList)
if (_texture_binding==osg::Geometry::BIND_PER_VERTEX || _texture_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_tcoordList)
}
#define VERIFY_DynGeoSet_Binding(binding,list) \
switch (binding) \
{ \
case osg::GeoSet::BIND_PERVERTEX: \
case osg::Geometry::BIND_PER_VERTEX: \
if (list.size() < _coordList.size()) { \
binding = osg::GeoSet::BIND_OFF; \
binding = osg::Geometry::BIND_OFF; \
list.clear(); } \
break; \
case osg::GeoSet::BIND_PERPRIM: \
case osg::Geometry::BIND_PER_PRIMITIVE: \
if (list.size() < _primLenList.size()) { \
binding = osg::GeoSet::BIND_OFF; \
binding = osg::Geometry::BIND_OFF; \
list.clear(); } \
break; \
case osg::GeoSet::BIND_OVERALL: \
case osg::Geometry::BIND_OVERALL: \
if (list.size() < 1) { \
binding = osg::GeoSet::BIND_OFF; \
binding = osg::Geometry::BIND_OFF; \
list.clear(); } \
break; \
default: \
break; \
}
DynGeoSet::DynGeoSet():osg::GeoSet()
const osg::Primitive::Mode NO_PRIMITIVE_TYPE = (osg::Primitive::Mode)0xffff;
DynGeoSet::DynGeoSet()
{
// disable the attribute delete functor since the vectors contained in DynGeoSet
// will delete the memory for us.
_adf = NULL;
_primtype=NO_PRIMITIVE_TYPE;
}
void DynGeoSet::setBinding()
@@ -98,38 +98,13 @@ void DynGeoSet::setBinding()
osg::StateSet* stateset = getStateSet();
if (stateset)
{
if (_normal_binding == osg::GeoSet::BIND_OFF)
if (_normal_binding == osg::Geometry::BIND_OFF)
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
}
}
bool DynGeoSet::setLists()
{
if ((_primLenList.size() > 0) && (_coordList.size() > 0))
{
setPrimLengths(&_primLenList.front());
setCoords(&_coordList.front());
if ((_normalList.size() > 0)
&& (getNormalBinding() != osg::GeoSet::BIND_OFF))
setNormals(&_normalList.front());
if ((_colorList.size() > 0)
&& (getColorBinding() != osg::GeoSet::BIND_OFF))
setColors(&_colorList.front());
if ((_tcoordList.size() > 0)
&& (getTextureBinding() != osg::GeoSet::BIND_OFF))
setTextureCoords(&_tcoordList.front());
return true;
}
return false;
}
void DynGeoSet::addToGeometry(osg::Geometry* geom)
{
int indexBase = 0;
@@ -153,7 +128,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
osg::Vec3Array* normals = geom->getNormalArray();
if (normals)
{
if (_normal_binding==osg::GeoSet::BIND_PERVERTEX || _normal_binding==osg::GeoSet::BIND_PERPRIM)
if (_normal_binding==osg::Geometry::BIND_PER_VERTEX || _normal_binding==osg::Geometry::BIND_PER_PRIMITIVE)
normals->insert(normals->end(),_normalList.begin(),_normalList.end());
}
else
@@ -163,9 +138,9 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
switch(_normal_binding)
{
case(osg::GeoSet::BIND_OVERALL):geom->setNormalBinding(osg::Geometry::BIND_OVERALL);break;
case(osg::GeoSet::BIND_PERVERTEX):geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);break;
case(osg::GeoSet::BIND_PERPRIM):geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);break;
case(osg::Geometry::BIND_OVERALL):geom->setNormalBinding(osg::Geometry::BIND_OVERALL);break;
case(osg::Geometry::BIND_PER_VERTEX):geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);break;
case(osg::Geometry::BIND_PER_PRIMITIVE):geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);break;
default:geom->setNormalBinding(osg::Geometry::BIND_OFF); break;
}
}
@@ -190,7 +165,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>(geom->getColorArray());
if (colors)
{
if (_color_binding==osg::GeoSet::BIND_PERVERTEX || _color_binding==osg::GeoSet::BIND_PERPRIM)
if (_color_binding==osg::Geometry::BIND_PER_VERTEX || _color_binding==osg::Geometry::BIND_PER_PRIMITIVE)
colors->insert(colors->end(),_colorList.begin(),_colorList.end());
}
else
@@ -200,29 +175,17 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
switch(_color_binding)
{
case(osg::GeoSet::BIND_OVERALL):geom->setColorBinding(osg::Geometry::BIND_OVERALL);break;
case(osg::GeoSet::BIND_PERVERTEX):geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);break;
case(osg::GeoSet::BIND_PERPRIM):geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);break;
case(osg::Geometry::BIND_OVERALL):geom->setColorBinding(osg::Geometry::BIND_OVERALL);break;
case(osg::Geometry::BIND_PER_VERTEX):geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);break;
case(osg::Geometry::BIND_PER_PRIMITIVE):geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);break;
default:geom->setColorBinding(osg::Geometry::BIND_OFF); break;
}
}
}
osg::Primitive::Mode mode = osg::Primitive::POLYGON;
switch(_primtype)
{
case(osg::GeoSet::POINTS):mode = osg::Primitive::POINTS; break;
case(osg::GeoSet::LINES):mode = osg::Primitive::LINES; break;
case(osg::GeoSet::TRIANGLES):mode = osg::Primitive::TRIANGLES; break;
case(osg::GeoSet::QUADS):mode = osg::Primitive::QUADS; break;
case(osg::GeoSet::POLYGON):mode = osg::Primitive::POLYGON; break;
default: mode = osg::Primitive::POLYGON;
}
}
if (mode!=osg::Primitive::POLYGON)
if (_primtype!=osg::Primitive::POLYGON)
{
geom->addPrimitive(new osg::DrawArrays(mode,indexBase,_coordList.size()));
geom->addPrimitive(new osg::DrawArrays(_primtype,indexBase,_coordList.size()));
}
else
{
@@ -230,7 +193,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom)
itr!=_primLenList.end();
++itr)
{
geom->addPrimitive(new osg::DrawArrays(mode,indexBase,*itr));
geom->addPrimitive(new osg::DrawArrays(_primtype,indexBase,*itr));
indexBase += *itr;
}
}
@@ -314,30 +277,12 @@ osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode)
}
osgUtil::Tesselator tesselator;
for(int i=0;i<geode->getNumDrawables();++i)
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
if (geom) tesselator.retesselatePolygons(*geom);
}
//Old GeoSet code.
// for(itr=_dynGeoSetList.begin();
// itr!=_dynGeoSetList.end();
// ++itr)
// {
// DynGeoSet* dgset = itr->get();
// if (dgset)
// {
// int prims = dgset->primLenListSize();
// if (prims > 0)
// {
// dgset->setLists();
// dgset->setNumPrims(prims);
// geode->addDrawable(dgset);
// }
// }
// }
return geode;
}
@@ -346,11 +291,13 @@ bool GeoSetBuilder::addPrimitive(bool dontMerge)
{
DynGeoSet* dgset = getDynGeoSet(); // This is the new geoset we want to add
if (dgset->getPrimType() == osg::GeoSet::NO_TYPE)
if (dgset->getPrimType()==NO_PRIMITIVE_TYPE)
{
dgset->setPrimType(findPrimType(dgset->coordListSize()));
}
// Still no primitive type?
if (dgset->getPrimType() == osg::GeoSet::NO_TYPE)
if (dgset->getPrimType()==NO_PRIMITIVE_TYPE)
return false;
dgset->setBinding();
@@ -389,18 +336,19 @@ DynGeoSet* GeoSetBuilder::findMatchingGeoSet()
}
osg::GeoSet::PrimitiveType GeoSetBuilder::findPrimType(const int nVertices)
osg::Primitive::Mode GeoSetBuilder::findPrimType(const int nVertices)
{
switch (nVertices)
{
case 1: return osg::GeoSet::POINTS;
case 2: return osg::GeoSet::LINES;
case 3: return osg::GeoSet::TRIANGLES;
case 4: return osg::GeoSet::QUADS;
case 1: return osg::Primitive::POINTS;
case 2: return osg::Primitive::LINES;
case 3: return osg::Primitive::TRIANGLES;
case 4: return osg::Primitive::QUADS;
}
if (nVertices >= 5) return osg::GeoSet::POLYGON;
return osg::GeoSet::NO_TYPE;
if (nVertices>=5) return osg::Primitive::POLYGON;
return NO_PRIMITIVE_TYPE;
}

View File

@@ -5,7 +5,6 @@
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Material>
@@ -27,7 +26,7 @@ class TmpGeoSet;
// DynGeoSet
//
////////////////////////////////////////////////////////////////////
#if 0
#if 1
# define COMPARE_DynGeoSet_Parameter(parameter) \
if (parameter<rhs.parameter) return -1; \
if (rhs.parameter<parameter) return 1;
@@ -37,10 +36,8 @@ class TmpGeoSet;
#endif
/** DynGeoSet - Dynamic GeoSet.
* Problem: osg::GeoSet use C arrays (static size) for coordinates,
* normals, colors and texture coordinates.
*/
class DynGeoSet : public osg::GeoSet
class DynGeoSet : public osg::Referenced
{
public:
@@ -52,11 +49,15 @@ class DynGeoSet : public osg::GeoSet
COMPARE_DynGeoSet_Parameter(_normal_binding)
COMPARE_DynGeoSet_Parameter(_texture_binding)
if ((_color_binding == osg::GeoSet::BIND_OVERALL)
&& (_colorList.size() >= 1) && (rhs._colorList.size() >= 1)
&& (_colorList[0] != rhs._colorList[0]))
return -1;
if (_color_binding == osg::Geometry::BIND_OVERALL)
{
if ((_colorList.size() >= 1) && (rhs._colorList.size() >= 1))
{
if (_colorList[0]<rhs._colorList[0]) return -1;
if (rhs._colorList[0]<_colorList[0]) return 1;
}
}
int result=getStateSet()->compare(*rhs.getStateSet(), true);
if (result!=0) return result;
@@ -66,18 +67,26 @@ class DynGeoSet : public osg::GeoSet
int compatible(const DynGeoSet& rhs) const
{
COMPARE_DynGeoSet_Parameter(_color_binding)
COMPARE_DynGeoSet_Parameter(_normal_binding)
COMPARE_DynGeoSet_Parameter(_texture_binding)
int result=getStateSet()->compare(*rhs.getStateSet(), true);
if (result!=0) return result;
if ((_color_binding == osg::GeoSet::BIND_OVERALL)
&& (_colorList.size() >= 1) && (rhs._colorList.size() >= 1)
&& (_colorList[0] != rhs._colorList[0]))
return -1;
COMPARE_DynGeoSet_Parameter(_normal_binding)
return 0;
if (_color_binding == osg::Geometry::BIND_OVERALL)
{
if ((_colorList.size() >= 1) && (rhs._colorList.size() >= 1))
{
if (_colorList[0]<rhs._colorList[0]) return -1;
if (rhs._colorList[0]<_colorList[0]) return 1;
}
}
return 0;
@@ -87,6 +96,21 @@ class DynGeoSet : public osg::GeoSet
bool operator == (const DynGeoSet& rhs) const { return compare(rhs)==0; }
bool operator != (const DynGeoSet& rhs) const { return compare(rhs)!=0; }
void setStateSet(osg::StateSet* stateset) { _stateset = stateset; }
osg::StateSet* getStateSet() { return _stateset.get(); }
const osg::StateSet* getStateSet() const { return _stateset.get(); }
void setColorBinding(osg::Geometry::AttributeBinding bind) { _color_binding = bind; }
void setNormalBinding(osg::Geometry::AttributeBinding bind) { _normal_binding = bind; }
void setTextureBinding(osg::Geometry::AttributeBinding bind) { _texture_binding = bind; }
osg::Geometry::AttributeBinding getColorBinding() const { return _color_binding; }
osg::Geometry::AttributeBinding getNormalBinding() const { return _normal_binding; }
osg::Geometry::AttributeBinding getTextureBinding() const { return _texture_binding; }
void setPrimType(osg::Primitive::Mode type) { _primtype=type; }
osg::Primitive::Mode getPrimType() const { return _primtype; }
inline void addPrimLen(const int len) { _primLenList.push_back(len); }
inline void addCoord(const osg::Vec3& coord) { _coordList.push_back(coord); }
inline void addNormal(const osg::Vec3& normal) { _normalList.push_back(normal); }
@@ -95,7 +119,6 @@ class DynGeoSet : public osg::GeoSet
void append(DynGeoSet* source);
void setBinding();
bool setLists();
void addToGeometry(osg::Geometry* geom);
@@ -113,11 +136,23 @@ class DynGeoSet : public osg::GeoSet
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<osg::Vec2> TcoordList;
PrimLenList _primLenList;
CoordList _coordList;
NormalList _normalList;
ColorList _colorList;
TcoordList _tcoordList;
osg::ref_ptr<osg::StateSet> _stateset;
osg::Primitive::Mode _primtype;
PrimLenList _primLenList;
CoordList _coordList;
osg::Geometry::AttributeBinding _normal_binding;
NormalList _normalList;
osg::Geometry::AttributeBinding _color_binding;
ColorList _colorList;
osg::Geometry::AttributeBinding _texture_binding;
TcoordList _tcoordList;
};
@@ -149,7 +184,7 @@ class GeoSetBuilder
void initPrimData();
DynGeoSet* findMatchingGeoSet();
osg::GeoSet::PrimitiveType findPrimType(const int nVertices);
osg::Primitive::Mode findPrimType(const int nVertices);
private:

View File

@@ -7,7 +7,6 @@
#include <osg/MatrixTransform>
#include <osg/Switch>
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/StateSet>
#include <osg/CullFace>
#include <osg/TexEnv>
@@ -672,16 +671,27 @@ osg::Group* ConvertFromFLT::visitSwitch(osg::Group& osgParent, SwitchRecord* rec
visitAncillary(osgParent, *group, rec)->addChild( group );
visitPrimaryNode(*group, (PrimNodeRecord*)rec);
for(int nChild=0; nChild<rec->getNumChildren(); nChild++)
for(unsigned int nChild=0; nChild<(unsigned int)rec->getNumChildren(); nChild++)
{
int nMaskBit = nChild % 32;
int nMaskWord = pSSwitch->nCurrentMask * pSSwitch->nWordsInMask + nChild / 32;
unsigned int nMaskBit = nChild % 32;
unsigned int nMaskWord = pSSwitch->nCurrentMask * pSSwitch->nWordsInMask + nChild / 32;
if (!(pSSwitch->aMask[nMaskWord] & (uint32(1) << nMaskBit)))
{
osg::Node* node = group->getChild(nChild);
if (node)
node->setNodeMask(0);
if (nChild<group->getNumChildren())
{
osg::Node* node = group->getChild(nChild);
if (node)
node->setNodeMask(0);
}
else
{
osg::notify(osg::WARN)<<"Warning::OpenFlight loader has come across an incorrectly handled switch."<<std::endl;
osg::notify(osg::WARN)<<" The number of OpenFlight children ("<<rec->getNumChildren()<<") "<<std::endl;
osg::notify(osg::WARN)<<" exceeds the number convered to OSG ("<<group->getNumChildren()<<")"<<std::endl;
}
}
}
@@ -742,11 +752,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
break;
case FaceRecord::WIREFRAME_NOT_CLOSED:
dgset->setPrimType(osg::GeoSet::LINE_STRIP);
dgset->setPrimType(osg::Primitive::LINE_STRIP);
break;
case FaceRecord::WIREFRAME_CLOSED:
dgset->setPrimType(osg::GeoSet::LINE_LOOP);
dgset->setPrimType(osg::Primitive::LINE_LOOP);
break;
}
@@ -776,39 +786,39 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
case FaceRecord::FACE_COLOR:
// Use face color, not illuminated
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ );
dgset->setColorBinding( osg::Geometry::BIND_OVERALL /*BIND_PERPRIM*/ );
break;
case FaceRecord::VERTEX_COLOR:
// Use vertex colors, not illuminated
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
dgset->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
break;
case FaceRecord::FACE_COLOR_LIGHTING:
// Use face color and vertex normal
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL );
dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
dgset->setColorBinding( osg::Geometry::BIND_OVERALL );
dgset->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
break;
case FaceRecord::VERTEX_COLOR_LIGHTING:
// Use vertex color and vertex normal
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON );
dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX );
dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
dgset->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
dgset->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
break;
default :
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL );
dgset->setColorBinding( osg::Geometry::BIND_OVERALL );
break;
}
}
else // Version 11, 12 & 13
{
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ );
dgset->setColorBinding( osg::Geometry::BIND_OVERALL /*BIND_PERPRIM*/ );
}
@@ -857,8 +867,8 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
_faceColor[3] = 1.0f - ((float)pSFace->wTransparency / 65535.0f);
if (pSFace->wTransparency > 0) bBlend = true;
if ((dgset->getColorBinding() == osg::GeoSet::BIND_OVERALL)
|| (dgset->getColorBinding() == osg::GeoSet::BIND_PERPRIM))
if ((dgset->getColorBinding() == osg::Geometry::BIND_OVERALL)
|| (dgset->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE))
dgset->addColor(_faceColor);
//
@@ -974,7 +984,7 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
}
#endif
dgset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
dgset->setTextureBinding(osg::Geometry::BIND_PER_VERTEX);
}
}
}
@@ -1050,7 +1060,7 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec
if (vertices > 0)
{
if (dgset->getPrimType() == osg::GeoSet::POINTS)
if (dgset->getPrimType() == osg::Primitive::POINTS)
{
for (i=0; i < vertices; i++)
dgset->addPrimLen(1);
@@ -1095,7 +1105,7 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
@@ -1107,9 +1117,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_NORMAL(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
@@ -1120,11 +1130,11 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_NORMAL(dgset, pVert)
if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_TCOORD(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
@@ -1135,9 +1145,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z());
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_TCOORD(dgset, pVert)
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
}
break;
@@ -1148,7 +1158,7 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX)
&& (rec->getSize() >= sizeof(SOldVertex)))
ADD_OLD_TCOORD(dgset, pVert)
}
@@ -1160,9 +1170,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX)
&& (rec->getSize() >= sizeof(SOldVertexColor)))
ADD_OLD_TCOORD(dgset, pVert)
}
@@ -1174,15 +1184,15 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]);
coord *= (float)_unitScale;
dgset->addCoord(coord);
if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX)
{
osg::Vec3 normal(pVert->n[0], pVert->n[1], pVert->n[2]);
normal /= (float)(1L<<30);
dgset->addNormal(normal);
}
if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool())
if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX)
if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX)
&& (rec->getSize() >= sizeof(SOldVertexColorNormal)))
ADD_OLD_TCOORD(dgset, pVert)
}
@@ -1249,10 +1259,10 @@ void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord*
osg::StateSet* stateSet = dgset->getStateSet();
SLightPoint *pSLightPoint = (SLightPoint*)rec->getData();
dgset->setPrimType(osg::GeoSet::POINTS);
dgset->setPrimType(osg::Primitive::POINTS);
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
dgset->setColorBinding(osg::GeoSet::BIND_PERVERTEX);
dgset->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
osg::Point* point = new osg::Point;
if (point)

View File

@@ -250,7 +250,7 @@ void CullVisitor::apply(Geode& node)
if (node_state) pushStateSet(node_state);
Matrix& matrix = getModelViewMatrix();
for(int i=0;i<node.getNumDrawables();++i)
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
Drawable* drawable = node.getDrawable(i);
const BoundingBox &bb =drawable->getBound();
@@ -316,7 +316,7 @@ void CullVisitor::apply(Billboard& node)
const Vec3& eye_local = getEyeLocal();
const Matrix& modelview = getModelViewMatrix();
for(int i=0;i<node.getNumDrawables();++i)
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
const Vec3& pos = node.getPos(i);

View File

@@ -82,9 +82,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
StateVisitor osv;
node->accept(osv);
osv.optimize();
MergeGeometryVisitor mgv;
node->accept(mgv);
#endif
}
@@ -138,7 +140,7 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor
void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode)
{
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::GeoSet* geoset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (geoset)
@@ -204,7 +206,7 @@ void Optimizer::StateVisitor::apply(osg::Geode& geode)
{
osg::StateSet* ss = geode.getStateSet();
if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,&geode);
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Drawable* drawable = geode.getDrawable(i);
if (drawable)
@@ -385,7 +387,7 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geode& geode)
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(_transformStack,matrix);
@@ -493,7 +495,7 @@ void Optimizer::FlattenStaticTransformsVisitor::doTransform(osg::Object* obj,osg
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
for(unsigned int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
@@ -650,7 +652,7 @@ void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode)
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(transform,matrix);
@@ -755,7 +757,7 @@ void Optimizer::RemoveLowestStaticTransformsVisitor::doTransform(osg::Object* ob
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
for(unsigned int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
@@ -1162,3 +1164,166 @@ void Optimizer::CombineLODsVisitor::combineLODs()
_groupList.clear();
}
////////////////////////////////////////////////////////////////////////////
// code to merge geometry object which share, state, and attribute bindings.
////////////////////////////////////////////////////////////////////////////
struct LessGeometry
{
bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs)
{
if (lhs->getStateSet()<rhs->getStateSet()) return true;
if (rhs->getStateSet()<lhs->getStateSet()) return false;
if (lhs->getColorBinding()<rhs->getColorBinding()) return true;
if (rhs->getColorBinding()<lhs->getColorBinding()) return false;
if (lhs->getNormalBinding()<rhs->getNormalBinding()) return true;
if (rhs->getNormalBinding()<lhs->getNormalBinding()) return false;
if (lhs->getNumTexCoordArrays()<rhs->getNumTexCoordArrays()) return true;
if (rhs->getNumTexCoordArrays()<lhs->getNumTexCoordArrays()) return false;
// therefore lhs->getNumTexCoordArrays()==rhs->getNumTexCoordArrays()
for(unsigned int i=0;i<lhs->getNumTexCoordArrays();++i)
{
if (rhs->getTexCoordArray(i))
{
if (!lhs->getTexCoordArray(i)) return true;
}
else if (lhs->getTexCoordArray(i)) return false;
}
if (lhs->getNormalBinding()==osg::Geometry::BIND_OVERALL)
{
// assumes that the bindings and arrays are set up correctly, this
// should be the case after running computeCorrectBindingsAndArraySizes();
const osg::Vec3& lhs_normal = (*(lhs->getNormalArray()))[0];
const osg::Vec3& rhs_normal = (*(rhs->getNormalArray()))[0];
if (lhs_normal<rhs_normal) return true;
if (rhs_normal<lhs_normal) return false;
}
if (lhs->getColorBinding()==osg::Geometry::BIND_OVERALL)
{
if (lhs->getColorArray()->getType()<rhs->getColorArray()->getType()) return true;
if (rhs->getColorArray()->getType()<lhs->getColorArray()->getType()) return false;
}
return false;
}
};
bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode)
{
if (geode.getNumDrawables()<2) return false;
typedef std::vector<osg::Geometry*> DuplicateList;
typedef std::map<osg::Geometry*,DuplicateList,LessGeometry> GeometryDuplicateMap;
GeometryDuplicateMap geometryDuplicateMap;
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
if (geom)
{
geom->computeCorrectBindingsAndArraySizes();
geometryDuplicateMap[geom].push_back(geom);
}
}
for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin();
itr!=geometryDuplicateMap.end();
++itr)
{
if (itr->second.size()>1)
{
osg::Geometry* lhs = itr->second[0];
for(DuplicateList::iterator dupItr=itr->second.begin()+1;
dupItr!=itr->second.end();
++dupItr)
{
osg::Geometry* rhs = *dupItr;
if (mergeGeometry(*lhs,*rhs))
{
geode.removeDrawable(rhs);
static int co = 0;
osg::notify(osg::INFO)<<"merged and removed Geometry "<<++co<<std::endl;
}
}
}
}
return false;
}
bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs)
{
unsigned int base = 0;
if (lhs.getVertexArray() && rhs.getVertexArray())
{
base = lhs.getVertexArray()->size();
lhs.getVertexArray()->insert(lhs.getVertexArray()->end(),rhs.getVertexArray()->begin(),rhs.getVertexArray()->end());
}
else if (rhs.getVertexArray())
{
lhs.setVertexArray(rhs.getVertexArray());
}
if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL)
{
lhs.getNormalArray()->insert(lhs.getNormalArray()->end(),rhs.getNormalArray()->begin(),rhs.getNormalArray()->end());
}
else if (rhs.getNormalArray())
{
lhs.setNormalArray(rhs.getNormalArray());
}
if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL)
{
// we need to add the handling of the other array types...
osg::Vec4Array* col_lhs = dynamic_cast<osg::Vec4Array*>(lhs.getColorArray());
osg::Vec4Array* col_rhs = dynamic_cast<osg::Vec4Array*>(rhs.getColorArray());
if (col_lhs && col_rhs)
{
col_lhs->insert(col_lhs->end(),col_rhs->begin(),col_rhs->end());
}
}
else if (rhs.getColorArray())
{
lhs.setColorArray(rhs.getColorArray());
}
for(unsigned int unit=0;unit<lhs.getNumTexCoordArrays();++unit)
{
// we need to add the handling of the other array types...
osg::Vec2Array* tex_lhs = dynamic_cast<osg::Vec2Array*>(lhs.getTexCoordArray(unit));
osg::Vec2Array* tex_rhs = dynamic_cast<osg::Vec2Array*>(rhs.getTexCoordArray(unit));
if (tex_lhs && tex_rhs)
{
tex_lhs->insert(tex_lhs->end(),tex_rhs->begin(),tex_rhs->end());
}
}
// shift the indices of the incomming primitives to account for the pre exisiting geometry.
for(osg::Geometry::PrimitiveList::iterator primItr=rhs.getPrimitiveList().begin();
primItr!=rhs.getPrimitiveList().end();
++primItr)
{
osg::Primitive* primitive = primItr->get();
primitive->offsetIndices(base);
}
lhs.getPrimitiveList().insert(lhs.getPrimitiveList().end(),rhs.getPrimitiveList().begin(),rhs.getPrimitiveList().end());
return true;
}