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:
Robert Osfield
2002-06-25 20:27:51 +00:00
parent 336c47e5fe
commit cbeeeefdab
20 changed files with 737 additions and 651 deletions

View File

@@ -1,8 +1,5 @@
// simple animation demo written by Graeme Harkness.
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Vec3>
#include <osg/Transform>
@@ -15,16 +12,10 @@
#include <osg/Math>
// ----------------------------------------------------------------------
// Global variables - this is basically the stuff which will be animated
// Global variables - this is basically the stuff wh ich will be animated
// ----------------------------------------------------------------------
osg::Geode* createCube(); //Forward Declaration added by SMW
class MyTransformCallback : public osg::NodeCallback{
public:
@@ -60,22 +51,6 @@ class MyTransformCallback : public osg::NodeCallback{
_previousTraversalNumber = nv->getTraversalNumber();
// Some memory stress testing added by Steve to reveal crashes under Windows.
// // Start Added by SMW
// osg::Transform* Tnode = (osg::Transform *)node;
// int i;
// osg::Node *n;
// while (Tnode->getNumChildren() > 0)
// {
// n = Tnode->getChild(0);
// Tnode->removeChild(n);
// }
// for (i = 0;i < 500;i++)
// {
// Tnode->addChild( createCube() );
// }
// // End Added by SMW
}
}
}
@@ -96,76 +71,76 @@ class MyTransformCallback : public osg::NodeCallback{
};
osg::Geode* createCube()
osg::Geode* createGeometryCube()
{
osg::Geode* geode = new osg::Geode();
// -------------------------------------------
// Set up a new GeoSet which will be our cube
// Set up a new Geometry which will be our cube
// -------------------------------------------
osg::GeoSet* cube = new osg::GeoSet();
osg::Geometry* cube = new osg::Geometry();
// set up the primitives
cube->setPrimType( osg::GeoSet::POLYGON );
cube->setNumPrims( 6 ); // the six square faces
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,0,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,4,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,8,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,12,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,16,4));
cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,20,4));
// set up the primitive indices
int* cubeLengthList = new int[6];
cubeLengthList[0] = 4; // each side of the cube has 4 vertices
cubeLengthList[1] = 4;
cubeLengthList[2] = 4;
cubeLengthList[3] = 4;
cubeLengthList[4] = 4;
cubeLengthList[5] = 4;
// set up coords.
osg::Vec3Array* coords = new osg::Vec3Array;
coords->resize(24);
(*coords)[0].set( -1.0000f, 1.0000f, -1.000f );
(*coords)[1].set( 1.0000f, 1.0000f, -1.0000f );
(*coords)[2].set( 1.0000f, -1.0000f, -1.0000f );
(*coords)[3].set( -1.0000f, -1.0000f, -1.000 );
cube->setPrimLengths( cubeLengthList );
(*coords)[4].set( 1.0000f, 1.0000f, -1.0000f );
(*coords)[5].set( 1.0000f, 1.0000f, 1.0000f );
(*coords)[6].set( 1.0000f, -1.0000f, 1.0000f );
(*coords)[7].set( 1.0000f, -1.0000f, -1.0000f );
(*coords)[8].set( 1.0000f, 1.0000f, 1.0000f );
(*coords)[9].set( -1.0000f, 1.0000f, 1.000f );
(*coords)[10].set( -1.0000f, -1.0000f, 1.000f );
(*coords)[11].set( 1.0000f, -1.0000f, 1.0000f );
(*coords)[12].set( -1.0000f, 1.0000f, 1.000 );
(*coords)[13].set( -1.0000f, 1.0000f, -1.000 );
(*coords)[14].set( -1.0000f, -1.0000f, -1.000 );
(*coords)[15].set( -1.0000f, -1.0000f, 1.000 );
(*coords)[16].set( -1.0000f, 1.0000f, 1.000 );
(*coords)[17].set( 1.0000f, 1.0000f, 1.0000f );
(*coords)[18].set( 1.0000f, 1.0000f, -1.0000f );
(*coords)[19].set( -1.0000f, 1.0000f, -1.000f );
(*coords)[20].set( -1.0000f, -1.0000f, 1.000f );
(*coords)[21].set( -1.0000f, -1.0000f, -1.000f );
(*coords)[22].set( 1.0000f, -1.0000f, -1.0000f );
(*coords)[23].set( 1.0000f, -1.0000f, 1.0000f );
// set up the coordinates.
osg::Vec3 *cubeCoords = new osg::Vec3[24];
cubeCoords[0].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[1].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[2].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[3].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[4].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[5].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[6].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[7].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[8].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[9].set( -1.0000f, 1.0000f, 1.000f );
cubeCoords[10].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[11].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[12].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[13].set( -1.0000f, 1.0000f, -1.000 );
cubeCoords[14].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[15].set( -1.0000f, -1.0000f, 1.000 );
cubeCoords[16].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[17].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[18].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[19].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[20].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[21].set( -1.0000f, -1.0000f, -1.000f );
cubeCoords[22].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[23].set( 1.0000f, -1.0000f, 1.0000f );
cube->setCoords( cubeCoords );
cube->setVertexArray( coords );
// set up the normals.
osg::Vec3 *cubeNormals = new osg::Vec3[6];
cubeNormals[0].set(0.0f,0.0f,-1.0f);
cubeNormals[1].set(1.0f,0.0f,0.0f);
cubeNormals[2].set(0.0f,0.0f,1.0f);
cubeNormals[3].set(-1.0f,0.0f,0.0f);
cubeNormals[4].set(0.0f,1.0f,0.0f);
cubeNormals[5].set(0.0f,-1.0f,0.0f);
cube->setNormals( cubeNormals );
cube->setNormalBinding( osg::GeoSet::BIND_PERPRIM );
osg::Vec3Array* cubeNormals = new osg::Vec3Array;
cubeNormals->resize(6);
(*cubeNormals)[0].set(0.0f,0.0f,-1.0f);
(*cubeNormals)[1].set(1.0f,0.0f,0.0f);
(*cubeNormals)[2].set(0.0f,0.0f,1.0f);
(*cubeNormals)[3].set(-1.0f,0.0f,0.0f);
(*cubeNormals)[4].set(0.0f,1.0f,0.0f);
(*cubeNormals)[5].set(0.0f,-1.0f,0.0f);
cube->setNormalArray( cubeNormals );
cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
// ---------------------------------------
// Set up a StateSet to make the cube red
@@ -201,7 +176,7 @@ int main( int argc, char **argv )
viewer.readCommandLine(commandLine);
osg::Transform* myTransform = new osg::Transform();
myTransform->addChild( createCube() );
myTransform->addChild( createGeometryCube() );
// move node in a circle at 90 degrees a sec.
myTransform->setAppCallback(new MyTransformCallback(myTransform,osg::inDegrees(90.0f)));

