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

@@ -274,66 +274,73 @@ To get full details of make options, type:
<br>
<hr>
<h3>
<a NAME="Mac OSX"></a><u>Compiling under MacOS X (instructions written
by Phil Atkin)</u></h3>
For anyone who's ever used a Unix box for development it really is so simple
it's insane.
<p>You need to have installed the Developer tools from the CD that comes
<a NAME="Mac OSX"></a><u>Compiling under MacOS X</u></h3>
For anyone who's ever used a Unix box for development, well, the mac
<i>is</i> a Unix box. It's very simple to get OpenSceneGraph building
and running under Mac OS X. The main requirement is that you need to have
installed the Developer tools from the CD that comes
for free with OS X. This gives you compilers, headers, frameworks - stuff
like GLUT and Carbon for developers.
<p>Everything is done command-line, so you need to get to the underlying
OS rather than the Aqua gloss. The Mac comes with an app in Applications/Utilities
like GLUT and Carbon for developers. Get those here:
<ul>
<li> The Apple <a href="http://developer.apple.com/tools/macosxtools.html">
developer tools website</a>.
</ul>
<p>Everything is done command-line, so you need to get to a shell before
proceeding. The Mac comes with an app in Applications/Utilities
called Terminal - open up any Finder window (e.g double-click on your hard
disk icon), click on the Applications icon at the top right of the window,
then click on the Utilities folder to get access to all the grubby apps
which give away the real OS roots underneath the shiny paint work. Anyone
developing will need Terminal so much they should put it in their Dock.
You do that by grabbing the icon of the app in the Utilities folder and
dragging it to the bottom of your screen, at which point the other app
icons in the Dock slide away to leave a gap which when you release the
mouse button leaves Terminal permanently available, just a mouse click
away on your desktop. When you start Terminal it brings you up a csh running
under Darwin (which is the BSD-with-knobs-on that underlies OS X), and
does a cd to ~ (otherwise /Users/username of whoever you are logged in
as, as far as the Finder in OS X is concerned you are in the Users/username
folder of the harddisk the machine booted from).
<p>Then you are in Unix land, and it's all very familiar.
<p>You will need a .cshrc file with $OSGHOME (as above), and this is a
filename that the Mac won't let you see from the Finder or in fact generate
from an app, so I used vi to create that. Then I just went
<p>cd $OSGHOME
<blockquote><tt>% make clean</tt>
<br><tt>% make macosx</tt></blockquote>
then click on the Utilities folder to get access to the Terminal.
When you start Terminal it brings you up a csh running from your ~/ directory.
Now, go to your OpenSceneGraph directory, and simply type:
<p>
<blockquote>
<tt>make -j2</tt>
</blockquote>
<p><br>And it sounds too good to be true but it is that simple. It's worth
doing some editing on the Makefiles in the Plugins and Demos directories
so that it only tries to build a subset, otherwise the developer will have
to dig out the support projects like jpeg etc. I have only built up to
now sgv, hangglide, osgcube, osgreflect, osgviews and in the Plugins have
built osg rgb 3ds and a couple others - will check and get back to you.
<p><u>Tricky bit :</u>
<p>Installing the libdl.a is more trouble, as you have to enable the root
account on the machine, which by default is switched off as the machines
ship for security reasons. Rather than typing in and risking error through
paraphrase, here is a link to a site which tells you how to do this -
<blockquote><a href="http://www.macos.utah.edu/Documentation/macosx/security/enablerootuser.html">http://www.macos.utah.edu/Documentation/macosx/security/enablerootuser.html</a></blockquote>
Or alternately,
<blockquote><a href="http://www.thinkmacintosh.com/osxfaq.html">http://www.thinkmacintosh.com/osxfaq.html</a></blockquote>
And some time later you'll be rewarded with a lovely set of binaries and
libraries. The Mac OSX build currently only builds a subset of the total
functionality in OpenSceneGraph, but a large subset at that. Some of
the remaining projects are known to build as well, but have external
dependencies on libraries such as libtiff, libjpg, libpng, etc. and
so are not included in the default build. However, if you examine
the file <tt>OpenSceneGraph/Make/makedefs</tt> you will find which extra
projects build for the mac, provided you have the external libraries
required. Details
on how to install these external libraries are outside the scope of
this document, but for starting points, see one of:
<ul>
<li> The <a href="http://fink.sourceforge.net">fink project</a>.
<li> The <a href="http://gnu-darwin.sourceforge.net/">GNU-Darwin project</a>.
</ul>
<h4> Running the examples </h4>
Once you've got OpenSceneGraph built, you're ready to run your examples.
As with other builds on other platforms, OpenSceneGraph requires
you to set a few environment variables which describe your installation. These
environment variables should be full-path, not relative, and a list
of these for a csh-derived environment follow:
<blockquote>
<tt>
setenv OSGHOME `pwd`/OpenSceneGraph <br>
setenv OSGFILEPATH `pwd`/OpenSceneGraph-Data <br>
setenv OSG_LD_LIBRARY_PATH ${OSGHOME}/lib <br>
setenv DYLD_LIBRARY_PATH ${OSG_LD_LIBRARY_PATH} <br>
</tt>
</blockquote>
<h4> Notes </h4>
<ul>
<li> <b>Input Focus</b>: Many OSG examples have keyboard commands, however, when launching
apps from the Mac Terminal, the focus seems to remain in the Terminal. Option-Clicking on
the graphics window focuses it as the recipient of events, and allows these keyboard commands
to then function properly.
<li> <b>Known Bugs</b>:
<li> <b>Installation</b>: No package based version of an OS X installer yet exists.
</ul>
<p><br>One you have a root account enabled, you have to su root you cd
to the directory which the Fink installer generates, and it puts libdl.a
and the associated .h files in sensible system places so the compiler just
finds them.
<p>There is one oddball problem - if you rely on Path to find the resulting
executables, a weird Core Graphics error occurs - so even though I set
up my path to include $(OSGHOME)/bin, and when I cd to $OSGHOME and type
for example hangglide, the application starts fine (so it is in the path),
but at the point it tries to use GLUT to open a window it falls over with
a CGS error (which is I think Core Graphics System). If you explicitly
go bin/hangglide it works fine. Weird, it may be an OS X 10.04 issue which
is gone in 10.1 or it may be a weirdy in the Mac GLUT implementation, but
forewarned is forearmed.&nbsp;
<hr>
<h3>
<a NAME="Cygwin"></a><u>Compiling under Cygwin</u></h3>
To compile, from the OSG root directory, type: make Note, make should automatically

