More clean up for synch with 0.8.42
This commit is contained in:
0
src/Demos/osgreflect/Makedepend
Normal file
0
src/Demos/osgreflect/Makedepend
Normal file
20
src/Demos/osgreflect/Makefile
Normal file
20
src/Demos/osgreflect/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
#!smake
|
||||
include ../../../Make/makedefs
|
||||
|
||||
C++FILES = \
|
||||
osgreflect.cpp \
|
||||
|
||||
TARGET = ../../../bin/osgreflect
|
||||
|
||||
TARGET_BIN_FILES = osgreflect
|
||||
|
||||
#note, use this library list when using the Performer osgPlugin.
|
||||
#LIBS = ${PFLIBS} -losgGLUT -losgUtil -losgDB -losg $(GLUTLIB) -lGLU -lGL -lm -lXmu -lX11 -lXi
|
||||
|
||||
#note, standard library list.
|
||||
LIBS = -losgGLUT -losgUtil -losgDB -losg $(GLUTLIB) -lGLU -lGL -lm -lXmu -lX11 -lXi
|
||||
|
||||
C++FLAGS += -I../../../include
|
||||
LDFLAGS += -L../../../lib
|
||||
|
||||
include ../../../Make/makerules
|
||||
484
src/Demos/osgreflect/osgreflect.cpp
Normal file
484
src/Demos/osgreflect/osgreflect.cpp
Normal file
@@ -0,0 +1,484 @@
|
||||
#include <osg/Node>
|
||||
#include <osg/GeoSet>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Texture>
|
||||
#include <osg/Transparency>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/ColorMask>
|
||||
#include <osg/Depth>
|
||||
#include <osg/ClipPlane>
|
||||
|
||||
#include <osgUtil/TrackballManipulator>
|
||||
#include <osgUtil/FlightManipulator>
|
||||
#include <osgUtil/DriveManipulator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <GL/glut.h>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A simple demo demonstrating planer reflections using multiple renderings
|
||||
// of a subgraph, overriding of state attribures and use of the stencil buffer.
|
||||
//
|
||||
// The multipass system implemented here is a variation if Mark Kilgard's
|
||||
// paper "Improving Shadows and Reflections via the Stencil Buffer" which
|
||||
// can be found on the developer parts of the NVidia web site.
|
||||
//
|
||||
// The variations comes from the fact that the mirrors stencil values
|
||||
// are done on the first pass, rather than the second as in Mark's paper.
|
||||
// The second pass is now Mark's first pass - drawing the unreflected scene,
|
||||
// but also unsets the stencil buffer. This variation stops the unreflected
|
||||
// world poking through the mirror to be seen in the final rendering and
|
||||
// also obscures the world correctly when on the reverse side of the mirror.
|
||||
// Although there is still some unresolved issue with the clip plane needing
|
||||
// to be flipped when looking at the reverse side of the mirror. Niether
|
||||
// of these issues are mentioned in the Mark's paper, but trip us up when
|
||||
// we apply them.
|
||||
|
||||
|
||||
// create an app visitor, to be used on each frame update,
|
||||
// the below app visitor rotates the loaded model.
|
||||
class AppVisitor : public osg::NodeVisitor {
|
||||
public:
|
||||
|
||||
bool _haveDoneTransformTransform;
|
||||
float _delta_angle;
|
||||
float _angular_velocity;
|
||||
osg::Vec3 _pivotPoint;
|
||||
osg::Transform* _modifyTransform;
|
||||
osg::Timer _timer;
|
||||
osg::Timer_t _previous_t;
|
||||
|
||||
AppVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
_haveDoneTransformTransform = true;
|
||||
_modifyTransform = NULL;
|
||||
_delta_angle = 0;
|
||||
_angular_velocity = 45; //degrees a sec.
|
||||
_previous_t = _timer.tick();
|
||||
}
|
||||
|
||||
virtual void reset()
|
||||
{
|
||||
// set to no transform done so far in this new traversal.
|
||||
_haveDoneTransformTransform = false;
|
||||
|
||||
// update angle of rotation.
|
||||
osg::Timer_t new_t = _timer.tick();
|
||||
_delta_angle = _angular_velocity*_timer.delta_s(_previous_t,new_t);
|
||||
_previous_t = new_t;
|
||||
|
||||
}
|
||||
|
||||
virtual void apply(osg::Transform& visitor_dcs)
|
||||
{
|
||||
|
||||
if (&visitor_dcs == _modifyTransform && !_haveDoneTransformTransform)
|
||||
{
|
||||
// update the specified dcs.
|
||||
visitor_dcs.preTranslate(_pivotPoint[0],_pivotPoint[1],_pivotPoint[2]);
|
||||
visitor_dcs.preRotate(_delta_angle,0.0f,0.0f,1.0f);
|
||||
visitor_dcs.preTranslate(-_pivotPoint[0],-_pivotPoint[1],-_pivotPoint[2]);
|
||||
|
||||
// set to true to prevent applying rotation more than once
|
||||
// since the subgraph appears twice in the overall scene.
|
||||
_haveDoneTransformTransform = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Function to read several files (typically one) as specified on the command
|
||||
* line, and return them in an osg::Node
|
||||
*/
|
||||
osg::Node* getNodeFromFiles(int argc,char **argv)
|
||||
{
|
||||
osg::Node *rootnode = new osg::Node;
|
||||
|
||||
int i;
|
||||
|
||||
typedef std::vector<osg::Node*> NodeList;
|
||||
NodeList nodeList;
|
||||
for( i = 1; i < argc; i++ )
|
||||
{
|
||||
|
||||
if (argv[i][0]=='-')
|
||||
{
|
||||
switch(argv[i][1])
|
||||
{
|
||||
case('l'):
|
||||
++i;
|
||||
if (i<argc)
|
||||
{
|
||||
osgDB::Registry::instance()->loadLibrary(argv[i]);
|
||||
}
|
||||
break;
|
||||
case('e'):
|
||||
++i;
|
||||
if (i<argc)
|
||||
{
|
||||
std::string libName = osgDB::Registry::instance()->createLibraryNameForExt(argv[i]);
|
||||
osgDB::Registry::instance()->loadLibrary(libName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
osg::Node *node = osgDB::readNodeFile( argv[i] );
|
||||
|
||||
if( node != (osg::Node *)0L )
|
||||
{
|
||||
if (node->getName().empty()) node->setName( argv[i] );
|
||||
nodeList.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nodeList.size()==0)
|
||||
{
|
||||
osg::notify(osg::WARN) << "No data loaded."<<endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (nodeList.size()==1)
|
||||
{
|
||||
rootnode = nodeList.front();
|
||||
}
|
||||
else // size >1
|
||||
{
|
||||
osg::Group* group = new osg::Group();
|
||||
for(NodeList::iterator itr=nodeList.begin();
|
||||
itr!=nodeList.end();
|
||||
++itr)
|
||||
{
|
||||
group->addChild(*itr);
|
||||
}
|
||||
|
||||
rootnode = group;
|
||||
}
|
||||
|
||||
return rootnode;
|
||||
}
|
||||
|
||||
osg::StateSet* createMirrorTexturedState(const std::string& filename)
|
||||
{
|
||||
osg::StateSet* dstate = new osg::StateSet;
|
||||
dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
|
||||
// set up the texture.
|
||||
osg::Image* image = osgDB::readImageFile(filename.c_str());
|
||||
if (image)
|
||||
{
|
||||
osg::Texture* texture = new osg::Texture;
|
||||
texture->setImage(image);
|
||||
dstate->setAttributeAndModes(texture,osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
return dstate;
|
||||
}
|
||||
|
||||
|
||||
osg::Drawable* createMirrorSurface(float xMin,float xMax,float yMin,float yMax,float z)
|
||||
{
|
||||
|
||||
// set up the drawstate.
|
||||
|
||||
// set up the geoset.
|
||||
osg::GeoSet* gset = new osg::GeoSet;
|
||||
|
||||
osg::Vec3* coords = new osg::Vec3 [4];
|
||||
coords[0].set(xMin,yMax,z);
|
||||
coords[1].set(xMin,yMin,z);
|
||||
coords[2].set(xMax,yMin,z);
|
||||
coords[3].set(xMax,yMax,z);
|
||||
gset->setCoords(coords);
|
||||
|
||||
osg::Vec3* norms = new osg::Vec3 [1];
|
||||
norms[0].set(0.0f,0.0f,1.0f);
|
||||
gset->setNormals(norms);
|
||||
gset->setNormalBinding(osg::GeoSet::BIND_OVERALL);
|
||||
|
||||
osg::Vec2* tcoords = new osg::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);
|
||||
|
||||
osg::Vec4* colours = new osg::Vec4;
|
||||
colours->set(1.0f,1.0f,1.0,1.0f);
|
||||
gset->setColors(colours);
|
||||
gset->setColorBinding(osg::GeoSet::BIND_OVERALL);
|
||||
|
||||
gset->setNumPrims(1);
|
||||
gset->setPrimType(osg::GeoSet::QUADS);
|
||||
|
||||
return gset;
|
||||
}
|
||||
|
||||
void write_usage()
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<endl;
|
||||
osg::notify(osg::NOTICE)<<"usage:"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" osgreflect [options] infile1 [infile2 ...]"<<endl;
|
||||
osg::notify(osg::NOTICE)<<endl;
|
||||
osg::notify(osg::NOTICE)<<"options:"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" -l libraryName - load plugin of name libraryName"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -l osgdb_pfb"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful for loading reader/writers which can load"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" other file formats in addition to its extension."<<endl;
|
||||
osg::notify(osg::NOTICE)<<" -e extensionName - load reader/wrter plugin for file extension"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -e pfb"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful short hand for specifying full library name as"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" done with -l above, as it automatically expands to the"<<endl;
|
||||
osg::notify(osg::NOTICE)<<" full library name appropriate for each platform."<<endl;
|
||||
osg::notify(osg::NOTICE)<<endl;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// initialize the GLUT
|
||||
glutInit( &argc, argv );
|
||||
|
||||
if (argc<2)
|
||||
{
|
||||
write_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// load a model from file, and add it into the root group node.
|
||||
osg::Node* loadedModel = getNodeFromFiles( argc, argv);
|
||||
|
||||
if (!loadedModel)
|
||||
{
|
||||
write_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
osg::Transform* loadedModelTransform = new osg::Transform;
|
||||
loadedModelTransform->addChild(loadedModel);
|
||||
|
||||
// calculate where to place the mirror according to the
|
||||
// loaded models bounding sphere.
|
||||
const osg::BoundingSphere& bs = loadedModelTransform->getBound();
|
||||
|
||||
float width_factor = 1.5;
|
||||
float height_factor = 0.3;
|
||||
|
||||
float xMin = bs.center().x()-bs.radius()*width_factor;
|
||||
float xMax = bs.center().x()+bs.radius()*width_factor;
|
||||
float yMin = bs.center().y()-bs.radius()*width_factor;
|
||||
float yMax = bs.center().y()+bs.radius()*width_factor;
|
||||
|
||||
float z = bs.center().z()-bs.radius()*height_factor;
|
||||
|
||||
|
||||
// create a textured, transparent node at the appropriate place.
|
||||
osg::Drawable* mirror = createMirrorSurface(xMin,xMax,yMin,yMax,z);
|
||||
|
||||
|
||||
osg::Group* rootNode = new osg::Group;
|
||||
|
||||
// make sure that the global color mask exists.
|
||||
osg::ColorMask* rootColorMask = new osg::ColorMask;
|
||||
rootColorMask->setMask(true,true,true,true);
|
||||
|
||||
// set up depth so all writing to depth goes to maximum depth.
|
||||
osg::Depth* rootDepth = new osg::Depth;
|
||||
rootDepth->setFunction(osg::Depth::LESS);
|
||||
rootDepth->setRange(0.0,1.0);
|
||||
|
||||
osg::StateSet* rootStateSet = new osg::StateSet();
|
||||
rootStateSet->setAttribute(rootColorMask);
|
||||
rootStateSet->setAttribute(rootDepth);
|
||||
|
||||
rootNode->setStateSet(rootStateSet);
|
||||
|
||||
|
||||
// bin1 - set up the stencil values and depth for mirror.
|
||||
{
|
||||
|
||||
// set up the stencil ops so that the stencil buffer get set at
|
||||
// the mirror plane
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::ALWAYS,1,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);
|
||||
|
||||
// switch off the writing to the color bit planes.
|
||||
osg::ColorMask* colorMask = new osg::ColorMask;
|
||||
colorMask->setMask(false,false,false,false);
|
||||
|
||||
osg::StateSet* statesetBin1 = new osg::StateSet();
|
||||
statesetBin1->setRenderBinDetails(1,"RenderBin");
|
||||
statesetBin1->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
statesetBin1->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
statesetBin1->setAttribute(colorMask);
|
||||
|
||||
// set up the mirror geode.
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(mirror);
|
||||
geode->setStateSet(statesetBin1);
|
||||
|
||||
rootNode->addChild(geode);
|
||||
|
||||
}
|
||||
|
||||
// bin one - draw scene without mirror or reflection, unset
|
||||
// stencil values where scene is infront of mirror and hence
|
||||
// occludes the mirror.
|
||||
{
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::ALWAYS,0,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);
|
||||
|
||||
osg::StateSet* statesetBin2 = new osg::StateSet();
|
||||
statesetBin2->setRenderBinDetails(2,"RenderBin");
|
||||
statesetBin2->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
|
||||
|
||||
osg::Group* groupBin2 = new osg::Group();
|
||||
groupBin2->setStateSet(statesetBin2);
|
||||
groupBin2->addChild(loadedModelTransform);
|
||||
|
||||
rootNode->addChild(groupBin2);
|
||||
}
|
||||
|
||||
// bin3 - set up the depth to the furthest depth value
|
||||
{
|
||||
|
||||
// set up the stencil ops so that only operator on this mirrors stencil value.
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::EQUAL,1,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
|
||||
|
||||
// switch off the writing to the color bit planes.
|
||||
osg::ColorMask* colorMask = new osg::ColorMask;
|
||||
colorMask->setMask(false,false,false,false);
|
||||
|
||||
// set up depth so all writing to depth goes to maximum depth.
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
depth->setRange(1.0,1.0);
|
||||
|
||||
osg::StateSet* statesetBin3 = new osg::StateSet();
|
||||
statesetBin3->setRenderBinDetails(3,"RenderBin");
|
||||
statesetBin3->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
statesetBin3->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
statesetBin3->setAttribute(colorMask);
|
||||
statesetBin3->setAttribute(depth);
|
||||
|
||||
// set up the mirror geode.
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(mirror);
|
||||
geode->setStateSet(statesetBin3);
|
||||
|
||||
rootNode->addChild(geode);
|
||||
|
||||
}
|
||||
|
||||
// bin4 - draw the reflection.
|
||||
{
|
||||
|
||||
// now create the 'reflection' of the loaded model by applying
|
||||
// create a Transform which flips the loaded model about the z axis
|
||||
// relative to the mirror node, the loadedModel is added to the
|
||||
// Transform so now appears twice in the scene, but is shared so there
|
||||
// is negligable memory overhead. Also use an osg::StateSet
|
||||
// attached to the Transform to override the face culling on the subgraph
|
||||
// to prevert an 'inside' out view of the reflected model.
|
||||
// set up the stencil ops so that only operator on this mirrors stencil value.
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::EQUAL,1,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
|
||||
|
||||
// this clip plane removes any of the scene which when mirror would
|
||||
// poke through the mirror. However, this clip plane should really
|
||||
// flip sides once the eye point goes to the back of the mirror...
|
||||
osg::ClipPlane* clipplane = new osg::ClipPlane;
|
||||
clipplane->setClipPlane(osg::Vec4(0.0f,0.0f,-1.0f,z));
|
||||
clipplane->setClipPlaneNum(0);
|
||||
|
||||
osg::StateSet* dstate = new osg::StateSet;
|
||||
dstate->setRenderBinDetails(4,"RenderBin");
|
||||
dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE_OFF);
|
||||
dstate->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
dstate->setAttributeAndModes(clipplane,osg::StateAttribute::ON);
|
||||
|
||||
osg::Transform* dcs = new osg::Transform;
|
||||
dcs->setStateSet(dstate);
|
||||
dcs->preTranslate(0.0f,0.0f,z);
|
||||
dcs->preScale(1.0f,1.0f,-1.0f);
|
||||
dcs->preTranslate(0.0f,0.0f,-z);
|
||||
|
||||
dcs->addChild(loadedModelTransform);
|
||||
|
||||
rootNode->addChild(dcs);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// bin5 - draw the textured mirror and blend it with the reflection.
|
||||
{
|
||||
|
||||
// set up depth so all writing to depth goes to maximum depth.
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::EQUAL,1,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::ZERO);
|
||||
|
||||
// set up additive blending.
|
||||
osg::Transparency* trans = new osg::Transparency;
|
||||
trans->setFunction(osg::Transparency::ONE,osg::Transparency::ONE);
|
||||
|
||||
osg::StateSet* statesetBin5 = createMirrorTexturedState("tank.rgb");
|
||||
|
||||
statesetBin5->setRenderBinDetails(5,"RenderBin");
|
||||
statesetBin5->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
statesetBin5->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
statesetBin5->setAttributeAndModes(trans,osg::StateAttribute::ON);
|
||||
statesetBin5->setAttribute(depth);
|
||||
|
||||
// set up the mirror geode.
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(mirror);
|
||||
geode->setStateSet(statesetBin5);
|
||||
|
||||
rootNode->addChild(geode);
|
||||
|
||||
}
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer;
|
||||
viewer.addViewport( rootNode );
|
||||
|
||||
|
||||
// create and register the app visitor.
|
||||
AppVisitor* appVisitor = new AppVisitor();
|
||||
appVisitor->_modifyTransform = loadedModelTransform;
|
||||
appVisitor->_pivotPoint = bs.center();
|
||||
|
||||
viewer.getViewportSceneView(0)->setAppVisitor(appVisitor);
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgUtil::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgUtil::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
src/Demos/sgv/README
Normal file
26
src/Demos/sgv/README
Normal file
@@ -0,0 +1,26 @@
|
||||
Note: Using sgv with Peformer (for IRIX and Linux users only)
|
||||
=============================================================
|
||||
|
||||
If you find problems with loading .pfb files its likely that its due to undefined
|
||||
symbols. This isn't a problem with the OSG implementation, but alas the only
|
||||
current solution is to directly link you app with the Performer libraries. The
|
||||
Makefile contains two library list. In Makefile you'll see something like :
|
||||
|
||||
#note, use this library list when using the Performer osgPlugin.
|
||||
#LIBS = ${PFLIBS} -losgGLUT -losgDB -losg -lGLU -lGL -lm -lXmu -lX11 -lXi
|
||||
|
||||
#note, standard library list.
|
||||
LIBS = -losgGLUT -losgDB -losg -lGLU -lGL -lm -lXmu -lX11 -lXi
|
||||
|
||||
Simple comment in the LIBS line with PFLIBS and comment out the standard LIBS,
|
||||
then :
|
||||
|
||||
make clean
|
||||
make
|
||||
|
||||
Hopefully the Performer distribution will eventually work as a dynamic plugin
|
||||
but until that day we're stuck with this 'hack'...
|
||||
|
||||
|
||||
Robert Osfield,
|
||||
March 20001.
|
||||
98
src/osg/ClipPlane.cpp
Normal file
98
src/osg/ClipPlane.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <osg/ClipPlane>
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
ClipPlane::ClipPlane()
|
||||
{
|
||||
_clipPlane = new double[4];
|
||||
_clipPlane[0] = 0.0;
|
||||
_clipPlane[1] = 0.0;
|
||||
_clipPlane[2] = 0.0;
|
||||
_clipPlane[3] = 0.0;
|
||||
_clipPlaneNum = 0;
|
||||
}
|
||||
|
||||
|
||||
ClipPlane::~ClipPlane()
|
||||
{
|
||||
delete _clipPlane;
|
||||
}
|
||||
|
||||
void ClipPlane::setClipPlane(const Vec4& plane)
|
||||
{
|
||||
_clipPlane[0] = plane[0];
|
||||
_clipPlane[1] = plane[1];
|
||||
_clipPlane[2] = plane[2];
|
||||
_clipPlane[3] = plane[3];
|
||||
}
|
||||
|
||||
void ClipPlane::setClipPlane(const Plane& plane)
|
||||
{
|
||||
_clipPlane[0] = plane[0];
|
||||
_clipPlane[1] = plane[1];
|
||||
_clipPlane[2] = plane[2];
|
||||
_clipPlane[3] = plane[3];
|
||||
}
|
||||
|
||||
void ClipPlane::setClipPlane(const double* plane)
|
||||
{
|
||||
if (plane)
|
||||
{
|
||||
_clipPlane[0] = plane[0];
|
||||
_clipPlane[1] = plane[1];
|
||||
_clipPlane[2] = plane[2];
|
||||
_clipPlane[3] = plane[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Warning: ClipPlane::setClipPlane() passed NULL plane array, ignoring operation."<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ClipPlane::getClipPlane(Vec4& plane) const
|
||||
{
|
||||
plane[0] = (float)_clipPlane[0];
|
||||
plane[1] = (float)_clipPlane[1];
|
||||
plane[2] = (float)_clipPlane[2];
|
||||
plane[3] = (float)_clipPlane[3];
|
||||
}
|
||||
|
||||
void ClipPlane::getClipPlane(Plane& plane) const
|
||||
{
|
||||
plane[0] = _clipPlane[0];
|
||||
plane[1] = _clipPlane[1];
|
||||
plane[2] = _clipPlane[2];
|
||||
plane[3] = _clipPlane[3];
|
||||
}
|
||||
|
||||
void ClipPlane::getClipPlane(double* plane) const
|
||||
{
|
||||
if (plane)
|
||||
{
|
||||
plane[0] = _clipPlane[0];
|
||||
plane[1] = _clipPlane[1];
|
||||
plane[2] = _clipPlane[2];
|
||||
plane[3] = _clipPlane[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Warning: ClipPlane::getClipPlane() passed NULL plane array, ignoring operation."<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ClipPlane::setClipPlaneNum(const unsigned int num)
|
||||
{
|
||||
_clipPlaneNum = num;
|
||||
}
|
||||
|
||||
const unsigned int ClipPlane::getClipPlaneNum() const
|
||||
{
|
||||
return _clipPlaneNum;
|
||||
}
|
||||
|
||||
void ClipPlane::apply(State&) const
|
||||
{
|
||||
glClipPlane((GLenum)(GL_CLIP_PLANE0+_clipPlaneNum),_clipPlane);
|
||||
}
|
||||
|
||||
23
src/osg/ColorMask.cpp
Normal file
23
src/osg/ColorMask.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <osg/ColorMask>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
ColorMask::ColorMask()
|
||||
{
|
||||
// set up same defaults as glColorMask.
|
||||
_red = true;
|
||||
_green = true;
|
||||
_blue = true;
|
||||
_alpha = true;
|
||||
}
|
||||
|
||||
|
||||
ColorMask::~ColorMask()
|
||||
{
|
||||
}
|
||||
|
||||
void ColorMask::apply(State&) const
|
||||
{
|
||||
glColorMask((GLboolean)_red,(GLboolean)_green,(GLboolean)_blue,(GLboolean)_alpha);
|
||||
}
|
||||
|
||||
25
src/osg/Depth.cpp
Normal file
25
src/osg/Depth.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <osg/Depth>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Depth::Depth()
|
||||
{
|
||||
_func = LESS;
|
||||
_depthWriteMask = true;
|
||||
|
||||
_zNear = 0.0;
|
||||
_zFar = 1.0;
|
||||
}
|
||||
|
||||
|
||||
Depth::~Depth()
|
||||
{
|
||||
}
|
||||
|
||||
void Depth::apply(State&) const
|
||||
{
|
||||
glDepthFunc((GLenum)_func);
|
||||
glDepthMask((GLboolean)_depthWriteMask);
|
||||
glDepthRange(_zNear,_zFar);
|
||||
}
|
||||
|
||||
159
src/osg/Drawable.cpp
Normal file
159
src/osg/Drawable.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <osg/Drawable>
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Drawable::DeletedDisplayListCache Drawable::s_deletedDisplayListCache;
|
||||
|
||||
Drawable::Drawable()
|
||||
{
|
||||
_bbox_computed = false;
|
||||
|
||||
// Note, if your are defining a subclass from drawable which is
|
||||
// dynamically updated then you should set both the following to
|
||||
// to false in your constructor. This will prevent any display
|
||||
// lists from being automatically created and safeguard the
|
||||
// dynamic updating of data.
|
||||
_supportsDisplayList = true;
|
||||
_useDisplayList = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Drawable::~Drawable()
|
||||
{
|
||||
dirtyDisplayList();
|
||||
}
|
||||
|
||||
|
||||
void Drawable::compile(State& state)
|
||||
{
|
||||
if (!_useDisplayList) return;
|
||||
|
||||
// get the contextID (user defined ID of 0 upwards) for the
|
||||
// current OpenGL context.
|
||||
uint contextID = state.getContextID();
|
||||
|
||||
// fill in array if required.
|
||||
while (_globjList.size()<=contextID) _globjList.push_back(0);
|
||||
|
||||
// get the globj for the current contextID.
|
||||
uint& globj = _globjList[contextID];
|
||||
|
||||
// call the globj if already set otherwise comple and execute.
|
||||
if( globj != 0 )
|
||||
{
|
||||
glDeleteLists( globj, 1 );
|
||||
}
|
||||
|
||||
|
||||
if (_dstate.valid())
|
||||
{
|
||||
_dstate->compile(state);
|
||||
}
|
||||
|
||||
globj = glGenLists( 1 );
|
||||
glNewList( globj, GL_COMPILE );
|
||||
drawImmediateMode(state);
|
||||
glEndList();
|
||||
|
||||
}
|
||||
|
||||
void Drawable::setSupportsDisplayList(const bool flag)
|
||||
{
|
||||
// if value unchanged simply return.
|
||||
if (_supportsDisplayList==flag) return;
|
||||
|
||||
// if previously set to true then need to check about display lists.
|
||||
if (_supportsDisplayList)
|
||||
{
|
||||
if (_useDisplayList)
|
||||
{
|
||||
// used to support display lists and display lists switched
|
||||
// on so now delete them and turn useDisplayList off.
|
||||
dirtyDisplayList();
|
||||
_useDisplayList = false;
|
||||
}
|
||||
}
|
||||
|
||||
// set with new value.
|
||||
_supportsDisplayList=flag;
|
||||
}
|
||||
|
||||
void Drawable::setUseDisplayList(const bool flag)
|
||||
{
|
||||
// if value unchanged simply return.
|
||||
if (_useDisplayList==flag) return;
|
||||
|
||||
// if was previously set to true, remove display list.
|
||||
if (_useDisplayList)
|
||||
{
|
||||
dirtyDisplayList();
|
||||
}
|
||||
|
||||
if (_supportsDisplayList)
|
||||
{
|
||||
|
||||
// set with new value.
|
||||
_useDisplayList = flag;
|
||||
|
||||
}
|
||||
else // does not support display lists.
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
notify(WARN)<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set with new value.
|
||||
_useDisplayList = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Drawable::dirtyDisplayList()
|
||||
{
|
||||
for(uint i=0;i<_globjList.size();++i)
|
||||
{
|
||||
if (_globjList[i] != 0)
|
||||
{
|
||||
Drawable::deleteDisplayList(i,_globjList[i]);
|
||||
_globjList[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Drawable::deleteDisplayList(uint contextID,uint globj)
|
||||
{
|
||||
if (globj!=0)
|
||||
{
|
||||
// insert the globj into the cache for the appropriate context.
|
||||
s_deletedDisplayListCache[contextID].insert(globj);
|
||||
}
|
||||
}
|
||||
|
||||
/** flush all the cached display list which need to be deleted
|
||||
* in the OpenGL context related to contextID.*/
|
||||
void Drawable::flushDeletedDisplayLists(uint contextID)
|
||||
{
|
||||
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
|
||||
if (citr!=s_deletedDisplayListCache.end())
|
||||
{
|
||||
std::set<uint>& displayListSet = citr->second;
|
||||
for(std::set<uint>::iterator gitr=displayListSet.begin();
|
||||
gitr!=displayListSet.end();
|
||||
++gitr)
|
||||
{
|
||||
glDeleteLists(*gitr,1);
|
||||
}
|
||||
|
||||
s_deletedDisplayListCache.erase(citr);
|
||||
}
|
||||
}
|
||||
19
src/osg/FrontFace.cpp
Normal file
19
src/osg/FrontFace.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "osg/GL"
|
||||
#include "osg/FrontFace"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
FrontFace::FrontFace()
|
||||
{
|
||||
_mode = COUNTER_CLOCKWISE;
|
||||
}
|
||||
|
||||
|
||||
FrontFace::~FrontFace()
|
||||
{
|
||||
}
|
||||
|
||||
void FrontFace::apply(State&) const
|
||||
{
|
||||
glFrontFace((GLenum)_mode);
|
||||
}
|
||||
74
src/osg/GLExtensions.cpp
Normal file
74
src/osg/GLExtensions.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif !defined macintosh
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "osg/GL"
|
||||
#include "osg/GLExtensions"
|
||||
#include "osg/Notify"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
const bool osg::isGLExtensionSupported(const char *extension)
|
||||
{
|
||||
typedef std::set<std::string> ExtensionSet;
|
||||
static ExtensionSet s_extensionSet;
|
||||
static const char* s_extensions = NULL;
|
||||
if (s_extensions==NULL)
|
||||
{
|
||||
// get the extension list from OpenGL.
|
||||
s_extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||
if (s_extensions==NULL) return false;
|
||||
|
||||
// insert the ' ' delimiated extensions words into the extensionSet.
|
||||
const char *startOfWord = s_extensions;
|
||||
const char *endOfWord;
|
||||
while ((endOfWord = strchr(startOfWord,' '))!=NULL)
|
||||
{
|
||||
s_extensionSet.insert(std::string(startOfWord,endOfWord));
|
||||
startOfWord = endOfWord+1;
|
||||
}
|
||||
if (*startOfWord!=0) s_extensionSet.insert(std::string(startOfWord));
|
||||
|
||||
osg::notify(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<endl;
|
||||
for(ExtensionSet::iterator itr=s_extensionSet.begin();
|
||||
itr!=s_extensionSet.end();
|
||||
++itr)
|
||||
{
|
||||
osg::notify(INFO)<<" "<<*itr<<endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// true if extension found in extensionSet.
|
||||
bool result = s_extensionSet.find(extension)!=s_extensionSet.end();
|
||||
|
||||
if (result) osg::notify(INFO)<<"OpenGL extension '"<<extension<<"' is supported."<<endl;
|
||||
else osg::notify(INFO)<<"OpenGL extension '"<<extension<<"' is not supported."<<endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void* osg::getGLExtensionFuncPtr(const char *funcName)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return wglGetProcAddress(funcName);
|
||||
#elif defined(macintosh)
|
||||
return NULL;
|
||||
#else
|
||||
static void *lib = dlopen("libGL.so", RTLD_LAZY);
|
||||
if (lib)
|
||||
return dlsym(lib, funcName);
|
||||
else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
64
src/osg/Impostor.cpp
Normal file
64
src/osg/Impostor.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "osg/Impostor"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Impostor::Impostor()
|
||||
{
|
||||
_impostorThreshold = -1.0f;
|
||||
}
|
||||
|
||||
|
||||
ImpostorSprite* Impostor::findBestImpostorSprite(const osg::Vec3& currLocalEyePoint)
|
||||
{
|
||||
float min_distance2 = FLT_MAX;
|
||||
ImpostorSprite* impostorSprite = NULL;
|
||||
for(ImpostorSpriteList::iterator itr=_impostorSpriteList.begin();
|
||||
itr!=_impostorSpriteList.end();
|
||||
++itr)
|
||||
{
|
||||
float distance2 = (currLocalEyePoint-(*itr)->getStoredLocalEyePoint()).length2();
|
||||
if (distance2<min_distance2)
|
||||
{
|
||||
min_distance2 = distance2;
|
||||
impostorSprite = itr->get();
|
||||
}
|
||||
}
|
||||
return impostorSprite;
|
||||
}
|
||||
|
||||
void Impostor::addImpostorSprite(ImpostorSprite* is)
|
||||
{
|
||||
if (is && is->getParent()!=this)
|
||||
{
|
||||
// add it to my impostor list first, so it remains referenced
|
||||
// when its reference in the previous_owner is removed.
|
||||
_impostorSpriteList.push_back(is);
|
||||
|
||||
if (is->getParent())
|
||||
{
|
||||
Impostor* previous_owner = is->getParent();
|
||||
ImpostorSpriteList& isl = previous_owner->_impostorSpriteList;
|
||||
|
||||
// find and erase reference to is.
|
||||
for(ImpostorSpriteList::iterator itr=isl.begin();
|
||||
itr!=isl.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)==is)
|
||||
{
|
||||
isl.erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
is->setParent(this);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const bool Impostor::computeBound() const
|
||||
{
|
||||
return LOD::computeBound();
|
||||
}
|
||||
273
src/osg/ImpostorSprite.cpp
Normal file
273
src/osg/ImpostorSprite.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable : 4786 )
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <osg/ImpostorSprite>
|
||||
#include <osg/Texture>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Notify>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
|
||||
ImpostorSprite::ImpostorSprite()
|
||||
{
|
||||
// don't use display list since we will be updating the geometry.
|
||||
_useDisplayList = false;
|
||||
_parent = NULL;
|
||||
|
||||
_ism = NULL;
|
||||
_previous = NULL;
|
||||
_next = NULL;
|
||||
|
||||
_texture = NULL;
|
||||
_s = 0;
|
||||
_t = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ImpostorSprite::~ImpostorSprite()
|
||||
{
|
||||
if (_ism)
|
||||
{
|
||||
_ism->remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
const float ImpostorSprite::calcPixelError(const Camera& camera,const int* viewport,const osg::Matrix* matrix) const
|
||||
{
|
||||
// find the maximum screen space pixel error between the control coords and the quad coners.
|
||||
float max_error_sqrd = 0.0f;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
|
||||
Vec3 projected_coord;
|
||||
Vec3 projected_control;
|
||||
if (matrix)
|
||||
{
|
||||
// project the coords of the quad into screen space.
|
||||
camera.project(_coords[i]*(*matrix),viewport,projected_coord);
|
||||
|
||||
// project the controls coords into screen space.
|
||||
camera.project(_controlcoords[i]*(*matrix),viewport,projected_control);
|
||||
}
|
||||
else
|
||||
{
|
||||
// project the coords of the quad into screen space.
|
||||
camera.project(_coords[i],viewport,projected_coord);
|
||||
|
||||
// project the controls coords into screen space.
|
||||
camera.project(_controlcoords[i],viewport,projected_control);
|
||||
}
|
||||
|
||||
float dx = (projected_coord.x()-projected_control.x());
|
||||
float dy = (projected_coord.y()-projected_control.y());
|
||||
|
||||
float error_sqrd = dx*dx+dy*dy;
|
||||
|
||||
if (error_sqrd > max_error_sqrd) max_error_sqrd = error_sqrd;
|
||||
|
||||
}
|
||||
|
||||
return sqrtf(max_error_sqrd);
|
||||
}
|
||||
|
||||
void ImpostorSprite::drawImmediateMode(State&)
|
||||
{
|
||||
// when the tex env is set to REPLACE, and the
|
||||
// texture is set up correctly the color has no effect.
|
||||
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
|
||||
glTexCoord2fv( (GLfloat *)&_texcoords[0] );
|
||||
glVertex3fv( (GLfloat *)&_coords[0] );
|
||||
|
||||
glTexCoord2fv( (GLfloat *)&_texcoords[1] );
|
||||
glVertex3fv( (GLfloat *)&_coords[1] );
|
||||
|
||||
glTexCoord2fv( (GLfloat *)&_texcoords[2] );
|
||||
glVertex3fv( (GLfloat *)&_coords[2] );
|
||||
|
||||
glTexCoord2fv( (GLfloat *)&_texcoords[3] );
|
||||
glVertex3fv( (GLfloat *)&_coords[3] );
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
const bool ImpostorSprite::computeBound() const
|
||||
{
|
||||
_bbox.init();
|
||||
_bbox.expandBy(_coords[0]);
|
||||
_bbox.expandBy(_coords[1]);
|
||||
_bbox.expandBy(_coords[2]);
|
||||
_bbox.expandBy(_coords[3]);
|
||||
|
||||
_bbox_computed=true;
|
||||
|
||||
if (!_bbox.isValid())
|
||||
{
|
||||
cout << "******* ImpostorSprite::computeBound() problem"<<endl;
|
||||
cout << "******* = "<<_coords[0]<<endl;
|
||||
cout << "******* = "<<_coords[1]<<endl;
|
||||
cout << "******* = "<<_coords[2]<<endl;
|
||||
cout << "******* = "<<_coords[3]<<endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImpostorSprite::setTexture(Texture* tex,int s,int t)
|
||||
{
|
||||
_texture = tex;
|
||||
_s = s;
|
||||
_t = t;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Helper class for managing the reuse of ImpostorSprite resources.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ImpostorSpriteManager::ImpostorSpriteManager()
|
||||
{
|
||||
_first = NULL;
|
||||
_last = NULL;
|
||||
}
|
||||
|
||||
|
||||
ImpostorSpriteManager::~ImpostorSpriteManager()
|
||||
{
|
||||
while (_first)
|
||||
{
|
||||
ImpostorSprite* next = _first->_next;
|
||||
_first->_ism = NULL;
|
||||
_first->_previous = NULL;
|
||||
_first->_next = NULL;
|
||||
_first = next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ImpostorSpriteManager::push_back(ImpostorSprite* is)
|
||||
{
|
||||
if (is==NULL || is==_last) return;
|
||||
|
||||
// remove entry for exisiting position in linked list
|
||||
// if it is already inserted.
|
||||
if (is->_previous)
|
||||
{
|
||||
(is->_previous)->_next = is->_next;
|
||||
}
|
||||
|
||||
if (is->_next)
|
||||
{
|
||||
(is->_next)->_previous = is->_previous;
|
||||
}
|
||||
|
||||
if (_first==is) _first = is->_next;
|
||||
|
||||
if (empty())
|
||||
{
|
||||
_first = is;
|
||||
_last = is;
|
||||
is->_ism = this;
|
||||
is->_previous = NULL;
|
||||
is->_next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// now add the element into the list.
|
||||
ImpostorSprite* previous_last = _last;
|
||||
previous_last->_next = is;
|
||||
_last = is;
|
||||
_last->_ism = this;
|
||||
_last->_previous = previous_last;
|
||||
_last->_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ImpostorSpriteManager::remove(ImpostorSprite* is)
|
||||
{
|
||||
if (is==NULL) return;
|
||||
|
||||
// remove entry for exisiting position in linked list
|
||||
// if it is already inserted.
|
||||
if (is->_previous)
|
||||
{
|
||||
(is->_previous)->_next = is->_next;
|
||||
}
|
||||
|
||||
if (is->_next)
|
||||
{
|
||||
(is->_next)->_previous = is->_previous;
|
||||
}
|
||||
|
||||
if (_first==is) _first = is->_next;
|
||||
if (_last==is) _last = is->_previous;
|
||||
}
|
||||
|
||||
ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,int frameNumber)
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
|
||||
// search for a valid impostor to reuse.
|
||||
ImpostorSprite* curr = _first;
|
||||
while (curr)
|
||||
{
|
||||
if (curr->getLastFrameUsed()<=frameNumber &&
|
||||
curr->s()==s &&
|
||||
curr->t()==t)
|
||||
{
|
||||
push_back(curr);
|
||||
return curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
curr = curr->_next;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// creating new impostor sprite.
|
||||
|
||||
|
||||
StateSet* stateset = new StateSet;
|
||||
|
||||
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
|
||||
Texture* texture = new Texture;
|
||||
stateset->setAttributeAndModes(texture,StateAttribute::ON);
|
||||
|
||||
TexEnv* texenv = new TexEnv;
|
||||
texenv->setMode(TexEnv::REPLACE);
|
||||
stateset->setAttribute(texenv);
|
||||
|
||||
AlphaFunc* alphafunc = new osg::AlphaFunc;
|
||||
alphafunc->setFunction( AlphaFunc::GREATER, 0.000f );
|
||||
stateset->setAttributeAndModes( alphafunc, StateAttribute::ON );
|
||||
|
||||
// stateset->setMode( GL_ALPHA_TEST, StateAttribute::OFF );
|
||||
|
||||
ImpostorSprite* is = new ImpostorSprite;
|
||||
is->setStateSet(stateset);
|
||||
is->setTexture(texture,s,t);
|
||||
|
||||
push_back(is);
|
||||
|
||||
return is;
|
||||
|
||||
}
|
||||
287
src/osg/LineSegment.cpp
Normal file
287
src/osg/LineSegment.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
#include "osg/LineSegment"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
const bool LineSegment::intersectAndClip(Vec3& s,Vec3& e,const BoundingBox& bb)
|
||||
{
|
||||
// compate s and e against the xMin to xMax range of bb.
|
||||
if (s.x()<=e.x())
|
||||
{
|
||||
|
||||
// trivial reject of segment wholely outside.
|
||||
if (e.x()<bb.xMin()) return false;
|
||||
if (s.x()>bb.xMax()) return false;
|
||||
|
||||
if (s.x()<bb.xMin())
|
||||
{
|
||||
// clip s to xMin.
|
||||
s = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x());
|
||||
}
|
||||
|
||||
if (e.x()>bb.xMax())
|
||||
{
|
||||
// clip e to xMax.
|
||||
e = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.x()<bb.xMin()) return false;
|
||||
if (e.x()>bb.xMax()) return false;
|
||||
|
||||
if (e.x()<bb.xMin())
|
||||
{
|
||||
// clip s to xMin.
|
||||
e = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x());
|
||||
}
|
||||
|
||||
if (s.x()>bb.xMax())
|
||||
{
|
||||
// clip e to xMax.
|
||||
s = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x());
|
||||
}
|
||||
}
|
||||
|
||||
// compate s and e against the yMin to yMax range of bb.
|
||||
if (s.y()<=e.y())
|
||||
{
|
||||
|
||||
// trivial reject of segment wholely outside.
|
||||
if (e.y()<bb.yMin()) return false;
|
||||
if (s.y()>bb.yMax()) return false;
|
||||
|
||||
if (s.y()<bb.yMin())
|
||||
{
|
||||
// clip s to yMin.
|
||||
s = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y());
|
||||
}
|
||||
|
||||
if (e.y()>bb.yMax())
|
||||
{
|
||||
// clip e to yMax.
|
||||
e = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.y()<bb.yMin()) return false;
|
||||
if (e.y()>bb.yMax()) return false;
|
||||
|
||||
if (e.y()<bb.yMin())
|
||||
{
|
||||
// clip s to yMin.
|
||||
e = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y());
|
||||
}
|
||||
|
||||
if (s.y()>bb.yMax())
|
||||
{
|
||||
// clip e to yMax.
|
||||
s = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y());
|
||||
}
|
||||
}
|
||||
|
||||
// compate s and e against the zMin to zMax range of bb.
|
||||
if (s.z()<=e.z())
|
||||
{
|
||||
|
||||
// trivial reject of segment wholely outside.
|
||||
if (e.z()<bb.zMin()) return false;
|
||||
if (s.z()>bb.zMax()) return false;
|
||||
|
||||
if (s.z()<bb.zMin())
|
||||
{
|
||||
// clip s to zMin.
|
||||
s = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z());
|
||||
}
|
||||
|
||||
if (e.z()>bb.zMax())
|
||||
{
|
||||
// clip e to zMax.
|
||||
e = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.z()<bb.zMin()) return false;
|
||||
if (e.z()>bb.zMax()) return false;
|
||||
|
||||
if (e.z()<bb.zMin())
|
||||
{
|
||||
// clip s to zMin.
|
||||
e = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z());
|
||||
}
|
||||
|
||||
if (s.z()>bb.zMax())
|
||||
{
|
||||
// clip e to zMax.
|
||||
s = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const bool LineSegment::intersect(const BoundingBox& bb) const
|
||||
{
|
||||
if (!bb.isValid()) return false;
|
||||
|
||||
Vec3 s=_s,e=_e;
|
||||
return intersectAndClip(s,e,bb);
|
||||
}
|
||||
|
||||
|
||||
const bool LineSegment::intersect(const BoundingBox& bb,float& r1,float& r2) const
|
||||
{
|
||||
if (!bb.isValid()) return false;
|
||||
|
||||
Vec3 s=_s,e=_e;
|
||||
bool result = intersectAndClip(s,e,bb);
|
||||
if (result)
|
||||
{
|
||||
float len = (_e-_s).length();
|
||||
if (len>0.0f)
|
||||
{
|
||||
float inv_len = 1.0f/len;
|
||||
r1 = (s-_s).length()*inv_len;
|
||||
r2 = (e-_e).length()*inv_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
r1 = 0.0f;
|
||||
r2 = 0.0f;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
const bool LineSegment::intersect(const BoundingSphere& bs,float& r1,float& r2) const
|
||||
{
|
||||
Vec3 sm = _s-bs._center;
|
||||
float c = sm.length2()-bs._radius*bs._radius;
|
||||
|
||||
Vec3 se = _e-_s;
|
||||
float a = se.length2();
|
||||
|
||||
float b = sm*se*2.0f;
|
||||
|
||||
float d = b*b-4.0f*a*c;
|
||||
|
||||
if (d<0.0f) return false;
|
||||
|
||||
d = sqrtf(d);
|
||||
|
||||
float div = 1.0f/(2.0f*a);
|
||||
|
||||
r1 = (-b-d)*div;
|
||||
r2 = (-b+d)*div;
|
||||
|
||||
if (r1<=0.0f && r2<=0.0f) return false;
|
||||
|
||||
if (r1>=1.0f && r2>=1.0f) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const bool LineSegment::intersect(const BoundingSphere& bs) const
|
||||
{
|
||||
Vec3 sm = _s-bs._center;
|
||||
float c = sm.length2()-bs._radius*bs._radius;
|
||||
if (c<0.0f) return true;
|
||||
|
||||
Vec3 se = _e-_s;
|
||||
float a = se.length2();
|
||||
|
||||
float b = (sm*se)*2.0f;
|
||||
|
||||
float d = b*b-4.0f*a*c;
|
||||
|
||||
if (d<0.0f) return false;
|
||||
|
||||
d = sqrtf(d);
|
||||
|
||||
float div = 1.0f/(2.0f*a);
|
||||
|
||||
float r1 = (-b-d)*div;
|
||||
float r2 = (-b+d)*div;
|
||||
|
||||
if (r1<=0.0f && r2<=0.0f) return false;
|
||||
|
||||
if (r1>=1.0f && r2>=1.0f) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const bool LineSegment::intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r)
|
||||
{
|
||||
if (v1==v2 || v2==v3 || v1==v3) return false;
|
||||
|
||||
Vec3 vse = _e-_s;
|
||||
|
||||
Vec3 v12 = v2-v1;
|
||||
Vec3 n12 = v12^vse;
|
||||
float ds12 = (_s-v1)*n12;
|
||||
float d312 = (v3-v1)*n12;
|
||||
if (d312>=0.0f)
|
||||
{
|
||||
if (ds12<0.0f) return false;
|
||||
if (ds12>d312) return false;
|
||||
}
|
||||
else // d312 < 0
|
||||
{
|
||||
if (ds12>0.0f) return false;
|
||||
if (ds12<d312) return false;
|
||||
}
|
||||
|
||||
Vec3 v23 = v3-v2;
|
||||
Vec3 n23 = v23^vse;
|
||||
float ds23 = (_s-v2)*n23;
|
||||
float d123 = (v1-v2)*n23;
|
||||
if (d123>=0.0f)
|
||||
{
|
||||
if (ds23<0.0f) return false;
|
||||
if (ds23>d123) return false;
|
||||
}
|
||||
else // d123 < 0
|
||||
{
|
||||
if (ds23>0.0f) return false;
|
||||
if (ds23<d123) return false;
|
||||
}
|
||||
|
||||
Vec3 v31 = v1-v3;
|
||||
Vec3 n31 = v31^vse;
|
||||
float ds31 = (_s-v3)*n31;
|
||||
float d231 = (v2-v3)*n31;
|
||||
if (d231>=0.0f)
|
||||
{
|
||||
if (ds31<0.0f) return false;
|
||||
if (ds31>d231) return false;
|
||||
}
|
||||
else // d231 < 0
|
||||
{
|
||||
if (ds31>0.0f) return false;
|
||||
if (ds31<d231) return false;
|
||||
}
|
||||
|
||||
float r3 = ds12/d312;
|
||||
float r1 = ds23/d123;
|
||||
float r2 = ds31/d231;
|
||||
|
||||
// float rt = r1+r2+r3;
|
||||
|
||||
Vec3 in = v1*r1+v2*r2+v3*r3;
|
||||
|
||||
float length = vse.length();
|
||||
vse /= length;
|
||||
float d = (in-_s)*vse;
|
||||
|
||||
if (d<0.0f) return false;
|
||||
if (d>length) return false;
|
||||
|
||||
r = d/length;
|
||||
|
||||
return true;
|
||||
}
|
||||
0
src/osg/Makedepend
Normal file
0
src/osg/Makedepend
Normal file
68
src/osg/PolygonMode.cpp
Normal file
68
src/osg/PolygonMode.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "osg/GL"
|
||||
#include "osg/PolygonMode"
|
||||
#include "osg/Notify"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
PolygonMode::PolygonMode()
|
||||
{
|
||||
_frontAndBack = true;
|
||||
_modeFront = FILL;
|
||||
_modeBack = FILL;
|
||||
}
|
||||
|
||||
|
||||
PolygonMode::~PolygonMode()
|
||||
{
|
||||
}
|
||||
|
||||
void PolygonMode::setMode(const Face face,const Mode mode)
|
||||
{
|
||||
switch(face)
|
||||
{
|
||||
case(FRONT):
|
||||
_frontAndBack = false;
|
||||
_modeFront = mode;
|
||||
break;
|
||||
case(BACK):
|
||||
_frontAndBack = false;
|
||||
_modeBack = mode;
|
||||
break;
|
||||
case(FRONT_AND_BACK):
|
||||
_frontAndBack = true;
|
||||
_modeFront = mode;
|
||||
_modeBack = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const PolygonMode::Mode PolygonMode::getMode(const Face face) const
|
||||
{
|
||||
switch(face)
|
||||
{
|
||||
case(FRONT):
|
||||
return _modeFront;
|
||||
break;
|
||||
case(BACK):
|
||||
return _modeBack;
|
||||
break;
|
||||
case(FRONT_AND_BACK):
|
||||
return _modeFront;
|
||||
}
|
||||
notify(WARN)<<"Warning : invalid Face passed to PolygonMode::getMode(Face face)"<<endl;
|
||||
return _modeFront;
|
||||
}
|
||||
|
||||
void PolygonMode::apply(State&) const
|
||||
{
|
||||
if (_frontAndBack)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK,(GLenum)_modeFront);
|
||||
}
|
||||
else
|
||||
{
|
||||
glPolygonMode(GL_FRONT,(GLenum)_modeFront);
|
||||
glPolygonMode(GL_BACK,(GLenum)_modeBack);
|
||||
}
|
||||
}
|
||||
|
||||
488
src/osg/State.cpp
Normal file
488
src/osg/State.cpp
Normal file
@@ -0,0 +1,488 @@
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <GL/glu.h>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
State::State()
|
||||
{
|
||||
_contextID = 0;
|
||||
_frameNumber = 0;
|
||||
_fineGrainedErrorDetection = true;
|
||||
}
|
||||
|
||||
State::~State()
|
||||
{
|
||||
}
|
||||
|
||||
void State::reset()
|
||||
{
|
||||
_modeMap.clear();
|
||||
_attributeMap.clear();
|
||||
_drawStateStack.clear();
|
||||
}
|
||||
|
||||
void State::pushStateSet(const StateSet* dstate)
|
||||
{
|
||||
_drawStateStack.push_back(dstate);
|
||||
if (dstate)
|
||||
{
|
||||
// iterator through all OpenGL modes in incomming StateSet
|
||||
// for each GLMode entry push it to the back of the appropriate
|
||||
// mode stack, taking into consideration current override status.
|
||||
const StateSet::ModeList& ds_modeList = dstate->getModeList();
|
||||
for(StateSet::ModeList::const_iterator mitr=ds_modeList.begin();
|
||||
mitr!=ds_modeList.end();
|
||||
++mitr)
|
||||
{
|
||||
// get the mode stack for incomming GLmode {mitr->first}.
|
||||
ModeStack& ms = _modeMap[mitr->first];
|
||||
if (ms.valueVec.empty())
|
||||
{
|
||||
// first pair so simply push incomming pair to back.
|
||||
ms.valueVec.push_back(mitr->second);
|
||||
}
|
||||
else if (ms.valueVec.back() & StateAttribute::OVERRIDE) // check the existing override flag
|
||||
{
|
||||
// push existing back since override keeps the previoius value.
|
||||
ms.valueVec.push_back(ms.valueVec.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
// no override on so simply push incomming pair to back.
|
||||
ms.valueVec.push_back(mitr->second);
|
||||
}
|
||||
ms.changed = true;
|
||||
}
|
||||
|
||||
// iterator through all StateAttribute's in incomming StateSet
|
||||
// for each Type entry push it to the back of the appropriate
|
||||
// attribute stack, taking into consideration current override status.
|
||||
const StateSet::AttributeList& ds_attributeList = dstate->getAttributeList();
|
||||
for(StateSet::AttributeList::const_iterator aitr=ds_attributeList.begin();
|
||||
aitr!=ds_attributeList.end();
|
||||
++aitr)
|
||||
{
|
||||
// get the attribute stack for incomming type {aitr->first}.
|
||||
AttributeStack& as = _attributeMap[aitr->first];
|
||||
if (as.attributeVec.empty())
|
||||
{
|
||||
// first pair so simply push incomming pair to back.
|
||||
as.attributeVec.push_back(
|
||||
AttributePair(aitr->second.first.get(),aitr->second.second));
|
||||
}
|
||||
else if (as.attributeVec.back().second & StateAttribute::OVERRIDE) // check the existing override flag
|
||||
{
|
||||
// push existing back since override keeps the previoius value.
|
||||
as.attributeVec.push_back(as.attributeVec.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
// no override on so simply push incomming pair to back.
|
||||
as.attributeVec.push_back(
|
||||
AttributePair(aitr->second.first.get(),aitr->second.second));
|
||||
}
|
||||
as.changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void State::popStateSet()
|
||||
{
|
||||
if (_drawStateStack.empty()) return;
|
||||
|
||||
const StateSet* dstate = _drawStateStack.back().get();
|
||||
|
||||
if (dstate)
|
||||
{
|
||||
// iterator through all OpenGL modes in incomming StateSet
|
||||
// for each GLMode entry pop_back of the appropriate
|
||||
// mode stack.
|
||||
const StateSet::ModeList& ds_modeList = dstate->getModeList();
|
||||
for(StateSet::ModeList::const_iterator mitr=ds_modeList.begin();
|
||||
mitr!=ds_modeList.end();
|
||||
++mitr)
|
||||
{
|
||||
// get the mode stack for incomming GLmode {mitr->first}.
|
||||
ModeStack& ms = _modeMap[mitr->first];
|
||||
if (!ms.valueVec.empty())
|
||||
{
|
||||
ms.valueVec.pop_back();
|
||||
}
|
||||
ms.changed = true;
|
||||
}
|
||||
|
||||
// iterator through all StateAttribute's in incomming StateSet
|
||||
// for each Type entry pop_back of the appropriate
|
||||
// attribute stack.
|
||||
const StateSet::AttributeList& ds_attributeList = dstate->getAttributeList();
|
||||
for(StateSet::AttributeList::const_iterator aitr=ds_attributeList.begin();
|
||||
aitr!=ds_attributeList.end();
|
||||
++aitr)
|
||||
{
|
||||
// get the attribute stack for incomming type {aitr->first}.
|
||||
AttributeStack& as = _attributeMap[aitr->first];
|
||||
if (!as.attributeVec.empty())
|
||||
{
|
||||
as.attributeVec.pop_back();
|
||||
}
|
||||
as.changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remove the top draw state from the stack.
|
||||
_drawStateStack.pop_back();
|
||||
}
|
||||
|
||||
void State::apply(const StateSet* dstate)
|
||||
{
|
||||
// equivilant to:
|
||||
//pushStateSet(dstate);
|
||||
//apply();
|
||||
//popStateSet();
|
||||
|
||||
if (dstate)
|
||||
{
|
||||
|
||||
|
||||
// first handle mode changes.
|
||||
{
|
||||
const StateSet::ModeList& ds_modeList = dstate->getModeList();
|
||||
|
||||
StateSet::ModeList::const_iterator ds_mitr = ds_modeList.begin();
|
||||
ModeMap::iterator this_mitr=_modeMap.begin();
|
||||
|
||||
while (this_mitr!=_modeMap.end() && ds_mitr!=ds_modeList.end())
|
||||
{
|
||||
if (this_mitr->first<ds_mitr->first)
|
||||
{
|
||||
|
||||
// note GLMode = this_mitr->first
|
||||
ModeStack& ms = this_mitr->second;
|
||||
if (ms.changed)
|
||||
{
|
||||
ms.changed = false;
|
||||
if (!ms.valueVec.empty())
|
||||
{
|
||||
bool new_value = ms.valueVec.back() & StateAttribute::ON;
|
||||
apply_mode(this_mitr->first,new_value,ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume default of disabled.
|
||||
apply_mode(this_mitr->first,false,ms);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++this_mitr;
|
||||
|
||||
}
|
||||
else if (ds_mitr->first<this_mitr->first)
|
||||
{
|
||||
|
||||
// ds_mitr->first is a new mode, therefore
|
||||
// need to insert a new mode entry for ds_mistr->first.
|
||||
ModeStack& ms = _modeMap[ds_mitr->first];
|
||||
|
||||
bool new_value = ds_mitr->second & StateAttribute::ON;
|
||||
apply_mode(ds_mitr->first,new_value,ms);
|
||||
|
||||
// will need to disable this mode on next apply so set it to changed.
|
||||
ms.changed = true;
|
||||
|
||||
++ds_mitr;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// this_mitr & ds_mitr refer to the same mode, check the overide
|
||||
// if any otherwise just apply the incomming mode.
|
||||
|
||||
ModeStack& ms = this_mitr->second;
|
||||
|
||||
if (!ms.valueVec.empty() && ms.valueVec.back() & StateAttribute::OVERRIDE)
|
||||
{
|
||||
// override is on, there just treat as a normal apply on modes.
|
||||
|
||||
if (ms.changed)
|
||||
{
|
||||
ms.changed = false;
|
||||
bool new_value = ms.valueVec.back() & StateAttribute::ON;
|
||||
apply_mode(this_mitr->first,new_value,ms);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no override on or no previous entry, therefore consider incomming mode.
|
||||
bool new_value = ds_mitr->second & StateAttribute::ON;
|
||||
if (apply_mode(ds_mitr->first,new_value,ms))
|
||||
{
|
||||
ms.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
++this_mitr;
|
||||
++ds_mitr;
|
||||
}
|
||||
}
|
||||
|
||||
// iterator over the remaining state modes to apply any previous changes.
|
||||
for(;
|
||||
this_mitr!=_modeMap.end();
|
||||
++this_mitr)
|
||||
{
|
||||
// note GLMode = this_mitr->first
|
||||
ModeStack& ms = this_mitr->second;
|
||||
if (ms.changed)
|
||||
{
|
||||
ms.changed = false;
|
||||
if (!ms.valueVec.empty())
|
||||
{
|
||||
bool new_value = ms.valueVec.back() & StateAttribute::ON;
|
||||
apply_mode(this_mitr->first,new_value,ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume default of disabled.
|
||||
apply_mode(this_mitr->first,false,ms);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// iterator over the remaining incomming modes to apply any new mode.
|
||||
for(;
|
||||
ds_mitr!=ds_modeList.end();
|
||||
++ds_mitr)
|
||||
{
|
||||
ModeStack& ms = _modeMap[ds_mitr->first];
|
||||
|
||||
bool new_value = ds_mitr->second & StateAttribute::ON;
|
||||
apply_mode(ds_mitr->first,new_value,ms);
|
||||
|
||||
// will need to disable this mode on next apply so set it to changed.
|
||||
ms.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// now handle attribute changes
|
||||
{
|
||||
const StateSet::AttributeList& ds_attributeList = dstate->getAttributeList();
|
||||
StateSet::AttributeList::const_iterator ds_aitr=ds_attributeList.begin();
|
||||
|
||||
AttributeMap::iterator this_aitr=_attributeMap.begin();
|
||||
|
||||
while (this_aitr!=_attributeMap.end() && ds_aitr!=ds_attributeList.end())
|
||||
{
|
||||
if (this_aitr->first<ds_aitr->first)
|
||||
{
|
||||
|
||||
// note attribute type = this_aitr->first
|
||||
AttributeStack& as = this_aitr->second;
|
||||
if (as.changed)
|
||||
{
|
||||
as.changed = false;
|
||||
if (!as.attributeVec.empty())
|
||||
{
|
||||
const StateAttribute* new_attr = as.attributeVec.back().first;
|
||||
apply_attribute(new_attr,as);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is really an error state, in theory we *should* have a
|
||||
// global state attribute set for all types.
|
||||
//notify(WARN)<<" No global StateAttribute set for type"<<(int)aitr->first<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
++this_aitr;
|
||||
|
||||
}
|
||||
else if (ds_aitr->first<this_aitr->first)
|
||||
{
|
||||
|
||||
// ds_mitr->first is a new attribute, therefore
|
||||
// need to insert a new attribute entry for ds_aistr->first.
|
||||
AttributeStack& as = _attributeMap[ds_aitr->first];
|
||||
|
||||
const StateAttribute* new_attr = ds_aitr->second.first.get();
|
||||
apply_attribute(new_attr,as);
|
||||
|
||||
// will need to disable this mode on next apply so set it to changed.
|
||||
as.changed = true;
|
||||
|
||||
++ds_aitr;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// this_mitr & ds_mitr refer to the same mode, check the overide
|
||||
// if any otherwise just apply the incomming mode.
|
||||
|
||||
AttributeStack& as = this_aitr->second;
|
||||
|
||||
if (!as.attributeVec.empty() && as.attributeVec.back().second)
|
||||
{
|
||||
// override is os, there just treat as a normal apply on modes.
|
||||
|
||||
if (as.changed)
|
||||
{
|
||||
as.changed = false;
|
||||
const StateAttribute* new_attr = as.attributeVec.back().first;
|
||||
apply_attribute(new_attr,as);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no override on or no previous entry, therefore consider incomming mode.
|
||||
const StateAttribute* new_attr = ds_aitr->second.first.get();
|
||||
if (apply_attribute(new_attr,as))
|
||||
{
|
||||
as.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
++this_aitr;
|
||||
++ds_aitr;
|
||||
}
|
||||
}
|
||||
|
||||
// iterator over the remaining state modes to apply any previous changes.
|
||||
for(;
|
||||
this_aitr!=_attributeMap.end();
|
||||
++this_aitr)
|
||||
{
|
||||
// note attribute type = this_aitr->first
|
||||
AttributeStack& as = this_aitr->second;
|
||||
if (as.changed)
|
||||
{
|
||||
as.changed = false;
|
||||
if (!as.attributeVec.empty())
|
||||
{
|
||||
const StateAttribute* new_attr = as.attributeVec.back().first;
|
||||
apply_attribute(new_attr,as);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is really an error state, in theory we *should* have a
|
||||
// global state attribute set for all types.
|
||||
//notify(WARN)<<" No global StateAttribute set for type"<<(int)aitr->first<<endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterator over the remaining incomming modes to apply any new mode.
|
||||
for(;
|
||||
ds_aitr!=ds_attributeList.end();
|
||||
++ds_aitr)
|
||||
{
|
||||
// ds_mitr->first is a new attribute, therefore
|
||||
// need to insert a new attribute entry for ds_aistr->first.
|
||||
AttributeStack& as = _attributeMap[ds_aitr->first];
|
||||
|
||||
const StateAttribute* new_attr = ds_aitr->second.first.get();
|
||||
apply_attribute(new_attr,as);
|
||||
|
||||
// will need to update this attribute on next apply so set it to changed.
|
||||
as.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// no incomming stateset, so simply apply state.
|
||||
apply();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void State::apply()
|
||||
{
|
||||
|
||||
// go through all active OpenGL modes, enabling/disable where
|
||||
// appropriate.
|
||||
for(ModeMap::iterator mitr=_modeMap.begin();
|
||||
mitr!=_modeMap.end();
|
||||
++mitr)
|
||||
{
|
||||
// note GLMode = mitr->first
|
||||
ModeStack& ms = mitr->second;
|
||||
if (ms.changed)
|
||||
{
|
||||
ms.changed = false;
|
||||
if (!ms.valueVec.empty())
|
||||
{
|
||||
bool new_value = ms.valueVec.back() & StateAttribute::ON;
|
||||
apply_mode(mitr->first,new_value,ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume default of disabled.
|
||||
apply_mode(mitr->first,false,ms);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// go through all active StateAttribute's, applying where appropriate.
|
||||
for(AttributeMap::iterator aitr=_attributeMap.begin();
|
||||
aitr!=_attributeMap.end();
|
||||
++aitr)
|
||||
{
|
||||
AttributeStack& as = aitr->second;
|
||||
if (as.changed)
|
||||
{
|
||||
as.changed = false;
|
||||
if (!as.attributeVec.empty())
|
||||
{
|
||||
const StateAttribute* new_attr = as.attributeVec.back().first;
|
||||
apply_attribute(new_attr,as);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is really an error state, in theory we *should* have a
|
||||
// global state attribute set for all types.
|
||||
//notify(WARN)<<" No global StateAttribute set for type"<<(int)aitr->first<<endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** mode has been set externally, update state to reflect this setting.*/
|
||||
void State::have_applied(const StateAttribute::GLMode mode,const StateAttribute::GLModeValue value)
|
||||
{
|
||||
ModeStack& ms = _modeMap[mode];
|
||||
|
||||
ms.last_applied_value = value & StateAttribute::ON;
|
||||
|
||||
// will need to disable this mode on next apply so set it to changed.
|
||||
ms.changed = true;
|
||||
}
|
||||
|
||||
/** attribute has been applied externally, update state to reflect this setting.*/
|
||||
void State::have_applied(const StateAttribute* attribute)
|
||||
{
|
||||
if (attribute)
|
||||
{
|
||||
AttributeStack& as = _attributeMap[attribute->getType()];
|
||||
|
||||
as.last_applied_attribute = attribute;
|
||||
|
||||
// will need to update this attribute on next apply so set it to changed.
|
||||
as.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
208
src/osg/StateSet.cpp
Normal file
208
src/osg/StateSet.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <osg/StateSet>
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Material>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/FrontFace>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Transparency>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
StateSet::StateSet()
|
||||
{
|
||||
_renderingHint = DEFAULT_BIN;
|
||||
|
||||
setRendingBinToInherit();
|
||||
}
|
||||
|
||||
|
||||
StateSet::~StateSet()
|
||||
{
|
||||
// note, all attached state attributes will be automatically
|
||||
// unreferenced by ref_ptr<> and therefore there is no need to
|
||||
// delete the memory manually.
|
||||
}
|
||||
|
||||
|
||||
void StateSet::setGlobalDefaults()
|
||||
{
|
||||
_renderingHint = DEFAULT_BIN;
|
||||
|
||||
setRendingBinToInherit();
|
||||
|
||||
setMode(GL_LIGHTING,StateAttribute::OFF);
|
||||
setMode(GL_FOG,StateAttribute::OFF);
|
||||
setMode(GL_POINT_SMOOTH,StateAttribute::OFF);
|
||||
|
||||
setMode(GL_TEXTURE_2D,StateAttribute::OFF);
|
||||
|
||||
setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
|
||||
setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
|
||||
setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
|
||||
setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);
|
||||
|
||||
setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
|
||||
setAttributeAndModes(new CullFace,StateAttribute::ON);
|
||||
setAttributeAndModes(new FrontFace,StateAttribute::ON);
|
||||
|
||||
Material *material = new Material;
|
||||
material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
|
||||
setAttributeAndModes(material,StateAttribute::ON);
|
||||
|
||||
setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
|
||||
setAttributeAndModes(new Transparency,StateAttribute::OFF);
|
||||
}
|
||||
|
||||
|
||||
void StateSet::setAllToInherit()
|
||||
{
|
||||
_renderingHint = DEFAULT_BIN;
|
||||
|
||||
setRendingBinToInherit();
|
||||
|
||||
_modeList.clear();
|
||||
_attributeList.clear();
|
||||
}
|
||||
|
||||
void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
|
||||
{
|
||||
if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
|
||||
else _modeList[mode] = value;
|
||||
}
|
||||
|
||||
void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
|
||||
{
|
||||
ModeList::iterator itr = _modeList.find(mode);
|
||||
if (itr!=_modeList.end())
|
||||
{
|
||||
_modeList.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
|
||||
{
|
||||
ModeList::const_iterator itr = _modeList.find(mode);
|
||||
if (itr!=_modeList.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
else
|
||||
return StateAttribute::INHERIT;
|
||||
}
|
||||
|
||||
void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
|
||||
{
|
||||
if (attribute)
|
||||
{
|
||||
if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
|
||||
else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
|
||||
}
|
||||
}
|
||||
|
||||
void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
|
||||
{
|
||||
if (attribute)
|
||||
{
|
||||
_attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
|
||||
attribute->setStateSetModes(*this,value);
|
||||
}
|
||||
}
|
||||
|
||||
void StateSet::setAttributeToInherit(const StateAttribute::Type type)
|
||||
{
|
||||
AttributeList::iterator itr = _attributeList.find(type);
|
||||
if (itr!=_attributeList.end())
|
||||
{
|
||||
itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
|
||||
_attributeList.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
|
||||
{
|
||||
AttributeList::const_iterator itr = _attributeList.find(type);
|
||||
if (itr!=_attributeList.end())
|
||||
{
|
||||
return itr->second.first.get();
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
|
||||
{
|
||||
AttributeList::const_iterator itr = _attributeList.find(type);
|
||||
if (itr!=_attributeList.end())
|
||||
{
|
||||
return &(itr->second);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StateSet::compile(State& state) const
|
||||
{
|
||||
for(AttributeList::const_iterator itr = _attributeList.begin();
|
||||
itr!=_attributeList.end();
|
||||
++itr)
|
||||
{
|
||||
itr->second.first->compile(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const StateSet::ModeVector StateSet::getModeVector() const
|
||||
{
|
||||
ModeVector vec;
|
||||
for (ModeList::const_iterator itr = _modeList.begin();
|
||||
itr!=_modeList.end();
|
||||
++itr)
|
||||
{
|
||||
vec.push_back(*itr);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
const StateSet::AttributeVector StateSet::getAttributeVector() const
|
||||
{
|
||||
AttributeVector vec;
|
||||
for (AttributeList::const_iterator itr = _attributeList.begin();
|
||||
itr!=_attributeList.end();
|
||||
++itr)
|
||||
{
|
||||
vec.push_back(itr->second.first.get());
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
void StateSet::setRenderingHint(const int hint)
|
||||
{
|
||||
_renderingHint = hint;
|
||||
// temporary hack to get new render bins working.
|
||||
if (_renderingHint==TRANSPARENT_BIN)
|
||||
{
|
||||
_binMode = USE_RENDERBIN_DETAILS;
|
||||
_binNum = 1;
|
||||
_binName = "DepthSortedBin";
|
||||
// _binName = "RenderBin";
|
||||
}
|
||||
}
|
||||
|
||||
void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
|
||||
{
|
||||
_binMode = mode;
|
||||
_binNum = binNum;
|
||||
_binName = binName;
|
||||
}
|
||||
|
||||
void StateSet::setRendingBinToInherit()
|
||||
{
|
||||
_binMode = INHERIT_RENDERBIN_DETAILS;
|
||||
_binNum = 0;
|
||||
_binName = "";
|
||||
}
|
||||
32
src/osg/Stencil.cpp
Normal file
32
src/osg/Stencil.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <osg/Stencil>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Stencil::Stencil()
|
||||
{
|
||||
// set up same defaults as glStencilFunc.
|
||||
_func = ALWAYS;
|
||||
_funcRef = 0;
|
||||
_funcMask = ~0;
|
||||
|
||||
// set up same defaults as glStencilOp.
|
||||
_sfail = KEEP;
|
||||
_zfail = KEEP;
|
||||
_zpass = KEEP;
|
||||
|
||||
// set up same defaults as glStencilMask.
|
||||
_writeMask = ~0;
|
||||
}
|
||||
|
||||
|
||||
Stencil::~Stencil()
|
||||
{
|
||||
}
|
||||
|
||||
void Stencil::apply(State&) const
|
||||
{
|
||||
glStencilFunc((GLenum)_func,_funcRef,_funcMask);
|
||||
glStencilOp((GLenum)_sfail,(GLenum)_zfail,(GLenum)_zpass);
|
||||
glStencilMask(_writeMask);
|
||||
}
|
||||
|
||||
87
src/osg/Transform.cpp
Normal file
87
src/osg/Transform.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "osg/Transform"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Transform::Transform()
|
||||
{
|
||||
_matrix = new osg::Matrix();
|
||||
_matrix->makeIdent();
|
||||
}
|
||||
|
||||
|
||||
Transform::Transform(const Matrix& mat )
|
||||
{
|
||||
(*_matrix) = mat;
|
||||
}
|
||||
|
||||
|
||||
Transform::~Transform()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Transform::setMatrix(const Matrix& mat )
|
||||
{
|
||||
(*_matrix) = mat;
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
|
||||
void Transform::preMult( const Matrix& mat )
|
||||
{
|
||||
_matrix->preMult( mat );
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
void Transform::preScale( const float sx, const float sy, const float sz )
|
||||
{
|
||||
_matrix->preScale( sx, sy, sz );
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
void Transform::preTranslate( const float tx, const float ty, const float tz )
|
||||
{
|
||||
_matrix->preTrans( tx, ty, tz );
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
|
||||
void Transform::preRotate( const float deg, const float x, const float y, const float z )
|
||||
{
|
||||
_matrix->preRot( deg, x, y, z );
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
const bool Transform::computeBound() const
|
||||
{
|
||||
if (!Group::computeBound()) return false;
|
||||
|
||||
Vec3 xdash = _bsphere._center;
|
||||
xdash.x() += _bsphere._radius;
|
||||
xdash = xdash*(*_matrix);
|
||||
|
||||
Vec3 ydash = _bsphere._center;
|
||||
ydash.y() += _bsphere._radius;
|
||||
ydash = ydash*(*_matrix);
|
||||
|
||||
Vec3 zdash = _bsphere._center;
|
||||
zdash.y() += _bsphere._radius;
|
||||
zdash = zdash*(*_matrix);
|
||||
|
||||
_bsphere._center = _bsphere._center*(*_matrix);
|
||||
|
||||
xdash -= _bsphere._center;
|
||||
float len_xdash = xdash.length();
|
||||
|
||||
ydash -= _bsphere._center;
|
||||
float len_ydash = ydash.length();
|
||||
|
||||
zdash -= _bsphere._center;
|
||||
float len_zdash = zdash.length();
|
||||
|
||||
_bsphere._radius = len_xdash;
|
||||
if (_bsphere._radius<len_ydash) _bsphere._radius = len_ydash;
|
||||
if (_bsphere._radius<len_zdash) _bsphere._radius = len_zdash;
|
||||
|
||||
return true;
|
||||
}
|
||||
43
src/osgPlugins/flt/OldMaterialPaletteRecord.cpp
Normal file
43
src/osgPlugins/flt/OldMaterialPaletteRecord.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// OldMaterialPaletteRecord.cpp
|
||||
|
||||
#include "flt.h"
|
||||
#include "Registry.h"
|
||||
#include "OldMaterialPaletteRecord.h"
|
||||
|
||||
using namespace flt;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OldMaterialPaletteRecord
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
RegisterRecordProxy<OldMaterialPaletteRecord> g_OldMaterialPaletteProxy;
|
||||
|
||||
OldMaterialPaletteRecord::OldMaterialPaletteRecord()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
OldMaterialPaletteRecord::~OldMaterialPaletteRecord()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void OldMaterialPaletteRecord::endian()
|
||||
{
|
||||
SOldMaterial *pSMaterial = (SOldMaterial*)getData();
|
||||
|
||||
for (int i=0; i < 64; i++)
|
||||
{
|
||||
pSMaterial->mat[i].Ambient.endian();
|
||||
pSMaterial->mat[i].Diffuse.endian();
|
||||
pSMaterial->mat[i].Specular.endian();
|
||||
pSMaterial->mat[i].Emissive.endian();
|
||||
ENDIAN( pSMaterial->mat[i].sfShininess );
|
||||
ENDIAN( pSMaterial->mat[i].sfAlpha );
|
||||
ENDIAN( pSMaterial->mat[i].diFlags );
|
||||
}
|
||||
}
|
||||
61
src/osgPlugins/flt/OldMaterialPaletteRecord.h
Normal file
61
src/osgPlugins/flt/OldMaterialPaletteRecord.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// OldMaterialPaletteRecord.h
|
||||
|
||||
#ifndef __FLT_OLD_MATERIAL_PALETTE_RECORD_H
|
||||
#define __FLT_OLD_MATERIAL_PALETTE_RECORD_H
|
||||
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "Record.h"
|
||||
#include "RecordVisitor.h"
|
||||
|
||||
|
||||
namespace flt {
|
||||
|
||||
|
||||
struct SOldMaterial
|
||||
{
|
||||
SRecHeader RecHeader;
|
||||
struct
|
||||
{
|
||||
float32x3 Ambient; // Ambient component of material
|
||||
float32x3 Diffuse; // Diffuse component of material
|
||||
float32x3 Specular; // Specular component of material
|
||||
float32x3 Emissive; // Emissive component of material
|
||||
float32 sfShininess; // Shininess. [0.0-128.0]
|
||||
float32 sfAlpha; // Alpha. [0.0-1.0], where 1.0 is opaque
|
||||
uint32 diFlags; // bit 0 Materials used
|
||||
// bit 1-31 Spare
|
||||
uint32 spares[31]; // Spares for material
|
||||
} mat[64];
|
||||
};
|
||||
|
||||
|
||||
class OldMaterialPaletteRecord : public AncillaryRecord
|
||||
{
|
||||
public:
|
||||
|
||||
OldMaterialPaletteRecord();
|
||||
|
||||
virtual Record* clone() const { return new OldMaterialPaletteRecord(); }
|
||||
virtual const char* className() const { return "OldMaterialPaletteRecord"; }
|
||||
virtual int classOpcode() const { return OLD_MATERIAL_PALETTE_OP; }
|
||||
virtual int sizeofData() const { return sizeof(SOldMaterial); }
|
||||
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
|
||||
// virtual void traverse(RecordVisitor& rv);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~OldMaterialPaletteRecord();
|
||||
|
||||
virtual void endian();
|
||||
// virtual void decode();
|
||||
|
||||
// virtual bool readLocalData(Input& fr);
|
||||
// virtual bool writeLocalData(Output& fw);
|
||||
|
||||
};
|
||||
|
||||
|
||||
}; // end namespace flt
|
||||
|
||||
#endif
|
||||
114
src/osgPlugins/osgtgz/ReaderWriterOSGTGZ.cpp
Normal file
114
src/osgPlugins/osgtgz/ReaderWriterOSGTGZ.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace osg;
|
||||
|
||||
class sgReaderWriterOSGTGZ : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual const char* className() { return "OSGTGZ Database Reader/Writer"; }
|
||||
virtual bool acceptsExtension(const std::string& extension)
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension,"osgtgz");
|
||||
}
|
||||
|
||||
virtual Node* readNode(const std::string& fileName)
|
||||
{
|
||||
std::string ext = osgDB::getFileExtension(fileName);
|
||||
if (!acceptsExtension(ext)) return NULL;
|
||||
|
||||
osg::notify(osg::INFO)<<"sgReaderWriterOSGTGZ::readNode( "<<fileName.c_str()<<" )\n";
|
||||
|
||||
char dirname[128];
|
||||
char command[1024];
|
||||
|
||||
#ifdef _WIN32
|
||||
sprintf( dirname, "C:/Windows/Temp/.osgdb_osgtgz");
|
||||
// note, the following C option under windows does not seem to work...
|
||||
// will pursue an better tar.exe later. RO.
|
||||
sprintf( command,
|
||||
"tar xfCz %s %s",
|
||||
fileName.c_str(), dirname );
|
||||
mkdir( dirname);
|
||||
#endif
|
||||
|
||||
#ifdef __linux
|
||||
sprintf( dirname, "/tmp/.osg%06d", getpid());
|
||||
sprintf( command,
|
||||
"tar xfCz %s %s",
|
||||
fileName.c_str(), dirname );
|
||||
mkdir( dirname, 0700 );
|
||||
#endif
|
||||
|
||||
#ifdef __sgi
|
||||
sprintf( dirname, "/tmp/.osg%06d", getpid());
|
||||
sprintf( command,
|
||||
"cp %s %s; cd %s;"
|
||||
"gzcat %s | tar xf -",
|
||||
fileName.c_str(), dirname, dirname,
|
||||
fileName.c_str() );
|
||||
mkdir( dirname, 0700 );
|
||||
#endif
|
||||
|
||||
system( command );
|
||||
|
||||
osg::Group *grp = new osg::Group;
|
||||
osgDB::setFilePath( dirname );
|
||||
|
||||
osgDB::DirectoryContents contents = osgDB::getDirectoryContents(dirname);
|
||||
for(osgDB::DirectoryContents::iterator itr = contents.begin();
|
||||
itr != contents.end();
|
||||
++itr)
|
||||
{
|
||||
std::string file_ext = osgDB::getLowerCaseFileExtension(*itr);
|
||||
if (osgDB::equalCaseInsensitive(file_ext,"osg"))
|
||||
{
|
||||
osg::Node *node = osgDB::readNodeFile( *itr );
|
||||
grp->addChild( node );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// note, is this the right command for windows?
|
||||
// is there any way of overiding the Y/N option? RO.
|
||||
sprintf( command, "erase %s", dirname );
|
||||
system( command );
|
||||
#else
|
||||
|
||||
sprintf( command, "rm -rf %s", dirname );
|
||||
system( command );
|
||||
#endif
|
||||
|
||||
if( grp->getNumChildren() == 0 )
|
||||
{
|
||||
grp->unref();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return grp;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// now register with sgRegistry to instantiate the above
|
||||
// reader/writer.
|
||||
osgDB::RegisterReaderWriterProxy<sgReaderWriterOSGTGZ> g_readerWriter_OSGTGZ_Proxy;
|
||||
330
src/osgPlugins/png/new_ReaderWriterPNG.cpp
Normal file
330
src/osgPlugins/png/new_ReaderWriterPNG.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
#include <osg/Image>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Geode>
|
||||
#include <osg/GL>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Follows is code extracted from the simage library. Original Authors:
|
||||
*
|
||||
* Systems in Motion,
|
||||
* <URL:http://www.sim.no>
|
||||
*
|
||||
* Peder Blekken <pederb@sim.no>
|
||||
* Morten Eriksen <mortene@sim.no>
|
||||
* Marius Bugge Monsen <mariusbu@sim.no>
|
||||
*
|
||||
* The original COPYING notice
|
||||
*
|
||||
* All files in this library are public domain, except simage_rgb.cpp which is
|
||||
* Copyright (c) Mark J Kilgard <mjk@nvidia.com>. I will contact Mark
|
||||
* very soon to hear if this source also can become public domain.
|
||||
*
|
||||
* Please send patches for bugs and new features to: <pederb@sim.no>.
|
||||
*
|
||||
* Peder Blekken
|
||||
*
|
||||
*
|
||||
* Ported into the OSG as a plugin, Robert Osfield Decemeber 2000.
|
||||
* Note, reference above to license of simage_rgb is not relevent to the OSG
|
||||
* as the OSG does not use it. Also for patches, bugs and new features
|
||||
* please send them direct to the OSG dev team rather than address above.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
* Based on example code found in the libjpeg archive
|
||||
*
|
||||
*/
|
||||
|
||||
using namespace osg;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <png.h>
|
||||
}
|
||||
|
||||
#define ERR_NO_ERROR 0
|
||||
#define ERR_OPEN 1
|
||||
#define ERR_MEM 2
|
||||
#define ERR_PNGLIB 3
|
||||
|
||||
static int pngerror = ERR_NO_ERROR;
|
||||
|
||||
/* my setjmp buffer */
|
||||
static jmp_buf setjmp_buffer;
|
||||
|
||||
/* called my libpng */
|
||||
static void
|
||||
warn_callback(png_structp /*ps*/, png_const_charp pc)
|
||||
{
|
||||
/*FIXME: notify? */
|
||||
osg::notify(osg::WARN)<<"Warning in .png reader: ";
|
||||
if (pc) osg::notify(osg::WARN)<< pc;
|
||||
osg::notify(osg::WARN)<<endl;
|
||||
}
|
||||
|
||||
static void
|
||||
err_callback(png_structp /*ps*/, png_const_charp pc)
|
||||
{
|
||||
/* FIXME: store error message? */
|
||||
longjmp(setjmp_buffer, 1);
|
||||
|
||||
osg::notify(osg::WARN)<<"Error in .png reader: ";
|
||||
if (pc) osg::notify(osg::WARN)<< pc;
|
||||
osg::notify(osg::WARN)<<endl;
|
||||
}
|
||||
|
||||
int
|
||||
simage_png_error(char * buffer, int buflen)
|
||||
{
|
||||
switch (pngerror) {
|
||||
case ERR_OPEN:
|
||||
strncpy(buffer, "PNG loader: Error opening file", buflen);
|
||||
break;
|
||||
case ERR_MEM:
|
||||
strncpy(buffer, "PNG loader: Out of memory error", buflen);
|
||||
break;
|
||||
case ERR_PNGLIB:
|
||||
strncpy(buffer, "PNG loader: Illegal png file", buflen);
|
||||
break;
|
||||
}
|
||||
return pngerror;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
simage_png_identify(const char * /*ptr*/,
|
||||
const unsigned char *header,
|
||||
int headerlen)
|
||||
{
|
||||
static unsigned char pngcmp[] = {0x89, 'P', 'N', 'G', 0xd, 0xa, 0x1a, 0xa};
|
||||
if (headerlen < 8) return 0;
|
||||
if (memcmp((const void*)header,
|
||||
(const void*)pngcmp, 8) == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
simage_png_load(const char *filename,
|
||||
int *width_ret,
|
||||
int *height_ret,
|
||||
int *numComponents_ret)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_uint_32 width, height;
|
||||
|
||||
int bit_depth, color_type, interlace_type;
|
||||
FILE *fp;
|
||||
unsigned char *buffer;
|
||||
int bytes_per_row;
|
||||
int number_passes;
|
||||
int channels;
|
||||
int format;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
pngerror = ERR_OPEN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create and initialize the png_struct with the desired error handler
|
||||
* functions. If you want to use the default stderr and longjump method,
|
||||
* you can supply NULL for the last three parameters. We also supply the
|
||||
* the compiler header file version, so that we know if the application
|
||||
* was compiled with a compatible version of the library. REQUIRED
|
||||
*/
|
||||
/*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
(void *)user_error_ptr, user_error_fn, user_warning_fn);*/
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, err_callback, warn_callback);
|
||||
|
||||
if (png_ptr == NULL) {
|
||||
pngerror = ERR_MEM;
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate/initialize the memory for image information. REQUIRED. */
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
pngerror = ERR_MEM;
|
||||
fclose(fp);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set error handling if you are using the setjmp/longjmp method (this is
|
||||
* the normal method of doing things with libpng). REQUIRED unless you
|
||||
* set up your own error handlers in the png_create_read_struct() earlier.
|
||||
*/
|
||||
|
||||
buffer = NULL;
|
||||
|
||||
if (setjmp(setjmp_buffer)) {
|
||||
pngerror = ERR_PNGLIB;
|
||||
/* Free all of the memory associated with the png_ptr and info_ptr */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(fp);
|
||||
/* If we get here, we had a problem reading the file */
|
||||
|
||||
if (buffer) free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up the input control if you are using standard C streams */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* The call to png_read_info() gives us all of the information from the
|
||||
* PNG file before the first IDAT (image data chunk). REQUIRED
|
||||
*/
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
|
||||
&interlace_type, NULL, NULL);
|
||||
|
||||
/**** Set up the data transformations you want. Note that these are all
|
||||
**** optional. Only call them if you want/need them. Many of the
|
||||
**** transformations only work on specific types of images, and many
|
||||
**** are mutually exclusive.
|
||||
****/
|
||||
|
||||
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
/* strip alpha bytes from the input data without combining with th
|
||||
* background (not recommended) */
|
||||
/* png_set_strip_alpha(png_ptr); */
|
||||
|
||||
/* extract multiple pixels with bit depths of 1, 2, and 4 from a single
|
||||
* byte into separate bytes (useful for paletted and grayscale images).
|
||||
*/
|
||||
/* png_set_packing(png_ptr); */
|
||||
|
||||
/* change the order of packed pixels to least significant bit first
|
||||
* (not useful if you are using png_set_packing). */
|
||||
/* png_set_packswap(png_ptr); */
|
||||
|
||||
/* expand paletted colors into true RGB triplets */
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
/* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
/* expand paletted or RGB images with transparency to full alpha channels
|
||||
* so the data will be available as RGBA quartets */
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
/* Add filler (or alpha) byte (before/after each RGB triplet) */
|
||||
/* png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); */
|
||||
|
||||
/* Turn on interlace handling. REQUIRED if you are not using
|
||||
* png_read_image(). To see how to handle interlacing passes,
|
||||
* see the png_read_row() method below.
|
||||
*/
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
channels = png_get_channels(png_ptr, info_ptr);
|
||||
|
||||
/* allocate the memory to hold the image using the fields of info_ptr. */
|
||||
|
||||
bytes_per_row = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
buffer = (unsigned char*) malloc(bytes_per_row*height);
|
||||
|
||||
format = channels; /* this is safer than the above */
|
||||
|
||||
if (buffer) {
|
||||
int pass, y;
|
||||
unsigned char *dummytab[1];
|
||||
for (pass = 0; pass < number_passes; pass++) {
|
||||
for ( y = 0; (unsigned int) y < height; y++ ) {
|
||||
/* flips image upside down */
|
||||
dummytab[0] = &buffer[bytes_per_row*(height-1-y)];
|
||||
png_read_rows(png_ptr, dummytab, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* read rest of file, and get additional chunks in info_ptr - REQUIRED */
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
/* clean up after the read, and free any memory allocated - REQUIRED */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
/* close the file */
|
||||
fclose(fp);
|
||||
|
||||
/* that's it */
|
||||
if (buffer) {
|
||||
*width_ret = width;
|
||||
*height_ret = height;
|
||||
*numComponents_ret = format;
|
||||
pngerror = ERR_NO_ERROR;
|
||||
}
|
||||
else {
|
||||
pngerror = ERR_MEM;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
class ReaderWriterPNG : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual const char* className() { return "PNG Image Reader"; }
|
||||
virtual bool acceptsExtension(const std::string& extension)
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension,"png");
|
||||
}
|
||||
|
||||
virtual osg::Image* readImage(const std::string& fileName)
|
||||
{
|
||||
|
||||
unsigned char *imageData = NULL;
|
||||
int width_ret;
|
||||
int height_ret;
|
||||
int numComponents_ret;
|
||||
|
||||
imageData = simage_png_load(fileName.c_str(),&width_ret,&height_ret,&numComponents_ret);
|
||||
|
||||
if (imageData==NULL) return NULL;
|
||||
|
||||
int s = width_ret;
|
||||
int t = height_ret;
|
||||
int r = 1;
|
||||
|
||||
int internalFormat = numComponents_ret;
|
||||
|
||||
unsigned int pixelFormat =
|
||||
numComponents_ret == 1 ? GL_LUMINANCE :
|
||||
numComponents_ret == 2 ? GL_LUMINANCE_ALPHA :
|
||||
numComponents_ret == 3 ? GL_RGB :
|
||||
numComponents_ret == 4 ? GL_RGBA : (GLenum)-1;
|
||||
|
||||
unsigned int dataType = GL_UNSIGNED_BYTE;
|
||||
|
||||
osg::Image* pOsgImage = new osg::Image;
|
||||
pOsgImage->setFileName(fileName.c_str());
|
||||
pOsgImage->setImage(s,t,r,
|
||||
internalFormat,
|
||||
pixelFormat,
|
||||
dataType,
|
||||
imageData);
|
||||
|
||||
return pOsgImage;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// now register with Registry to instantiate the above
|
||||
// reader/writer.
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterPNG> g_readerWriter_PNG_Proxy;
|
||||
170
src/osgPlugins/png/prev_ReaderWriterPNG.cpp
Normal file
170
src/osgPlugins/png/prev_ReaderWriterPNG.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include <osg/Image>
|
||||
#include "osg/Notify"
|
||||
#include <osg/Geode>
|
||||
#include "osg/GL"
|
||||
|
||||
#include "osgDB/Registry"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <png.h>
|
||||
}
|
||||
|
||||
|
||||
/* Transparency parameters */
|
||||
#define PNG_ALPHA -2 /* Use alpha channel in PNG file, if there is one */
|
||||
#define PNG_SOLID -1 /* No transparency */
|
||||
#define PNG_STENCIL 0 /* Sets alpha to 0 for r=g=b=0, 1 otherwise */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int Width;
|
||||
unsigned int Height;
|
||||
unsigned int Depth;
|
||||
unsigned int Alpha;
|
||||
} pngInfo;
|
||||
|
||||
class ReaderWriterPNG : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual const char* className() { return "PNG Image Reader/Writer"; }
|
||||
virtual bool acceptsExtension(const std::string& extension) { return extension=="png"; }
|
||||
|
||||
virtual Image* readImage(const std::string& fileName)
|
||||
{
|
||||
|
||||
int trans = PNG_ALPHA;
|
||||
FILE *fp = NULL;
|
||||
pngInfo pInfo;
|
||||
pngInfo *pinfo = &pInfo;
|
||||
|
||||
unsigned char header[8];
|
||||
png_structp png;
|
||||
png_infop info;
|
||||
png_infop endinfo;
|
||||
png_bytep data; //, data2;
|
||||
png_bytep *row_p;
|
||||
double fileGamma;
|
||||
|
||||
png_uint_32 width, height;
|
||||
int depth, color;
|
||||
|
||||
png_uint_32 i;
|
||||
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
info = png_create_info_struct(png);
|
||||
endinfo = png_create_info_struct(png);
|
||||
|
||||
fp = fopen(fileName.c_str(), "rb");
|
||||
if (fp && fread(header, 1, 8, fp) && png_check_sig(header, 8))
|
||||
png_init_io(png, fp);
|
||||
else
|
||||
{
|
||||
png_destroy_read_struct(&png, &info, &endinfo);
|
||||
return NULL;
|
||||
}
|
||||
png_set_sig_bytes(png, 8);
|
||||
|
||||
png_read_info(png, info);
|
||||
png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
|
||||
|
||||
if (pinfo != NULL)
|
||||
{
|
||||
pinfo->Width = width;
|
||||
pinfo->Height = height;
|
||||
pinfo->Depth = depth;
|
||||
}
|
||||
|
||||
if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
|
||||
if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA)
|
||||
{
|
||||
png_set_strip_alpha(png);
|
||||
color &= ~PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
|
||||
// if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
|
||||
if (color == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_expand(png);
|
||||
|
||||
/*--GAMMA--*/
|
||||
// checkForGammaEnv();
|
||||
double screenGamma = 2.2 / 1.0;
|
||||
if (png_get_gAMA(png, info, &fileGamma))
|
||||
png_set_gamma(png, screenGamma, fileGamma);
|
||||
else
|
||||
png_set_gamma(png, screenGamma, 1.0/2.2);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
|
||||
row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
|
||||
|
||||
bool StandardOrientation = false;
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
if (StandardOrientation)
|
||||
row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
|
||||
else
|
||||
row_p[i] = &data[png_get_rowbytes(png, info)*i];
|
||||
}
|
||||
|
||||
png_read_image(png, row_p);
|
||||
free(row_p);
|
||||
|
||||
int iBitCount;
|
||||
|
||||
if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
iBitCount = 24;
|
||||
if (pinfo != NULL) pinfo->Alpha = 0;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
iBitCount = 32;
|
||||
if (pinfo != NULL) pinfo->Alpha = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
png_read_end(png, endinfo);
|
||||
png_destroy_read_struct(&png, &info, &endinfo);
|
||||
|
||||
// free(data);
|
||||
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
|
||||
osg::Image* pOsgImage = new osg::Image();
|
||||
|
||||
pOsgImage->setFileName(fileName.c_str());
|
||||
if (iBitCount == 24)
|
||||
pOsgImage->setImage(width, height, 1,
|
||||
iBitCount / 8,// int internalFormat,
|
||||
GL_RGB, // unsigned int pixelFormat
|
||||
GL_UNSIGNED_BYTE,// unsigned int dataType
|
||||
data);
|
||||
else
|
||||
pOsgImage->setImage(width, height, 1,
|
||||
iBitCount / 8,// int internalFormat,
|
||||
GL_RGBA, // unsigned int pixelFormat
|
||||
GL_UNSIGNED_BYTE,// unsigned int dataType
|
||||
data);
|
||||
return pOsgImage;
|
||||
}
|
||||
};
|
||||
|
||||
// now register with Registry to instantiate the above
|
||||
// reader/writer.
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterPNG> g_readerWriter_PNG_Proxy;
|
||||
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