View File

@@ -1,5 +1,4 @@
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Vec3>
@@ -52,22 +51,6 @@ class MyTransformCallback : public osg::NodeCallback{
_previousTraversalNumber = nv->getTraversalNumber();
// Some memory stress testing added by Steve to reveal crashes under Windows.
// // Start Added by SMW
// osg::Transform* Tnode = (osg::Transform *)node;
// int i;
// osg::Node *n;
// while (Tnode->getNumChildren() > 0)
// {
// n = Tnode->getChild(0);
// Tnode->removeChild(n);
// }
// for (i = 0;i < 500;i++)
// {
// Tnode->addChild( createCube() );
// }
// // End Added by SMW
}
}
}
@@ -88,93 +71,6 @@ class MyTransformCallback : public osg::NodeCallback{
};
osg::Geode* createCube()
{
osg::Geode* geode = new osg::Geode();
// -------------------------------------------
// Set up a new GeoSet which will be our cube
// -------------------------------------------
osg::GeoSet* cube = new osg::GeoSet();
// set up the primitives
cube->setPrimType( osg::GeoSet::POLYGON );
cube->setNumPrims( 6 ); // the six square faces
// set up the primitive indices
int* cubeLengthList = new int[6];
cubeLengthList[0] = 4; // each side of the cube has 4 vertices
cubeLengthList[1] = 4;
cubeLengthList[2] = 4;
cubeLengthList[3] = 4;
cubeLengthList[4] = 4;
cubeLengthList[5] = 4;
cube->setPrimLengths( cubeLengthList );
// set up the coordinates.
osg::Vec3 *cubeCoords = new osg::Vec3[24];
cubeCoords[0].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[1].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[2].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[3].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[4].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[5].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[6].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[7].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[8].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[9].set( -1.0000f, 1.0000f, 1.000f );
cubeCoords[10].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[11].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[12].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[13].set( -1.0000f, 1.0000f, -1.000 );
cubeCoords[14].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[15].set( -1.0000f, -1.0000f, 1.000 );
cubeCoords[16].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[17].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[18].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[19].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[20].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[21].set( -1.0000f, -1.0000f, -1.000f );
cubeCoords[22].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[23].set( 1.0000f, -1.0000f, 1.0000f );
cube->setCoords( cubeCoords );
// set up the normals.
osg::Vec3 *cubeNormals = new osg::Vec3[6];
cubeNormals[0].set(0.0f,0.0f,-1.0f);
cubeNormals[1].set(1.0f,0.0f,0.0f);
cubeNormals[2].set(0.0f,0.0f,1.0f);
cubeNormals[3].set(-1.0f,0.0f,0.0f);
cubeNormals[4].set(0.0f,1.0f,0.0f);
cubeNormals[5].set(0.0f,-1.0f,0.0f);
cube->setNormals( cubeNormals );
cube->setNormalBinding( osg::GeoSet::BIND_PERPRIM );
// ---------------------------------------
// Set up a StateSet to make the cube red
// ---------------------------------------
osg::StateSet* cubeState = new osg::StateSet();
osg::Material* redMaterial = new osg::Material();
osg::Vec4 red( 1.0f, 0.0f, 0.0f, 1.0f );
redMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, red );
cubeState->setAttribute( redMaterial );
cube->setStateSet( cubeState );
geode->addDrawable( cube );
return geode;
}
osg::Geode* createGeometryCube()
{
osg::Geode* geode = new osg::Geode();
@@ -280,7 +176,6 @@ int main( int argc, char **argv )
viewer.readCommandLine(commandLine);
osg::Transform* myTransform = new osg::Transform();
// myTransform->addChild( createCube() );
myTransform->addChild( createGeometryCube() );
// move node in a circle at 90 degrees a sec.

View File

@@ -979,8 +979,55 @@ bool GeoSet::getStats(Statistics &stat)
return true;
}
void GeoSet::applyPrimitiveOperation(PrimitiveFunctor& functor)
{
// will easily convert into a Geometry.
if (!_coords || !_numcoords) return;
functor.setVertexArray(_numcoords,_coords);
if( _needprimlen )
{
// LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP,
// TRIANGLE_FAN, QUAD_STRIP, POLYGONS
int index = 0;
if( _primLengths == (int *)0 )
{
return;
}
for( int i = 0; i < _numprims; i++ )
{
if( _cindex.valid() )
{
if (_cindex._is_ushort)
functor.drawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] );
else
functor.drawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] );
}
else
functor.drawArrays( (GLenum)_oglprimtype, index, _primLengths[i] );
index += _primLengths[i];
}
}
else // POINTS, LINES, TRIANGLES, QUADS
{
if( _cindex.valid())
{
if (_cindex._is_ushort)
functor.drawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._ushort );
else
functor.drawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._uint );
}
else
functor.drawArrays( (GLenum)_oglprimtype, 0, _numcoords );
}
}
Geometry* GeoSet::convertToGeometry()
{

View File

@@ -73,6 +73,8 @@ void Geometry::setTexCoordArray(unsigned int unit,AttributeArray* array)
_texCoordList.resize(unit+1,0);
_texCoordList[unit] = array;
dirtyDisplayList();
}
AttributeArray* Geometry::getTexCoordArray(unsigned int unit)
@@ -245,6 +247,22 @@ Drawable::AttributeBitMask Geometry::applyAttributeOperation(AttributeFunctor& )
return 0;
}
void Geometry::applyPrimitiveOperation(PrimitiveFunctor& functor)
{
if (!_vertexArray.valid() || _vertexArray->empty()) return;
functor.setVertexArray(_vertexArray->size(),&(_vertexArray->front()));
for(PrimitiveList::iterator itr=_primitives.begin();
itr!=_primitives.end();
++itr)
{
(*itr)->applyPrimitiveOperation(functor);
}
}
const bool Geometry::computeBound() const
{
_bbox.init();

View File

@@ -5,7 +5,7 @@
#include <osg/Notify>
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/Texture>
@@ -491,35 +491,33 @@ Geode* osg::createGeodeForImage(osg::Image* image,const float s,const float t)
dstate->setAttributeAndModes(texture,osg::StateAttribute::ON);
// set up the geoset.
osg::GeoSet* gset = osgNew osg::GeoSet;
gset->setStateSet(dstate);
Geometry* geom = osgNew Geometry;
geom->setStateSet(dstate);
osg::Vec3* coords = osgNew Vec3[4];
coords[0].set(-x,0.0f,y);
coords[1].set(-x,0.0f,-y);
coords[2].set(x,0.0f,-y);
coords[3].set(x,0.0f,y);
gset->setCoords(coords);
Vec3Array* coords = osgNew Vec3Array(4);
(*coords)[0].set(-x,0.0f,y);
(*coords)[1].set(-x,0.0f,-y);
(*coords)[2].set(x,0.0f,-y);
(*coords)[3].set(x,0.0f,y);
geom->setVertexArray(coords);
osg::Vec2* tcoords = osgNew Vec2[4];
tcoords[0].set(0.0f,1.0f);
tcoords[1].set(0.0f,0.0f);
tcoords[2].set(1.0f,0.0f);
tcoords[3].set(1.0f,1.0f);
gset->setTextureCoords(tcoords);
gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
Vec2Array* tcoords = osgNew Vec2Array(4);
(*tcoords)[0].set(0.0f,1.0f);
(*tcoords)[1].set(0.0f,0.0f);
(*tcoords)[2].set(1.0f,0.0f);
(*tcoords)[3].set(1.0f,1.0f);
geom->setTexCoordArray(0,tcoords);
osg::Vec4* colours = osgNew Vec4[1];
colours->set(1.0f,1.0f,1.0,1.0f);
gset->setColors(colours);
gset->setColorBinding(osg::GeoSet::BIND_OVERALL);
osg::Vec4Array* colours = osgNew osg::Vec4Array(1);
(*colours)[0].set(1.0f,1.0f,1.0,1.0f);
geom->setColorArray(colours);
geom->setColorBinding(Geometry::BIND_OVERALL);
gset->setNumPrims(1);
gset->setPrimType(osg::GeoSet::QUADS);
geom->addPrimitive(osgNew DrawArrays(Primitive::QUADS,0,4));
// set up the geode.
osg::Geode* geode = osgNew osg::Geode;
geode->addDrawable(gset);
geode->addDrawable(geom);
return geode;

View File

@@ -6,7 +6,7 @@
#include <math.h>
#include <float.h>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osg/ImpostorSprite>
#include <osg/Texture>
#include <osg/TexEnv>

View File

@@ -3,7 +3,6 @@
#include <osg/Group>
#include <osg/Geode>
#include <osg/GeoSet>
using namespace osg;
@@ -163,59 +162,7 @@ float computePolytopeVolume(const PointList& front, const PointList& back)
return volume;
}
Drawable* createOccluderDrawable(const PointList& front, const PointList& back)
{
// create a drawable for occluder.
osg::GeoSet* geoset = osgNew osg::GeoSet;
int totalNumber = front.size()+back.size();
osg::Vec3* coords = osgNew osg::Vec3[front.size()+back.size()];
osg::Vec3* cptr = coords;
for(PointList::const_iterator fitr=front.begin();
fitr!=front.end();
++fitr)
{
*cptr = fitr->second;
++cptr;
}
for(PointList::const_iterator bitr=back.begin();
bitr!=back.end();
++bitr)
{
*cptr = bitr->second;
++cptr;
}
geoset->setCoords(coords);
osg::Vec4* color = osgNew osg::Vec4[1];
color[0].set(1.0f,1.0f,1.0f,0.5f);
geoset->setColors(color);
geoset->setColorBinding(osg::GeoSet::BIND_OVERALL);
geoset->setPrimType(osg::GeoSet::POINTS);
geoset->setNumPrims(totalNumber);
//cout << "totalNumber = "<<totalNumber<<endl;
osg::Geode* geode = osgNew osg::Geode;
geode->addDrawable(geoset);
osg::StateSet* stateset = osgNew osg::StateSet;
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geoset->setStateSet(stateset);
return geoset;
}
bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables)
bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool /*createDrawables*/)
{
@@ -291,24 +238,6 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
_volume = computePolytopeVolume(points,farPoints)/volumeview;
if (createDrawables && !nodePath.empty())
{
osg::Group* group = dynamic_cast<osg::Group*>(nodePath.back());
if (group)
{
osg::Matrix invMV;
invMV.invert(MV);
transform(points,invMV);
transform(farPoints,invMV);
osg::Geode* geode = osgNew osg::Geode;
group->addChild(geode);
geode->addDrawable(createOccluderDrawable(points,farPoints));
}
}
for(ConvexPlanerOccluder::HoleList::const_iterator hitr=occluder.getHoleList().begin();
hitr!=occluder.getHoleList().end();
@@ -350,24 +279,6 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
// remove the hole's volume from the occluder volume.
_volume -= computePolytopeVolume(points,farPoints)/volumeview;
if (createDrawables && !nodePath.empty())
{
osg::Group* group = dynamic_cast<osg::Group*>(nodePath.back());
if (group)
{
osg::Matrix invMV;
invMV.invert(MV);
transform(points,invMV);
transform(farPoints,invMV);
osg::Geode* geode = osgNew osg::Geode;
group->addChild(geode);
geode->addDrawable(createOccluderDrawable(points,farPoints));
}
}
}
}

