More clean up for synch with 0.8.42

This commit is contained in:
Don BURNS
2001-09-19 21:19:47 +00:00
parent 2462c6273c
commit 7e81f6cfa6
292 changed files with 39673 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
#include "osg/Transform"
#include "osg/Geode"
#include "osg/LOD"
#include "osg/Billboard"
#include "osg/LightSource"
#include "osg/Impostor"
#include "osg/Notify"
#include "osgUtil/CullViewState"
#include <float.h>
using namespace osg;
using namespace osgUtil;
//#define USE_OLD_CULL
CullViewState::CullViewState()
{
_matrix = NULL;
_inverse = NULL;
_ratio2 = 0.002f*0.002f;
_bbCornerNear = 8; // note this is an error value, valid range is 0..7
_bbCornerFar = 8; // these error values are used to show a unset corner.
}
CullViewState::~CullViewState()
{
}

1209
src/osgUtil/CullVisitor.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
#include <osgUtil/DepthSortedBin>
#include <osgUtil/RenderStage>
#include <algorithm>
using namespace osg;
using namespace osgUtil;
// register a RenderStage prototype with the RenderBin prototype list.
RegisterRenderBinProxy<DepthSortedBin> s_registerDepthSortedBinProxy;
DepthSortedBin::DepthSortedBin()
{
_drawOrder = BACK_TO_FRONT;
}
DepthSortedBin::~DepthSortedBin()
{
}
void DepthSortedBin::reset()
{
RenderBin::reset();
_renderLeafList.clear();
}
struct DepthSortFunctor2
{
const bool operator() (const RenderLeaf* lhs,const RenderLeaf* rhs)
{
return (lhs->_depth<rhs->_depth);
}
};
void DepthSortedBin::sort_local()
{
_renderLeafList.clear();
int totalsize=0;
RenderGraphList::iterator itr;
for(itr=_renderGraphList.begin();
itr!=_renderGraphList.end();
++itr)
{
totalsize += (*itr)->_leaves.size();
}
_renderLeafList.reserve(totalsize);
// first copy all the leaves from the render graphs into the leaf list.
for(itr=_renderGraphList.begin();
itr!=_renderGraphList.end();
++itr)
{
for(RenderGraph::LeafList::iterator dw_itr = (*itr)->_leaves.begin();
dw_itr != (*itr)->_leaves.end();
++dw_itr)
{
_renderLeafList.push_back(dw_itr->get());
}
}
// now sort the list into acending depth order.
std::sort(_renderLeafList.begin(),_renderLeafList.end(),DepthSortFunctor2());
}
void DepthSortedBin::draw_local(osg::State& state,RenderLeaf*& previous)
{
if (_drawOrder==BACK_TO_FRONT)
{
// render the bin from back to front.
for(RenderLeafList::reverse_iterator itr= _renderLeafList.rbegin();
itr!= _renderLeafList.rend();
++itr)
{
RenderLeaf* rl = *itr;
rl->render(state,previous);
previous = rl;
}
}
else
{
// render the from front to back.
for(RenderLeafList::iterator itr= _renderLeafList.begin();
itr!= _renderLeafList.end();
++itr)
{
RenderLeaf* rl = *itr;
rl->render(state,previous);
previous = rl;
}
}
}

View File

