o Added osgUtil::StateOptimizeVisitor which traversing the scene

graph and builds up a map of all StateAttributes and StateSets
    and then removes the duplicates. This promotes state sharing
    throughout the scene graph which inturn can significantly improve
    performance thanks to reduced state changing. Particularily
    effective on datasets where a great deal of duplicated state
exists.
  o Added pure virtual compare(const osg::StateAttribute&)
    method to osg::StateAttribute, and implemented it in all the
    subclasses from StateAttribute. Added <,== & != operator
    on StateAttribute and Matrix to support new StateOptimizeVisitor.
  o Added META_Object, META_Node and META_StateAttribute macros to
    Object, Node and StateAttribute respectively which define the
    standard pure virtual methods such as clone, className
    & isSameKindAs.  Changed all the appropriate header files to
    use these macro's rather define them in each header, these cleans
    up the headers considerably.
  o Corrected the implementation of osg::Light::getType so it correctly
    uses a unique type for each of the OpenGL lights (GL_LIGHT0..
    GL_LIGHT7 relates to osg::StateAttriburte::LIGHT_0..LIGHT_7.
  o Changed the definition of osg::StateStateAttribute::Type to
    is now a unsigned int rather than an enum, and have changed the
    name of the previous Type enum list to be Types.  This makes it
    more consistent with the difination of values found in
StateAttribute
    and also easier to extend with having to cast to an enum.
  o From Pail Fredrikson, updated Maitrx.new implemention which uses
    the same matrix orientation as the original Matrix implemention.
This commit is contained in:
Don BURNS 2001-09-19 23:46:48 +00:00
parent 81f553aaee
commit 736e0f73c3
10 changed files with 419 additions and 0 deletions

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::COMPARE_StateAttribute_Parameter</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::COMPARE_StateAttribute_Parameter</A></H2><H2>(parameter)</H2><BLOCKQUOTE>COMPARE_StateAttribute_Parameter macro is a helper for implementing the StatateAtribute::compare() method.</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>COMPARE_StateAttribute_Parameter macro is a helper for implementing the StatateAtribute::compare() method.
Macro assumes that variable rhs has been corrected defined by code preceesing
macro.</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::COMPARE_StateAttribute_Types</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::COMPARE_StateAttribute_Types</A></H2><H2>(TYPE, rhs_attribute)</H2><BLOCKQUOTE>COMPARE_StateAttribute_Types macro is a helper for implementing the StatateAtribute::compare() method</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>COMPARE_StateAttribute_Types macro is a helper for implementing the StatateAtribute::compare() method</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::METANODE</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::METANODE</A></H2><H2>(name)</H2><BLOCKQUOTE>Use METAOBJ macro when subclassing from Node to make it more convinient to define the standard clone, isSameKindAs, className and accept methods which are required for all Node subclasses</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>Use METAOBJ macro when subclassing from Node to make it more
convinient to define the standard clone, isSameKindAs, className
and accept methods which are required for all Node subclasses</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::METAOBJ</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::METAOBJ</A></H2><H2>(name)</H2><BLOCKQUOTE>Use METAOBJ macro when subclassing from Object to make it more convinient to define the standard clone, isSameKindAs and className methods which are required for all Object subclasses</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>Use METAOBJ macro when subclassing from Object to make it more
convinient to define the standard clone, isSameKindAs and className
methods which are required for all Object subclasses</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::META_Node</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::META_Node</A></H2><H2>(name)</H2><BLOCKQUOTE>META_Node macro define the standard clone, isSameKindAs, className and accept methods.</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>META_Node macro define the standard clone, isSameKindAs, className
and accept methods. Use when subclassing from Node to make it
more convinient to define the required pure virtual methods.</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,23 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::META_Object</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::META_Object</A></H2><H2>(name)</H2><BLOCKQUOTE>META_Object macro define the standard clone, isSameKindAs and className methods.</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>META_Object macro define the standard clone, isSameKindAs and className methods.
Use when subclassing from Object to make it more convinient to define
the standard pure virtual clone, isSameKindAs and className methods
which are required for all Object subclasses.</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,24 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>#define osg::META_StateAttribute</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>#define <A HREF="#DOC.DOCU">osg::META_StateAttribute</A></H2><H2>(name, type)</H2><BLOCKQUOTE>META_StateAttribute macro define the standard clone, isSameKindAs, className and getType methods.</BLOCKQUOTE>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>META_StateAttribute macro define the standard clone, isSameKindAs,
className and getType methods.
Use when subclassing from Object to make it more convinient to define
the standard pure virtual methods which are required for all Object
subclasses.</BLOCKQUOTE>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,92 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>class OSGUTIL_EXPORT osgUtil::OptimizeStateVisitor</TITLE>
<META NAME="GENERATOR" CONTENT="DOC++ 3.4.8">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>class OSGUTIL_EXPORT <A HREF="#DOC.DOCU">osgUtil::OptimizeStateVisitor</A></H2></H2><BLOCKQUOTE>Insert impostor nodes into scene graph.</BLOCKQUOTE>
<HR>
<H2>Inheritance:</H2>
<APPLET CODE="ClassGraph.class" WIDTH=600 HEIGHT=65>
<param name=classes value="Mosg::NodeVisitor,M,COptimizeStateVisitor,MOptimizeStateVisitor.html">
<param name=before value="M,M">
<param name=after value="Md_,M">
<param name=indent value="0,1">
<param name=arrowdir value="down">
</APPLET>
<HR>
<DL>
<P><DL>
<DT><H3>Public Methods</H3><DD><DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif> <B><A HREF="#DOC.2.16.1">OptimizeStateVisitor</A></B>()
<DD><I>default to traversing all children</I>
<DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>virtual void <B><A HREF="#DOC.2.16.2">reset</A></B>()
<DD><I>empty visitor, make it ready for next traversal</I>
<DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>void <B><A HREF="#DOC.2.16.3">addStateSet</A></B>(osg::StateSet* stateset)
<DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>virtual void <B><A HREF="#DOC.2.16.4">apply</A></B>(osg::Node&amp; node)
<DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>virtual void <B><A HREF="#DOC.2.16.5">apply</A></B>(osg::Geode&amp; geode)
<DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>void <B><A HREF="#DOC.2.16.6">optimize</A></B>()
</DL></P>
<P><DL>
<DT><H3>Protected Members</H3><DD><DT>
<IMG ALT="[more]" BORDER=0 SRC=icon1.gif>typedef std::set&lt;osg::StateSet*&gt; StateSetList StateSetList <B><A HREF="#DOC.2.16.7">_statesets</A></B>
</DL></P>
</DL>
<A NAME="DOC.DOCU"></A>
<HR>
<H2>Documentation</H2>
<BLOCKQUOTE>Insert impostor nodes into scene graph.
For example of usage see src/Demos/osgimpostor.</BLOCKQUOTE>
<DL>
<A NAME="OptimizeStateVisitor"></A>
<A NAME="DOC.2.16.1"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B> OptimizeStateVisitor()</B></TT>
<DD>default to traversing all children
<DL><DT><DD></DL><P>
<A NAME="reset"></A>
<A NAME="DOC.2.16.2"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>virtual void reset()</B></TT>
<DD>empty visitor, make it ready for next traversal
<DL><DT><DD></DL><P>
<A NAME="addStateSet"></A>
<A NAME="DOC.2.16.3"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>void addStateSet(osg::StateSet* stateset)</B></TT>
<DL><DT><DD></DL><P>
<A NAME="apply"></A>
<A NAME="DOC.2.16.4"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>virtual void apply(osg::Node&amp; node)</B></TT>
<DL><DT><DD></DL><P>
<A NAME="apply"></A>
<A NAME="DOC.2.16.5"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>virtual void apply(osg::Geode&amp; geode)</B></TT>
<DL><DT><DD></DL><P>
<A NAME="optimize"></A>
<A NAME="DOC.2.16.6"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>void optimize()</B></TT>
<DL><DT><DD></DL><P>
<A NAME="_statesets"></A>
<A NAME="DOC.2.16.7"></A>
<DT><IMG ALT="o" BORDER=0 SRC=icon2.gif><TT><B>typedef std::set&lt;osg::StateSet*&gt; StateSetList StateSetList _statesets</B></TT>
<DL><DT><DD></DL><P></DL>
<HR><DL><DT><B>This class has no child classes.</B></DL>
<DL><DT><DD></DL><P><P><I><A HREF="index.html">Alphabetic index</A></I> <I><A HREF="HIER.html">HTML hierarchy of classes</A> or <A HREF="HIERjava.html">Java</A></I></P><HR>
<BR>
This page was generated with the help of <A HREF="http://docpp.sourceforge.net">DOC++</A>.
</BODY>
</HTML>

View File

@ -0,0 +1,40 @@
#ifndef OSGUTIL_OPTIMIZESTATEVISITOR
#define OSGUTIL_OPTIMIZESTATEVISITOR
#include <osg/NodeVisitor>
#include <osgUtil/Export>
namespace osgUtil {
/** Insert impostor nodes into scene graph.
* For example of usage see src/Demos/osgimpostor.
*/
class OSGUTIL_EXPORT OptimizeStateVisitor : public osg::NodeVisitor
{
public:
/// default to traversing all children.
OptimizeStateVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
/** empty visitor, make it ready for next traversal.*/
virtual void reset();
void addStateSet(osg::StateSet* stateset);
virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& geode);
void optimize();
protected:
typedef std::set<osg::StateSet*> StateSetList;
StateSetList _statesets;
};
};
#endif