View File

@@ -1158,8 +1158,8 @@ void Viewer::keyboard(unsigned char key, int x, int y)
if (key=='r' && geode)
{
// remove geoset..
osg::GeoSet* gset = hitr->_geoset.get();
osg::notify(osg::NOTICE) << " geoset ("<<gset<<") "<<geode->removeDrawable(gset)<<")"<< std::endl;
osg::Drawable* drawable = hitr->_drawable.get();
osg::notify(osg::NOTICE) << " drawable ("<<drawable<<") "<<geode->removeDrawable(drawable)<<")"<< std::endl;
}
}

View File

@@ -629,7 +629,7 @@ bool Primitve_writeLocalData(const Primitive& prim,Output& fw)
case(UByteDrawElementsPrimitiveType):
{
const UByteDrawElements& cprim = static_cast<const UByteDrawElements&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
Array_writeLocalData(fw,cprim.begin(),cprim.end());
return true;
}
@@ -637,7 +637,7 @@ bool Primitve_writeLocalData(const Primitive& prim,Output& fw)
case(UShortDrawElementsPrimitiveType):
{
const UShortDrawElements& cprim = static_cast<const UShortDrawElements&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
Array_writeLocalData(fw,cprim.begin(),cprim.end());
return true;
}
@@ -645,7 +645,7 @@ bool Primitve_writeLocalData(const Primitive& prim,Output& fw)
case(UIntDrawElementsPrimitiveType):
{
const UIntDrawElements& cprim = static_cast<const UIntDrawElements&>(prim);
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<std::endl;
fw<<cprim.className()<<" "<<Geometry_getPrimitiveModeStr(cprim.getMode())<<" "<<cprim.size()<<std::endl;
Array_writeLocalData(fw,cprim.begin(),cprim.end());
return true;
}

