Added osg::Drawable::PrimitiveFunctor and TriangleFunctor subclass for
querrying the primitive data inside Drawables. Moved various support classes over from being osg::GeoSet based to osg::Geometry based.
This commit is contained in:
@@ -1,16 +1,11 @@
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable : 4786 )
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <osg/GeoSet>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Types>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "NvTriStripObjects.h"
|
||||
|
||||
using namespace osg;
|
||||
@@ -23,7 +18,9 @@ struct TriangleAcumulatorFunctor
|
||||
WordVec in_indices;
|
||||
const Vec3* _vbase;
|
||||
|
||||
TriangleAcumulatorFunctor( const Vec3* vbase ) : _vbase(vbase) {}
|
||||
TriangleAcumulatorFunctor() : _vbase(0) {}
|
||||
|
||||
void setCoords( const Vec3* vbase ) { _vbase = vbase; }
|
||||
|
||||
inline void operator() ( const Vec3 &v1, const Vec3 &v2, const Vec3 &v3 )
|
||||
{
|
||||
@@ -37,267 +34,172 @@ struct TriangleAcumulatorFunctor
|
||||
}
|
||||
};
|
||||
|
||||
void createStrips(
|
||||
NvStripInfoVec& strips,
|
||||
NvFaceInfoVec& leftoverFaces,
|
||||
int& noPrims,
|
||||
int **lens,
|
||||
osg::ushort **osg_indices)
|
||||
void TriStripVisitor::stripify(Geometry& geom)
|
||||
{
|
||||
int nStripCount = strips.size();
|
||||
assert(nStripCount > 0);
|
||||
|
||||
noPrims = strips.size()+leftoverFaces.size();
|
||||
*lens = osgNew int [noPrims];
|
||||
unsigned int numSurfacePrimitives = 0;
|
||||
unsigned int numNonSurfacePrimitives = 0;
|
||||
|
||||
int* lensPtr = *lens;
|
||||
|
||||
unsigned int i;
|
||||
int noIndices = 0;
|
||||
for (i = 0; i < strips.size(); i++)
|
||||
Geometry::PrimitiveList& primitives = geom.getPrimitiveList();
|
||||
Geometry::PrimitiveList::iterator itr;
|
||||
for(itr=primitives.begin();
|
||||
itr!=primitives.end();
|
||||
++itr)
|
||||
{
|
||||
noIndices += strips[i]->m_faces.size()+2;
|
||||
}
|
||||
|
||||
noIndices += leftoverFaces.size()*3;
|
||||
|
||||
*osg_indices = osgNew 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
|
||||
switch((*itr)->getMode())
|
||||
{
|
||||
NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
|
||||
case(Primitive::TRIANGLES):
|
||||
case(Primitive::TRIANGLE_STRIP):
|
||||
case(Primitive::TRIANGLE_FAN):
|
||||
case(Primitive::QUADS):
|
||||
case(Primitive::QUAD_STRIP):
|
||||
case(Primitive::POLYGON):
|
||||
++numSurfacePrimitives;
|
||||
break;
|
||||
default:
|
||||
++numNonSurfacePrimitives;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!numSurfacePrimitives) return;
|
||||
|
||||
TriangleFunctor<TriangleAcumulatorFunctor> taf;
|
||||
|
||||
// If there is a second face, reorder vertices such that the
|
||||
// unique vertex is first
|
||||
if (nStripFaceCount > 1)
|
||||
Geometry::PrimitiveList new_primitives;
|
||||
new_primitives.reserve(primitives.size());
|
||||
|
||||
for(itr=primitives.begin();
|
||||
itr!=primitives.end();
|
||||
++itr)
|
||||
{
|
||||
switch((*itr)->getMode())
|
||||
{
|
||||
case(Primitive::TRIANGLES):
|
||||
case(Primitive::TRIANGLE_STRIP):
|
||||
case(Primitive::TRIANGLE_FAN):
|
||||
case(Primitive::QUADS):
|
||||
case(Primitive::QUAD_STRIP):
|
||||
case(Primitive::POLYGON):
|
||||
(*itr)->applyPrimitiveOperation(taf);
|
||||
break;
|
||||
default:
|
||||
new_primitives.push_back(*itr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!taf.in_indices.empty())
|
||||
{
|
||||
int in_numVertices = -1;
|
||||
for(WordVec::iterator itr=taf.in_indices.begin();
|
||||
itr!=taf.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 = 2;
|
||||
NvStripInfoVec strips;
|
||||
NvFaceInfoVec leftoverFaces;
|
||||
|
||||
NvStripifier stripifier;
|
||||
stripifier.Stripify(taf.in_indices,
|
||||
in_numVertices,
|
||||
in_cacheSize,
|
||||
in_minStripLength,
|
||||
strips,
|
||||
leftoverFaces);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < strips.size(); ++i)
|
||||
{
|
||||
|
||||
NvStripInfo *strip = strips[i];
|
||||
int nStripFaceCount = strip->m_faces.size();
|
||||
|
||||
osg::UShortDrawElements* elements = osgNew osg::UShortDrawElements(osg::Primitive::TRIANGLE_STRIP);
|
||||
elements->reserve(nStripFaceCount+2);
|
||||
new_primitives.push_back(elements);
|
||||
|
||||
NvFaceInfo tLastFace(0, 0, 0);
|
||||
|
||||
// Handle the first face in the strip
|
||||
{
|
||||
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);
|
||||
}
|
||||
NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
|
||||
|
||||
// If there is a third face, reorder vertices such that the
|
||||
// shared vertex is last
|
||||
if (nStripFaceCount > 2)
|
||||
// If there is a second face, reorder vertices such that the
|
||||
// unique vertex is first
|
||||
if (nStripFaceCount > 1)
|
||||
{
|
||||
int nShared = NvStripifier::GetSharedVertex(strip->m_faces[2], &tFirstFace);
|
||||
if (nShared == tFirstFace.m_v1)
|
||||
int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
|
||||
if (nUnique == tFirstFace.m_v1)
|
||||
{
|
||||
std::swap(tFirstFace.m_v1, tFirstFace.m_v2);
|
||||
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;
|
||||
elements->push_back(tFirstFace.m_v0);
|
||||
elements->push_back(tFirstFace.m_v1);
|
||||
elements->push_back(tFirstFace.m_v2);
|
||||
|
||||
// Update last face info
|
||||
tLastFace.m_v0 = tLastFace.m_v1;
|
||||
tLastFace.m_v1 = tLastFace.m_v2;
|
||||
tLastFace.m_v2 = nUnique;
|
||||
tLastFace = tFirstFace;
|
||||
}
|
||||
|
||||
for (int j = 1; j < nStripFaceCount; j++)
|
||||
{
|
||||
int nUnique = NvStripifier::GetUniqueVertexInB(&tLastFace, strip->m_faces[j]);
|
||||
if (nUnique != -1)
|
||||
{
|
||||
elements->push_back(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())
|
||||
if (leftoverFaces.size())
|
||||
{
|
||||
int in_numVertices = -1;
|
||||
for(WordVec::iterator itr=tt.in_indices.begin();
|
||||
itr!=tt.in_indices.end();
|
||||
++itr)
|
||||
|
||||
osg::UShortDrawElements* triangles = osgNew osg::UShortDrawElements(osg::Primitive::TRIANGLES);
|
||||
triangles->reserve(leftoverFaces.size()*3);
|
||||
new_primitives.push_back(triangles);
|
||||
|
||||
for (i = 0; i < leftoverFaces.size(); ++i)
|
||||
{
|
||||
if (*itr>in_numVertices) in_numVertices=*itr;
|
||||
|
||||
triangles->push_back(leftoverFaces[i]->m_v0);
|
||||
triangles->push_back(leftoverFaces[i]->m_v1);
|
||||
triangles->push_back(leftoverFaces[i]->m_v2);
|
||||
}
|
||||
// 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.computeNumVerts();
|
||||
gset.dirtyDisplayList();
|
||||
gset.dirtyBound();
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(INFO) << "No triangles to stripify"<< std::endl;
|
||||
}
|
||||
|
||||
geom.setPrimitiveList(new_primitives);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +208,7 @@ 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);
|
||||
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
|
||||
if (geom) stripify(*geom);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user