View File

@ -0,0 +1,132 @@
#include <osg/Notify>
#include <osg/Geode>
#include <osgUtil/OptimizeStateVisitor>
#include <typeinfo>
#include <algorithm>
using namespace osgUtil;
struct LessAttributeFunctor
{
bool operator () (const osg::StateAttribute* lhs,const osg::StateAttribute* rhs) const
{
return (*lhs<*rhs);
}
};
/*
struct LessStateSetFunctor
{
bool operator () (const osg::StateSet* lhs,const osg::StateSet* rhs) const
{
return (*lhs<*rhs);
}
};
*/
void OptimizeStateVisitor::reset()
{
_statesets.clear();
}
void OptimizeStateVisitor::addStateSet(osg::StateSet* stateset)
{
_statesets.insert(stateset);
}
void OptimizeStateVisitor::apply(osg::Node& node)
{
osg::StateSet* ss = node.getStateSet();
if (ss) addStateSet(ss);
traverse(node);
}
void OptimizeStateVisitor::apply(osg::Geode& geode)
{
osg::StateSet* ss = geode.getStateSet();
if (ss) addStateSet(ss);
for(int i=0;i<geode.getNumDrawables();++i)
{
ss = geode.getDrawable(i)->getStateSet();
if (ss) addStateSet(ss);
}
}
void OptimizeStateVisitor::optimize()
{
osg::notify(osg::INFO) << "Num of StateSet="<<_statesets.size()<<endl;
// create map from state attributes to stateset which contain them.
typedef std::map<osg::StateAttribute*,StateSetList> AttributeToStateSetMap;
AttributeToStateSetMap _attributeToStateSetMap;
// NOTE will need to track state attribute override value too.
for(StateSetList::iterator sitr=_statesets.begin();
sitr!=_statesets.end();
++sitr)
{
osg::StateSet::AttributeList& attributes = (*sitr)->getAttributeList();
for(osg::StateSet::AttributeList::iterator aitr= attributes.begin();
aitr!=attributes.end();
++aitr)
{
_attributeToStateSetMap[aitr->second.first.get()].insert(*sitr);
}
}
if (_attributeToStateSetMap.size()<2)
{
osg::notify(osg::INFO) << "Too few state attributes to optimize."<<endl;
return;
}
// create unique set of state attribute pointers.
typedef std::vector<osg::StateAttribute*> AttributeList;
AttributeList _attributeList;
for(AttributeToStateSetMap::iterator aitr=_attributeToStateSetMap.begin();
aitr!=_attributeToStateSetMap.end();
++aitr)
{
_attributeList.push_back(aitr->first);
}
// sort the attributes so that equal attributes sit along side each
// other.
std::sort(_attributeList.begin(),_attributeList.end(),LessAttributeFunctor());
osg::notify(osg::INFO) << "state attribute list"<<endl;
for(AttributeList::iterator aaitr = _attributeList.begin();
aaitr!=_attributeList.end();
++aaitr)
{
osg::notify(osg::INFO) << " "<<*aaitr << " "<<(*aaitr)->className()<<endl;
}
osg::notify(osg::INFO) << "searching for duplicates"<<endl;
// find the duplicates.
AttributeList::iterator first_unique = _attributeList.begin();
AttributeList::iterator current = first_unique; ++current;
for(; current!=_attributeList.end();++current)
{
if (**current==**first_unique)
{
osg::notify(osg::INFO) << " found duplicate "<<(*current)->className()<<" first="<<*first_unique<<" current="<<*current<<endl;
StateSetList& statesetlist = _attributeToStateSetMap[*current];
for(StateSetList::iterator sitr=statesetlist.begin();
sitr!=statesetlist.end();
++sitr)
{
osg::notify(osg::INFO) << " replace duplicate "<<*current<<" with "<<*first_unique<< endl;
osg::StateSet* stateset = *sitr;
stateset->setAttribute(*first_unique);
}
}
else first_unique = current;
}
}