View File

@@ -27,7 +27,7 @@ Hit::Hit(const Hit& hit)
_localLineSegment = hit._localLineSegment;
_nodePath = hit._nodePath;
_geode = hit._geode;
_geoset = hit._geoset;
_drawable = hit._drawable;
_matrix = hit._matrix;
_inverse = hit._inverse;
@@ -58,7 +58,7 @@ Hit& Hit::operator = (const Hit& hit)
_localLineSegment = hit._localLineSegment;
_nodePath = hit._nodePath;
_geode = hit._geode;
_geoset = hit._geoset;
_drawable = hit._drawable;
_vecIndexList = hit._vecIndexList;
_primitiveIndex = hit._primitiveIndex;
@@ -180,7 +180,8 @@ void IntersectVisitor::addLineSegment(LineSegment* seg)
if (!seg->valid())
{
notify(WARN)<<"Warning: invalid line segment passed to IntersectVisitor::addLineSegment(..), segment ignored.."<< std::endl;
notify(WARN)<<"Warning: invalid line segment passed to IntersectVisitor::addLineSegment(..)"<<std::endl;
notify(WARN)<<" "<<seg->start()<<" "<<seg->end()<<" segment ignored.."<< std::endl;
return;
}
@@ -304,7 +305,16 @@ struct TriangleIntersect
typedef std::multimap<float,std::pair<int,osg::Vec3> > TriangleHitList;
TriangleHitList _thl;
TriangleIntersect()
{
}
TriangleIntersect(const LineSegment& seg,float ratio=FLT_MAX)
{
set(seg,ratio);
}
void set(const LineSegment& seg,float ratio=FLT_MAX)
{
_seg=new LineSegment(seg);
_hit=false;
@@ -315,7 +325,6 @@ struct TriangleIntersect
_d = _seg->end()-_seg->start();
_length = _d.length();
_d /= _length;
}
// bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r)
@@ -408,6 +417,14 @@ struct TriangleIntersect
float r = d/_length;
if (!in.valid())
{
osg::notify(WARN)<<"Warning:: Picked up error in TriangleIntersect"<<std::endl;
osg::notify(WARN)<<" ("<<v1<<",\t"<<v2<<",\t"<<v3<<")"<<std::endl;
osg::notify(WARN)<<" ("<<r1<<",\t"<<r2<<",\t"<<r3<<")"<<std::endl;
return;
}
_thl.insert(std::pair<const float,std::pair<int,osg::Vec3> > (r,std::pair<int,osg::Vec3>(_index-1,normal)));
_hit = true;
@@ -415,13 +432,13 @@ struct TriangleIntersect
};
bool IntersectVisitor::intersect(GeoSet& gset)
bool IntersectVisitor::intersect(Drawable& drawable)
{
bool hitFlag = false;
IntersectState* cis = _intersectStateStack.back().get();
const BoundingBox& bb = gset.getBound();
const BoundingBox& bb = drawable.getBound();
for(IntersectState::LineSegmentList::iterator sitr=cis->_segList.begin();
sitr!=cis->_segList.end();
@@ -429,8 +446,10 @@ bool IntersectVisitor::intersect(GeoSet& gset)
{
if (sitr->second->intersect(bb))
{
TriangleIntersect ti(*sitr->second);
for_each_triangle(gset,ti);
TriangleFunctor<TriangleIntersect> ti;
ti.set(*sitr->second);
drawable.applyPrimitiveOperation(ti);
if (ti._hit)
{
@@ -442,7 +461,7 @@ bool IntersectVisitor::intersect(GeoSet& gset)
hit._nodePath = _nodePath;
hit._matrix = cis->_matrix;
hit._inverse = cis->_inverse;
hit._geoset = &gset;
hit._drawable = &drawable;
if (_nodePath.empty()) hit._geode = NULL;
else hit._geode = dynamic_cast<Geode*>(_nodePath.back());
@@ -470,49 +489,13 @@ bool IntersectVisitor::intersect(GeoSet& gset)
}
void IntersectVisitor::apply(Geode& geode)
{
if (!enterNode(geode)) return;
for(int i = 0; i < geode.getNumDrawables(); i++ )
{
osg::GeoSet* gset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (gset) intersect(*gset);
else
{
IntersectState* cis = _intersectStateStack.back().get();
// simply default to intersecting with bounding box.
for(IntersectState::LineSegmentList::iterator sitr=cis->_segList.begin();
sitr!=cis->_segList.end();
++sitr)
{
if (sitr->second->intersect(geode.getDrawable(i)->getBound()))
{
Hit hit;
hit._nodePath = _nodePath;
hit._matrix = cis->_matrix;
hit._inverse = cis->_inverse;
hit._geoset = NULL;
if (_nodePath.empty()) hit._geode = NULL;
else hit._geode = dynamic_cast<Geode*>(_nodePath.back());
hit._ratio = 0.0f;
hit._primitiveIndex = -1;
hit._originalLineSegment = sitr->first;
hit._localLineSegment = sitr->second;
hit._intersectPoint = geode.getDrawable(i)->getBound().center();
hit._intersectNormal.set(0.0,0.0,1.0);
_segHitList[sitr->first.get()].push_back(hit);
std::sort(_segHitList[sitr->first.get()].begin(),_segHitList[sitr->first.get()].end());
}
}
}
intersect(*geode.getDrawable(i));
}
leaveNode();

View File

@@ -64,9 +64,9 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
}
// // convert the old style GeoSet to Geometry
// ConvertGeoSetsToGeometryVisitor cgtg;
// node->accept(cgtg);
// convert the old style GeoSet to Geometry
// ConvertGeoSetsToGeometryVisitor cgtg;
// node->accept(cgtg);
if (options & SHARE_DUPLICATE_STATE)

View File

@@ -22,7 +22,7 @@ struct LessPtr
};
// triangle functor.
struct TriangleFunctor
struct SmoothTriangleFunctor
{
osg::Vec3 *_coordBase;
@@ -31,7 +31,7 @@ struct TriangleFunctor
typedef std::multiset<const osg::Vec3*,LessPtr> CoordinateSet;
CoordinateSet _coordSet;
TriangleFunctor(osg::Vec3 *cb,int noVertices, osg::Vec3 *nb) : _coordBase(cb),_normalBase(nb)
SmoothTriangleFunctor(osg::Vec3 *cb,int noVertices, osg::Vec3 *nb) : _coordBase(cb),_normalBase(nb)
{
osg::Vec3* vptr = cb;
for(int i=0;i<noVertices;++i)
@@ -116,7 +116,7 @@ void SmoothingVisitor::smooth(osg::GeoSet& gset)
norms[j].set(0.0f,0.0f,0.0f);
}
TriangleFunctor tf(coords,ncoords,norms);
SmoothTriangleFunctor tf(coords,ncoords,norms);
for_each_triangle( gset, tf );
for(j = 0; j < ncoords; j++ )

View File

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