More clean up for synch with 0.8.42
This commit is contained in:
32
src/osgUtil/CullViewState.cpp
Normal file
32
src/osgUtil/CullViewState.cpp
Normal 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
1209
src/osgUtil/CullVisitor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
97
src/osgUtil/DepthSortedBin.cpp
Normal file
97
src/osgUtil/DepthSortedBin.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
176
src/osgUtil/InsertImpostorsVisitor.cpp
Normal file
176
src/osgUtil/InsertImpostorsVisitor.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
1638
src/osgUtil/NvTriStripObjects.cpp
Normal file
1638
src/osgUtil/NvTriStripObjects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
296
src/osgUtil/NvTriStripObjects.h
Normal file
296
src/osgUtil/NvTriStripObjects.h
Normal 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
179
src/osgUtil/RenderBin.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/osgUtil/RenderGraph.cpp
Normal file
62
src/osgUtil/RenderGraph.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
63
src/osgUtil/RenderLeaf.cpp
Normal file
63
src/osgUtil/RenderLeaf.cpp
Normal 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
134
src/osgUtil/RenderStage.cpp
Normal 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);
|
||||
}
|
||||
61
src/osgUtil/RenderStageLighting.cpp
Normal file
61
src/osgUtil/RenderStageLighting.cpp
Normal 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();
|
||||
|
||||
}
|
||||
32
src/osgUtil/RenderToTextureStage.cpp
Normal file
32
src/osgUtil/RenderToTextureStage.cpp
Normal 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]);
|
||||
|
||||
}
|
||||
39
src/osgUtil/SceneViewManipulator.cpp
Normal file
39
src/osgUtil/SceneViewManipulator.cpp
Normal 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;
|
||||
}
|
||||
155
src/osgUtil/SmoothingVisitor.cpp
Normal file
155
src/osgUtil/SmoothingVisitor.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
68
src/osgUtil/StateSetManipulator.cpp
Normal file
68
src/osgUtil/StateSetManipulator.cpp
Normal 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
262
src/osgUtil/Tesselator.cpp
Normal 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();
|
||||
}
|
||||
|
||||
310
src/osgUtil/TriStripVisitor.cpp
Normal file
310
src/osgUtil/TriStripVisitor.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
64
src/osgUtil/VisualsRequirementsVisitor.cpp
Normal file
64
src/osgUtil/VisualsRequirementsVisitor.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user