@@ -0,0 +1,176 @@
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <osgUtil/InsertImpostorsVisitor>
#include <algorithm>
using namespace osg;
using namespace osgUtil;
InsertImpostorsVisitor::InsertImpostorsVisitor()
{
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
_impostorThresholdRatio = 10.0f;
_maximumNumNestedImpostors = 3;
_numNestedImpostors = 0;
}
void InsertImpostorsVisitor::reset()
{
_groupList.clear();
_lodList.clear();
_numNestedImpostors = 0;
}
void InsertImpostorsVisitor::apply(Node& node)
{
traverse(node);
}
void InsertImpostorsVisitor::apply(Group& node)
{
_groupList.push_back(&node);
++_numNestedImpostors;
if (_numNestedImpostors<_maximumNumNestedImpostors)
{
traverse(node);
}
--_numNestedImpostors;
}
void InsertImpostorsVisitor::apply(LOD& node)
{
_lodList.push_back(&node);
++_numNestedImpostors;
if (_numNestedImpostors<_maximumNumNestedImpostors)
{
traverse(node);
}
--_numNestedImpostors;
}
void InsertImpostorsVisitor::apply(Impostor& node)
{
++_numNestedImpostors;
if (_numNestedImpostors<_maximumNumNestedImpostors)
{
traverse(node);
}
--_numNestedImpostors;
}
/* insert the required impostors into the scene graph.*/
void InsertImpostorsVisitor::insertImpostors()
{
bool _insertImpostorsAboveGroups = true;
bool _replaceLODsByImpostors = true;
// handle group's
if (_insertImpostorsAboveGroups)
{
std::sort(_groupList.begin(),_groupList.end());
Group* previousGroup = NULL;
for(GroupList::iterator itr=_groupList.begin();
itr!=_groupList.end();
++itr)
{
Group* group = (*itr);
if (group!=previousGroup)
{
const BoundingSphere& bs = group->getBound();
if (bs.isValid())
{
// take a copy of the original parent list
// before we change it around by adding the group
// to an impostor.
Node::ParentList parentList = group->getParents();
Impostor* impostor = new Impostor;
// standard LOD settings
impostor->addChild(group);
impostor->setRange(0,0.0f);
impostor->setRange(1,1e7f);
impostor->setCenter(bs.center());
// impostor specfic settings.
impostor->setImpostorThresholdToBound(_impostorThresholdRatio);
// now replace the group by the new impostor in all of the
// group's original parent list.
for(Node::ParentList::iterator pitr=parentList.begin();
pitr!=parentList.end();
++pitr)
{
(*pitr)->replaceChild(group,impostor);
}
}
}
}
}
// handle LOD's
if (_replaceLODsByImpostors)
{
std::sort(_lodList.begin(),_lodList.end());
LOD* previousLOD = NULL;
for(LODList::iterator itr=_lodList.begin();
itr!=_lodList.end();
++itr)
{
osg::LOD* lod = (*itr);
if (lod!=previousLOD)
{
const osg::BoundingSphere& bs = lod->getBound();
if (bs.isValid())
{
// take a copy of the original parent list
// before we change it around by adding the lod
// to an impostor.
Node::ParentList parentList = lod->getParents();
osg::Impostor* impostor = new Impostor;
// standard LOD settings
for(int ci=0;ci<lod->getNumChildren();++ci)
{
impostor->addChild(lod->getChild(ci));
}
for(int ri=0;ri<lod->getNumRanges();++ri)
{
impostor->setRange(ri,lod->getRange(ri));
}
impostor->setCenter(lod->getCenter());
// impostor specfic settings.
impostor->setImpostorThresholdToBound(_impostorThresholdRatio);
// now replace the lod by the new impostor in all of the
// lod's original parent list.
for(Node::ParentList::iterator pitr=parentList.begin();
pitr!=parentList.end();
++pitr)
{
(*pitr)->replaceChild(lod,impostor);
}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,296 @@
#ifndef NV_TRISTRIP_OBJECTS_H
#define NV_TRISTRIP_OBJECTS_H
#include <assert.h>
#include <vector>
#include <list>
/////////////////////////////////////////////////////////////////////////////////
//
// Types defined for stripification
//
/////////////////////////////////////////////////////////////////////////////////
typedef int WORD;
typedef unsigned int UINT;
struct MyVertex
{
float x, y, z;
float nx, ny, nz;
};
typedef MyVertex MyVector;
struct MyFace
{
int v1, v2, v3;
float nx, ny, nz;
};
class VertexCache
{
public:
VertexCache(int size);
VertexCache();
~VertexCache();
bool InCache(int entry);
int AddEntry(int entry);
void Clear();
void Copy(VertexCache* inVcache);
int At(int index);
void Set(int index, int value);
private:
int *entries;
int numEntries;
};
inline bool VertexCache::InCache(int entry)
{
bool returnVal = false;
for(int i = 0; i < numEntries; i++)
{
if(entries[i] == entry)
{
returnVal = true;
break;
}
}
return returnVal;
}
inline int VertexCache::AddEntry(int entry)
{
int removed;
removed = entries[numEntries - 1];
//push everything right one
for(int i = numEntries - 2; i >= 0; i--)
{
entries[i + 1] = entries[i];
}
entries[0] = entry;
return removed;
}
class NvFaceInfo
{
public:
// vertex indices
NvFaceInfo(int v0, int v1, int v2)
{
m_v0 = v0; m_v1 = v1; m_v2 = v2;
m_stripId = -1;
m_testStripId = -1;
m_experimentId = -1;
}
// data members are left public
int m_v0, m_v1, m_v2;
int m_stripId; // real strip Id
int m_testStripId; // strip Id in an experiment
int m_experimentId; // in what experiment was it given an experiment Id?
};
// nice and dumb edge class that points knows its
// indices, the two faces, and the next edge using
// the lesser of the indices
class NvEdgeInfo
{
public:
// constructor puts 1 ref on us
NvEdgeInfo (int v0, int v1)
{
m_v0 = v0;
m_v1 = v1;
m_face0 = NULL;
m_face1 = NULL;
m_nextV0 = NULL;
m_nextV1 = NULL;
// we will appear in 2 lists. this is a good
// way to make sure we delete it the second time
// we hit it in the edge infos
m_refCount = 2;
}
// ref and unref
void Unref () { if (--m_refCount == 0) delete this; }
// data members are left public
UINT m_refCount;
NvFaceInfo *m_face0, *m_face1;
int m_v0, m_v1;
NvEdgeInfo *m_nextV0, *m_nextV1;
};
// This class is a quick summary of parameters used
// to begin a triangle strip. Some operations may
// want to create lists of such items, so they were
// pulled out into a class
class NvStripStartInfo
{
public:
NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1)
{
m_startFace = startFace;
m_startEdge = startEdge;
m_toV1 = toV1;
}
NvFaceInfo *m_startFace;
NvEdgeInfo *m_startEdge;
bool m_toV1;
};
typedef std::vector<NvFaceInfo*> NvFaceInfoVec;
typedef std::list <NvFaceInfo*> NvFaceInfoList;
typedef std::list <NvFaceInfoVec*> NvStripList;
typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec;
typedef std::vector<WORD> WordVec;
typedef std::vector<MyVertex> MyVertexVec;
typedef std::vector<MyFace> MyFaceVec;
// This is a summary of a strip that has been built
class NvStripInfo
{
public:
// A little information about the creation of the triangle strips
NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
m_startInfo(startInfo)
{
m_stripId = stripId;
m_experimentId = experimentId;
visited = false;
}
// This is an experiment if the experiment id is >= 0
inline bool IsExperiment () const { return m_experimentId >= 0; }
inline bool IsInStrip (const NvFaceInfo *faceInfo) const
{
if(faceInfo == NULL)
return false;
return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
}
bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
// take the given forward and backward strips and combine them together
void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
// mark the triangle as taken by this strip
bool IsMarked (NvFaceInfo *faceInfo);
void MarkTriangle(NvFaceInfo *faceInfo);
// build the strip
void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
// public data members
NvStripStartInfo m_startInfo;
NvFaceInfoVec m_faces;
int m_stripId;
int m_experimentId;
bool visited;
};
typedef std::vector<NvStripInfo*> NvStripInfoVec;
//The actual stripifier
class NvStripifier
{
public:
// Constructor
NvStripifier();
~NvStripifier();
//the target vertex cache size, the structure to place the strips in, and the input indices
void Stripify(const WordVec &in_indices, const int in_numVertices, const int in_cacheSize, const int in_minStripLength,
NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
static bool NextIsCW(const int numIndices);
static bool IsCW(NvFaceInfo *faceInfo, int v0, int v1);
void CreateStrips(NvStripInfoVec& strips,
NvFaceInfoVec& leftoverFaces,
WordVec& stripIndices);
void OptimizeVertices(NvStripInfoVec& strips,
NvFaceInfoVec& leftoverFaces,
WordVec& stripIndices,
MyVertexVec& vertices,
MyVertexVec& optimizedVerts);
protected:
WordVec indices;
int cacheSize;
unsigned int minStripLength;
float meshJump;
bool bFirstTimeResetPoint;
/////////////////////////////////////////////////////////////////////////////////
//
// Big mess of functions called during stripification
//
/////////////////////////////////////////////////////////////////////////////////
static int GetNextIndex(const WordVec &indices, NvFaceInfo *face);
static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end);
void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
float AvgStripSize(const NvStripInfoVec &strips);
int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const int numVertices);
bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
// let our strip info classes and the other classes get
// to these protected stripificaton methods if they want
friend NvStripInfo;
};
#endif

179
src/osgUtil/RenderBin.cpp Normal file
View File

@@ -0,0 +1,179 @@
#include <osgUtil/RenderBin>
#include <osgUtil/RenderStage>
using namespace osg;
using namespace osgUtil;
// register a RenderStage prototype with the RenderBin prototype list.
RegisterRenderBinProxy<RenderBin> s_registerRenderBinProxy;
typedef std::map< std::string, osg::ref_ptr<RenderBin> > RenderBinPrototypeList;
RenderBinPrototypeList* renderBinPrototypeList()
{
static RenderBinPrototypeList s_renderBinPrototypeList;
return &s_renderBinPrototypeList;
}
RenderBin* RenderBin::createRenderBin(const std::string& binName)
{
// cout << "creating RB "<<binName<<endl;
RenderBinPrototypeList::iterator itr = renderBinPrototypeList()->find(binName);
if (itr != renderBinPrototypeList()->end()) return dynamic_cast<RenderBin*>(itr->second->clone());
else return NULL;
}
void RenderBin::addRenderBinPrototype(RenderBin* proto)
{
if (proto)
{
(*renderBinPrototypeList())[proto->className()] = proto;
// cout << "Adding RB "<<proto->className()<<endl;
}
}
void RenderBin::removeRenderBinPrototype(RenderBin* proto)
{
if (proto)
{
RenderBinPrototypeList::iterator itr = renderBinPrototypeList()->find(proto->className());
if (itr != renderBinPrototypeList()->end()) renderBinPrototypeList()->erase(itr);
}
}
RenderBin::RenderBin()
{
_binNum = 0;
_parent = NULL;
_stage = NULL;
}
RenderBin::~RenderBin()
{
}
void RenderBin::reset()
{
_renderGraphList.clear();
_bins.clear();
}
void RenderBin::sort()
{
for(RenderBinList::iterator itr = _bins.begin();
itr!=_bins.end();
++itr)
{
itr->second->sort();
}
sort_local();
}
RenderBin* RenderBin::find_or_insert(int binNum,const std::string& binName)
{
// search for appropriate bin.
RenderBinList::iterator itr = _bins.find(binNum);
if (itr!=_bins.end()) return itr->second.get();
// create a renderin bin and insert into bin list.
RenderBin* rb = RenderBin::createRenderBin(binName);
if (rb)
{
RenderStage* rs = dynamic_cast<RenderStage*>(rb);
if (rs)
{
rs->_binNum = binNum;
rs->_parent = NULL;
rs->_stage = rs;
_stage->addToDependencyList(rs);
}
else
{
rb->_binNum = binNum;
rb->_parent = this;
rb->_stage = _stage;
_bins[binNum] = rb;
}
}
return rb;
}
void RenderBin::draw(osg::State& state,RenderLeaf*& previous)
{
// draw first set of draw bins.
RenderBinList::iterator itr;
for(itr = _bins.begin();
itr->first<0 && itr!=_bins.end();
++itr)
{
itr->second->draw(state,previous);
}
draw_local(state,previous);
for(;
itr!=_bins.end();
++itr)
{
itr->second->draw(state,previous);
}
}
void RenderBin::draw_local(osg::State& state,RenderLeaf*& previous)
{
// draw local bin.
for(RenderGraphList::iterator oitr=_renderGraphList.begin();
oitr!=_renderGraphList.end();
++oitr)
{
for(RenderGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin();
dw_itr != (*oitr)->_leaves.end();
++dw_itr)
{
RenderLeaf* rl = dw_itr->get();
rl->render(state,previous);
previous = rl;
}
}
}
// stats
#include <osg/GeoSet>
void RenderBin::getPrims(Statistics *primStats)
{
for(RenderBinList::iterator itr = _bins.begin();
itr!=_bins.end();
++itr)
{
primStats->nbins++;
}
for(RenderGraphList::iterator oitr=_renderGraphList.begin();
oitr!=_renderGraphList.end();
++oitr)
{
for(RenderGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin();
dw_itr != (*oitr)->_leaves.end();
++dw_itr)
{
RenderLeaf* rl = dw_itr->get();
Drawable* dw= rl->_drawable;
primStats->numOpaque++; // number of geosets
if (rl->_matrix.get()) primStats->nummat++; // number of matrices
if (dw) { // then tot up the types 1-14
GeoSet *gs=dynamic_cast<osg::GeoSet*>(dw);
if (gs)
{
primStats->addstat(gs);
// rl->getPrims(state,previous);??
// previous = rl;
}
}
}
}
}

View File

@@ -0,0 +1,62 @@
#include "osgUtil/RenderGraph"
#include "osg/Notify"
using namespace osg;
using namespace osgUtil;
void RenderGraph::reset()
{
_parent = NULL;
_stateset = NULL;
_depth = 0;
_children.clear();
_leaves.clear();
}
/** recursively clean the RenderGraph of all its drawables, lights and depths.
* Leaves children intact, and ready to be populated again.*/
void RenderGraph::clean()
{
// clean local drawables etc.
_leaves.clear();
// call clean on all children.
for(ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
itr->second->clean();
}
}
/** recursively prune the RenderGraph of empty children.*/
void RenderGraph::prune()
{
std::vector<const osg::StateSet*> toEraseList;
// call prune on all children.
for(ChildList::iterator citr=_children.begin();
citr!=_children.end();
++citr)
{
citr->second->prune();
if (citr->second->empty())
{
toEraseList.push_back(citr->first);
}
}
for(std::vector<const osg::StateSet*>::iterator eitr=toEraseList.begin();
eitr!=toEraseList.end();
++eitr)
{
_children.erase(*eitr);
}
}

View File

@@ -0,0 +1,63 @@
#include <osgUtil/RenderLeaf>
#include <osgUtil/RenderGraph>
using namespace osg;
using namespace osgUtil;
void RenderLeaf::render(State& state,RenderLeaf* previous)
{
if (previous)
{
RenderGraph* prev_rg = previous->_parent;
RenderGraph* prev_rg_parent = prev_rg->_parent;
RenderGraph* rg = _parent;
if (prev_rg_parent!=rg->_parent)
{
RenderGraph::moveRenderGraph(state,prev_rg_parent,rg->_parent);
// send state changes and matrix changes to OpenGL.
state.apply(rg->_stateset.get());
}
else if (rg!=prev_rg)
{
// send state changes and matrix changes to OpenGL.
state.apply(rg->_stateset.get());
}
Matrix* prev_matrix = previous->_matrix.get();
if (_matrix != prev_matrix)
{
if (prev_matrix) glPopMatrix();
if (_matrix.valid())
{
glPushMatrix();
glMultMatrixf((GLfloat*)_matrix->_mat);
}
}
_drawable->draw(state);
}
else
{
RenderGraph::moveRenderGraph(state,NULL,_parent->_parent);
// send state changes and matrix changes to OpenGL.
state.apply(_parent->_stateset.get());
if (_matrix.valid())
{
glPushMatrix();
glMultMatrixf((GLfloat*)_matrix->_mat);
}
_drawable->draw(state);
}
}

134
src/osgUtil/RenderStage.cpp Normal file
View File

@@ -0,0 +1,134 @@
#include <osgUtil/RenderStage>
using namespace osg;
using namespace osgUtil;
// register a RenderStage prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderStage> s_registerRenderStageProxy;
RenderStage::RenderStage()
{
// point RenderBin's _stage to this to ensure that references to
// stage don't go tempted away to any other stage.
_stage = this;
_stageDrawnThisFrame = false;
_clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
_clearColor.set(0.0f,0.0f,0.0f,0.0f);
_clearAccum.set(0.0f,0.0f,0.0f,0.0f);
_clearDepth = 1.0;
_clearStencil = 0;
}
RenderStage::~RenderStage()
{
}
void RenderStage::reset()
{
_dependencyList.clear();
_stageDrawnThisFrame = false;
if (_renderStageLighting.valid()) _renderStageLighting->reset();
RenderBin::reset();
}
void RenderStage::addToDependencyList(RenderStage* rs)
{
if (rs) _dependencyList.push_back(rs);
}
void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
{
if (_stageDrawnThisFrame) return;
_stageDrawnThisFrame = true;
for(DependencyList::iterator itr=_dependencyList.begin();
itr!=_dependencyList.end();
++itr)
{
(*itr)->draw(state,previous);
}
// set up the back buffer.
#define USE_SISSOR_TEST
#ifdef USE_SISSOR_TEST
glScissor( _view[0], _view[1], _view[2], _view[3] );
glEnable( GL_SCISSOR_TEST );
#endif
glViewport( _view[0], _view[1], _view[2], _view[3] );
// glEnable( GL_DEPTH_TEST );
if (_clearMask & GL_COLOR_BUFFER_BIT)
glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
if (_clearMask & GL_DEPTH_BUFFER_BIT)
glClearDepth( _clearDepth);
if (_clearMask & GL_STENCIL_BUFFER_BIT)
glClearStencil( _clearStencil);
if (_clearMask & GL_ACCUM_BUFFER_BIT)
glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
// clear a color bit planes - osg::ColorMask could also be used here.
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
glClear( _clearMask );
#ifdef USE_SISSOR_TEST
glDisable( GL_SCISSOR_TEST );
#endif
// set up projection
const Matrix& projectionMat = _camera->getProjectionMatrix();
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMultMatrixf((GLfloat*)projectionMat._mat);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
Light* light = getLight();
if (getLightingMode()==RenderStageLighting::HEADLIGHT && light)
{
light->apply(state);
}
// set up camera modelview.
const Matrix& modelView = _camera->getModelViewMatrix();
glMultMatrixf((GLfloat*)modelView._mat);
if (getLightingMode()==RenderStageLighting::SKY_LIGHT && light)
{
light->apply(state);
}
// apply the lights.
if (_renderStageLighting.valid()) _renderStageLighting->draw(state,previous);
// draw the children and local.
RenderBin::draw(state,previous);
// now reset the state so its back in its default state.
if (previous)
{
RenderGraph::moveToRootRenderGraph(state,previous->_parent);
state.apply();
if (previous->_matrix.valid()) glPopMatrix();
previous = NULL;
}
}
// Statistics features
void RenderStage::getPrims(Statistics *primStats)
{
if (_renderStageLighting.valid()) primStats->nlights+=_renderStageLighting->_lightList.size();
RenderBin::getPrims(primStats);
}

View File

@@ -0,0 +1,61 @@
#include <osgUtil/RenderStageLighting>
using namespace osg;
using namespace osgUtil;
// register a RenderStageLighting prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderStageLighting> s_registerRenderStageLightingProxy;
RenderStageLighting::RenderStageLighting()
{
}
RenderStageLighting::~RenderStageLighting()
{
}
void RenderStageLighting::reset()
{
_lightList.clear();
}
void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
{
if (previous)
{
RenderGraph::moveToRootRenderGraph(state,previous->_parent);
state.apply();
if (previous->_matrix.valid()) glPopMatrix();
previous = NULL;
}
Matrix* prev_matrix = NULL;
// apply the light list.
for(LightList::iterator litr=_lightList.begin();
litr!=_lightList.end();
++litr)
{
Matrix* matrix = (*litr).second.get();
if (matrix != prev_matrix)
{
if (prev_matrix) glPopMatrix();
if (matrix)
{
glPushMatrix();
glMultMatrixf((GLfloat*)matrix->_mat);
}
prev_matrix = matrix;
}
// apply the light source.
litr->first->apply(state);
}
// clean up matrix stack.
if (prev_matrix) glPopMatrix();
}

View File

@@ -0,0 +1,32 @@
#include <osgUtil/RenderToTextureStage>
#include <osgDB/ReadFile>
using namespace osg;
using namespace osgUtil;
// register a RenderToTextureStage prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderToTextureStage> s_registerRenderToTextureStageProxy;
RenderToTextureStage::RenderToTextureStage()
{
}
RenderToTextureStage::~RenderToTextureStage()
{
}
void RenderToTextureStage::reset()
{
RenderStage::reset();
}
void RenderToTextureStage::draw(osg::State& state,RenderLeaf*& previous)
{
RenderStage::draw(state,previous);
// now copy the rendered image to attached texture.
if (_texture.valid()) _texture->copyTexImage2D(state,_view[0],_view[1],_view[2],_view[3]);
}

View File

@@ -0,0 +1,39 @@
#include <osgUtil/SceneViewManipulator>
#include <osgUtil/TrackballManipulator>
using namespace osgUtil;
SceneViewManipulator::SceneViewManipulator():
_cm(new TrackballManipulator),
_gm(new StateSetManipulator)
{
}
SceneViewManipulator::~SceneViewManipulator()
{
}
void SceneViewManipulator::setSceneView(SceneView* sv)
{
_sv=sv;
_cm->setNode(sv->getSceneData());
_cm->setCamera(sv->getCamera());
_gm->setStateSet(sv->getGlobalState());
}
SceneView *SceneViewManipulator::getSceneView()
{
return _sv.get();
}
const SceneView *SceneViewManipulator::getSceneView() const
{
return _sv.get();
}
bool SceneViewManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
if(_cm->handle(ea,aa)) return true;
if(_gm->handle(ea,aa)) return true;
return false;
}

View File

@@ -0,0 +1,155 @@
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <stdio.h>
#include <list>
#include <set>
#include <osg/GeoSet>
#include <osgUtil/SmoothingVisitor>
using namespace osg;
using namespace osgUtil;
struct LessPtr
{
inline bool operator() (const osg::Vec3* lhs,const osg::Vec3* rhs) const
{
return *lhs<*rhs;
}
};
// triangle functor.
struct TriangleFunctor
{
osg::Vec3 *_coordBase;
osg::Vec3 *_normalBase;
typedef std::multiset<const osg::Vec3*,LessPtr> CoordinateSet;
CoordinateSet _coordSet;
TriangleFunctor(osg::Vec3 *cb,int noVertices, osg::Vec3 *nb) : _coordBase(cb),_normalBase(nb)
{
osg::Vec3* vptr = cb;
for(int i=0;i<noVertices;++i)
{
_coordSet.insert(vptr++);
}
}
inline void updateNormal(const osg::Vec3& normal,const osg::Vec3* vptr)
{
std::pair<CoordinateSet::iterator,CoordinateSet::iterator> p =
_coordSet.equal_range(vptr);
for(CoordinateSet::iterator itr=p.first;
itr!=p.second;
++itr)
{
osg::Vec3* nptr = _normalBase + (*itr-_coordBase);
(*nptr) += normal;
}
}
inline void operator() ( const osg::Vec3 &v1, const osg::Vec3 &v2, const osg::Vec3 &v3 )
{
// calc orientation of triangle.
osg::Vec3 normal = (v2-v1)^(v3-v1);
// normal.normalize();
updateNormal(normal,&v1);
updateNormal(normal,&v2);
updateNormal(normal,&v3);
}
};
void SmoothingVisitor::smooth(osg::GeoSet& gset)
{
GeoSet::PrimitiveType primTypeIn = gset.getPrimType();
GeoSet::PrimitiveType primTypeOut = gset.getPrimType();
// determine whether to do smoothing or not, and if
// the primitive type needs to be modified enable smoothed normals.
bool doSmoothing;
switch(primTypeIn)
{
case(GeoSet::TRIANGLES):
case(GeoSet::TRIANGLE_STRIP):
case(GeoSet::TRIANGLE_FAN):
doSmoothing = true;
break;
case(GeoSet::FLAT_TRIANGLE_STRIP):
primTypeOut = GeoSet::TRIANGLE_STRIP;
doSmoothing = true;
break;
case(GeoSet::FLAT_TRIANGLE_FAN):
primTypeOut = GeoSet::TRIANGLE_FAN;
doSmoothing = true;
break;
case(GeoSet::QUADS):
case(GeoSet::QUAD_STRIP):
case(GeoSet::POLYGON):
doSmoothing = true;
break;
default: // points and lines etc.
doSmoothing = false;
break;
}
if (doSmoothing)
{
gset.computeNumVerts();
int ncoords = gset.getNumCoords();
osg::Vec3 *coords = gset.getCoords();
osg::GeoSet::IndexPointer cindex = gset.getCoordIndices();
osg::Vec3 *norms = new osg::Vec3[ncoords];
int j;
for(j = 0; j < ncoords; j++ )
{
norms[j].set(0.0f,0.0f,0.0f);
}
TriangleFunctor tf(coords,ncoords,norms);
for_each_triangle( gset, tf );
for(j = 0; j < ncoords; j++ )
{
norms[j].normalize();
}
gset.setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
if (cindex.valid())
{
if (cindex._is_ushort)
gset.setNormals( norms, cindex._ptr._ushort );
else
gset.setNormals( norms, cindex._ptr._uint );
}
else
{
gset.setNormals( norms );
}
if (primTypeIn!=primTypeOut)
gset.setPrimType( primTypeOut );
gset.dirtyDisplayList();
}
}
void SmoothingVisitor::apply(osg::Geode& geode)
{
for(int i = 0; i < geode.getNumDrawables(); i++ )
{
osg::GeoSet* gset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (gset) smooth(*gset);
}
}

View File

@@ -0,0 +1,68 @@
#include <osgUtil/StateSetManipulator>
using namespace osg;
using namespace osgUtil;
StateSetManipulator::StateSetManipulator(): _drawState(NULL)
{
}
StateSetManipulator::~StateSetManipulator()
{
}
void StateSetManipulator::setStateSet(StateSet *drawState)
{
_drawState=drawState;
if(!_drawState.valid()) return;
_backface = (_drawState->getMode(GL_CULL_FACE)==osg::StateAttribute::ON);
_lighting =(_drawState->getMode(GL_LIGHTING)==osg::StateAttribute::ON);
_texture =(_drawState->getMode(GL_TEXTURE_2D)==osg::StateAttribute::ON);
}
StateSet *StateSetManipulator::getStateSet()
{
return _drawState.get();
}
const StateSet *StateSetManipulator::getStateSet() const
{
return _drawState.get();
}
bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
if(!_drawState.valid()) return false;
if(ea.getEventType()==GUIEventAdapter::KEYBOARD){
switch( ea.getKey() ){
case 'b' :
_backface = !_backface;
if( _backface ) _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
else _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
case 'l' :
_lighting = !_lighting ;
if( _lighting ) _drawState->setMode(GL_LIGHTING,osg::StateAttribute::ON);
else _drawState->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
case 't' :
_texture = !_texture;
if (_texture) _drawState->setMode(GL_TEXTURE_2D,osg::StateAttribute::INHERIT);
else _drawState->setMode(GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
}
}
return false;
}

262
src/osgUtil/Tesselator.cpp Normal file
View File

@@ -0,0 +1,262 @@
#include <osg/GL>
#include <osg/Notify>
#include <osgUtil/Tesselator>
#include <GL/glu.h>
using namespace osg;
using namespace osgUtil;
/* Win32 calling conventions. (or a least thats what the GLUT example tess.c uses.)*/
#ifndef CALLBACK
#define CALLBACK
#endif
static Tesselator* s_tesselator = NULL;
void CALLBACK beginCallback(GLenum which)
{
s_tesselator->beginPrimitive(which);
}
void CALLBACK errorCallback(GLenum errorCode)
{
s_tesselator->_errorCode = errorCode;
}
void CALLBACK endCallback()
{
s_tesselator->endPrimitive();
}
void CALLBACK vertexCallback(GLvoid *data)
{
Tesselator::VertexIndexSet* vip = (Tesselator::VertexIndexSet*)data;
vip->accumulate();
}
Tesselator::Tesselator()
{
}
Tesselator::~Tesselator()
{
}
void Tesselator::tesselate(osg::Vec3* coords,int numIndices, int* indices,InputBoundaryDirection ibd)
{
init();
_coordVec.reserve(numIndices);
if (ibd==COUNTER_CLOCK_WISE)
{
for(int i=0;i<numIndices;++i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
else
{
for(int i=numIndices-1;i>=0;--i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
do_it();
}
void Tesselator::tesselate(osg::Vec3* coords,int numIndices, osg::ushort* indices,InputBoundaryDirection ibd)
{
init();
_coordVec.reserve(numIndices);
if (ibd==COUNTER_CLOCK_WISE)
{
for(int i=0;i<numIndices;++i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
else
{
for(int i=numIndices-1;i>=0;--i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
do_it();
}
void Tesselator::tesselate(osg::Vec3* coords,int numIndices, osg::uint* indices,InputBoundaryDirection ibd)
{
init();
_coordVec.reserve(numIndices);
if (ibd==COUNTER_CLOCK_WISE)
{
for(int i=0;i<numIndices;++i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
else
{
for(int i=numIndices-1;i>=0;--i)
{
_coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i]));
}
}
do_it();
}
void Tesselator::init()
{
_errorCode = 0;
_coordVec.clear();
_acummulated_indices.clear();
_tesselated_indices.clear();
_currentPrimtiveType=0;
}
#ifdef GLU_VERSION_1_2
void Tesselator::do_it()
{
GLUtesselator *tobj = gluNewTess();
gluTessCallback(tobj, (GLenum)GLU_TESS_VERTEX,
(GLvoid (CALLBACK*) ()) (&vertexCallback));
gluTessCallback(tobj, (GLenum)GLU_TESS_BEGIN,
(GLvoid (CALLBACK*) ()) (&beginCallback));
gluTessCallback(tobj, (GLenum)GLU_TESS_END,
(GLvoid (CALLBACK*) ()) (&endCallback));
gluTessCallback(tobj, (GLenum)GLU_TESS_ERROR,
(GLvoid (CALLBACK*) ()) (&errorCallback));
s_tesselator = this;
gluTessBeginPolygon(tobj,NULL);
gluTessBeginContour(tobj);
for(CoordVec::iterator itr=_coordVec.begin();
itr!=_coordVec.end();
++itr)
{
gluTessVertex(tobj,itr->_vertex,itr->_vertex);
}
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
gluDeleteTess(tobj);
if (_errorCode!=0)
{
const GLubyte *estring = gluErrorString((GLenum)_errorCode);
osg::notify(osg::WARN)<<"Tessellation Error: "<<estring<<endl;
osg::notify(osg::WARN)<<" Num indices created = "<<_tesselated_indices.size()<<endl;
}
}
#else
// old style glu tesseleation.
void Tesselator::do_it()
{
GLUtriangulatorObj *tobj = gluNewTess();
gluTessCallback(tobj, (GLenum)GLU_VERTEX,
(GLvoid (CALLBACK*) ()) (&vertexCallback));
gluTessCallback(tobj, (GLenum)GLU_BEGIN,
(GLvoid (CALLBACK*) ()) (&beginCallback));
gluTessCallback(tobj, (GLenum)GLU_END,
(GLvoid (CALLBACK*) ()) (&endCallback));
gluTessCallback(tobj, (GLenum)GLU_ERROR,
(GLvoid (CALLBACK*) ()) (&errorCallback));
s_tesselator = this;
gluBeginPolygon(tobj);
for(CoordVec::iterator itr=_coordVec.begin();
itr!=_coordVec.end();
++itr)
{
gluTessVertex(tobj,itr->_vertex,itr->_vertex);
}
gluEndPolygon(tobj);
gluDeleteTess(tobj);
if (_errorCode!=0)
{
const GLubyte *estring = gluErrorString((GLenum)_errorCode);
osg::notify(osg::WARN)<<"Tessellation Error: "<<estring<<endl;
osg::notify(osg::WARN)<<" Num indices created = "<<_tesselated_indices.size()<<endl;
}
}
#endif
void Tesselator::beginPrimitive(int primitiveType)
{
_currentPrimtiveType = primitiveType;
}
void Tesselator::endPrimitive()
{
if (_acummulated_indices.size()>=3)
{
switch(_currentPrimtiveType)
{
case(GL_TRIANGLE_FAN):
{
osg::uint first = _acummulated_indices[0];
for(unsigned int i=2;i<_acummulated_indices.size();++i)
{
_tesselated_indices.push_back(first);
_tesselated_indices.push_back(_acummulated_indices[i-1]);
_tesselated_indices.push_back(_acummulated_indices[i]);
}
}
break;
case(GL_TRIANGLE_STRIP):
{
for(unsigned int i=2;i<_acummulated_indices.size();++i)
{
if (i%2)
{
// i == 3,5,7 etc
// add in order.
_tesselated_indices.push_back(_acummulated_indices[i-2]);
_tesselated_indices.push_back(_acummulated_indices[i-1]);
_tesselated_indices.push_back(_acummulated_indices[i]);
}
else
{
// i == 2,4,6 etc
// add in flipping orde to preserve anticlockwise direction.
_tesselated_indices.push_back(_acummulated_indices[i-1]);
_tesselated_indices.push_back(_acummulated_indices[i-2]);
_tesselated_indices.push_back(_acummulated_indices[i]);
}
}
}
break;
case(GL_TRIANGLES):
{
for(unsigned int i=2;i<_acummulated_indices.size();i+=3)
{
_tesselated_indices.push_back(_acummulated_indices[i-2]);
_tesselated_indices.push_back(_acummulated_indices[i-1]);
_tesselated_indices.push_back(_acummulated_indices[i]);
}
}
break;
}
}
_acummulated_indices.clear();
}

View File

@@ -0,0 +1,310 @@
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <stdio.h>
#include <osg/GeoSet>
#include <osg/Geode>
#include <osg/Types>
#include <osgUtil/TriStripVisitor>
#include "NvTriStripObjects.h"
using namespace osg;
using namespace osgUtil;
// triangle functor.
struct TriangleAcumulatorFunctor
{
WordVec in_indices;
const Vec3* _vbase;
TriangleAcumulatorFunctor( const Vec3* vbase ) : _vbase(vbase) {}
inline void operator() ( const Vec3 &v1, const Vec3 &v2, const Vec3 &v3 )
{
int p1 = (int)(&v1-_vbase);
int p2 = (int)(&v2-_vbase);
int p3 = (int)(&v3-_vbase);
if (p1==p2 || p1==p3 || p2==p3) return;
in_indices.push_back(p1);
in_indices.push_back(p2);
in_indices.push_back(p3);
}
};
void createStrips(
NvStripInfoVec& strips,
NvFaceInfoVec& leftoverFaces,
int& noPrims,
int **lens,
osg::ushort **osg_indices)
{
int nStripCount = strips.size();
assert(nStripCount > 0);
noPrims = strips.size()+leftoverFaces.size();
*lens = new int [noPrims];
int* lensPtr = *lens;
unsigned int i;
int noIndices = 0;
for (i = 0; i < strips.size(); i++)
{
noIndices += strips[i]->m_faces.size()+2;
}
noIndices += leftoverFaces.size()*3;
*osg_indices = new osg::ushort[noIndices];
osg::ushort *osg_indicesPtr = *osg_indices;
for (i = 0; i < strips.size(); i++)
{
NvStripInfo *strip = strips[i];
int nStripFaceCount = strip->m_faces.size();
*(lensPtr++) = nStripFaceCount+2;
NvFaceInfo tLastFace(0, 0, 0);
// Handle the first face in the strip
{
NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
// If there is a second face, reorder vertices such that the
// unique vertex is first
if (nStripFaceCount > 1)
{
int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
if (nUnique == tFirstFace.m_v1)
{
std::swap(tFirstFace.m_v0, tFirstFace.m_v1);
}
else if (nUnique == tFirstFace.m_v2)
{
std::swap(tFirstFace.m_v0, tFirstFace.m_v2);
}
// If there is a third face, reorder vertices such that the
// shared vertex is last
if (nStripFaceCount > 2)
{
int nShared = NvStripifier::GetSharedVertex(strip->m_faces[2], &tFirstFace);
if (nShared == tFirstFace.m_v1)
{
std::swap(tFirstFace.m_v1, tFirstFace.m_v2);
}
}
}
*(osg_indicesPtr++) = tFirstFace.m_v0;
*(osg_indicesPtr++) = tFirstFace.m_v1;
*(osg_indicesPtr++) = tFirstFace.m_v2;
// Update last face info
tLastFace = tFirstFace;
}
for (int j = 1; j < nStripFaceCount; j++)
{
int nUnique = NvStripifier::GetUniqueVertexInB(&tLastFace, strip->m_faces[j]);
if (nUnique != -1)
{
*(osg_indicesPtr++) = nUnique;
// Update last face info
tLastFace.m_v0 = tLastFace.m_v1;
tLastFace.m_v1 = tLastFace.m_v2;
tLastFace.m_v2 = nUnique;
}
}
}
for (i = 0; i < leftoverFaces.size(); ++i)
{
*(lensPtr++) = 3;
*(osg_indicesPtr++) = leftoverFaces[i]->m_v0;
*(osg_indicesPtr++) = leftoverFaces[i]->m_v1;
*(osg_indicesPtr++) = leftoverFaces[i]->m_v2;
}
}
void TriStripVisitor::stripify(GeoSet& gset)
{
GeoSet::PrimitiveType primTypeIn = gset.getPrimType();
GeoSet::PrimitiveType primTypeOut = gset.getPrimType();
// determine whether to do smoothing or not, and if
// the primitive type needs to be modified enable smoothed normals.
bool doStripify;
switch(primTypeIn)
{
case(GeoSet::QUADS):
case(GeoSet::QUAD_STRIP):
case(GeoSet::POLYGON):
case(GeoSet::TRIANGLES):
case(GeoSet::TRIANGLE_STRIP):
case(GeoSet::TRIANGLE_FAN):
primTypeOut = GeoSet::TRIANGLE_STRIP;
doStripify = true;
break;
case(GeoSet::FLAT_TRIANGLE_STRIP):
case(GeoSet::FLAT_TRIANGLE_FAN):
// comment out for time being since per vertex colors and normals need
// to take account of the osg::GeoSet::_flat_shaded_skip
// primTypeOut = GeoSet::FLAT_TRIANGLE_STRIP;
// doStripify = true;
// break;
default: // points and lines etc.
doStripify = false;
break;
}
if (doStripify)
{
TriangleAcumulatorFunctor tt(gset.getCoords());
for_each_triangle( gset, tt );
if (!tt.in_indices.empty())
{
int in_numVertices = -1;
for(WordVec::iterator itr=tt.in_indices.begin();
itr!=tt.in_indices.end();
++itr)
{
if (*itr>in_numVertices) in_numVertices=*itr;
}
// the largest indice is in_numVertices, but indices start at 0
// so increment to give to the corrent number of verticies.
++in_numVertices;
int in_cacheSize = 16;
int in_minStripLength = 1;
NvStripInfoVec strips;
NvFaceInfoVec leftoverFaces;
NvStripifier stripifier;
stripifier.Stripify(tt.in_indices,
in_numVertices,
in_cacheSize,
in_minStripLength,
strips,
leftoverFaces);
int noPrims;
int *lens;
osg::ushort* osg_indices;
createStrips(strips,leftoverFaces,noPrims,&lens,&osg_indices);
if (primTypeIn!=primTypeOut)
gset.setPrimType( primTypeOut );
gset.setPrimLengths(lens);
gset.setNumPrims(noPrims);
gset.setCoords(gset.getCoords(),osg_indices);
if (gset.getTextureCoords())
{
switch(gset.getTextureBinding())
{
case(GeoSet::BIND_OVERALL):
// leave as before
break;
case(GeoSet::BIND_PERPRIM):
// switch off tex coords..
gset.setTextureBinding(GeoSet::BIND_OFF);
gset.setTextureCoords(NULL);
break;
case(GeoSet::BIND_PERVERTEX):
// set up the indexing.
gset.setTextureCoords(gset.getTextureCoords(),osg_indices);
break;
case(GeoSet::BIND_OFF):
case(GeoSet::BIND_DEFAULT):
// switch off tex coords..
gset.setTextureCoords(NULL);
break;
}
}
if (gset.getColors())
{
switch(gset.getColorBinding())
{
case(GeoSet::BIND_OVERALL):
// leave as before
break;
case(GeoSet::BIND_PERPRIM):
// switch off colors..
gset.setColorBinding(GeoSet::BIND_OFF);
gset.setColors(NULL);
break;
case(GeoSet::BIND_PERVERTEX):
// set up the indexing.
gset.setColors(gset.getColors(),osg_indices);
break;
case(GeoSet::BIND_OFF):
case(GeoSet::BIND_DEFAULT):
// switch off colors..
gset.setColors(NULL);
break;
}
}
if (gset.getNormals())
{
switch(gset.getNormalBinding())
{
case(GeoSet::BIND_OVERALL):
// leave as before
break;
case(GeoSet::BIND_PERPRIM):
// switch off normals..
gset.setNormalBinding(GeoSet::BIND_OFF);
gset.setNormals(NULL);
break;
case(GeoSet::BIND_PERVERTEX):
// set up the indexing.
gset.setNormals(gset.getNormals(),osg_indices);
break;
case(GeoSet::BIND_OFF):
case(GeoSet::BIND_DEFAULT):
// switch off normals..
gset.setNormals(NULL);
break;
}
}
gset.dirtyDisplayList();
}
else
{
cout << "No triangles to stripify"<<endl;
}
}
}
void TriStripVisitor::apply(Geode& geode)
{
for(int i = 0; i < geode.getNumDrawables(); ++i )
{
osg::GeoSet* gset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (gset) stripify(*gset);
}
}

View File

@@ -0,0 +1,64 @@
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <stdio.h>
#include <list>
#include <set>
#include <osg/GeoSet>
#include <osgUtil/VisualsRequirementsVisitor>
using namespace osg;
using namespace osgUtil;
VisualsRequirementsVisitor::VisualsRequirementsVisitor()
{
setTraversalMode(NodeVisitor::TRAVERSE_ALL_CHILDREN);
_requiresDoubleBuffer = true;
_requiresRBG = true;
_requiresDepthBuffer = true;
_minimumNumberAlphaBits = 0;
_minimumNumberStencilBits = 0;
}
void VisualsRequirementsVisitor::applyStateSet(StateSet& stateset)
{
if (stateset.getMode(GL_STENCIL_TEST) & StateAttribute::ON)
{
_minimumNumberStencilBits = 1;
}
if (stateset.getAttribute(StateAttribute::STENCIL))
{
_minimumNumberStencilBits = 1;
}
}
void VisualsRequirementsVisitor::apply(Node& node)
{
osg::StateSet* stateset = node.getStateSet();
if (stateset) applyStateSet(*stateset);
traverse(node);
}
void VisualsRequirementsVisitor::apply(Geode& geode)
{
osg::StateSet* geode_stateset = geode.getStateSet();
if (geode_stateset) applyStateSet(*geode_stateset);
for(int i = 0; i < geode.getNumDrawables(); i++ )
{
osg::StateSet* stateset = geode.getDrawable(i)->getStateSet();
if (stateset) applyStateSet(*stateset);
}
}
void VisualsRequirementsVisitor::apply(Impostor& impostor)
{
_minimumNumberAlphaBits = 1;
apply((Node&)impostor);
}