View File

@@ -58,9 +58,10 @@ class SG_EXPORT Array : public Object
Type getType() const { return _arrayType; }
GLint dataSize() const { return _dataSize; }
GLenum dataType() const { return _dataType; }
virtual const GLvoid* dataPointer() const = 0;
GLint getDataSize() const { return _dataSize; }
GLenum getDataType() const { return _dataType; }
virtual const GLvoid* getDataPointer() const = 0;
virtual unsigned int getNumElements() const = 0;
protected:
@@ -101,7 +102,8 @@ class TemplateArray : public Array, public std::vector<T>
virtual Object* clone(const CopyOp& copyop) const { return osgNew TemplateArray(*this,copyop); }
virtual void accept(ArrayVisitor& av) { av.apply(*this); }
virtual const GLvoid* dataPointer() const { if (!empty()) return &front(); else return 0; }
virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; }
virtual unsigned int getNumElements() const { return size(); }
protected:

View File

@@ -54,13 +54,13 @@ class SG_EXPORT Geode : public Node
/** return the number of geoset's.*/
inline const int getNumDrawables() const { return _drawables.size(); }
inline const unsigned int getNumDrawables() const { return _drawables.size(); }
/** return geoset at position i.*/
inline Drawable* getDrawable( const int i ) { return _drawables[i].get(); }
inline Drawable* getDrawable( const unsigned int i ) { return _drawables[i].get(); }
/** return geoset at position i.*/
inline const Drawable* getDrawable( const int i ) const { return _drawables[i].get(); }
inline const Drawable* getDrawable( const unsigned int i ) const { return _drawables[i].get(); }
/** return true if geoset is contained within Geode.*/
inline const bool containsDrawable(const Drawable* gset) const

View File

@@ -80,6 +80,10 @@ class SG_EXPORT Geometry : public Drawable
void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); dirtyDisplayList(); }
bool verifyBindings() const;
void computeCorrectBindingsAndArraySizes();
/** draw Geometry directly ignoring an OpenGL display list which could be attached.
* This is the internal draw method which does the drawing itself,

View File

@@ -124,6 +124,8 @@ class Primitive : public Object
virtual void draw() const = 0;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor&) {}
virtual void offsetIndices(int offset) = 0;
protected:
@@ -174,6 +176,8 @@ class SG_EXPORT DrawArrays : public Primitive
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor);
virtual void offsetIndices(int offset) { _first += offset; }
protected:
GLint _first;
@@ -223,6 +227,8 @@ class SG_EXPORT DrawArrayLengths : public Primitive, public VectorSizei
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor);
virtual void offsetIndices(int offset) { _first += offset; }
protected:
GLint _first;
@@ -261,6 +267,8 @@ class SG_EXPORT DrawElementsUByte : public Primitive, public VectorUByte
virtual void draw() const ;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor);
virtual void offsetIndices(int offset);
};
@@ -297,6 +305,8 @@ class SG_EXPORT DrawElementsUShort : public Primitive, public VectorUShort
virtual void draw() const;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor);
virtual void offsetIndices(int offset);
};
class SG_EXPORT DrawElementsUInt : public Primitive, public VectorUInt
@@ -333,6 +343,7 @@ class SG_EXPORT DrawElementsUInt : public Primitive, public VectorUInt
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor);
virtual void offsetIndices(int offset);
};
// backwards compatibility with first incarnation of DrawElements nameing convention.

View File

@@ -73,7 +73,7 @@ class OSGUTIL_EXPORT AppVisitor : public osg::NodeVisitor
else if (node.getNumChildrenRequiringAppTraversal()>0) traverse(node);
// call the app callbacks on the drawables.
for(int i=0;i<node.getNumDrawables();++i)
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
osg::Drawable::AppCallback* callback = node.getDrawable(i)->getAppCallback();
if (callback) callback->app(this,node.getDrawable(i));

View File

@@ -7,6 +7,7 @@
#include <osg/NodeVisitor>
#include <osg/Matrix>
#include <osg/Geometry>
#include <osgUtil/Export>
@@ -315,7 +316,22 @@ class OSGUTIL_EXPORT Optimizer
StateSetMap _statesets;
};
class OSGUTIL_EXPORT MergeGeometryVisitor : public osg::NodeVisitor
{
public:
/// default to traversing all children.
MergeGeometryVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Geode& geode) { mergeGeode(geode); }
virtual void apply(osg::Billboard& billboard) { /* don't do anything*/ }
static bool mergeGeode(osg::Geode& geode);
static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs);
};
};
}

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