Removed osgGLUT and Demos/*.
Integrated Marco's updated examples/*/*.dsp's.
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osganimate.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osganimate
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osganimate.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osganimate
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,250 +0,0 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
|
||||
{
|
||||
// set up the animation path
|
||||
osg::AnimationPath* animationPath = new osg::AnimationPath;
|
||||
animationPath->setLoopMode(osg::AnimationPath::LOOP);
|
||||
|
||||
int numSamples = 40;
|
||||
float yaw = 0.0f;
|
||||
float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
|
||||
float roll = osg::inDegrees(30.0f);
|
||||
|
||||
double time=0.0f;
|
||||
double time_delta = looptime/(double)numSamples;
|
||||
for(int i=0;i<numSamples;++i)
|
||||
{
|
||||
osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
|
||||
osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0)));
|
||||
|
||||
animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
|
||||
|
||||
yaw += yaw_delta;
|
||||
time += time_delta;
|
||||
|
||||
}
|
||||
return animationPath;
|
||||
}
|
||||
|
||||
osg::Node* createBase(const osg::Vec3& center,float radius)
|
||||
{
|
||||
|
||||
|
||||
|
||||
int numTilesX = 10;
|
||||
int numTilesY = 10;
|
||||
|
||||
float width = 2*radius;
|
||||
float height = 2*radius;
|
||||
|
||||
osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
|
||||
osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
|
||||
osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f));
|
||||
|
||||
// fill in vertices for grid, note numTilesX+1 * numTilesY+1...
|
||||
osg::Vec3Array* coords = new osg::Vec3Array;
|
||||
int iy;
|
||||
for(iy=0;iy<=numTilesY;++iy)
|
||||
{
|
||||
for(int ix=0;ix<=numTilesX;++ix)
|
||||
{
|
||||
coords->push_back(v000+dx*(float)ix+dy*(float)iy);
|
||||
}
|
||||
}
|
||||
|
||||
//Just two colours - black and white.
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
|
||||
colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
|
||||
int numColors=colors->size();
|
||||
|
||||
|
||||
int numIndicesPerRow=numTilesX+1;
|
||||
osg::UByteArray* coordIndices = new osg::UByteArray; // assumes we are using less than 256 points...
|
||||
osg::UByteArray* colorIndices = new osg::UByteArray;
|
||||
for(iy=0;iy<numTilesY;++iy)
|
||||
{
|
||||
for(int ix=0;ix<numTilesX;++ix)
|
||||
{
|
||||
// four vertices per quad.
|
||||
coordIndices->push_back(ix +(iy+1)*numIndicesPerRow);
|
||||
coordIndices->push_back(ix +iy*numIndicesPerRow);
|
||||
coordIndices->push_back((ix+1)+iy*numIndicesPerRow);
|
||||
coordIndices->push_back((ix+1)+(iy+1)*numIndicesPerRow);
|
||||
|
||||
// one color per quad
|
||||
colorIndices->push_back((ix+iy)%numColors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set up a single normal
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
|
||||
|
||||
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
geom->setVertexArray(coords);
|
||||
geom->setVertexIndices(coordIndices);
|
||||
|
||||
geom->setColorArray(colors);
|
||||
geom->setColorIndices(colorIndices);
|
||||
geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
|
||||
geom->setNormalArray(normals);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size()));
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geom);
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg::Node* createMovingModel(const osg::Vec3& center, float radius)
|
||||
{
|
||||
float animationLength = 10.0f;
|
||||
|
||||
osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
|
||||
|
||||
osg::Group* model = new osg::Group;
|
||||
|
||||
osg::Node* glider = osgDB::readNodeFile("glider.osg");
|
||||
if (glider)
|
||||
{
|
||||
const osg::BoundingSphere& bs = glider->getBound();
|
||||
|
||||
float size = radius/bs.radius()*0.3f;
|
||||
osg::MatrixTransform* positioned = new osg::MatrixTransform;
|
||||
positioned->setDataVariance(osg::Object::STATIC);
|
||||
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
|
||||
osg::Matrix::scale(size,size,size)*
|
||||
osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));
|
||||
|
||||
positioned->addChild(glider);
|
||||
|
||||
osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;
|
||||
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
|
||||
xform->addChild(positioned);
|
||||
|
||||
model->addChild(xform);
|
||||
}
|
||||
|
||||
osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
|
||||
if (cessna)
|
||||
{
|
||||
const osg::BoundingSphere& bs = cessna->getBound();
|
||||
|
||||
float size = radius/bs.radius()*0.3f;
|
||||
osg::MatrixTransform* positioned = new osg::MatrixTransform;
|
||||
positioned->setDataVariance(osg::Object::STATIC);
|
||||
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
|
||||
osg::Matrix::scale(size,size,size)*
|
||||
osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f));
|
||||
|
||||
positioned->addChild(cessna);
|
||||
|
||||
osg::MatrixTransform* xform = new osg::MatrixTransform;
|
||||
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
|
||||
xform->addChild(positioned);
|
||||
|
||||
model->addChild(xform);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
osg::Node* createModel()
|
||||
{
|
||||
osg::Vec3 center(0.0f,0.0f,0.0f);
|
||||
float radius = 100.0f;
|
||||
|
||||
osg::Group* root = new osg::Group;
|
||||
|
||||
root->addChild(createMovingModel(center,radius*0.8f));
|
||||
|
||||
root->addChild(createBase(center-osg::Vec3(0.0f,0.0f,radius*0.5),radius));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* model = createModel();
|
||||
if (!model)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// tilt the scene so the default eye position is looking down on the model.
|
||||
osg::MatrixTransform* rootnode = new osg::MatrixTransform;
|
||||
rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
|
||||
rootnode->addChild(model);
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgbillboard.cpp
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgbillboard
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgbillboard.cpp
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
|
||||
EXEC = osgbillboard
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,211 +0,0 @@
|
||||
#include <osg/Node>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/LineWidth>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
//
|
||||
// A simple demo demonstrating different texturing modes,
|
||||
// including using of texture extensions.
|
||||
//
|
||||
|
||||
|
||||
typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
|
||||
|
||||
/** create quad at specified position. */
|
||||
osg::Drawable* createSquare(const osg::Vec3& corner,const osg::Vec3& width,const osg::Vec3& height, osg::Image* image=NULL)
|
||||
{
|
||||
// set up the Geometry.
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(4);
|
||||
(*coords)[0] = corner;
|
||||
(*coords)[1] = corner+width;
|
||||
(*coords)[2] = corner+width+height;
|
||||
(*coords)[3] = corner+height;
|
||||
|
||||
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec3Array* norms = new osg::Vec3Array(1);
|
||||
(*norms)[0] = width^height;
|
||||
(*norms)[0].normalize();
|
||||
|
||||
geom->setNormalArray(norms);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec2Array* tcoords = new osg::Vec2Array(4);
|
||||
(*tcoords)[0].set(0.0f,0.0f);
|
||||
(*tcoords)[1].set(1.0f,0.0f);
|
||||
(*tcoords)[2].set(1.0f,1.0f);
|
||||
(*tcoords)[3].set(0.0f,1.0f);
|
||||
geom->setTexCoordArray(0,tcoords);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
|
||||
|
||||
if (image)
|
||||
{
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
geom->setStateSet(stateset);
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
osg::Drawable* createAxis(const osg::Vec3& corner,const osg::Vec3& xdir,const osg::Vec3& ydir,const osg::Vec3& zdir)
|
||||
{
|
||||
// set up the Geometry.
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(6);
|
||||
(*coords)[0] = corner;
|
||||
(*coords)[1] = corner+xdir;
|
||||
(*coords)[2] = corner;
|
||||
(*coords)[3] = corner+ydir;
|
||||
(*coords)[4] = corner;
|
||||
(*coords)[5] = corner+zdir;
|
||||
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec4 x_color(0.0f,1.0f,1.0f,1.0f);
|
||||
osg::Vec4 y_color(0.0f,1.0f,1.0f,1.0f);
|
||||
osg::Vec4 z_color(1.0f,0.0f,0.0f,1.0f);
|
||||
|
||||
osg::Vec4Array* color = new osg::Vec4Array(6);
|
||||
(*color)[0] = x_color;
|
||||
(*color)[1] = x_color;
|
||||
(*color)[2] = y_color;
|
||||
(*color)[3] = y_color;
|
||||
(*color)[4] = z_color;
|
||||
(*color)[5] = z_color;
|
||||
|
||||
geom->setColorArray(color);
|
||||
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,6));
|
||||
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
osg::LineWidth* linewidth = new osg::LineWidth();
|
||||
linewidth->setWidth(4.0f);
|
||||
stateset->setAttributeAndModes(linewidth,osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
geom->setStateSet(stateset);
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
osg::Node* createModel()
|
||||
{
|
||||
|
||||
// create the root node which will hold the model.
|
||||
osg::Group* root = new osg::Group();
|
||||
|
||||
// add the drawable into a single goede to be shared...
|
||||
osg::Billboard* center = new osg::Billboard();
|
||||
center->setMode(osg::Billboard::POINT_ROT_EYE);
|
||||
center->addDrawable(
|
||||
createSquare(osg::Vec3(-0.5f,0.0f,-0.5f),osg::Vec3(1.0f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f),osgDB::readImageFile("Images/reflect.rgb")),
|
||||
osg::Vec3(0.0f,0.0f,0.0f));
|
||||
|
||||
osg::Billboard* x_arrow = new osg::Billboard();
|
||||
x_arrow->setMode(osg::Billboard::AXIAL_ROT);
|
||||
x_arrow->setAxis(osg::Vec3(1.0f,0.0f,0.0f));
|
||||
x_arrow->setNormal(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
x_arrow->addDrawable(
|
||||
createSquare(osg::Vec3(-0.5f,0.0f,-0.5f),osg::Vec3(1.0f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f),osgDB::readImageFile("Cubemap_axis/posx.png")),
|
||||
osg::Vec3(5.0f,0.0f,0.0f));
|
||||
|
||||
osg::Billboard* y_arrow = new osg::Billboard();
|
||||
y_arrow->setMode(osg::Billboard::AXIAL_ROT);
|
||||
y_arrow->setAxis(osg::Vec3(0.0f,1.0f,0.0f));
|
||||
y_arrow->setNormal(osg::Vec3(1.0f,0.0f,0.0f));
|
||||
y_arrow->addDrawable(
|
||||
createSquare(osg::Vec3(0.0f,-0.5f,-0.5f),osg::Vec3(0.0f,1.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f),osgDB::readImageFile("Cubemap_axis/posy.png")),
|
||||
osg::Vec3(0.0f,5.0f,0.0f));
|
||||
|
||||
osg::Billboard* z_arrow = new osg::Billboard();
|
||||
z_arrow->setMode(osg::Billboard::AXIAL_ROT);
|
||||
z_arrow->setAxis(osg::Vec3(0.0f,0.0f,1.0f));
|
||||
z_arrow->setNormal(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
z_arrow->addDrawable(
|
||||
createSquare(osg::Vec3(-0.5f,0.0f,-0.5f),osg::Vec3(1.0f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f),osgDB::readImageFile("Cubemap_axis/posz.png")),
|
||||
osg::Vec3(0.0f,0.0f,5.0f));
|
||||
|
||||
|
||||
|
||||
osg::Geode* axis = new osg::Geode();
|
||||
axis->addDrawable(createAxis(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(5.0f,0.0f,0.0f),osg::Vec3(0.0f,5.0f,0.0f),osg::Vec3(0.0f,0.0f,5.0f)));
|
||||
|
||||
|
||||
root->addChild(center);
|
||||
root->addChild(x_arrow);
|
||||
root->addChild(y_arrow);
|
||||
root->addChild(z_arrow);
|
||||
root->addChild(axis);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create a model from the images.
|
||||
osg::Node* rootNode = createModel();
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport( rootNode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcallback.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcallback
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcallback.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcallback
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,189 +0,0 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
|
||||
class UpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
std::cout<<"update callback - pre traverse"<<node<<std::endl;
|
||||
traverse(node,nv);
|
||||
std::cout<<"update callback - post traverse"<<node<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class CullCallback : public osg::NodeCallback
|
||||
{
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
std::cout<<"cull callback - pre traverse"<<node<<std::endl;
|
||||
traverse(node,nv);
|
||||
std::cout<<"cull callback - post traverse"<<node<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class DrawableDrawCallback : public osg::Drawable::DrawCallback
|
||||
{
|
||||
virtual void drawImplementation(osg::State& state,const osg::Drawable* drawable) const
|
||||
{
|
||||
std::cout<<"draw call back - pre drawImplementation"<<drawable<<std::endl;
|
||||
drawable->drawImplementation(state);
|
||||
std::cout<<"draw call back - post drawImplementation"<<drawable<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
struct TransformCallback : public osg::Transform::ComputeTransformCallback
|
||||
{
|
||||
/** Get the transformation matrix which moves from local coords to world coords.*/
|
||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,const osg::Transform* transform, osg::NodeVisitor* nv) const
|
||||
{
|
||||
std::cout<<"computeLocalToWorldMatrix - pre transform->computeLocalToWorldMatrix"<<std::endl;
|
||||
bool result = transform->computeLocalToWorldMatrix(matrix,nv);
|
||||
std::cout<<"computeLocalToWorldMatrix - post transform->computeLocalToWorldMatrix"<<std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get the transformation matrix which moves from world coords to local coords.*/
|
||||
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,const osg::Transform* transform, osg::NodeVisitor* nv) const
|
||||
{
|
||||
std::cout<<"computeWorldToLocalMatrix - pre transform->computeWorldToLocalMatrix"<<std::endl;
|
||||
bool result = transform->computeWorldToLocalMatrix(matrix,nv);
|
||||
std::cout<<"computeWorldToLocalMatrix - post transform->computeWorldToLocalMatrix"<<std::endl;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct DrawableUpdateCallback : public osg::Drawable::UpdateCallback
|
||||
{
|
||||
virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)
|
||||
{
|
||||
std::cout<<"Drawable update callback "<<drawable<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
struct DrawableCullCallback : public osg::Drawable::CullCallback
|
||||
{
|
||||
/** do customized cull code.*/
|
||||
virtual bool cull(osg::NodeVisitor*, osg::Drawable* drawable, osg::State* /*state*/) const
|
||||
{
|
||||
std::cout<<"Drawable cull callback "<<drawable<<std::endl;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class InsertCallbacksVisitor : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
InsertCallbacksVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
node.setUpdateCallback(new UpdateCallback());
|
||||
node.setCullCallback(new CullCallback());
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode& geode)
|
||||
{
|
||||
geode.setUpdateCallback(new UpdateCallback());
|
||||
|
||||
//note, it makes no sense to attach a cull callback to the node
|
||||
//at there are no nodes to traverse below the geode, only
|
||||
//drawables, and as such the Cull node callbacks is ignored.
|
||||
//If you wish to control the culling of drawables
|
||||
//then use a drawable cullback...
|
||||
|
||||
for(unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||
{
|
||||
geode.getDrawable(i)->setUpdateCallback(new DrawableUpdateCallback());
|
||||
geode.getDrawable(i)->setCullCallback(new DrawableCullCallback());
|
||||
geode.getDrawable(i)->setDrawCallback(new DrawableDrawCallback());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(osg::Transform& node)
|
||||
{
|
||||
node.setComputeTransformCallback(new TransformCallback());
|
||||
apply((osg::Node&)node);
|
||||
}
|
||||
};
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// insert all the callbacks
|
||||
InsertCallbacksVisitor icv;
|
||||
rootnode->accept(icv);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgclip.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgclip
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgclip.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgclip
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,189 +0,0 @@
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/ClipNode>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Material>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/LineStipple>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
#include <osgUtil/TransformCallback>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
void write_usage(std::ostream& out,const std::string& name)
|
||||
{
|
||||
out << std::endl;
|
||||
out <<"usage:"<< std::endl;
|
||||
out <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
|
||||
out << std::endl;
|
||||
out <<"options:"<< std::endl;
|
||||
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
|
||||
out <<" i.e. -l osgdb_pfb"<< std::endl;
|
||||
out <<" Useful for loading reader/writers which can load"<< std::endl;
|
||||
out <<" other file formats in addition to its extension."<< std::endl;
|
||||
out <<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
|
||||
out <<" i.e. -e pfb"<< std::endl;
|
||||
out <<" Useful short hand for specifying full library name as"<< std::endl;
|
||||
out <<" done with -l above, as it automatically expands to"<< std::endl;
|
||||
out <<" the full library name appropriate for each platform."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stereo - switch on stereo rendering, using the default of,"<< std::endl;
|
||||
out <<" ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
|
||||
out <<" environmental variable. See doc/stereo.html for "<< std::endl;
|
||||
out <<" further details on setting up accurate stereo "<< std::endl;
|
||||
out <<" for your system. "<< std::endl;
|
||||
out <<" -stereo ANAGLYPHIC - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
|
||||
out <<" -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stencil - use a visual with stencil buffer enabled, this "<< std::endl;
|
||||
out <<" also allows the depth complexity statistics mode"<< std::endl;
|
||||
out <<" to be used (press 'p' three times to cycle to it)."<< std::endl;
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
|
||||
osg::Node* decorate_with_clip_node(osg::Node* subgraph)
|
||||
{
|
||||
osg::Group* rootnode = new osg::Group;
|
||||
|
||||
|
||||
// create wireframe view of the model so the user can see
|
||||
// what parts are being culled away.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
//osg::Material* material = new osg::Material;
|
||||
osg::PolygonMode* polymode = new osg::PolygonMode;
|
||||
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
|
||||
stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
|
||||
osg::Group* wireframe_subgraph = new osg::Group;
|
||||
wireframe_subgraph->setStateSet(stateset);
|
||||
wireframe_subgraph->addChild(subgraph);
|
||||
rootnode->addChild(wireframe_subgraph);
|
||||
|
||||
/*
|
||||
// simple approach to adding a clipnode above a subrgaph.
|
||||
|
||||
// create clipped part.
|
||||
osg::ClipNode* clipped_subgraph = new osg::ClipNode;
|
||||
|
||||
osg::BoundingSphere bs = subgraph->getBound();
|
||||
bs.radius()*= 0.4f;
|
||||
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
|
||||
clipped_subgraph->createClipBox(bb);
|
||||
clipped_subgraph->addChild(subgraph);
|
||||
rootnode->addChild(clipped_subgraph);
|
||||
*/
|
||||
|
||||
|
||||
// more complex approach to managing ClipNode, allowing
|
||||
// ClipNode node to be transformed independantly from the subgraph
|
||||
// that it is clipping.
|
||||
|
||||
osg::MatrixTransform* transform= new osg::MatrixTransform;
|
||||
|
||||
osg::NodeCallback* nc = new osgUtil::TransformCallback(subgraph->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
|
||||
transform->setUpdateCallback(nc);
|
||||
|
||||
osg::ClipNode* clipnode = new osg::ClipNode;
|
||||
osg::BoundingSphere bs = subgraph->getBound();
|
||||
bs.radius()*= 0.4f;
|
||||
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
clipnode->createClipBox(bb);
|
||||
clipnode->setCullingActive(false);
|
||||
|
||||
transform->addChild(clipnode);
|
||||
rootnode->addChild(transform);
|
||||
|
||||
|
||||
// create clipped part.
|
||||
osg::Group* clipped_subgraph = new osg::Group;
|
||||
|
||||
clipped_subgraph->setStateSet(clipnode->getStateSet());
|
||||
clipped_subgraph->addChild(subgraph);
|
||||
rootnode->addChild(clipped_subgraph);
|
||||
|
||||
return rootnode;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
if (!loadedModel)
|
||||
{
|
||||
write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decorate the scenegraph with a clip node.
|
||||
osg::Node* rootnode = decorate_with_clip_node(loadedModel);
|
||||
|
||||
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
broadcaster.cpp\
|
||||
osgcluster.cpp\
|
||||
receiver.cpp\
|
||||
|
||||
HEADERFILES =\
|
||||
broadcaster.h\
|
||||
receiver.h\
|
||||
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(SOCKET_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
$(HEADERFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcluster
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,13 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
broadcaster.cpp\
|
||||
osgcluster.cpp\
|
||||
receiver.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(SOCKET_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcluster
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,67 +0,0 @@
|
||||
osgcluster demonstates basic clustering of machines across a local area
|
||||
network using UDP packets to send camera position updates from a master viewer
|
||||
to slave viewers.
|
||||
|
||||
Note, the broadcaster and reciever classes have currently been implement
|
||||
for Linux/IRIX, hence osgcluster will only work on these systems. It should
|
||||
also work with little extra work on other Unix based OS's. Support for
|
||||
WinSocket needs to be added to allow support for Windows. Anybody know
|
||||
WinSocket enough to tackle this? If so let us know.
|
||||
|
||||
-
|
||||
|
||||
On the master machine run:
|
||||
|
||||
osgcluster -m -f 30 mymodel.osg
|
||||
|
||||
|
||||
On the slave machines run:
|
||||
|
||||
for left channel:
|
||||
|
||||
osgcluster -s -f 30 -o 30 mymodel.osg
|
||||
|
||||
for right channel:
|
||||
|
||||
osgcluster -s -f 30 -o 30 mymodel.osg
|
||||
|
||||
The options are :
|
||||
|
||||
-m set to viewer to master so that it broadcasts its camera postion.
|
||||
-s set to viewer to slave so that it recivers its camera postion.
|
||||
-n set the socket number to communicate over, defaults to 8100.
|
||||
-o set offset the slave camera from the master position by specified
|
||||
number of degress. positive offset turns camera towards right.
|
||||
-f set the horizontal field of view of the camera.
|
||||
|
||||
Sepetember 2001.
|
||||
Robert Osfield.
|
||||
|
||||
|
||||
|
||||
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 2001.
|
||||
@@ -1,188 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined (WIN32)
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__linux)
|
||||
#include <unistd.h>
|
||||
#include <linux/sockios.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <unistd.h>
|
||||
#include <sys/sockio.h>
|
||||
#elif defined(__sgi)
|
||||
#include <unistd.h>
|
||||
#include <net/soioctl.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
// nothing needed
|
||||
#elif defined(__sun)
|
||||
#include <unistd.h>
|
||||
#include <sys/sockio.h>
|
||||
#elif defined (__DARWIN_OSX__)
|
||||
#include <unistd.h>
|
||||
#include <sys/sockio.h>
|
||||
#elif defined (WIN32)
|
||||
#include <winsock.h>
|
||||
#include <stdio.h>
|
||||
#elif defined (__hpux__)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#error Teach me how to build on this system
|
||||
#endif
|
||||
|
||||
#include "broadcaster.h"
|
||||
|
||||
#define _VERBOSE 1
|
||||
|
||||
Broadcaster::Broadcaster( void )
|
||||
{
|
||||
_port = 0;
|
||||
_initialized = false;
|
||||
_buffer = 0L;
|
||||
_address = 0;
|
||||
}
|
||||
|
||||
Broadcaster::~Broadcaster( void )
|
||||
{
|
||||
#if defined (WIN32)
|
||||
closesocket( _so);
|
||||
#else
|
||||
close( _so );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Broadcaster::init( void )
|
||||
{
|
||||
#if defined (WIN32)
|
||||
WORD version = MAKEWORD(1,1);
|
||||
WSADATA wsaData;
|
||||
// First, we start up Winsock
|
||||
WSAStartup(version, &wsaData);
|
||||
#endif
|
||||
|
||||
if( _port == 0 )
|
||||
{
|
||||
fprintf( stderr, "Broadcaster::init() - port not defined\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
|
||||
{
|
||||
perror( "Socket" );
|
||||
return false;
|
||||
}
|
||||
#if defined (WIN32)
|
||||
const BOOL on = TRUE;
|
||||
#else
|
||||
int on = 1;
|
||||
#endif
|
||||
|
||||
#if defined (WIN32)
|
||||
setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(int));
|
||||
#else
|
||||
setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons( _port );
|
||||
if( _address == 0 )
|
||||
{
|
||||
#if defined (WIN32)
|
||||
setsockopt( _so, SOL_SOCKET, SO_BROADCAST, (const char *) &on, sizeof(int));
|
||||
#else
|
||||
setsockopt( _so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
#if !defined (WIN32)
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
#if defined (__linux)
|
||||
strcpy( ifr.ifr_name, "eth0" );
|
||||
#elif defined(__sun)
|
||||
strcpy( ifr.ifr_name, "hme0" );
|
||||
#elif !defined (WIN32)
|
||||
strcpy( ifr.ifr_name, "ef0" );
|
||||
#endif
|
||||
#if defined (WIN32) // get the server address
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||
}
|
||||
#else
|
||||
if( (ioctl( _so, SIOCGIFBRDADDR, &ifr)) < 0 )
|
||||
{
|
||||
perror( "Broadcaster::init() Cannot get Broadcast Address" );
|
||||
return false;
|
||||
}
|
||||
saddr.sin_addr.s_addr = (((sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
saddr.sin_addr.s_addr = _address;
|
||||
}
|
||||
#endif
|
||||
#define _VERBOSE 1
|
||||
#ifdef _VERBOSE
|
||||
unsigned char *ptr = (unsigned char *)&saddr.sin_addr.s_addr;
|
||||
printf( "Broadcast address : %u.%u.%u.%u\n", ptr[0], ptr[1], ptr[2], ptr[3] );
|
||||
#endif
|
||||
|
||||
_initialized = true;
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
void Broadcaster::setHost( const char *hostname )
|
||||
{
|
||||
struct hostent *h;
|
||||
if( (h = gethostbyname( hostname )) == 0L )
|
||||
{
|
||||
fprintf( stderr, "Broadcaster::setHost() - Cannot resolv an address for \"%s\".\n", hostname );
|
||||
_address = 0;
|
||||
}
|
||||
else
|
||||
_address = *(( unsigned long *)h->h_addr);
|
||||
}
|
||||
|
||||
void Broadcaster::setPort( const short port )
|
||||
{
|
||||
_port = port;
|
||||
}
|
||||
|
||||
void Broadcaster::setBuffer( void *buffer, const unsigned int size )
|
||||
{
|
||||
_buffer = buffer;
|
||||
_buffer_size = size;
|
||||
}
|
||||
|
||||
void Broadcaster::sync( void )
|
||||
{
|
||||
if(!_initialized) init();
|
||||
|
||||
if( _buffer == 0L )
|
||||
{
|
||||
fprintf( stderr, "Broadcaster::sync() - No buffer\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
unsigned int size = sizeof( SOCKADDR_IN );
|
||||
sendto( _so, (const char *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
|
||||
int err = WSAGetLastError ();
|
||||
int *dum = (int*) _buffer;
|
||||
#else
|
||||
unsigned int size = sizeof( struct sockaddr_in );
|
||||
sendto( _so, (const void *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef __BROADCASTER_H
|
||||
#define __BROADCASTER_H
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Broadcaster.h
|
||||
//
|
||||
// Class definition for broadcasting a buffer to a LAN
|
||||
//
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
class Broadcaster
|
||||
{
|
||||
public :
|
||||
|
||||
Broadcaster( void );
|
||||
~Broadcaster( void );
|
||||
|
||||
// Set the broadcast port
|
||||
void setPort( const short port );
|
||||
|
||||
// Set the buffer to be broadcast
|
||||
void setBuffer( void *buffer, const unsigned int buffer_size );
|
||||
|
||||
// Set a recipient host. If this is used, the Broadcaster
|
||||
// no longer broadcasts, but rather directs UDP packets at
|
||||
// host.
|
||||
void setHost( const char *hostname );
|
||||
|
||||
// Sync broadcasts the buffer
|
||||
void sync( void );
|
||||
|
||||
private :
|
||||
bool init( void );
|
||||
|
||||
private :
|
||||
#if defined (WIN32)
|
||||
SOCKET _so;
|
||||
#else
|
||||
int _so;
|
||||
#endif
|
||||
bool _initialized;
|
||||
short _port;
|
||||
void *_buffer;
|
||||
unsigned int _buffer_size;
|
||||
#if defined (WIN32)
|
||||
SOCKADDR_IN saddr;
|
||||
#else
|
||||
struct sockaddr_in saddr;
|
||||
#endif
|
||||
unsigned long _address;
|
||||
};
|
||||
#endif
|
||||
@@ -1,405 +0,0 @@
|
||||
#ifdef USE_MEM_CHECK
|
||||
#include <mcheck.h>
|
||||
#endif
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Quat>
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
#include "receiver.h"
|
||||
#include "broadcaster.h"
|
||||
|
||||
typedef unsigned char * BytePtr;
|
||||
template <class T>
|
||||
inline void swapBytes( T &s )
|
||||
{
|
||||
if( sizeof( T ) == 1 ) return;
|
||||
|
||||
T d = s;
|
||||
BytePtr sptr = (BytePtr)&s;
|
||||
BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
|
||||
|
||||
for( unsigned int i = 0; i < sizeof(T); i++ )
|
||||
*(sptr++) = *(dptr--);
|
||||
}
|
||||
|
||||
class CameraPacket {
|
||||
public:
|
||||
|
||||
CameraPacket():_masterKilled(false)
|
||||
{
|
||||
_byte_order = 0x12345678;
|
||||
}
|
||||
|
||||
void setPacket(const osg::Camera& camera,const osg::FrameStamp* frameStamp)
|
||||
{
|
||||
_eye = camera.getEyePoint();
|
||||
_center = camera.getCenterPoint();
|
||||
_up = camera.getUpVector();
|
||||
if (frameStamp)
|
||||
{
|
||||
_frameStamp = *frameStamp;
|
||||
}
|
||||
}
|
||||
|
||||
void getCamera(osg::Camera& camera,float angle_offset=0.0f)
|
||||
{
|
||||
|
||||
osg::Vec3 lv = _center-_eye;
|
||||
osg::Matrix matrix;
|
||||
matrix.makeIdentity();
|
||||
matrix.makeRotate(angle_offset,_up.x(),_up.y(),_up.z());
|
||||
lv = lv*matrix;
|
||||
|
||||
camera.setLookAt(_eye,_eye+lv,_up);
|
||||
|
||||
}
|
||||
|
||||
void getSceneViewUpdate(osgUtil::SceneView& sv)
|
||||
{
|
||||
// note pass a separate reference counted FrameStamp
|
||||
// rather than this frame stamp as it can get overwritten.
|
||||
sv.setFrameStamp(new osg::FrameStamp(_frameStamp));
|
||||
}
|
||||
|
||||
|
||||
void checkByteOrder( void )
|
||||
{
|
||||
if( _byte_order == 0x78563412 ) // We're backwards
|
||||
{
|
||||
swapBytes( _byte_order );
|
||||
swapBytes( _masterKilled );
|
||||
swapBytes( _eye[0] );
|
||||
swapBytes( _eye[1] );
|
||||
swapBytes( _eye[2] );
|
||||
swapBytes( _center[0] );
|
||||
swapBytes( _center[1] );
|
||||
swapBytes( _center[2] );
|
||||
swapBytes( _up[0] );
|
||||
swapBytes( _up[1] );
|
||||
swapBytes( _up[2] );
|
||||
swapBytes( _attachMatrix );
|
||||
for( int i = 0; i < 16; i++ )
|
||||
swapBytes( _matrix.ptr()[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setMasterKilled(const bool flag) { _masterKilled = flag; }
|
||||
const bool getMasterKilled() const { return _masterKilled; }
|
||||
|
||||
unsigned long _byte_order;
|
||||
bool _masterKilled;
|
||||
osg::Vec3 _eye;
|
||||
osg::Vec3 _center;
|
||||
osg::Vec3 _up;
|
||||
bool _attachMatrix;
|
||||
osg::Matrix _matrix;
|
||||
|
||||
// note don't use a ref_ptr as used elsewhere for FrameStamp
|
||||
// since we don't want to copy the pointer - but the memory.
|
||||
// FrameStamp doesn't have a private destructor to allow
|
||||
// us to do this, even though its a reference counted object.
|
||||
osg::FrameStamp _frameStamp;
|
||||
|
||||
};
|
||||
|
||||
// using namespace osgUtil required to get round VisualStudio's inablility
|
||||
// to handle osgUtil::SceneView::app() in the code below, only SceneView::app
|
||||
// works..but this breaks the IRIX build, unless you have the osgUtil??!
|
||||
// Robert Osfield, July 2002.
|
||||
using namespace osgUtil;
|
||||
|
||||
class MySceneView : public SceneView {
|
||||
|
||||
public:
|
||||
|
||||
enum ViewerMode
|
||||
{
|
||||
STAND_ALONE,
|
||||
SLAVE,
|
||||
MASTER
|
||||
};
|
||||
|
||||
MySceneView(ViewerMode viewerMode,int socketNumber,float camera_fov, float camera_offset):
|
||||
_viewerMode(viewerMode),_socketNumber(socketNumber),
|
||||
_camera_fov(camera_fov), _camera_offset(camera_offset)
|
||||
{
|
||||
setDefaults();
|
||||
getCamera()->setAdjustAspectRatioMode(osg::Camera::ADJUST_VERTICAL);
|
||||
getCamera()->setFOV(camera_fov,camera_fov*(600.0f/800.0f),1.0f,1000.0f);
|
||||
|
||||
_bc.setPort(socketNumber);
|
||||
_rc.setPort(socketNumber);
|
||||
};
|
||||
|
||||
~MySceneView()
|
||||
{
|
||||
if (_viewerMode==MASTER)
|
||||
{
|
||||
// need to broadcast my death.
|
||||
CameraPacket cp;
|
||||
cp.setPacket(*getCamera(),getFrameStamp());
|
||||
cp.setMasterKilled(true);
|
||||
|
||||
_bc.setBuffer(&cp, sizeof( CameraPacket ));
|
||||
_bc.sync();
|
||||
|
||||
std::cout << "broadcasting death"<<std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// override the basic SceneView::app traversal.
|
||||
virtual void update()
|
||||
{
|
||||
SceneView::update();
|
||||
switch (_viewerMode)
|
||||
{
|
||||
case(MASTER):
|
||||
{
|
||||
CameraPacket cp;
|
||||
cp.setPacket(*getCamera(),getFrameStamp());
|
||||
|
||||
_bc.setBuffer(&cp, sizeof( CameraPacket ));
|
||||
_bc.sync();
|
||||
|
||||
}
|
||||
break;
|
||||
case(SLAVE):
|
||||
{
|
||||
CameraPacket cp;
|
||||
|
||||
_rc.setBuffer(&cp, sizeof( CameraPacket ));
|
||||
_rc.sync();
|
||||
|
||||
cp.checkByteOrder();
|
||||
|
||||
|
||||
cp.getCamera(*getCamera(),_camera_offset);
|
||||
cp.getSceneViewUpdate(*this);
|
||||
|
||||
if (cp.getMasterKilled())
|
||||
{
|
||||
std::cout << "recieved master killed"<<std::endl;
|
||||
_viewerMode = STAND_ALONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// no need to anything here, just a normal interactive viewer.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
ViewerMode _viewerMode;
|
||||
int _socketNumber;
|
||||
float _camera_fov;
|
||||
float _camera_offset;
|
||||
unsigned long _byte_order;
|
||||
|
||||
|
||||
Broadcaster _bc;
|
||||
Receiver _rc;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* 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,
|
||||
MySceneView::ViewerMode& viewerMode, int& socketNumber,
|
||||
float& camera_fov, float& camera_offset)
|
||||
{
|
||||
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('m'):
|
||||
viewerMode = MySceneView::MASTER;
|
||||
break;
|
||||
case('s'):
|
||||
viewerMode = MySceneView::SLAVE;
|
||||
break;
|
||||
case('n'):
|
||||
++i;
|
||||
if (i<argc)
|
||||
{
|
||||
socketNumber = atoi(argv[i]);
|
||||
}
|
||||
break;
|
||||
case('f'):
|
||||
++i;
|
||||
if (i<argc)
|
||||
{
|
||||
camera_fov = atoi(argv[i]);
|
||||
}
|
||||
break;
|
||||
case('o'):
|
||||
++i;
|
||||
if (i<argc)
|
||||
{
|
||||
camera_offset = atoi(argv[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
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."<<std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (master) osg::notify(osg::NOTICE)<<"set to MASTER, broadcasting on socketNumber "<<socketNumber<<std::endl;
|
||||
else osg::notify(osg::NOTICE)<<"set to SLAVE, reciving on socketNumber "<<socketNumber<<std::endl;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// initialize the GLUT
|
||||
glutInit( &argc, argv );
|
||||
|
||||
if (argc<2)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"usage:"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" osgcluster [options] infile1 [infile2 ...]"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"options:"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -m - set this viewer to be master"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -s - set this viewer to be a slave"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -o - offset the slave camera from the master position"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" by specified number of degress. A positive offset "<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" turns camera towards right."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -f - set the horizontal field of view of the camera."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -n SocketNumber - set the socket number, defaults to 8100."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" to broadcast on if a master"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" to reciever on if a slave"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -l libraryName - load plugin of name libraryName"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -l osgdb_pfb"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful for loading reader/writers which can load"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" other file formats in addition to its extension."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -e extensionName - load reader/wrter plugin for file extension"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -e pfb"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful short hand for specifying full library name as"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" done with -l above, as it automatically expands to the"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" full library name appropriate for each platform."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
osg::Timer timer;
|
||||
osg::Timer_t before_load = timer.tick();
|
||||
|
||||
MySceneView::ViewerMode viewerMode = MySceneView::STAND_ALONE;
|
||||
int socketNumber=8100;
|
||||
float camera_fov=45.0f;
|
||||
float camera_offset=45.0f;
|
||||
|
||||
osg::Node* rootnode = getNodeFromFiles( argc, argv, viewerMode, socketNumber,camera_fov,camera_offset);
|
||||
|
||||
osg::Timer_t after_load = timer.tick();
|
||||
std::cout << "Time for load = "<<timer.delta_s(before_load,after_load)<<" seconds"<<std::endl;
|
||||
|
||||
osg::ref_ptr<MySceneView> mySceneView = new MySceneView(viewerMode,socketNumber,camera_fov,osg::inDegrees(camera_offset));
|
||||
mySceneView->setSceneData(rootnode);
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer;
|
||||
viewer.setWindowTitle(argv[0]);
|
||||
viewer.addViewport( mySceneView.get() );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#if defined (WIN32)
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "receiver.h"
|
||||
|
||||
Receiver::Receiver( void )
|
||||
{
|
||||
_port = 0;
|
||||
_initialized = false;
|
||||
_buffer = 0L;
|
||||
}
|
||||
|
||||
Receiver::~Receiver( void )
|
||||
{
|
||||
#if defined (WIN32)
|
||||
closesocket( _so);
|
||||
#else
|
||||
close( _so );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Receiver::init( void )
|
||||
{
|
||||
#ifdef WIN32
|
||||
WORD version = MAKEWORD(1,1);
|
||||
WSADATA wsaData;
|
||||
// First, we start up Winsock
|
||||
WSAStartup(version, &wsaData);
|
||||
#endif
|
||||
|
||||
if( _port == 0 )
|
||||
{
|
||||
fprintf( stderr, "Receiver::init() - port not defined\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
|
||||
{
|
||||
perror( "Socket" );
|
||||
return false;
|
||||
}
|
||||
#if defined (WIN32)
|
||||
// const BOOL on = TRUE;
|
||||
// setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(int));
|
||||
#else
|
||||
int on = 1;
|
||||
setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
// struct sockaddr_in saddr;
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons( _port );
|
||||
#if defined (WIN32)
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
#else
|
||||
saddr.sin_addr.s_addr = 0;
|
||||
#endif
|
||||
|
||||
if( bind( _so, (struct sockaddr *)&saddr, sizeof( saddr )) < 0 )
|
||||
{
|
||||
perror( "bind" );
|
||||
return false;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
|
||||
void Receiver::setPort( const short port )
|
||||
{
|
||||
_port = port;
|
||||
}
|
||||
|
||||
void Receiver::setBuffer( void *buffer, const unsigned int size )
|
||||
{
|
||||
_buffer = buffer;
|
||||
_buffer_size = size;
|
||||
}
|
||||
|
||||
void Receiver::sync( void )
|
||||
{
|
||||
if(!_initialized) init();
|
||||
|
||||
if( _buffer == 0L )
|
||||
{
|
||||
fprintf( stderr, "Receiver::sync() - No buffer\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__linux) || defined(__FreeBSD__)
|
||||
socklen_t
|
||||
#else
|
||||
int
|
||||
#endif
|
||||
size = sizeof( struct sockaddr_in );
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO( &fdset );
|
||||
FD_SET( _so, &fdset );
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
#if defined (WIN32)
|
||||
// saddr.sin_port = htons( _port );
|
||||
recvfrom( _so, (char *)_buffer, _buffer_size, 0, (sockaddr*)&saddr, &size );
|
||||
// recvfrom(sock_Receive, szMessage, 256, 0, (sockaddr*)&addr_Cli, &clilen)
|
||||
int err = WSAGetLastError ();
|
||||
int *dum = (int*) _buffer;
|
||||
|
||||
while( select( _so+1, &fdset, 0L, 0L, &tv ) )
|
||||
{
|
||||
if( FD_ISSET( _so, &fdset ) )
|
||||
{
|
||||
recvfrom( _so, (char *)_buffer, _buffer_size, 0, (sockaddr*)&saddr, &size );
|
||||
}
|
||||
}
|
||||
#else
|
||||
recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size );
|
||||
while( select( _so+1, &fdset, 0L, 0L, &tv ) )
|
||||
{
|
||||
if( FD_ISSET( _so, &fdset ) )
|
||||
{
|
||||
recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef __RECEIVER_H
|
||||
#define __RECEIVER_H
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Receiver.h
|
||||
//
|
||||
// Class definition for the recipient of a broadcasted message
|
||||
//
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
class Receiver
|
||||
{
|
||||
public :
|
||||
|
||||
Receiver();
|
||||
~Receiver();
|
||||
|
||||
// setBuffer defines the buffer into which the broadcasted
|
||||
// message will be received.
|
||||
void setBuffer( void *buffer, const unsigned int size );
|
||||
|
||||
// Define what port to listen and bind to
|
||||
void setPort( const short port );
|
||||
|
||||
// Sync does a blocking wait to recieve next message
|
||||
void sync( void );
|
||||
|
||||
private :
|
||||
bool init( void );
|
||||
|
||||
private :
|
||||
#if defined (WIN32)
|
||||
SOCKET _so;
|
||||
#else
|
||||
int _so;
|
||||
#endif
|
||||
#if defined (WIN32)
|
||||
SOCKADDR_IN saddr;
|
||||
#else
|
||||
struct sockaddr_in saddr;
|
||||
#endif
|
||||
bool _initialized;
|
||||
short _port;
|
||||
void *_buffer;
|
||||
unsigned int _buffer_size;
|
||||
};
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
OrientationConverter.cpp\
|
||||
osgconv.cpp\
|
||||
|
||||
HEADERFILES = \
|
||||
OrientationConverter.h
|
||||
|
||||
LIBS += -losg -losgUtil -losgDB $(GL_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
$(HEADERFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgconv
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
OrientationConverter.cpp\
|
||||
osgconv.cpp\
|
||||
|
||||
LIBS += -losg -losgUtil -losgDB $(GL_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgconv
|
||||
|
||||
INSTFILES =\
|
||||
$(CXXFILES)\
|
||||
Makefile.inst=Makefile
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,64 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include "OrientationConverter.h"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
OrientationConverter::OrientationConverter( void )
|
||||
{
|
||||
R.makeIdentity();
|
||||
T.makeIdentity();
|
||||
_trans_set = false;
|
||||
S.makeIdentity();
|
||||
}
|
||||
|
||||
void OrientationConverter::setRotation( const Vec3 &from, const Vec3 &to )
|
||||
{
|
||||
R = Matrix::rotate( from, to );
|
||||
}
|
||||
|
||||
void OrientationConverter::setTranslation( const Vec3 &trans )
|
||||
{
|
||||
T = Matrix::translate(trans);
|
||||
_trans_set = true;
|
||||
}
|
||||
|
||||
void OrientationConverter::setScale( const Vec3 &scale )
|
||||
{
|
||||
S = Matrix::scale(scale);
|
||||
}
|
||||
|
||||
|
||||
Node* OrientationConverter::convert( Node *node )
|
||||
{
|
||||
// Order of operations here is :
|
||||
// 1. Translate to world origin (0,0,0)
|
||||
// 2. Rotate to new orientation
|
||||
// 3. Scale in new orientation coordinates
|
||||
// 4. If an absolute translation was specified then
|
||||
// - translate to absolute translation in world coordinates
|
||||
// else
|
||||
// - translate back to model's original origin.
|
||||
BoundingSphere bs = node->getBound();
|
||||
Matrix C = Matrix::translate( -bs.center() );
|
||||
if( _trans_set == false )
|
||||
T = Matrix::translate( bs.center() );
|
||||
|
||||
osg::Group* root = new osg::Group;
|
||||
osg::MatrixTransform* transform = new osg::MatrixTransform;
|
||||
|
||||
transform->setDataVariance(osg::Object::STATIC);
|
||||
transform->setMatrix( C * R * S * T );
|
||||
|
||||
root->addChild(transform);
|
||||
transform->addChild(node);
|
||||
|
||||
osgUtil::Optimizer::FlattenStaticTransformsVisitor fstv;
|
||||
root->accept(fstv);
|
||||
fstv.removeTransforms(root);
|
||||
|
||||
return root->getChild(0);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef _ORIENTATION_CONVERTER_H
|
||||
#define _ORIENTATION_CONVERTER_H
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Node>
|
||||
#include <osg/Geode>
|
||||
|
||||
class OrientationConverter {
|
||||
public :
|
||||
OrientationConverter(void);
|
||||
void setRotation( const osg::Vec3 &from,
|
||||
const osg::Vec3 &to );
|
||||
void setTranslation( const osg::Vec3 &trans);
|
||||
void setScale( const osg::Vec3 &trans);
|
||||
|
||||
/** return the root of the updated subgraph as the subgraph
|
||||
* the node passed in my flatten during optimization.*/
|
||||
osg::Node* convert( osg::Node* node );
|
||||
|
||||
private :
|
||||
OrientationConverter( const OrientationConverter& ) {}
|
||||
OrientationConverter& operator = (const OrientationConverter& ) { return *this; }
|
||||
|
||||
osg::Matrix R, T, S;
|
||||
bool _trans_set;
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -1,249 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgDB/ReaderWriter>
|
||||
|
||||
#include "OrientationConverter.h"
|
||||
|
||||
typedef std::vector<std::string> FileNameList;
|
||||
|
||||
static bool do_convert = false;
|
||||
|
||||
|
||||
static void usage( const char *prog, const char *msg )
|
||||
{
|
||||
osg::notify(osg::NOTICE)<< std::endl;
|
||||
osg::notify(osg::NOTICE) << msg << std::endl;
|
||||
osg::notify(osg::NOTICE)<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<"usage:"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" " << prog << " [options] infile1 [infile2 ...] outfile"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<"options:"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -O option - ReaderWriter option"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -l libraryName - load plugin of name libraryName"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -l osgdb_pfb"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful for loading reader/writers which can load"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" other file formats in addition to its extension."<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" i.e. -e pfb"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" Useful short hand for specifying full library name as"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" done with -l above, as it automatically expands to the"<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" full library name appropriate for each platform."<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -o orientation - Convert geometry from input files to output files."<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<
|
||||
" Format of orientation argument must be the following:\n"
|
||||
"\n"
|
||||
" X1,Y1,Z1-X2,Y2,Z2\n"
|
||||
"\n"
|
||||
" where X1,Y1,Z1 represent the UP vector in the input\n"
|
||||
" files and X2,Y2,Z2 represent the UP vector of the\n"
|
||||
" output file. For example, to convert a model built\n"
|
||||
" in a Y-Up coordinate system to a model with a Z-up\n"
|
||||
" coordinate system, the argument looks like\n"
|
||||
"\n"
|
||||
" 0,1,0-0,0,1"
|
||||
"\n"
|
||||
<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -t translation - Convert spatial position of output files. Format of\n"
|
||||
" translation argument must be the following :\n"
|
||||
"\n"
|
||||
" X,Y,Z\n"
|
||||
"\n"
|
||||
" where X, Y, and Z represent the coordinates of the\n"
|
||||
" absolute position in world space\n"
|
||||
<< std::endl;
|
||||
osg::notify(osg::NOTICE)<<" -s scale - Scale size of model. Scale argument must be the \n"
|
||||
" following :\n"
|
||||
"\n"
|
||||
" SX,SY,SZ\n"
|
||||
"\n"
|
||||
" where SX, SY, and SZ represent the scale factors\n"
|
||||
" Caution: Scaling will be done in destination orientation\n"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_args( int argc, char **argv, FileNameList &fileNames,
|
||||
OrientationConverter &oc, osgDB::ReaderWriter::Options* options )
|
||||
{
|
||||
int nexti;
|
||||
std::string opt = "";
|
||||
|
||||
for(int i = 1; i < argc; i=nexti )
|
||||
{
|
||||
nexti = i+1;
|
||||
|
||||
if (argv[i][0]=='-')
|
||||
{
|
||||
for( unsigned int j = 1; j < strlen( argv[i] ); j++ )
|
||||
{
|
||||
switch(argv[i][j])
|
||||
{
|
||||
case 'O':
|
||||
if (nexti<argc) {
|
||||
if (opt.size() == 0)
|
||||
opt = argv[nexti++];
|
||||
else
|
||||
opt = opt+" "+argv[nexti++];
|
||||
}
|
||||
else {
|
||||
usage( argv[0], "ReaderWriter option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case('e'):
|
||||
if (nexti<argc)
|
||||
{
|
||||
std::string libName = osgDB::Registry::instance()->createLibraryNameForExt(argv[nexti++]);
|
||||
osgDB::Registry::instance()->loadLibrary(libName);
|
||||
}
|
||||
else
|
||||
{
|
||||
usage( argv[0], "Extension option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case('l'):
|
||||
if (nexti<argc)
|
||||
{
|
||||
osgDB::Registry::instance()->loadLibrary(argv[nexti++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
usage( argv[0], "Library option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o' :
|
||||
if( nexti < argc )
|
||||
{
|
||||
osg::Vec3 from, to;
|
||||
if( sscanf( argv[nexti++], "%f,%f,%f-%f,%f,%f",
|
||||
&from[0], &from[1], &from[2],
|
||||
&to[0], &to[1], &to[2] )
|
||||
!= 6 )
|
||||
{
|
||||
usage( argv[0], "Orientation argument format incorrect." );
|
||||
return false;
|
||||
}
|
||||
oc.setRotation( from, to );
|
||||
do_convert = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage( argv[0], "Orientation conversion option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't' :
|
||||
if( nexti < argc )
|
||||
{
|
||||
osg::Vec3 trans(0,0,0);
|
||||
if( sscanf( argv[nexti++], "%f,%f,%f",
|
||||
&trans[0], &trans[1], &trans[2] ) != 3 )
|
||||
{
|
||||
usage( argv[0], "Translation argument format incorrect." );
|
||||
return false;
|
||||
}
|
||||
oc.setTranslation( trans );
|
||||
do_convert = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage( argv[0], "Translation conversion option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's' :
|
||||
if( nexti < argc )
|
||||
{
|
||||
osg::Vec3 scale(0,0,0);
|
||||
if( sscanf( argv[nexti++], "%f,%f,%f",
|
||||
&scale[0], &scale[1], &scale[2] ) != 3 )
|
||||
{
|
||||
usage( argv[0], "Scale argument format incorrect." );
|
||||
return false;
|
||||
}
|
||||
oc.setScale( scale );
|
||||
do_convert = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage( argv[0], "Scale conversion option requires an argument." );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
std::string a = "Invalid option " ;
|
||||
a += "'";
|
||||
a += argv[i][j] ;
|
||||
a += "'.";
|
||||
usage( argv[0], a.c_str() );
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
fileNames.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNames.empty())
|
||||
{
|
||||
usage( argv[0], "No files specified." );
|
||||
return false;
|
||||
}
|
||||
|
||||
options->setOptionString(opt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
FileNameList fileNames;
|
||||
OrientationConverter oc;
|
||||
|
||||
osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options;
|
||||
osgDB::Registry::instance()->setOptions(options);
|
||||
|
||||
if( parse_args( argc, argv, fileNames, oc, options ) == false )
|
||||
return -1;
|
||||
|
||||
std::string fileNameOut("converted.osg");
|
||||
if (fileNames.size()>1)
|
||||
{
|
||||
fileNameOut = fileNames.back();
|
||||
fileNames.pop_back();
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> root = osgDB::readNodeFiles(fileNames);
|
||||
|
||||
if( do_convert )
|
||||
root = oc.convert( root.get() );
|
||||
|
||||
if (root.valid())
|
||||
{
|
||||
osgDB::writeNodeFile(*root,fileNameOut);
|
||||
osg::notify(osg::NOTICE)<<"Data written to '"<<fileNameOut<<"'."<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error no data loaded."<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcopy.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcopy
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcopy.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcopy
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,244 +0,0 @@
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Texture>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
// Customize the CopyOp so that we add our own verbose
|
||||
// output of what's being copied.
|
||||
class MyCopyOp : public osg::CopyOp
|
||||
{
|
||||
public:
|
||||
|
||||
inline MyCopyOp(CopyFlags flags=SHALLOW_COPY):
|
||||
osg::CopyOp(flags),
|
||||
_indent(0),
|
||||
_step(4) {}
|
||||
|
||||
inline void moveIn() const { _indent += _step; }
|
||||
inline void moveOut() const { _indent -= _step; }
|
||||
inline void writeIndent() const
|
||||
{
|
||||
for(int i=0;i<_indent;++i) std::cout << " ";
|
||||
}
|
||||
|
||||
virtual Referenced* operator() (const Referenced* ref) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Referenced "<<ref<<std::endl;
|
||||
moveIn();
|
||||
osg::Referenced* ret_ref = CopyOp::operator()(ref);
|
||||
moveOut();
|
||||
return ret_ref;
|
||||
}
|
||||
|
||||
virtual Object* operator() (const Object* obj) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Object "<<obj;
|
||||
if (obj) std::cout<<" "<<obj->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::Object* ret_obj = CopyOp::operator()(obj);
|
||||
moveOut();
|
||||
return ret_obj;
|
||||
}
|
||||
|
||||
virtual Node* operator() (const Node* node) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Node "<<node;
|
||||
if (node) std::cout<<" "<<node->className()<<" '"<<node->getName()<<"'";
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::Node* ret_node = CopyOp::operator()(node);
|
||||
moveOut();
|
||||
return ret_node;
|
||||
}
|
||||
|
||||
virtual Drawable* operator() (const Drawable* drawable) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Drawable "<<drawable;
|
||||
if (drawable) std::cout<<" "<<drawable->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::Drawable* ret_drawable = CopyOp::operator()(drawable);
|
||||
moveOut();
|
||||
return ret_drawable;
|
||||
}
|
||||
|
||||
virtual StateSet* operator() (const StateSet* stateset) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying StateSet "<<stateset;
|
||||
if (stateset) std::cout<<" "<<stateset->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::StateSet* ret_stateset = CopyOp::operator()(stateset);
|
||||
moveOut();
|
||||
return ret_stateset;
|
||||
}
|
||||
|
||||
virtual StateAttribute* operator() (const StateAttribute* attr) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying StateAttribute "<<attr;
|
||||
if (attr) std::cout<<" "<<attr->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::StateAttribute* ret_attr = CopyOp::operator()(attr);
|
||||
moveOut();
|
||||
return ret_attr;
|
||||
}
|
||||
|
||||
virtual Texture* operator() (const Texture* text) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Texture "<<text;
|
||||
if (text) std::cout<<" "<<text->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::Texture* ret_text = CopyOp::operator()(text);
|
||||
moveOut();
|
||||
return ret_text;
|
||||
}
|
||||
|
||||
virtual Image* operator() (const Image* image) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Image "<<image;
|
||||
if (image) std::cout<<" "<<image->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
Image* ret_image = CopyOp::operator()(image);
|
||||
moveOut();
|
||||
return ret_image;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// must be mutable since CopyOp is passed around as const to
|
||||
// the various clone/copy constructors.
|
||||
mutable int _indent;
|
||||
mutable int _step;
|
||||
};
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// ------------- Start of copy specific code -------------------------------------------------------
|
||||
|
||||
// do a deep copy, using MyCopyOp to reveal whats going on under the good,
|
||||
// in your own code you'd typically just use the basic osg::CopyOp something like
|
||||
// osg::Node* mycopy = dynamic_cast<osg::Node*>(rootnode->clone(osg::CopyOp::DEEP_COPY_ALL));
|
||||
std::cout << "Doing a deep copy of scene graph"<<std::endl;
|
||||
// note, we need the dyanmic_cast because MS Visual Studio can't handle covarient
|
||||
// return types, so that clone has return just Object*. bahh hum bug
|
||||
osg::Node* deep_copy = dynamic_cast<osg::Node*>(rootnode->clone(MyCopyOp(osg::CopyOp::DEEP_COPY_ALL)));
|
||||
|
||||
std::cout << "----------------------------------------------------------------"<<std::endl;
|
||||
|
||||
// do a shallow copy.
|
||||
std::cout << "Doing a shallow copy of scene graph"<<std::endl;
|
||||
osg::Node* shallow_copy = dynamic_cast<osg::Node*>(rootnode->clone(MyCopyOp(osg::CopyOp::SHALLOW_COPY)));
|
||||
|
||||
|
||||
// write out the various scene graphs so that they can be browsed, either
|
||||
// in an editor or using a graphics diff tool gdiff/xdiff/xxdiff.
|
||||
std::cout << std::endl << "Writing out the original scene graph as 'original.osg'"<<std::endl;
|
||||
osgDB::writeNodeFile(*rootnode,"original.osg");
|
||||
|
||||
std::cout << "Writing out the deep copied scene graph as 'deep_copy.osg'"<<std::endl;
|
||||
osgDB::writeNodeFile(*deep_copy,"deep_copy.osg");
|
||||
|
||||
std::cout << "Writing out the shallow copied scene graph as 'shallow_copy.osg'"<<std::endl;
|
||||
osgDB::writeNodeFile(*shallow_copy,"shallow_copy.osg");
|
||||
|
||||
|
||||
// You can use a bit mask to control which parts of the scene graph are shallow copied
|
||||
// vs deep copied. The options are (from include/osg/CopyOp) :
|
||||
// enum Options {
|
||||
// SHALLOW_COPY = 0,
|
||||
// DEEP_COPY_OBJECTS = 1,
|
||||
// DEEP_COPY_NODES = 2,
|
||||
// DEEP_COPY_DRAWABLES = 4,
|
||||
// DEEP_COPY_STATESETS = 8,
|
||||
// DEEP_COPY_STATEATTRIBUTES = 16,
|
||||
// DEEP_COPY_TEXTURES = 32,
|
||||
// DEEP_COPY_IMAGES = 64,
|
||||
// DEEP_COPY_ALL = 0xffffffff
|
||||
// };
|
||||
//
|
||||
// These options you can use together such as :
|
||||
// osg::Node* mycopy = dynamic_cast<osg::Node*>(rootnode->clone(osg::CopyOp::DEEP_COPY_NODES | DEEP_COPY_DRAWABLES));
|
||||
// Which shares state but creates copies of all nodes and drawables (which contain the geometry).
|
||||
//
|
||||
// You may also want to subclass from CopyOp to provide finer grained control of what gets shared (shallow copy) vs
|
||||
// cloned (deep copy).
|
||||
|
||||
|
||||
|
||||
// ------------- End of copy specific code -------------------------------------------------------
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcube.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcube
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcube.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcube
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,206 +0,0 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Material>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Math>
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Global variables - this is basically the stuff wh ich will be animated
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
class MyTransformCallback : public osg::NodeCallback{
|
||||
|
||||
public:
|
||||
|
||||
MyTransformCallback(osg::MatrixTransform* node,float angularVelocity)
|
||||
{
|
||||
_nodeToOperateOn = node;
|
||||
_angular_velocity = angularVelocity;
|
||||
_previousTraversalNumber = -1;
|
||||
_orig_t = _timer.tick();
|
||||
}
|
||||
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (nv)
|
||||
{
|
||||
if (_nodeToOperateOn && node==_nodeToOperateOn)
|
||||
{
|
||||
// ensure that we do not operate on this node more than
|
||||
// once during this traversal. This is an issue since node
|
||||
// can be shared between multiple parents.
|
||||
if (nv->getTraversalNumber()!=_previousTraversalNumber)
|
||||
{
|
||||
osg::Timer_t new_t = _timer.tick();
|
||||
float delta_angle = _angular_velocity*_timer.delta_s(_orig_t,new_t);
|
||||
|
||||
osg::Matrix matrix;
|
||||
matrix.makeRotate(delta_angle,1.0f,1.0f,1.0f);
|
||||
matrix *= osg::Matrix::translate(1.0f,0.0f,0.0f);
|
||||
matrix *= osg::Matrix::rotate(delta_angle,0.0f,0.0f,1.0f);
|
||||
|
||||
_nodeToOperateOn->setMatrix(matrix);
|
||||
|
||||
_previousTraversalNumber = nv->getTraversalNumber();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// must continue subgraph traversal.
|
||||
traverse(node,nv);
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
osg::MatrixTransform* _nodeToOperateOn;
|
||||
float _angular_velocity;
|
||||
|
||||
int _previousTraversalNumber;
|
||||
osg::Timer _timer;
|
||||
osg::Timer_t _orig_t;
|
||||
|
||||
};
|
||||
|
||||
osg::Geode* createGeometryCube()
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// -------------------------------------------
|
||||
// Set up a new Geometry which will be our cube
|
||||
// -------------------------------------------
|
||||
osg::Geometry* cube = new osg::Geometry();
|
||||
|
||||
// set up the primitives
|
||||
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,4));
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,4,4));
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,8,4));
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,12,4));
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,16,4));
|
||||
cube->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,20,4));
|
||||
|
||||
|
||||
// set up coords.
|
||||
osg::Vec3Array* coords = new osg::Vec3Array;
|
||||
coords->resize(24);
|
||||
|
||||
(*coords)[0].set( -1.0000f, 1.0000f, -1.000f );
|
||||
(*coords)[1].set( 1.0000f, 1.0000f, -1.0000f );
|
||||
(*coords)[2].set( 1.0000f, -1.0000f, -1.0000f );
|
||||
(*coords)[3].set( -1.0000f, -1.0000f, -1.000 );
|
||||
|
||||
(*coords)[4].set( 1.0000f, 1.0000f, -1.0000f );
|
||||
(*coords)[5].set( 1.0000f, 1.0000f, 1.0000f );
|
||||
(*coords)[6].set( 1.0000f, -1.0000f, 1.0000f );
|
||||
(*coords)[7].set( 1.0000f, -1.0000f, -1.0000f );
|
||||
|
||||
(*coords)[8].set( 1.0000f, 1.0000f, 1.0000f );
|
||||
(*coords)[9].set( -1.0000f, 1.0000f, 1.000f );
|
||||
(*coords)[10].set( -1.0000f, -1.0000f, 1.000f );
|
||||
(*coords)[11].set( 1.0000f, -1.0000f, 1.0000f );
|
||||
|
||||
(*coords)[12].set( -1.0000f, 1.0000f, 1.000 );
|
||||
(*coords)[13].set( -1.0000f, 1.0000f, -1.000 );
|
||||
(*coords)[14].set( -1.0000f, -1.0000f, -1.000 );
|
||||
(*coords)[15].set( -1.0000f, -1.0000f, 1.000 );
|
||||
|
||||
(*coords)[16].set( -1.0000f, 1.0000f, 1.000 );
|
||||
(*coords)[17].set( 1.0000f, 1.0000f, 1.0000f );
|
||||
(*coords)[18].set( 1.0000f, 1.0000f, -1.0000f );
|
||||
(*coords)[19].set( -1.0000f, 1.0000f, -1.000f );
|
||||
|
||||
(*coords)[20].set( -1.0000f, -1.0000f, 1.000f );
|
||||
(*coords)[21].set( -1.0000f, -1.0000f, -1.000f );
|
||||
(*coords)[22].set( 1.0000f, -1.0000f, -1.0000f );
|
||||
(*coords)[23].set( 1.0000f, -1.0000f, 1.0000f );
|
||||
|
||||
|
||||
cube->setVertexArray( coords );
|
||||
|
||||
|
||||
// set up the normals.
|
||||
osg::Vec3Array* cubeNormals = new osg::Vec3Array;
|
||||
cubeNormals->resize(6);
|
||||
|
||||
(*cubeNormals)[0].set(0.0f,0.0f,-1.0f);
|
||||
(*cubeNormals)[1].set(1.0f,0.0f,0.0f);
|
||||
(*cubeNormals)[2].set(0.0f,0.0f,1.0f);
|
||||
(*cubeNormals)[3].set(-1.0f,0.0f,0.0f);
|
||||
(*cubeNormals)[4].set(0.0f,1.0f,0.0f);
|
||||
(*cubeNormals)[5].set(0.0f,-1.0f,0.0f);
|
||||
|
||||
cube->setNormalArray( cubeNormals );
|
||||
cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
|
||||
|
||||
// ---------------------------------------
|
||||
// Set up a StateSet to make the cube red
|
||||
// ---------------------------------------
|
||||
osg::StateSet* cubeState = new osg::StateSet();
|
||||
osg::Material* redMaterial = new osg::Material();
|
||||
osg::Vec4 red( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
redMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, red );
|
||||
cubeState->setAttribute( redMaterial );
|
||||
|
||||
cube->setStateSet( cubeState );
|
||||
|
||||
geode->addDrawable( cube );
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
osg::MatrixTransform* myTransform = new osg::MatrixTransform();
|
||||
myTransform->addChild( createGeometryCube() );
|
||||
|
||||
// move node in a circle at 90 degrees a sec.
|
||||
myTransform->setUpdateCallback(new MyTransformCallback(myTransform,osg::inDegrees(90.0f)));
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport( myTransform );
|
||||
|
||||
// register trackball maniupulators.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcubemap.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcubemap
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcubemap.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcubemap
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,128 +0,0 @@
|
||||
#include <osg/Group>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/TexEnvCombine>
|
||||
|
||||
#include <osgUtil/ReflectionMapGenerator>
|
||||
#include <osgUtil/HighlightMapGenerator>
|
||||
#include <osgUtil/HalfWayMapGenerator>
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
void create_specular_highlights(osg::Node *node)
|
||||
{
|
||||
osg::StateSet *ss = node->getOrCreateStateSet();
|
||||
|
||||
// create and setup the texture object
|
||||
osg::TextureCubeMap *tcm = new osg::TextureCubeMap;
|
||||
tcm->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
|
||||
tcm->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
|
||||
tcm->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP);
|
||||
tcm->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||
tcm->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
|
||||
// generate the six highlight map images (light direction = [1, 1, -1])
|
||||
osgUtil::HighlightMapGenerator *mapgen = new osgUtil::HighlightMapGenerator(
|
||||
osg::Vec3(1, 1, -1), // light direction
|
||||
osg::Vec4(1, 0.9f, 0.8f, 1), // light color
|
||||
8); // specular exponent
|
||||
|
||||
mapgen->generateMap();
|
||||
|
||||
// assign the six images to the texture object
|
||||
tcm->setImage(osg::TextureCubeMap::POSITIVE_X, mapgen->getImage(osg::TextureCubeMap::POSITIVE_X));
|
||||
tcm->setImage(osg::TextureCubeMap::NEGATIVE_X, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_X));
|
||||
tcm->setImage(osg::TextureCubeMap::POSITIVE_Y, mapgen->getImage(osg::TextureCubeMap::POSITIVE_Y));
|
||||
tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Y));
|
||||
tcm->setImage(osg::TextureCubeMap::POSITIVE_Z, mapgen->getImage(osg::TextureCubeMap::POSITIVE_Z));
|
||||
tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Z));
|
||||
|
||||
// enable texturing, replacing any textures in the subgraphs
|
||||
ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||
|
||||
// texture coordinate generation
|
||||
osg::TexGen *tg = new osg::TexGen;
|
||||
tg->setMode(osg::TexGen::REFLECTION_MAP);
|
||||
ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||
|
||||
// use TexEnvCombine to add the highlights to the original lighting
|
||||
osg::TexEnvCombine *te = new osg::TexEnvCombine;
|
||||
te->setCombine_RGB(osg::TexEnvCombine::ADD);
|
||||
te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
te->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
|
||||
te->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
|
||||
te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
|
||||
ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create specular highlights
|
||||
create_specular_highlights(rootnode);
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport(rootnode);
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeodemo.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osggeodemo
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeomdemo.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osggeomdemo
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,186 +0,0 @@
|
||||
// Geo demo written by Geoff Michel, November 2002.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <osg/GL>
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
#include <osgGA/AnimationPathManipulator>
|
||||
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
// currently not a satisfactory solution, but this is early days for the
|
||||
// geo loader and having direct links with it.
|
||||
#include "../../osgPlugins/geo/osgGeoAnimation.h"
|
||||
|
||||
|
||||
//== event trapper gets events
|
||||
|
||||
class geodemoEventHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
geodemoEventHandler( ) { mouse_x=mouse_y=0;}
|
||||
virtual ~geodemoEventHandler( ) {}
|
||||
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
|
||||
{
|
||||
mouse_x=ea.getX();
|
||||
mouse_y=ea.getY();
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
virtual void accept(osgGA::GUIEventHandlerVisitor& v)
|
||||
{
|
||||
v.visit(*this);
|
||||
}
|
||||
inline int getMouseX(void) {return mouse_x;};
|
||||
inline int getMouseY(void) {return mouse_y;};
|
||||
|
||||
private:
|
||||
int mouse_x, mouse_y;
|
||||
};
|
||||
|
||||
static geodemoEventHandler *ghand=NULL;
|
||||
inline double DEG2RAD(const double val) { return val*0.0174532925199432957692369076848861;}
|
||||
inline double RAD2DEG(const double val) { return val*57.2957795130823208767981548141052;}
|
||||
|
||||
double dodynamics(const double time, const double val, const std::string name)
|
||||
{ // Each local variable named 'name' declared in the geo modeller is passed into here.
|
||||
// its current value is val; returns new value. Time - elapsed time
|
||||
static double heading,speed; // these are only required for my 'dynamics'
|
||||
if (name == "xpos") {
|
||||
return (val+speed*sin(heading));
|
||||
// std::cout << " nx " << (*itr->getValue()) ;
|
||||
} else if (name == "ypos") {
|
||||
return (val+speed*cos(heading));
|
||||
// std::cout << " ny " << (*itr->getValue()) ;
|
||||
} else if (name == "sped") {
|
||||
speed=(0.00025*(ghand->getMouseY()-300)); // (*itr->getValue());
|
||||
return (speed);
|
||||
} else if (name == "heading") {
|
||||
heading-= 0.01*DEG2RAD(ghand->getMouseX()-400); // =DEG2RAD(*itr->getValue());
|
||||
return (RAD2DEG(heading));
|
||||
} else if (name == "conerot") {
|
||||
return ((ghand->getMouseX()-400));
|
||||
} else if (name == "planrot") {
|
||||
return ((ghand->getMouseY()-300)/200.0);
|
||||
} else if (name == "secint" || name == "minutehand"|| name == "hourhand") {
|
||||
// std::cout << " updating " << name << " " << val << std::endl;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-p <filename>","Use specificed animation path file for camera animation");
|
||||
|
||||
// read the commandline args.
|
||||
std::string pathfile;
|
||||
while (arguments.read("-p",pathfile)) {}
|
||||
|
||||
float camera_fov=-1;
|
||||
while (arguments.read("-fov",camera_fov)) {}
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
if( !pathfile.empty() ) {
|
||||
osgGA::AnimationPathManipulator *apm = new osgGA::AnimationPathManipulator(pathfile);
|
||||
if( apm->valid() )
|
||||
viewer.registerCameraManipulator(apm);
|
||||
else
|
||||
delete apm;
|
||||
}
|
||||
|
||||
geoHeader *gh = dynamic_cast<geoHeader *>(rootnode);
|
||||
if (gh) { // it is a geo file, so set function to update its animation variables.
|
||||
ghand=new geodemoEventHandler();
|
||||
gh->setUserUpdate(dodynamics);
|
||||
viewer.prependEventHandler(ghand);
|
||||
} else { // maybe a group with geo models below.
|
||||
osg::Group *gpall=dynamic_cast<osg::Group *>(rootnode);
|
||||
if (gpall) {
|
||||
int nchild=gpall->getNumChildren();
|
||||
for (int i=0; i<nchild; i++) {
|
||||
osg::Node *nod=gpall->getChild(i);
|
||||
gh = dynamic_cast<geoHeader *>(nod);
|
||||
if (gh)
|
||||
{
|
||||
ghand=new geodemoEventHandler();
|
||||
gh->setUserUpdate(dodynamics);
|
||||
viewer.prependEventHandler(ghand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
osgUtil::SceneView *sc=viewer.getViewportSceneView(0);
|
||||
if (sc && camera_fov>0) {
|
||||
osg::Camera *cm=sc->getCamera();
|
||||
if (cm) cm->setFOV(camera_fov,camera_fov*(600.0f/800.0f),1.0f,1000.0f);
|
||||
}
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeometry.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osggeometry
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeometry.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osggeometry
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,692 +0,0 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Material>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/PolygonStipple>
|
||||
#include <osg/TriangleFunctor>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Math>
|
||||
|
||||
|
||||
|
||||
// This demos uses the illustrates how to creates the various different types of geometry that
|
||||
// the osg::Geometry class can represent. This demos uses the OpenGL red books diagram of different
|
||||
// OpenGL Primitives as a template for all the equivilant OpenSceneGraph Primitives. The OpenSceneGraph
|
||||
// wraps OpenGL very thinly so uses all the same enum and naming conventions. The coordinate data is also
|
||||
// wrapped around OpenGL's vertex arrays and draw arrays/elements calls. Familarity with
|
||||
// OpenGL will help understand the the osg::Geometry class which encapsulate all this, or if you
|
||||
// havn't learnt OpenGL yet, learning osg::Geometry will help you understand how OpenGL
|
||||
// works!
|
||||
|
||||
// The osg::Geometry class "is a" subclass of osg::Drawable base class, so is an object that provides
|
||||
// a draw method for drawing objects in the scene. osg::Geometry contains all the vertex, normal
|
||||
// color and texture coordate arrays required to specify the coordinates of your objects, and the
|
||||
// primtives join these coordinates together as the points, lines or surfaces that you will see
|
||||
// rendered on your screen.
|
||||
//
|
||||
// This demo is split into two functions, the createScene() function which creates the scene graph
|
||||
// with the various primitives in it, and the main() which sets up a basic viewer window and
|
||||
// adds to the it the scene generated by createScene().
|
||||
|
||||
|
||||
struct NormalPrint
|
||||
{
|
||||
void operator() (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3) const
|
||||
{
|
||||
osg::Vec3 normal = (v2-v1)^(v3-v2);
|
||||
normal.normalize();
|
||||
std::cout << "\t("<<v1<<") ("<<v2<<") ("<<v3<<") "<<") normal ("<<normal<<")"<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// decompose Drawable primtives into triangles, print out these triangles and computed normals.
|
||||
void printTriangles(const std::string& name, osg::Drawable& drawable)
|
||||
{
|
||||
std::cout<<name<<std::endl;
|
||||
|
||||
osg::TriangleFunctor<NormalPrint> tf;
|
||||
drawable.accept(tf);
|
||||
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createScene()
|
||||
{
|
||||
// create the Geode (Geometry Node) to contain all our osg::Geometry objects.
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// follows are separate blocks for creating POINTS, LINES, LINE_STRIP, LINE_LOOP, POLYGON, QUADS,
|
||||
// QUAD_STRIP, TRIANGLES, TRIANGLE_STRIP and TRIANGLE_FAN primtives. A image of these primtives
|
||||
// are provided in the distribution : OpenSceneGraph-Data/Images/primtives.gif.
|
||||
|
||||
|
||||
// create POINTS
|
||||
{
|
||||
// create Geometry object to store all the vetices and points primtive.
|
||||
osg::Geometry* pointsGeom = new osg::Geometry();
|
||||
|
||||
// create a Vec3Array and add to it all my coordinates.
|
||||
// Like all the *Array variants (see include/osg/Array) , Vec3Array is derivied from both osg::Array
|
||||
// and std::vector<>. osg::Array's are reference counted and hence sharable,
|
||||
// which std::vector<> provides all the convinience, flexibility and robustness
|
||||
// of the most popular of all STL containers.
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(osg::Vec3(-1.02168, -2.15188e-09, 0.885735));
|
||||
vertices->push_back(osg::Vec3(-0.976368, -2.15188e-09, 0.832179));
|
||||
vertices->push_back(osg::Vec3(-0.873376, 9.18133e-09, 0.832179));
|
||||
vertices->push_back(osg::Vec3(-0.836299, -2.15188e-09, 0.885735));
|
||||
vertices->push_back(osg::Vec3(-0.790982, 9.18133e-09, 0.959889));
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
pointsGeom->setVertexArray(vertices);
|
||||
|
||||
|
||||
|
||||
// create the color of the geometry, one single for the whole geometry.
|
||||
// for consitency of design even one single color must added as an element
|
||||
// in a color array.
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
// add a white color, colors take the form r,g,b,a with 0.0 off, 1.0 full on.
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
|
||||
// pass the color arry to points geometry, note the binding to tell the geometry
|
||||
// that only use one color for the whole object.
|
||||
pointsGeom->setColorArray(colors);
|
||||
pointsGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// set the normal in the same way color.
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
pointsGeom->setNormalArray(normals);
|
||||
pointsGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// create and add a DrawArray Primitive (see include/osg/Primtive). The first
|
||||
// paramter passed to the DrawArrays constructor is the Primtive::Mode which
|
||||
// in this case is POINTS (which has the same value GL_POINTS), the second
|
||||
// parameter is the index position into the vertex array of the first point
|
||||
// to draw, and the third parameter is the number of points to draw.
|
||||
pointsGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,vertices->size()));
|
||||
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(pointsGeom);
|
||||
}
|
||||
|
||||
// create LINES
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* linesGeom = new osg::Geometry();
|
||||
|
||||
// this time we'll prealloacte the vertex array to the size we
|
||||
// need and then simple set them as array elements, 8 points
|
||||
// makes 4 line segments.
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(8);
|
||||
(*vertices)[0].set(-1.13704, -2.15188e-09, 0.40373);
|
||||
(*vertices)[1].set(-0.856897, -2.15188e-09, 0.531441);
|
||||
(*vertices)[2].set(-0.889855, -2.15188e-09, 0.444927);
|
||||
(*vertices)[3].set(-0.568518, -2.15188e-09, 0.40373);
|
||||
(*vertices)[4].set(-1.00933, -2.15188e-09, 0.370773);
|
||||
(*vertices)[5].set(-0.716827, -2.15188e-09, 0.292498);
|
||||
(*vertices)[6].set(-1.07936, 9.18133e-09, 0.317217);
|
||||
(*vertices)[7].set(-0.700348, 9.18133e-09, 0.362533);
|
||||
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
linesGeom->setVertexArray(vertices);
|
||||
|
||||
// set the colors as before, plus using the aobve
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
linesGeom->setColorArray(colors);
|
||||
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// set the normal in the same way color.
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
linesGeom->setNormalArray(normals);
|
||||
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,8));
|
||||
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(linesGeom);
|
||||
}
|
||||
|
||||
// create LINE_STRIP
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* linesGeom = new osg::Geometry();
|
||||
|
||||
// this time we'll prealloacte the vertex array to the size
|
||||
// and then use an iterator to fill in the values, a bit perverse
|
||||
// but does demonstrate that we have just a standard std::vector underneath.
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(5);
|
||||
osg::Vec3Array::iterator vitr = vertices->begin();
|
||||
(vitr++)->set(-0.0741545, -2.15188e-09, 0.416089);
|
||||
(vitr++)->set(0.234823, -2.15188e-09, 0.259541);
|
||||
(vitr++)->set(0.164788, -2.15188e-09, 0.366653);
|
||||
(vitr++)->set(-0.0288379, -2.15188e-09, 0.333695);
|
||||
(vitr++)->set(-0.0453167, -2.15188e-09, 0.280139);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
linesGeom->setVertexArray(vertices);
|
||||
|
||||
// set the colors as before, plus using the aobve
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
linesGeom->setColorArray(colors);
|
||||
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// set the normal in the same way color.
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
linesGeom->setNormalArray(normals);
|
||||
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,5));
|
||||
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(linesGeom);
|
||||
}
|
||||
|
||||
// create LINE_LOOP
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* linesGeom = new osg::Geometry();
|
||||
|
||||
// this time we'll a C arrays to initilize the vertices.
|
||||
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
osg::Vec3(0.741546, -2.15188e-09, 0.453167),
|
||||
osg::Vec3(0.840418, -2.15188e-09, 0.304858),
|
||||
osg::Vec3(1.12468, -2.15188e-09, 0.300738),
|
||||
osg::Vec3(1.03816, 9.18133e-09, 0.453167),
|
||||
osg::Vec3(0.968129, -2.15188e-09, 0.337815),
|
||||
osg::Vec3(0.869256, -2.15188e-09, 0.531441)
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
linesGeom->setVertexArray(vertices);
|
||||
|
||||
// set the colors as before, plus using the aobve
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
linesGeom->setColorArray(colors);
|
||||
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// set the normal in the same way color.
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
linesGeom->setNormalArray(normals);
|
||||
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,numCoords));
|
||||
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(linesGeom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// now we'll stop creating separate normal and color arrays
|
||||
// since we are using the same values all the time, we'll just
|
||||
// share the same ColorArray and NormalArrays..
|
||||
|
||||
// set the colors as before, use a ref_ptr rather than just
|
||||
// standard C pointer, as that in the case of it not being
|
||||
// assigned it will still be cleaned up automatically.
|
||||
osg::ref_ptr<osg::Vec4Array> shared_colors = new osg::Vec4Array;
|
||||
shared_colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
|
||||
// same trick for shared normal.
|
||||
osg::ref_ptr<osg::Vec3Array> shared_normals = new osg::Vec3Array;
|
||||
shared_normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
|
||||
|
||||
|
||||
// Note on vertex ordering.
|
||||
// While the OpenGL diagram should vertices specified in a clockwise direction
|
||||
// in reality you need to specify coords for polygons into a anticlockwise direction
|
||||
// for their front face to be pointing towards your, get this wrong and you could
|
||||
// find back face culling removing the wrong faces of your models. The OpenGL diagram
|
||||
// is just plain wrong, but its nice diagram so we'll keep it for now!
|
||||
|
||||
// create POLYGON
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
// this time we'll a C arrays to initilize the vertices.
|
||||
// note, anticlockwsie ordering.
|
||||
// note II, OpenGL polygons must be convex plan polygons, otherwise
|
||||
// undefined results will occur. If you have concave polygons or ones
|
||||
// that cross over themselves then use the osgUtil::Tesselator to fix
|
||||
// the polygons into a set of valid polygons.
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
osg::Vec3(-1.0464, 0.0f, -0.193626),
|
||||
osg::Vec3(-1.0258, 0.0f, -0.26778),
|
||||
osg::Vec3(-0.807461, 0.0f, -0.181267),
|
||||
osg::Vec3(-0.766264, 0.0f, -0.0576758),
|
||||
osg::Vec3(-0.980488, 0.0f, -0.094753)
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
// use the shared color array.
|
||||
polyGeom->setColorArray(shared_colors.get());
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// use the shared normal array.
|
||||
polyGeom->setNormalArray(shared_normals.get());
|
||||
polyGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,numCoords));
|
||||
|
||||
printTriangles("Polygon",*polyGeom);
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(polyGeom);
|
||||
}
|
||||
|
||||
|
||||
// create QUADS
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
// note, anticlockwsie ordering.
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
osg::Vec3(0.0247182, 0.0f, -0.156548),
|
||||
osg::Vec3(0.0247182, 0.0f, -0.00823939),
|
||||
osg::Vec3(-0.160668, 0.0f, -0.0453167),
|
||||
osg::Vec3(-0.222464, 0.0f, -0.13183),
|
||||
|
||||
osg::Vec3(0.238942, 0.0f, -0.251302),
|
||||
osg::Vec3(0.333696, 0.0f, 0.0329576),
|
||||
osg::Vec3(0.164788, 0.0f, -0.0453167),
|
||||
osg::Vec3(0.13595, 0.0f, -0.255421)
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
// use the shared color array.
|
||||
polyGeom->setColorArray(shared_colors.get());
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// use the shared normal array.
|
||||
polyGeom->setNormalArray(shared_normals.get());
|
||||
polyGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,numCoords));
|
||||
|
||||
|
||||
printTriangles("Quads",*polyGeom);
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(polyGeom);
|
||||
}
|
||||
|
||||
// create QUAD_STRIP
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
// note, first coord at top, second at bottom, reverse to that buggy OpenGL image..
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
osg::Vec3(0.733306, -2.15188e-09, -0.0741545),
|
||||
osg::Vec3(0.758024, -2.15188e-09, -0.205985),
|
||||
|
||||
osg::Vec3(0.885735, -2.15188e-09, -0.0576757),
|
||||
osg::Vec3(0.885735, -2.15188e-09, -0.214224),
|
||||
|
||||
osg::Vec3(0.964009, 9.18133e-09, -0.0370773),
|
||||
osg::Vec3(1.0464, 9.18133e-09, -0.173027),
|
||||
|
||||
osg::Vec3(1.11232, -2.15188e-09, 0.0123591),
|
||||
osg::Vec3(1.12468, 9.18133e-09, -0.164788),
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
// use the shared color array.
|
||||
polyGeom->setColorArray(shared_colors.get());
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// use the shared normal array.
|
||||
polyGeom->setNormalArray(shared_normals.get());
|
||||
polyGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,numCoords));
|
||||
|
||||
|
||||
printTriangles("Quads strip",*polyGeom);
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(polyGeom);
|
||||
}
|
||||
|
||||
// create TRIANGLES, TRIANGLE_STRIP and TRIANGLE_FAN all in one Geometry/
|
||||
{
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
// note, first coord at top, second at bottom, reverse to that buggy OpenGL image..
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
// TRIANGLES 6 vertices, v0..v5
|
||||
// note in aniclockwise order.
|
||||
osg::Vec3(-1.12056, -2.15188e-09, -0.840418),
|
||||
osg::Vec3(-0.95165, -2.15188e-09, -0.840418),
|
||||
osg::Vec3(-1.11644, 9.18133e-09, -0.716827),
|
||||
|
||||
// note in aniclockwise order.
|
||||
osg::Vec3(-0.840418, 9.18133e-09, -0.778623),
|
||||
osg::Vec3(-0.622074, 9.18133e-09, -0.613835),
|
||||
osg::Vec3(-1.067, 9.18133e-09, -0.609715),
|
||||
|
||||
// TRIANGLE STRIP 6 vertices, v6..v11
|
||||
// note defined top point first,
|
||||
// then anticlockwise for the next two points,
|
||||
// then alternating to bottom there after.
|
||||
osg::Vec3(-0.160668, -2.15188e-09, -0.531441),
|
||||
osg::Vec3(-0.160668, -2.15188e-09, -0.749785),
|
||||
osg::Vec3(0.0617955, 9.18133e-09, -0.531441),
|
||||
osg::Vec3(0.168908, -2.15188e-09, -0.753905),
|
||||
osg::Vec3(0.238942, -2.15188e-09, -0.531441),
|
||||
osg::Vec3(0.280139, -2.15188e-09, -0.823939),
|
||||
|
||||
// TRIANGLE FAN 5 vertices, v12..v16
|
||||
// note defined in anticlockwsie order.
|
||||
osg::Vec3(0.844538, 9.18133e-09, -0.712708),
|
||||
osg::Vec3(1.0258, 9.18133e-09, -0.799221),
|
||||
osg::Vec3(1.03816, -2.15188e-09, -0.692109),
|
||||
osg::Vec3(0.988727, 9.18133e-09, -0.568518),
|
||||
osg::Vec3(0.840418, -2.15188e-09, -0.506723),
|
||||
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
// use the shared color array.
|
||||
polyGeom->setColorArray(shared_colors.get());
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// use the shared normal array.
|
||||
polyGeom->setNormalArray(shared_normals.get());
|
||||
polyGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// This time we simply use primitive, and hardwire the number of coords to use
|
||||
// since we know up front,
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,6));
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,6,6));
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,12,5));
|
||||
|
||||
// polygon stipple
|
||||
osg::StateSet* stateSet = new osg::StateSet();
|
||||
polyGeom->setStateSet(stateSet);
|
||||
osg::PolygonStipple* polygonStipple = new osg::PolygonStipple;
|
||||
stateSet->setAttributeAndModes(polygonStipple,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
|
||||
printTriangles("Triangles/Strip/Fan",*polyGeom);
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(polyGeom);
|
||||
}
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
|
||||
// define a node callback to animation a transform as a cycle along the y axis, between 0 and 2.0.
|
||||
class MyTransformCallback : public osg::NodeCallback
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
MyTransformCallback(float angularVelocity)
|
||||
{
|
||||
_angular_velocity = angularVelocity;
|
||||
}
|
||||
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
|
||||
if (nv && transform && nv->getFrameStamp())
|
||||
{
|
||||
double time = nv->getFrameStamp()->getReferenceTime();
|
||||
transform->setMatrix(osg::Matrix::translate(0.0f,1.0f+cosf(time*_angular_velocity),0.0f));
|
||||
}
|
||||
|
||||
// must continue subgraph traversal.
|
||||
traverse(node,nv);
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
float _angular_velocity;
|
||||
|
||||
};
|
||||
|
||||
|
||||
osg::Node* createBackground()
|
||||
{
|
||||
|
||||
// we'll create a texture mapped quad to sit behind the Geometry
|
||||
osg::Image* image = osgDB::readImageFile("Images/primitives.gif");
|
||||
if (!image) return NULL;
|
||||
|
||||
|
||||
// create Geometry object to store all the vetices and lines primtive.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
// note, anticlockwsie ordering.
|
||||
osg::Vec3 myCoords[] =
|
||||
{
|
||||
osg::Vec3(-1.22908f,0.0f,1.0f),
|
||||
osg::Vec3(-1.22908f,0.0f,-1.0f),
|
||||
osg::Vec3(1.22908f,0.0f,-1.0f),
|
||||
osg::Vec3(1.22908f,0.0f,1.0f)
|
||||
};
|
||||
|
||||
int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(new osg::Vec3Array(numCoords,myCoords));
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
polyGeom->setColorArray(colors);
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
// set the normal in the same way color.
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
|
||||
polyGeom->setNormalArray(normals);
|
||||
polyGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec2 myTexCoords[] =
|
||||
{
|
||||
osg::Vec2(0,1),
|
||||
osg::Vec2(0,0),
|
||||
osg::Vec2(1,0),
|
||||
osg::Vec2(1,1)
|
||||
};
|
||||
|
||||
int numTexCoords = sizeof(myCoords)/sizeof(osg::Vec2);
|
||||
|
||||
// pass the created tex coord array to the points geometry object,
|
||||
// and use it to set texture unit 0.
|
||||
polyGeom->setTexCoordArray(0,new osg::Vec2Array(numTexCoords,myTexCoords));
|
||||
|
||||
// well use indices and DrawElements to define the primitive this time.
|
||||
unsigned short myIndices[] =
|
||||
{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
};
|
||||
|
||||
int numIndices = sizeof(myIndices)/sizeof(unsigned short);
|
||||
|
||||
// Theere are three variants of the DrawElements osg::Primitive, UByteDrawElements which
|
||||
// contains unsigned char indicies, UShortDrawElements which contains unsigned short indices,
|
||||
// and UIntDrawElements whcih contains ... unsigned int indices.
|
||||
// The first parameter to DrawElements is
|
||||
polyGeom->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS,numIndices,myIndices));
|
||||
|
||||
// new we need to add the texture to the Drawable, we do so by creating a
|
||||
// StateSet to contain the Texture2D StateAttribute.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
// set up the texture.
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
|
||||
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
|
||||
|
||||
polyGeom->setStateSet(stateset);
|
||||
|
||||
|
||||
// create the Geode (Geometry Node) to contain all our osg::Geometry objects.
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// add the points geomtry to the geode.
|
||||
geode->addDrawable(polyGeom);
|
||||
|
||||
//return geode;
|
||||
|
||||
// create a tranform to move the background back and forward with.
|
||||
|
||||
osg::MatrixTransform* transform = new osg::MatrixTransform();
|
||||
transform->setUpdateCallback(new MyTransformCallback(1.0f));
|
||||
transform->addChild(geode);
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// create the model
|
||||
osg::Group* root = new osg::Group;
|
||||
root->addChild( createScene() );
|
||||
root->addChild( createBackground() );
|
||||
|
||||
//osgDB::writeNodeFile(*root,"geoemtry.osg");
|
||||
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport( root );
|
||||
|
||||
// register trackball maniupulators.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
base.cpp\
|
||||
GliderManipulator.cpp\
|
||||
osghangglide.cpp\
|
||||
hat.cpp\
|
||||
sky.cpp\
|
||||
tank.cpp\
|
||||
terrain.cpp\
|
||||
trees.cpp\
|
||||
|
||||
HEADERFILES = \
|
||||
GliderManipulator.h\
|
||||
hat.h\
|
||||
terrain_coords.h\
|
||||
terrain_normals.h\
|
||||
terrain_texcoords.h\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
$(HEADERFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osghangglide
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,19 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
base.cpp\
|
||||
GliderManipulator.cpp\
|
||||
osghangglide.cpp\
|
||||
hat.cpp\
|
||||
ReaderWriterFLY.cpp\
|
||||
sky.cpp\
|
||||
tank.cpp\
|
||||
terrain.cpp\
|
||||
trees.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osghangglide
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,241 +0,0 @@
|
||||
#include "GliderManipulator.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgGA;
|
||||
|
||||
GliderManipulator::GliderManipulator()
|
||||
{
|
||||
_modelScale = 0.01f;
|
||||
_velocity = 0.0f;
|
||||
_yawMode = YAW_AUTOMATICALLY_WHEN_BANKED;
|
||||
}
|
||||
|
||||
|
||||
GliderManipulator::~GliderManipulator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GliderManipulator::setNode(osg::Node* node)
|
||||
{
|
||||
_node = node;
|
||||
if (_node.get())
|
||||
{
|
||||
const osg::BoundingSphere& boundingSphere=_node->getBound();
|
||||
_modelScale = boundingSphere._radius;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const osg::Node* GliderManipulator::getNode() const
|
||||
{
|
||||
return _node.get();
|
||||
}
|
||||
|
||||
|
||||
void GliderManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter& us)
|
||||
{
|
||||
if(_node.get() && _camera.get())
|
||||
{
|
||||
|
||||
const osg::BoundingSphere& boundingSphere=_node->getBound();
|
||||
|
||||
osg::Vec3 eye = boundingSphere._center+osg::Vec3(-boundingSphere._radius*0.25f,-boundingSphere._radius*0.25f,-boundingSphere._radius*0.03f);
|
||||
|
||||
_camera->setView(eye,
|
||||
eye+osg::Vec3(1.0f,1.0f,-0.1f),
|
||||
osg::Vec3(0.0f,0.0f,1.0f));
|
||||
|
||||
_velocity = boundingSphere._radius*0.01f;
|
||||
|
||||
us.requestRedraw();
|
||||
|
||||
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
|
||||
|
||||
flushMouseEventStack();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GliderManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& us)
|
||||
{
|
||||
flushMouseEventStack();
|
||||
|
||||
us.requestContinuousUpdate(false);
|
||||
|
||||
const osg::BoundingSphere& boundingSphere=_node->getBound();
|
||||
_velocity = boundingSphere._radius*0.01f;
|
||||
|
||||
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool GliderManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
|
||||
{
|
||||
if(!_camera.get()) return false;
|
||||
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case(GUIEventAdapter::PUSH):
|
||||
{
|
||||
|
||||
addMouseEvent(ea);
|
||||
us.requestContinuousUpdate(true);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::RELEASE):
|
||||
{
|
||||
|
||||
addMouseEvent(ea);
|
||||
us.requestContinuousUpdate(true);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::DRAG):
|
||||
{
|
||||
|
||||
addMouseEvent(ea);
|
||||
us.requestContinuousUpdate(true);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::MOVE):
|
||||
{
|
||||
|
||||
addMouseEvent(ea);
|
||||
us.requestContinuousUpdate(true);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::KEYDOWN):
|
||||
if (ea.getKey()==' ')
|
||||
{
|
||||
flushMouseEventStack();
|
||||
home(ea,us);
|
||||
us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
return true;
|
||||
}
|
||||
else if (ea.getKey()=='+')
|
||||
{
|
||||
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()*1.25f);
|
||||
return true;
|
||||
}
|
||||
else if (ea.getKey()=='-')
|
||||
{
|
||||
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()/1.25f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case(GUIEventAdapter::FRAME):
|
||||
addMouseEvent(ea);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
return true;
|
||||
|
||||
case(GUIEventAdapter::RESIZE):
|
||||
init(ea,us);
|
||||
us.requestRedraw();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GliderManipulator::flushMouseEventStack()
|
||||
{
|
||||
_ga_t1 = NULL;
|
||||
_ga_t0 = NULL;
|
||||
}
|
||||
|
||||
|
||||
void GliderManipulator::addMouseEvent(const GUIEventAdapter& ea)
|
||||
{
|
||||
_ga_t1 = _ga_t0;
|
||||
_ga_t0 = &ea;
|
||||
}
|
||||
|
||||
|
||||
bool GliderManipulator::calcMovement()
|
||||
{
|
||||
_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE);
|
||||
|
||||
// return if less then two events have been added.
|
||||
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
|
||||
|
||||
|
||||
float dt = _ga_t0->time()-_ga_t1->time();
|
||||
|
||||
if (dt<0.0f)
|
||||
{
|
||||
notify(WARN) << "warning dt = "<<dt<< std::endl;
|
||||
dt = 0.0f;
|
||||
}
|
||||
|
||||
unsigned int buttonMask = _ga_t1->getButtonMask();
|
||||
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
|
||||
{
|
||||
// pan model.
|
||||
|
||||
_velocity += dt*_modelScale*0.05f;
|
||||
|
||||
}
|
||||
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
|
||||
buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
|
||||
{
|
||||
|
||||
_velocity = 0.0f;
|
||||
|
||||
}
|
||||
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
|
||||
{
|
||||
|
||||
_velocity -= dt*_modelScale*0.05f;
|
||||
|
||||
}
|
||||
|
||||
float mx = (_ga_t0->getXmin()+_ga_t0->getXmax())/2.0f;
|
||||
float my = (_ga_t0->getYmin()+_ga_t0->getYmax())/2.0f;
|
||||
|
||||
float dx = _ga_t0->getX()-mx;
|
||||
float dy = _ga_t0->getY()-my;
|
||||
|
||||
osg::Vec3 center = _camera->getEyePoint();
|
||||
osg::Vec3 sv = _camera->getSideVector();
|
||||
osg::Vec3 lv = _camera->getLookVector();
|
||||
|
||||
float pitch = inDegrees(dy*0.15f*dt);
|
||||
float roll = inDegrees(dx*0.1f*dt);
|
||||
|
||||
osg::Matrix mat;
|
||||
mat.makeTranslate(-center);
|
||||
mat *= Matrix::rotate(pitch,sv.x(),sv.y(),sv.z());
|
||||
mat *= Matrix::rotate(roll,lv.x(),lv.y(),lv.z());
|
||||
if (_yawMode==YAW_AUTOMATICALLY_WHEN_BANKED)
|
||||
{
|
||||
float bank = asinf(sv.z());
|
||||
float yaw = inRadians(bank)*dt;
|
||||
mat *= Matrix::rotate(yaw,0.0f,0.0f,1.0f);
|
||||
}
|
||||
|
||||
lv *= (_velocity*dt);
|
||||
|
||||
mat *= Matrix::translate(center+lv);
|
||||
|
||||
_camera->transformLookAt(mat);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef HANGGLIDE_GLIDERMANIPULATOR
|
||||
#define HANGGLIDE_GLIDERMANIPULATOR 1
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
|
||||
class GliderManipulator : public osgGA::CameraManipulator
|
||||
{
|
||||
public:
|
||||
|
||||
GliderManipulator();
|
||||
virtual ~GliderManipulator();
|
||||
|
||||
/** Attach a node to the manipulator.
|
||||
Automatically detaches previously attached node.
|
||||
setNode(NULL) detaches previously nodes.
|
||||
Is ignored by manipulators which do not require a reference model.*/
|
||||
virtual void setNode(osg::Node*);
|
||||
|
||||
/** Return node if attached.*/
|
||||
virtual const osg::Node* getNode() const;
|
||||
|
||||
/** Move the camera to the default position.
|
||||
May be ignored by manipulators if home functionality is not appropriate.*/
|
||||
virtual void home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
|
||||
|
||||
/** Start/restart the manipulator.*/
|
||||
virtual void init(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
|
||||
|
||||
/** handle events, return true if handled, false otherwise.*/
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
|
||||
|
||||
enum YawControlMode {
|
||||
YAW_AUTOMATICALLY_WHEN_BANKED,
|
||||
NO_AUTOMATIC_YAW
|
||||
};
|
||||
|
||||
/** Set the yaw control between no yaw and yawing when banked.*/
|
||||
void setYawControlMode(YawControlMode ycm) { _yawMode = ycm; }
|
||||
|
||||
private:
|
||||
|
||||
/** Reset the internal GUIEvent stack.*/
|
||||
void flushMouseEventStack();
|
||||
/** Add the current mouse GUIEvent to internal stack.*/
|
||||
void addMouseEvent(const osgGA::GUIEventAdapter& ea);
|
||||
|
||||
/** For the give mouse movement calculate the movement of the camera.
|
||||
Return true is camera has moved and a redraw is required.*/
|
||||
bool calcMovement();
|
||||
|
||||
// Internal event stack comprising last three mouse events.
|
||||
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
|
||||
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
|
||||
|
||||
osg::ref_ptr<osg::Node> _node;
|
||||
|
||||
float _modelScale;
|
||||
float _velocity;
|
||||
|
||||
YawControlMode _yawMode;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/Depth>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Node *makeBase( void )
|
||||
{
|
||||
int i, c;
|
||||
float theta;
|
||||
float ir = 20.0f;
|
||||
|
||||
Vec3Array *coords = new Vec3Array(19);
|
||||
Vec2Array *tcoords = new Vec2Array(19);
|
||||
Vec4Array *colors = new Vec4Array(1);
|
||||
|
||||
(*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
|
||||
|
||||
c = 0;
|
||||
(*coords)[c].set(0.0f,0.0f,0.0f);
|
||||
(*tcoords)[c].set(0.0f,0.0f);
|
||||
|
||||
for( i = 0; i <= 18; i++ )
|
||||
{
|
||||
theta = osg::DegreesToRadians((float)i * 20.0);
|
||||
|
||||
(*coords)[c].set(ir * cosf( theta ), ir * sinf( theta ), 0.0f);
|
||||
(*tcoords)[c].set((*coords)[c][0]/36.0f,(*coords)[c][1]/36.0f);
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
Geometry *geom = new Geometry;
|
||||
|
||||
geom->setVertexArray( coords );
|
||||
|
||||
geom->setTexCoordArray( 0, tcoords );
|
||||
|
||||
geom->setColorArray( colors );
|
||||
geom->setColorBinding( Geometry::BIND_OVERALL );
|
||||
|
||||
geom->addPrimitiveSet( new DrawArrays(PrimitiveSet::TRIANGLE_FAN,0,19) );
|
||||
|
||||
Texture2D *tex = new Texture2D;
|
||||
|
||||
tex->setImage(osgDB::readImageFile("Images/water.rgb"));
|
||||
tex->setWrap( Texture2D::WRAP_S, Texture2D::REPEAT );
|
||||
tex->setWrap( Texture2D::WRAP_T, Texture2D::REPEAT );
|
||||
|
||||
StateSet *dstate = new StateSet;
|
||||
dstate->setMode( GL_LIGHTING, StateAttribute::OFF );
|
||||
dstate->setTextureAttributeAndModes(0, tex, StateAttribute::ON );
|
||||
|
||||
dstate->setTextureAttribute(0, new TexEnv );
|
||||
|
||||
// clear the depth to the far plane.
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
depth->setRange(1.0,1.0);
|
||||
dstate->setAttributeAndModes(depth,StateAttribute::ON );
|
||||
|
||||
dstate->setRenderBinDetails(-1,"RenderBin");
|
||||
|
||||
|
||||
geom->setStateSet( dstate );
|
||||
|
||||
Geode *geode = new Geode;
|
||||
geode->addDrawable( geom );
|
||||
|
||||
return geode;
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
#pragma warning( disable : 4244 )
|
||||
#endif
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/Math>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "terrain_coords.h"
|
||||
#include "hat.h"
|
||||
|
||||
static int inited = 0;
|
||||
|
||||
static float dbcenter[3];
|
||||
static float dbradius;
|
||||
|
||||
static void getDatabaseCenterRadius( float dbcenter[3], float *dbradius )
|
||||
{
|
||||
int i;
|
||||
double n=0.0;
|
||||
double center[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float cnt;
|
||||
|
||||
cnt = 39 * 38;
|
||||
for( i = 0; i < cnt; i++ )
|
||||
{
|
||||
center[0] += (double)vertex[i][0];
|
||||
center[1] += (double)vertex[i][1];
|
||||
center[2] += (double)vertex[i][2];
|
||||
|
||||
n = n + 1.0;
|
||||
}
|
||||
|
||||
center[0] /= n;
|
||||
center[1] /= n;
|
||||
center[2] /= n;
|
||||
|
||||
float r = 0.0;
|
||||
|
||||
// for( i = 0; i < sizeof( vertex ) / (sizeof( float[3] )); i++ )
|
||||
for( i = 0; i < cnt; i++ )
|
||||
{
|
||||
double d = sqrt(
|
||||
(((double)vertex[i][0] - center[0]) * ((double)vertex[i][0] - center[0])) +
|
||||
(((double)vertex[i][1] - center[1]) * ((double)vertex[i][1] - center[1])) +
|
||||
(((double)vertex[i][2] - center[2]) * ((double)vertex[i][2] - center[2])) );
|
||||
|
||||
if( d > (double)r ) r = (float)d;
|
||||
|
||||
}
|
||||
|
||||
*dbradius = r;
|
||||
dbcenter[0] = (float)center[0];
|
||||
dbcenter[1] = (float)center[1];
|
||||
dbcenter[2] = (float)center[2];
|
||||
|
||||
int index = 19 * 39 + 19;
|
||||
dbcenter[0] = vertex[index][0] - 0.15;
|
||||
dbcenter[1] = vertex[index][1];
|
||||
dbcenter[2] = vertex[index][2] + 0.35;
|
||||
}
|
||||
|
||||
|
||||
static void init( void )
|
||||
{
|
||||
getDatabaseCenterRadius( dbcenter, &dbradius );
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
|
||||
static void getNormal( float *v1, float *v2, float *v3, float *n )
|
||||
{
|
||||
float V1[4], V2[4];
|
||||
float f;
|
||||
int i;
|
||||
|
||||
/* Two vectors v2->v1 and v2->v3 */
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
V1[i] = v1[i] - v2[i];
|
||||
V2[i] = v3[i] - v2[i];
|
||||
}
|
||||
|
||||
/* Cross product between V1 and V2 */
|
||||
|
||||
n[0] = (V1[1] * V2[2]) - (V1[2] * V2[1]);
|
||||
n[1] = -((V1[0] * V2[2]) - ( V1[2] * V2[0] ));
|
||||
n[2] = (V1[0] * V2[1] ) - (V1[1] * V2[0] );
|
||||
|
||||
/* Normalize */
|
||||
|
||||
f = sqrtf( ( n[0] * n[0] ) + ( n[1] * n[1] ) + ( n[2] * n[2] ) );
|
||||
n[0] /= f;
|
||||
n[1] /= f;
|
||||
n[2] /= f;
|
||||
}
|
||||
|
||||
|
||||
float Hat( float x, float y, float z )
|
||||
{
|
||||
int m, n;
|
||||
int i, j;
|
||||
float tri[3][3];
|
||||
float norm[3];
|
||||
float d, pz;
|
||||
|
||||
if( inited == 0 ) init();
|
||||
|
||||
// m = columns
|
||||
// n = rows
|
||||
m = (sizeof( vertex ) /(sizeof( float[3])))/39;
|
||||
n = 39;
|
||||
|
||||
i = 0;
|
||||
while( i < ((m-1)*39) && x > (vertex[i+n][0] - dbcenter[0]) )
|
||||
i += n;
|
||||
|
||||
j = 0;
|
||||
|
||||
while( j < n-1 && y > (vertex[i+j+1][1] - dbcenter[1]) )
|
||||
j++;
|
||||
|
||||
tri[0][0] = vertex[i+0+j+0][0] - dbcenter[0];
|
||||
tri[0][1] = vertex[i+0+j+0][1] - dbcenter[1];
|
||||
//tri[0][2] = vertex[i+0+j+0][2] - dbcenter[2];
|
||||
tri[0][2] = vertex[i+0+j+0][2];
|
||||
|
||||
tri[1][0] = vertex[i+n+j+0][0] - dbcenter[0];
|
||||
tri[1][1] = vertex[i+n+j+0][1] - dbcenter[1];
|
||||
//tri[1][2] = vertex[i+n+j+0][2] - dbcenter[2];
|
||||
tri[1][2] = vertex[i+n+j+0][2];
|
||||
|
||||
tri[2][0] = vertex[i+0+j+1][0] - dbcenter[0];
|
||||
tri[2][1] = vertex[i+0+j+1][1] - dbcenter[1];
|
||||
//tri[2][2] = vertex[i+0+j+1][2] - dbcenter[2];
|
||||
tri[2][2] = vertex[i+0+j+1][2];
|
||||
|
||||
getNormal( tri[0], tri[1], tri[2], norm );
|
||||
|
||||
d = (tri[0][0] * norm[0]) +
|
||||
(tri[0][1] * norm[1]) +
|
||||
(tri[0][2] * norm[2]);
|
||||
|
||||
d *= -1;
|
||||
pz = (-(norm[0] * x) - (norm[1] * y) - d)/norm[2];
|
||||
|
||||
return z - pz;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#ifndef __HAT_H
|
||||
#define __HAT_H
|
||||
extern float Hat( float x, float y, float z );
|
||||
#endif
|
||||
@@ -1,151 +0,0 @@
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Depth>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/ClearNode>
|
||||
#include <osg/Transform>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/AnimationPathManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include "GliderManipulator.h"
|
||||
|
||||
extern osg::Node *makeTerrain( void );
|
||||
extern osg::Node *makeTrees( void );
|
||||
extern osg::Node *makeTank( void );
|
||||
extern osg::Node *makeWindsocks( void );
|
||||
extern osg::Node *makeGliders( void );
|
||||
extern osg::Node *makeGlider( void );
|
||||
extern osg::Node *makeSky( void );
|
||||
extern osg::Node *makeBase( void );
|
||||
extern osg::Node *makeClouds( void );
|
||||
|
||||
struct MoveEarthySkyWithEyePointCallback : public osg::Transform::ComputeTransformCallback
|
||||
{
|
||||
/** Get the transformation matrix which moves from local coords to world coords.*/
|
||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,const osg::Transform*, osg::NodeVisitor* nv) const
|
||||
{
|
||||
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cv)
|
||||
{
|
||||
osg::Vec3 eyePointLocal = cv->getEyeLocal();
|
||||
matrix.preMult(osg::Matrix::translate(eyePointLocal.x(),eyePointLocal.y(),0.0f));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Get the transformation matrix which moves from world coords to local coords.*/
|
||||
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,const osg::Transform*, osg::NodeVisitor* nv) const
|
||||
{
|
||||
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cv)
|
||||
{
|
||||
osg::Vec3 eyePointLocal = cv->getEyeLocal();
|
||||
matrix.postMult(osg::Matrix::translate(-eyePointLocal.x(),-eyePointLocal.y(),0.0f));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
osg::Group* createModel()
|
||||
{
|
||||
// no database loaded so automatically create Ed Levin Park..
|
||||
osg::Group* group = new osg::Group;
|
||||
|
||||
// the base and sky subgraphs go to set the earth sky of the
|
||||
// model and clear the color and depth buffer for us, by using
|
||||
// osg::Depth, and setting their bin numbers to less than 0,
|
||||
// to force them to draw before the rest of the scene.
|
||||
|
||||
osg::ClearNode* clearNode = new osg::ClearNode;
|
||||
clearNode->setRequiresClear(false); // we've got base and sky to do it.
|
||||
|
||||
// use a transform to make the sky and base around with the eye point.
|
||||
osg::Transform* transform = new osg::Transform;
|
||||
|
||||
// transform's value isn't knowm until in the cull traversal so its bounding
|
||||
// volume is can't be determined, therefore culling will be invalid,
|
||||
// so switch it off, this cause all our paresnts to switch culling
|
||||
// off as well. But don't worry culling will be back on once underneath
|
||||
// this node or any other branch above this transform.
|
||||
transform->setCullingActive(false);
|
||||
|
||||
// set the compute transform callback to do all the work of
|
||||
// determining the transform according to the current eye point.
|
||||
transform->setComputeTransformCallback(new MoveEarthySkyWithEyePointCallback);
|
||||
|
||||
// add the sky and base layer.
|
||||
transform->addChild(makeSky()); // bin number -2 so drawn first.
|
||||
transform->addChild(makeBase()); // bin number -1 so draw second.
|
||||
|
||||
// add the transform to the earth sky.
|
||||
clearNode->addChild(transform);
|
||||
|
||||
// add to earth sky to the scene.
|
||||
group->addChild(clearNode);
|
||||
|
||||
// the rest of the scene drawn after the base and sky above.
|
||||
group->addChild(makeTrees()); // will drop into a transparent, depth sorted bin (1)
|
||||
group->addChild(makeTerrain()); // will drop into default bin - state sorted 0
|
||||
group->addChild(makeTank()); // will drop into default bin - state sorted 0
|
||||
// add the following in the future...
|
||||
// makeGliders
|
||||
// makeClouds
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode) rootnode = createModel();
|
||||
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
unsigned int pos = viewer.registerCameraManipulator(new GliderManipulator());
|
||||
|
||||
// Open window so camera manipulator's warp pointer request will succeed
|
||||
viewer.open();
|
||||
|
||||
viewer.selectCameraManipulator(pos);
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/Depth>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4244 )
|
||||
#pragma warning( disable : 4305 )
|
||||
#endif
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Node *makeSky( void )
|
||||
{
|
||||
int i, j;
|
||||
float lev[] = { -5, -1.0, 1.0, 15.0, 30.0, 60.0, 90.0 };
|
||||
float cc[][4] =
|
||||
{
|
||||
{ 0.0, 0.0, 0.15 },
|
||||
{ 0.0, 0.0, 0.15 },
|
||||
{ 0.4, 0.4, 0.7 },
|
||||
{ 0.2, 0.2, 0.6 },
|
||||
{ 0.1, 0.1, 0.6 },
|
||||
{ 0.1, 0.1, 0.6 },
|
||||
{ 0.1, 0.1, 0.6 },
|
||||
};
|
||||
float x, y, z;
|
||||
float alpha, theta;
|
||||
float radius = 20.0f;
|
||||
int nlev = sizeof( lev )/sizeof(float);
|
||||
|
||||
Geometry *geom = new Geometry;
|
||||
|
||||
Vec3Array& coords = *(new Vec3Array(19*nlev));
|
||||
Vec4Array& colors = *(new Vec4Array(19*nlev));
|
||||
Vec2Array& tcoords = *(new Vec2Array(19*nlev));
|
||||
|
||||
|
||||
int ci = 0;
|
||||
|
||||
for( i = 0; i < nlev; i++ )
|
||||
{
|
||||
for( j = 0; j <= 18; j++ )
|
||||
{
|
||||
alpha = osg::DegreesToRadians(lev[i]);
|
||||
theta = osg::DegreesToRadians((float)(j*20));
|
||||
|
||||
x = radius * cosf( alpha ) * cosf( theta );
|
||||
y = radius * cosf( alpha ) * -sinf( theta );
|
||||
z = radius * sinf( alpha );
|
||||
|
||||
coords[ci][0] = x;
|
||||
coords[ci][1] = y;
|
||||
coords[ci][2] = z;
|
||||
|
||||
colors[ci][0] = cc[i][0];
|
||||
colors[ci][1] = cc[i][1];
|
||||
colors[ci][2] = cc[i][2];
|
||||
colors[ci][3] = 1.0;
|
||||
|
||||
tcoords[ci][0] = (float)j/18.0;
|
||||
tcoords[ci][0] = (float)i/(float)(nlev-1);
|
||||
|
||||
ci++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
for( i = 0; i < nlev-1; i++ )
|
||||
{
|
||||
DrawElementsUShort* drawElements = new DrawElementsUShort(PrimitiveSet::TRIANGLE_STRIP);
|
||||
drawElements->reserve(38);
|
||||
|
||||
for( j = 0; j <= 18; j++ )
|
||||
{
|
||||
drawElements->push_back((i+1)*19+j);
|
||||
drawElements->push_back((i+0)*19+j);
|
||||
}
|
||||
|
||||
geom->addPrimitiveSet(drawElements);
|
||||
}
|
||||
|
||||
geom->setVertexArray( &coords );
|
||||
geom->setTexCoordArray( 0, &tcoords );
|
||||
|
||||
geom->setColorArray( &colors );
|
||||
geom->setColorBinding( Geometry::BIND_PER_VERTEX );
|
||||
|
||||
|
||||
Texture2D *tex = new Texture2D;
|
||||
tex->setImage(osgDB::readImageFile("Images/white.rgb"));
|
||||
|
||||
StateSet *dstate = new StateSet;
|
||||
|
||||
dstate->setTextureAttributeAndModes(0, tex, StateAttribute::OFF );
|
||||
dstate->setTextureAttribute(0, new TexEnv );
|
||||
dstate->setMode( GL_LIGHTING, StateAttribute::OFF );
|
||||
dstate->setMode( GL_CULL_FACE, StateAttribute::ON );
|
||||
|
||||
|
||||
// clear the depth to the far plane.
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setFunction(osg::Depth::ALWAYS);
|
||||
depth->setRange(1.0,1.0);
|
||||
dstate->setAttributeAndModes(depth,StateAttribute::ON );
|
||||
|
||||
dstate->setRenderBinDetails(-2,"RenderBin");
|
||||
|
||||
geom->setStateSet( dstate );
|
||||
|
||||
Geode *geode = new Geode;
|
||||
geode->addDrawable( geom );
|
||||
|
||||
geode->setName( "Sky" );
|
||||
|
||||
return geode;
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/Group>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Matrix>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4244 )
|
||||
#pragma warning( disable : 4305 )
|
||||
#endif
|
||||
|
||||
using namespace osg;
|
||||
|
||||
extern void getDatabaseCenterRadius( float dbcenter[3], float *dbradius );
|
||||
|
||||
static float radius = 2.0;
|
||||
static float dbcenter[3], dbradius;
|
||||
|
||||
static void conv( const Vec3& a, const Matrix& mat, Vec3& b )
|
||||
{
|
||||
int i;
|
||||
Vec3 t;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
t[i] = (a[0] * mat(0,i)) +
|
||||
(a[1] * mat(1,i)) +
|
||||
(a[2] * mat(2,i)) +
|
||||
mat(3,i);
|
||||
}
|
||||
b[0] = t[0];
|
||||
b[1] = t[1];
|
||||
b[2] = t[2];
|
||||
}
|
||||
|
||||
|
||||
Node *makeTank( void )
|
||||
{
|
||||
|
||||
Geode *geode = new Geode;
|
||||
|
||||
getDatabaseCenterRadius( dbcenter, &dbradius );
|
||||
|
||||
Matrix mat(
|
||||
0.05, 0, 0, 0,
|
||||
0, 0.05, 0, 0,
|
||||
0, 0, 0.05, 0,
|
||||
1.5999 - 0.3,
|
||||
3.1474,
|
||||
dbcenter[2] + 0.6542 - 0.09,
|
||||
1
|
||||
);
|
||||
|
||||
// 42 required for sodes, 22 for the top.
|
||||
Vec3Array& vc = *(new Vec3Array(42+22));
|
||||
Vec2Array& tc = *(new Vec2Array(42+22));
|
||||
|
||||
Geometry *gset = new Geometry;
|
||||
gset->setVertexArray( &vc );
|
||||
gset->setTexCoordArray( 0, &tc );
|
||||
|
||||
// create the sides of the tank.
|
||||
unsigned int i, c = 0;
|
||||
for( i = 0; i <= 360; i += 18 )
|
||||
{
|
||||
float x, y, z;
|
||||
float s, t;
|
||||
float theta = osg::DegreesToRadians((float)i);
|
||||
|
||||
s = (float)i/90.0;
|
||||
t = 1.0;
|
||||
|
||||
x = radius * cosf( theta );
|
||||
y = radius * sinf( theta );
|
||||
z = 1.0;
|
||||
|
||||
vc[c][0] = x;
|
||||
vc[c][1] = y;
|
||||
vc[c][2] = z;
|
||||
|
||||
tc[c][0] = s;
|
||||
tc[c][1] = t;
|
||||
|
||||
c++;
|
||||
|
||||
t = 0.0;
|
||||
z = 0.0;
|
||||
|
||||
vc[c][0] = x;
|
||||
vc[c][1] = y;
|
||||
vc[c][2] = z;
|
||||
|
||||
tc[c][0] = s;
|
||||
tc[c][1] = t;
|
||||
c++;
|
||||
}
|
||||
|
||||
gset->addPrimitiveSet( new DrawArrays(PrimitiveSet::TRIANGLE_STRIP,0,c) );
|
||||
|
||||
// create the top of the tank.
|
||||
|
||||
int prev_c = c;
|
||||
|
||||
vc[c][0] = 0.0f;
|
||||
vc[c][1] = 0.0f;
|
||||
vc[c][2] = 1.0f;
|
||||
|
||||
tc[c][0] = 0.0f;
|
||||
tc[c][1] = 0.0f;
|
||||
c++;
|
||||
|
||||
for( i = 0; i <= 360; i += 18 )
|
||||
{
|
||||
float x, y, z;
|
||||
float s, t;
|
||||
float theta = osg::DegreesToRadians((float)i);
|
||||
|
||||
// s = (float)i/360.0;
|
||||
// t = 1.0;
|
||||
s = cosf( theta );
|
||||
t = sinf( theta );
|
||||
|
||||
x = radius * cosf( theta );
|
||||
y = radius * sinf( theta );
|
||||
z = 1.0;
|
||||
|
||||
vc[c][0] = x;
|
||||
vc[c][1] = y;
|
||||
vc[c][2] = z;
|
||||
|
||||
tc[c][0] = s;
|
||||
tc[c][1] = t;
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
for( i = 0; i < c; i++ )
|
||||
conv( vc[i], mat, vc[i] );
|
||||
|
||||
gset->addPrimitiveSet(new DrawArrays(PrimitiveSet::TRIANGLE_FAN,prev_c,c-prev_c));
|
||||
|
||||
|
||||
|
||||
|
||||
Texture2D *tex = new Texture2D;
|
||||
|
||||
tex->setWrap( Texture2D::WRAP_S, Texture2D::REPEAT );
|
||||
tex->setWrap( Texture2D::WRAP_T, Texture2D::REPEAT );
|
||||
tex->setImage(osgDB::readImageFile("Images/tank.rgb"));
|
||||
|
||||
StateSet *dstate = new StateSet;
|
||||
dstate->setTextureAttributeAndModes(0, tex, StateAttribute::ON );
|
||||
dstate->setTextureAttribute(0, new TexEnv );
|
||||
|
||||
gset->setStateSet( dstate );
|
||||
geode->addDrawable( gset );
|
||||
|
||||
return geode;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
// #include <math.h>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include "terrain_coords.h"
|
||||
#include "terrain_texcoords.h"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
void getDatabaseCenterRadius( float dbcenter[3], float *dbradius )
|
||||
{
|
||||
int i;
|
||||
double n=0.0;
|
||||
double center[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float cnt;
|
||||
|
||||
cnt = 39 * 38;
|
||||
for( i = 0; i < cnt; i++ )
|
||||
{
|
||||
center[0] += (double)vertex[i][0];
|
||||
center[1] += (double)vertex[i][1];
|
||||
center[2] += (double)vertex[i][2];
|
||||
|
||||
n = n + 1.0;
|
||||
}
|
||||
|
||||
center[0] /= n;
|
||||
center[1] /= n;
|
||||
center[2] /= n;
|
||||
|
||||
float r = 0.0;
|
||||
|
||||
// for( i = 0; i < sizeof( vertex ) / (sizeof( float[3] )); i++ )
|
||||
for( i = 0; i < cnt; i++ )
|
||||
{
|
||||
double d = sqrt(
|
||||
(((double)vertex[i][0] - center[0]) * ((double)vertex[i][0] - center[0])) +
|
||||
(((double)vertex[i][1] - center[1]) * ((double)vertex[i][1] - center[1])) +
|
||||
(((double)vertex[i][2] - center[2]) * ((double)vertex[i][2] - center[2])) );
|
||||
|
||||
if( d > (double)r ) r = (float)d;
|
||||
|
||||
}
|
||||
|
||||
*dbradius = r;
|
||||
dbcenter[0] = (float)center[0];
|
||||
dbcenter[1] = (float)center[1];
|
||||
dbcenter[2] = (float)center[2];
|
||||
|
||||
int index = 19 * 39 + 19;
|
||||
dbcenter[0] = vertex[index][0] - 0.15;
|
||||
dbcenter[1] = vertex[index][1];
|
||||
dbcenter[2] = vertex[index][2] + 0.35;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Node *makeTerrain( void )
|
||||
{
|
||||
int m, n;
|
||||
int i, j;
|
||||
float dbcenter[3];
|
||||
float dbradius;
|
||||
|
||||
getDatabaseCenterRadius( dbcenter, &dbradius );
|
||||
|
||||
m = (sizeof( vertex ) /(sizeof( float[3])))/39;
|
||||
n = 39;
|
||||
|
||||
Vec3Array& v = *(new Vec3Array(m*n));
|
||||
Vec2Array& t = *(new Vec2Array(m*n));
|
||||
Vec4Array& col = *(new Vec4Array(1));
|
||||
|
||||
col[0][0] = col[0][1] = col[0][2] = col[0][3] = 1.0f;
|
||||
|
||||
for( i = 0; i < m * n; i++ )
|
||||
{
|
||||
v[i][0] = vertex[i][0] - dbcenter[0];
|
||||
v[i][1] = vertex[i][1] - dbcenter[1];
|
||||
v[i][2] = vertex[i][2];
|
||||
|
||||
t[i][0] = texcoord[i][0] + 0.025;
|
||||
t[i][1] = texcoord[i][1];
|
||||
}
|
||||
|
||||
Geometry *geom = new Geometry;
|
||||
|
||||
geom->setVertexArray( &v );
|
||||
geom->setTexCoordArray( 0, &t );
|
||||
|
||||
geom->setColorArray( &col );
|
||||
geom->setColorBinding( Geometry::BIND_OVERALL );
|
||||
|
||||
for( i = 0; i < m-2; i++ )
|
||||
{
|
||||
DrawElementsUShort* elements = new DrawElementsUShort(PrimitiveSet::TRIANGLE_STRIP);
|
||||
elements->reserve(39*2);
|
||||
for( j = 0; j < n; j++ )
|
||||
{
|
||||
elements->push_back((i+0)*n+j);
|
||||
elements->push_back((i+1)*n+j);
|
||||
}
|
||||
geom->addPrimitiveSet(elements);
|
||||
}
|
||||
|
||||
|
||||
Texture2D *tex = new Texture2D;
|
||||
|
||||
tex->setImage(osgDB::readImageFile("Images/lz.rgb"));
|
||||
|
||||
StateSet *dstate = new StateSet;
|
||||
dstate->setMode( GL_LIGHTING, StateAttribute::OFF );
|
||||
dstate->setTextureAttributeAndModes(0, tex, StateAttribute::ON );
|
||||
dstate->setTextureAttribute(0, new TexEnv );
|
||||
|
||||
geom->setStateSet( dstate );
|
||||
|
||||
Geode *geode = new Geode;
|
||||
geode->addDrawable( geom );
|
||||
|
||||
return geode;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,273 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Group>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/AlphaFunc>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include "hat.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4244 )
|
||||
#pragma warning( disable : 4305 )
|
||||
#endif
|
||||
|
||||
using namespace osg;
|
||||
|
||||
#define sqr(x) ((x)*(x))
|
||||
|
||||
extern void getDatabaseCenterRadius( float dbcenter[3], float *dbradius );
|
||||
|
||||
static float dbcenter[3], dbradius;
|
||||
|
||||
static struct _tree
|
||||
{
|
||||
int n;
|
||||
float x, y, z;
|
||||
float w, h;
|
||||
}
|
||||
|
||||
|
||||
trees[] =
|
||||
{
|
||||
{ 0, -0.4769, -0.8972, -0.4011, 0.2000, 0.1200 },
|
||||
{ 1, -0.2543, -0.9117, -0.3873, 0.2000, 0.1200 },
|
||||
{ 2, -0.0424, -0.8538, -0.3728, 0.2000, 0.1200 },
|
||||
{ 3, 0.1590, -0.8827, -0.3594, 0.2000, 0.1200 },
|
||||
{ 4, -0.4981, -1.0853, -0.4016, 0.3500, 0.1200 },
|
||||
{ 5, -0.5405, -1.2590, -0.4050, 0.2000, 0.1200 },
|
||||
{ 6, -0.5723, -1.5339, -0.4152, 0.2000, 0.1200 },
|
||||
{ 7, -0.6252, -1.8667, -0.4280, 0.2000, 0.1200 },
|
||||
{ 8, -0.5617, -2.1851, -0.4309, 0.2000, 0.1200 },
|
||||
{ 9, -0.5087, -2.4166, -0.4215, 0.2000, 0.1200 },
|
||||
{ 10, -0.4345, -2.3443, -0.4214, 0.2000, 0.1200 },
|
||||
{ 11, -3.0308, -1.5484, -0.4876, 0.2000, 0.1200 },
|
||||
{ 12, -3.0202, -1.6497, -0.4963, 0.2000, 0.1200 },
|
||||
{ 13, -2.9355, -1.8378, -0.4969, 0.2000, 0.1200 },
|
||||
{ 14, -0.6040, -2.0259, -0.4300, 0.2000, 0.1200 },
|
||||
{ 15, -0.5442, -1.3442, -0.4080, 0.1000, 0.1200 },
|
||||
{ 16, -0.5639, -1.6885, -0.4201, 0.1000, 0.1200 },
|
||||
{ 17, 0.9246, 3.4835, 0.5898, 0.2500, 0.1000 },
|
||||
{ 18, 0.0787, 3.8687, 0.3329, 0.2500, 0.1200 },
|
||||
{ 19, 0.2885, 3.7130, 0.4047, 0.2500, 0.1200 },
|
||||
{ 20, 0.2033, 3.6228, 0.3704, 0.2500, 0.1200 },
|
||||
{ 21, -0.2098, 3.9015, 0.2327, 0.2500, 0.1200 },
|
||||
{ 22, -0.3738, 3.7376, 0.1722, 0.2500, 0.1200 },
|
||||
{ 23, -0.2557, 3.6064, 0.1989, 0.2500, 0.1200 },
|
||||
{ 24, 0.0590, 3.7294, 0.3210, 0.2500, 0.1200 },
|
||||
{ 25, -0.4721, 3.8851, 0.1525, 0.2500, 0.1200 },
|
||||
{ 26, 0.9639, 3.2048, 0.5868, 0.1200, 0.0800 },
|
||||
{ 27, 0.7082, -1.0409, -0.3221, 0.1000, 0.1000 },
|
||||
{ 28, -0.2426, -2.3442, -0.4150, 0.1000, 0.1380 },
|
||||
{ 29, -0.1770, -2.4179, -0.4095, 0.1000, 0.1580 },
|
||||
{ 30, -0.0852, -2.5327, -0.4056, 0.1000, 0.1130 },
|
||||
{ 31, -0.0131, -2.6065, -0.4031, 0.1000, 0.1150 },
|
||||
{ 32, 0.0787, -2.6638, -0.4012, 0.1000, 0.1510 },
|
||||
{ 33, 0.1049, -2.7622, -0.3964, 0.1000, 0.1270 },
|
||||
{ 34, 0.1770, -2.8687, -0.3953, 0.1000, 0.1100 },
|
||||
{ 35, 0.3213, -2.9507, -0.3974, 0.1000, 0.1190 },
|
||||
{ 36, 0.4065, -3.0163, -0.4014, 0.1000, 0.1120 },
|
||||
{ 37, 0.3738, -3.1802, -0.4025, 0.1000, 0.1860 },
|
||||
{ 38, 0.5508, -3.2048, -0.3966, 0.1000, 0.1490 },
|
||||
{ 39, 0.5836, -3.3031, -0.3900, 0.1000, 0.1670 },
|
||||
{ 40, -0.3082, -2.7212, -0.3933, 0.1000, 0.1840 },
|
||||
{ 41, -0.1967, -2.6474, -0.4017, 0.1000, 0.1600 },
|
||||
{ 42, -0.1180, -2.7458, -0.3980, 0.1000, 0.1250 },
|
||||
{ 43, -0.3344, -2.8359, -0.3964, 0.1000, 0.1430 },
|
||||
{ 44, -0.2492, -2.8933, -0.3838, 0.1000, 0.1890 },
|
||||
{ 45, -0.1246, -3.0491, -0.3768, 0.1000, 0.1830 },
|
||||
{ 46, 0.0000, -3.0818, -0.3696, 0.1000, 0.1370 },
|
||||
{ 47, -0.2295, -3.0409, -0.3706, 0.1000, 0.1660 },
|
||||
{ 48, -1.3245, 2.6638, 0.0733, 0.0500, 0.0500 },
|
||||
{ 49, 2.2425, -1.5491, -0.2821, 0.2300, 0.1200 },
|
||||
{ 50, 0.2164, -2.1311, -0.4000, 0.1000, 0.0690 },
|
||||
{ 51, 0.2885, -2.2130, -0.4000, 0.1000, 0.0790 },
|
||||
{ 52, 0.3606, -2.2786, -0.4000, 0.1000, 0.0565 },
|
||||
{ 53, 0.4328, -2.3442, -0.4000, 0.1000, 0.0575 },
|
||||
{ 54, 0.5246, -2.4343, -0.4086, 0.1000, 0.0755 },
|
||||
{ 55, 0.6360, -2.5245, -0.4079, 0.1000, 0.0635 },
|
||||
{ 56, 0.7541, -2.4261, -0.4007, 0.1000, 0.0550 },
|
||||
{ 57, 0.7934, -2.2786, -0.3944, 0.1000, 0.0595 },
|
||||
{ 58, 1.0295, -2.2868, -0.3837, 0.1000, 0.0560 },
|
||||
{ 59, 0.8459, -2.6474, -0.4051, 0.1000, 0.0930 },
|
||||
{ 60, 1.0426, -2.6884, -0.4001, 0.1000, 0.0745 },
|
||||
{ 61, 1.1475, -2.7458, -0.3883, 0.1000, 0.0835 },
|
||||
{ 62, -0.1967, -1.4180, -0.3988, 0.1000, 0.0920 },
|
||||
{ 63, -0.0131, -1.2704, -0.3856, 0.1000, 0.0690 },
|
||||
{ 64, 0.2098, -1.2049, -0.3664, 0.1000, 0.0790 },
|
||||
{ 65, 0.3410, -1.3196, -0.3652, 0.1000, 0.0565 },
|
||||
{ 66, 0.5705, -1.2704, -0.3467, 0.1000, 0.0575 },
|
||||
{ 67, 0.6360, -1.4344, -0.3532, 0.1000, 0.0755 },
|
||||
{ 68, 0.9246, -1.4180, -0.3329, 0.1000, 0.0635 },
|
||||
{ 69, 1.0623, -1.3360, -0.3183, 0.1000, 0.0550 },
|
||||
{ 70, 1.2393, -1.3934, -0.3103, 0.1000, 0.0595 },
|
||||
{ 71, 1.3639, -1.4753, -0.3079, 0.1000, 0.0560 },
|
||||
{ 72, 1.4819, -1.5983, -0.3210, 0.1000, 0.0930 },
|
||||
{ 73, 1.7835, -1.5819, -0.3065, 0.1000, 0.0745 },
|
||||
{ 74, 1.9343, -2.1065, -0.3307, 0.1000, 0.0835 },
|
||||
{ 75, 2.1245, -2.3196, -0.3314, 0.1000, 0.0920 },
|
||||
{ 76, 2.2556, -2.3032, -0.3230, 0.1000, 0.0800 },
|
||||
{ 77, 2.4196, -2.3688, -0.3165, 0.1000, 0.0625 },
|
||||
{ 78, 1.7835, -2.5327, -0.3543, 0.1000, 0.0715 },
|
||||
{ 79, 1.7180, -2.8933, -0.3742, 0.1000, 0.0945 },
|
||||
{ 80, 1.9343, -3.0409, -0.3727, 0.1000, 0.0915 },
|
||||
{ 81, 2.4524, -3.4671, -0.3900, 0.1000, 0.0685 },
|
||||
{ 82, 2.4786, -2.8851, -0.3538, 0.1000, 0.0830 },
|
||||
{ 83, 2.3343, -2.6228, -0.3420, 0.1000, 0.0830 },
|
||||
{ 84, 2.8130, -2.0737, -0.2706, 0.1000, 0.0890 },
|
||||
{ 85, 2.6360, -1.8278, -0.2661, 0.1000, 0.0975 },
|
||||
{ 86, 2.3958, -1.7130, -0.2774, 0.2000, 0.1555 },
|
||||
{ 87, 2.2688, -1.2868, -0.2646, 0.1000, 0.0835 },
|
||||
{ 88, 2.4196, -1.1147, -0.2486, 0.1000, 0.0770 },
|
||||
{ 89, 2.7802, -2.3933, -0.3017, 0.1000, 0.0655 },
|
||||
{ 90, 3.0163, -2.4179, -0.2905, 0.1000, 0.0725 },
|
||||
{ 91, 2.9310, -2.2540, -0.2798, 0.1000, 0.0910 },
|
||||
{ 92, 2.6622, -2.0983, -0.2823, 0.1000, 0.0680 },
|
||||
{ 93, 2.3147, -1.9753, -0.2973, 0.1000, 0.0620 },
|
||||
{ 94, 2.1573, -1.8770, -0.3013, 0.1000, 0.0525 },
|
||||
{ 95, 2.0196, -1.7868, -0.3044, 0.1000, 0.0970 },
|
||||
{ 96, 2.7802, -3.3031, -0.3900, 0.1000, 0.0510 },
|
||||
{ 97, 2.8589, -3.1720, -0.3900, 0.1000, 0.0755 },
|
||||
{ 98, 3.0163, -2.8114, -0.3383, 0.1000, 0.0835 },
|
||||
{ 99, 3.5081, -2.4179, -0.2558, 0.1000, 0.0770 },
|
||||
{ 100, 3.5277, -2.3196, -0.2366, 0.1000, 0.0765 },
|
||||
{ 101, 3.6654, -2.5819, -0.2566, 0.1000, 0.0805 },
|
||||
{ 102, 3.7179, -2.7622, -0.2706, 0.1000, 0.0980 },
|
||||
{ 103, 3.7769, -2.4671, -0.2339, 0.1000, 0.0640 },
|
||||
{ 104, 3.3441, -2.4671, -0.2693, 0.1000, 0.0940 },
|
||||
{ -1, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static Geometry *makeTree( _tree *tree, StateSet *dstate )
|
||||
{
|
||||
float vv[][3] =
|
||||
{
|
||||
{ -tree->w/2.0, 0.0, 0.0 },
|
||||
{ tree->w/2.0, 0.0, 0.0 },
|
||||
{ tree->w/2.0, 0.0, 2 * tree->h },
|
||||
{ -tree->w/2.0, 0.0, 2 * tree->h },
|
||||
};
|
||||
|
||||
Vec3Array& v = *(new Vec3Array(4));
|
||||
Vec2Array& t = *(new Vec2Array(4));
|
||||
Vec4Array& l = *(new Vec4Array(1));
|
||||
|
||||
int i;
|
||||
|
||||
l[0][0] = l[0][1] = l[0][2] = l[0][3] = 1;
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
v[i][0] = vv[i][0];
|
||||
v[i][1] = vv[i][1];
|
||||
v[i][2] = vv[i][2];
|
||||
}
|
||||
|
||||
t[0][0] = 0.0; t[0][1] = 0.0;
|
||||
t[1][0] = 1.0; t[1][1] = 0.0;
|
||||
t[2][0] = 1.0; t[2][1] = 1.0;
|
||||
t[3][0] = 0.0; t[3][1] = 1.0;
|
||||
|
||||
Geometry *geom = new Geometry;
|
||||
|
||||
geom->setVertexArray( &v );
|
||||
|
||||
geom->setTexCoordArray( 0, &t );
|
||||
|
||||
geom->setColorArray( &l );
|
||||
geom->setColorBinding( Geometry::BIND_OVERALL );
|
||||
|
||||
geom->addPrimitiveSet( new DrawArrays(PrimitiveSet::QUADS,0,4) );
|
||||
|
||||
geom->setStateSet( dstate );
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
|
||||
static float ttx, tty;
|
||||
|
||||
static int ct( const void *a, const void *b )
|
||||
{
|
||||
_tree *ta = (_tree *)a;
|
||||
_tree *tb = (_tree *)b;
|
||||
|
||||
float da = sqrtf( sqr(ta->x - ttx) + sqr(ta->y - tty) );
|
||||
float db = sqrtf( sqr(tb->x - ttx) + sqr(tb->y - tty) );
|
||||
|
||||
if( da < db )
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Node *makeTrees( void )
|
||||
{
|
||||
Group *group = new Group;
|
||||
int i;
|
||||
|
||||
getDatabaseCenterRadius( dbcenter, &dbradius );
|
||||
struct _tree *t;
|
||||
|
||||
Texture2D *tex = new Texture2D;
|
||||
tex->setImage(osgDB::readImageFile("Images/tree0.rgba"));
|
||||
|
||||
StateSet *dstate = new StateSet;
|
||||
|
||||
dstate->setTextureAttributeAndModes(0, tex, StateAttribute::ON );
|
||||
dstate->setTextureAttribute(0, new TexEnv );
|
||||
|
||||
dstate->setAttributeAndModes( new BlendFunc, StateAttribute::ON );
|
||||
|
||||
AlphaFunc* alphaFunc = new AlphaFunc;
|
||||
alphaFunc->setFunction(AlphaFunc::GEQUAL,0.05f);
|
||||
dstate->setAttributeAndModes( alphaFunc, StateAttribute::ON );
|
||||
|
||||
dstate->setMode( GL_LIGHTING, StateAttribute::OFF );
|
||||
|
||||
dstate->setRenderingHint( StateSet::TRANSPARENT_BIN );
|
||||
|
||||
int tt[] = { 15, 30, 45, 58, 72, 75, 93, 96, 105, -1 };
|
||||
int *ttp = tt;
|
||||
|
||||
i = 0;
|
||||
while( i < 105 )
|
||||
{
|
||||
ttx = trees[i].x;
|
||||
tty = trees[i].y;
|
||||
qsort( &trees[i], 105 - i, sizeof( _tree ), ct );
|
||||
|
||||
i += *ttp;
|
||||
ttp++;
|
||||
}
|
||||
|
||||
t = trees;
|
||||
i = 0;
|
||||
ttp = tt;
|
||||
while( *ttp != -1 )
|
||||
{
|
||||
Billboard *bb = new Billboard;
|
||||
//int starti = i;
|
||||
|
||||
for( ; i < (*ttp); i++ )
|
||||
{
|
||||
t->x -= 0.3f;
|
||||
float h = Hat(t->x, t->y, t->z );
|
||||
Vec3 pos( t->x, t->y, t->z-h );
|
||||
Geometry *geom = makeTree( t, dstate );
|
||||
bb->addDrawable( geom, pos );
|
||||
t++;
|
||||
}
|
||||
group->addChild( bb );
|
||||
ttp++;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osghud.cpp\
|
||||
|
||||
#LINKARGS += -L/usr/local/lib
|
||||
LIBS += -losgText $(OSG_LIBS) -L/usr/local/lib $(FREETYPE_LIB) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osghud
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osghud.cpp\
|
||||
|
||||
LIBS += -losgText $(OSG_LIBS) $(FREETYPE_LIB) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osghud
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,196 +0,0 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Projection>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Material>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Depth>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgText/Text>
|
||||
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
osg::Node* createHUD()
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
std::string timesFont("fonts/times.ttf");
|
||||
|
||||
// turn lighting off for the text and disable depth test to ensure its always ontop.
|
||||
osg::StateSet* stateset = geode->getOrCreateStateSet();
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
|
||||
|
||||
osg::Vec3 position(150.0f,800.0f,0.0f);
|
||||
osg::Vec3 delta(0.0f,-120.0f,0.0f);
|
||||
|
||||
{
|
||||
osgText::Text* text = new osgText::Text;
|
||||
geode->addDrawable( text );
|
||||
|
||||
text->setFont(timesFont);
|
||||
text->setText("Head Up Displays are simple :-)");
|
||||
text->setPosition(position);
|
||||
|
||||
position += delta;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
osgText::Text* text = new osgText::Text;
|
||||
geode->addDrawable( text );
|
||||
|
||||
text->setFont(timesFont);
|
||||
text->setText("All you need to do is create your text in a subgraph.");
|
||||
text->setPosition(position);
|
||||
|
||||
position += delta;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
osgText::Text* text = new osgText::Text;
|
||||
geode->addDrawable( text );
|
||||
|
||||
text->setFont(timesFont);
|
||||
text->setText("Disable depth test in this subgraph to ensure its always ontop.");
|
||||
text->setPosition(position);
|
||||
|
||||
position += delta;
|
||||
}
|
||||
|
||||
{
|
||||
osgText::Text* text = new osgText::Text;
|
||||
geode->addDrawable( text );
|
||||
|
||||
text->setFont(timesFont);
|
||||
text->setText("Then place an osg::Projection node above the subgraph\nto create an orthographic projection.");
|
||||
text->setPosition(position);
|
||||
|
||||
position += delta;
|
||||
}
|
||||
|
||||
{
|
||||
osgText::Text* text = new osgText::Text;
|
||||
geode->addDrawable( text );
|
||||
|
||||
text->setFont(timesFont);
|
||||
text->setText("And add an osg::ModelViewMatrix set to ABSOLUTE to ensure\nit remains independent from any external model view matrices.");
|
||||
text->setPosition(position);
|
||||
|
||||
position += delta;
|
||||
}
|
||||
|
||||
// create the hud.
|
||||
osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
|
||||
modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
|
||||
modelview_abs->setMatrix(osg::Matrix::identity());
|
||||
modelview_abs->addChild(geode);
|
||||
|
||||
osg::Projection* projection = new osg::Projection;
|
||||
projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
|
||||
projection->addChild(modelview_abs);
|
||||
|
||||
return projection;
|
||||
|
||||
}
|
||||
|
||||
struct MyCallback : public osg::NodeCallback
|
||||
{
|
||||
|
||||
MyCallback(const std::string& str):_message(str) {}
|
||||
|
||||
virtual void operator() (osg::Node* node,osg::NodeVisitor* nv)
|
||||
{
|
||||
std::cout<<"In my callback '"<<_message<<"'"<<std::endl;
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
std::string _message;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// make sure the root node is group so we can add extra nodes to it.
|
||||
osg::Group* group = dynamic_cast<osg::Group*>(rootnode);
|
||||
if (!group)
|
||||
{
|
||||
group = new osg::Group;
|
||||
group->addChild(rootnode);
|
||||
rootnode = group;
|
||||
}
|
||||
|
||||
// add the HUD subgraph.
|
||||
group->addChild(createHUD());
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
TestManipulator.cpp\
|
||||
osgimpostor.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgimpostor
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgimpostor.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgimpostor
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,382 +0,0 @@
|
||||
#include "TestManipulator.h"
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgGA;
|
||||
|
||||
TestManipulator::TestManipulator()
|
||||
{
|
||||
_modelScale = 0.01f;
|
||||
_minimumZoomScale = 0.05f;
|
||||
_thrown = false;
|
||||
|
||||
_distance = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
TestManipulator::~TestManipulator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TestManipulator::setNode(osg::Node* node)
|
||||
{
|
||||
_node = node;
|
||||
if (_node.get())
|
||||
{
|
||||
const osg::BoundingSphere& boundingSphere=_node->getBound();
|
||||
_modelScale = boundingSphere._radius;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const osg::Node* TestManipulator::getNode() const
|
||||
{
|
||||
return _node.get();
|
||||
}
|
||||
|
||||
|
||||
osg::Node* TestManipulator::getNode()
|
||||
{
|
||||
return _node.get();
|
||||
}
|
||||
|
||||
|
||||
/*ea*/
|
||||
void TestManipulator::home(const GUIEventAdapter& ,GUIActionAdapter& us)
|
||||
{
|
||||
if(_node.get() && _camera.get())
|
||||
{
|
||||
|
||||
const osg::BoundingSphere& boundingSphere=_node->getBound();
|
||||
|
||||
_camera->setView(boundingSphere.center()+osg::Vec3(0.0f, 0.0f, 20.0f),
|
||||
boundingSphere.center()+osg::Vec3(0.0f, 1.0f, 20.0f),
|
||||
osg::Vec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
computeLocalDataFromCamera();
|
||||
|
||||
us.requestRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
|
||||
{
|
||||
flushMouseEventStack();
|
||||
|
||||
computeLocalDataFromCamera();
|
||||
}
|
||||
|
||||
bool TestManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
|
||||
{
|
||||
if(!_camera.get()) return false;
|
||||
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case(GUIEventAdapter::PUSH):
|
||||
{
|
||||
flushMouseEventStack();
|
||||
addMouseEvent(ea);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
_thrown = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::RELEASE):
|
||||
{
|
||||
if (ea.getButtonMask()==0)
|
||||
{
|
||||
|
||||
if (isMouseMoving())
|
||||
{
|
||||
if (calcMovement())
|
||||
{
|
||||
us.requestRedraw();
|
||||
us.requestContinuousUpdate(true);
|
||||
_thrown = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flushMouseEventStack();
|
||||
addMouseEvent(ea);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
_thrown = false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
flushMouseEventStack();
|
||||
addMouseEvent(ea);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
_thrown = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::DRAG):
|
||||
{
|
||||
addMouseEvent(ea);
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
_thrown = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::MOVE):
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
case(GUIEventAdapter::KEYDOWN):
|
||||
if (ea.getKey()==' ')
|
||||
{
|
||||
flushMouseEventStack();
|
||||
_thrown = false;
|
||||
home(ea,us);
|
||||
us.requestRedraw();
|
||||
us.requestContinuousUpdate(false);
|
||||
return true;
|
||||
} else if (ea.getKey()=='+')
|
||||
{
|
||||
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()*1.25f);
|
||||
return true;
|
||||
}
|
||||
else if (ea.getKey()=='-')
|
||||
{
|
||||
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()/1.25f);
|
||||
return true;
|
||||
}
|
||||
// this is quick hack to test out othographic projection.
|
||||
// else if (ea.getKey()=='O')
|
||||
// {
|
||||
// float dist = _camera->getLookDistance();
|
||||
// _camera->setOrtho(-dist,dist,-dist,dist,-dist,dist);
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
case(GUIEventAdapter::FRAME):
|
||||
_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_LOOK_DISTANCE);
|
||||
if (_thrown)
|
||||
{
|
||||
if (calcMovement()) us.requestRedraw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TestManipulator::isMouseMoving()
|
||||
{
|
||||
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
|
||||
|
||||
static const float velocity = 100.0f;
|
||||
|
||||
float dx = _ga_t0->getX()-_ga_t1->getX();
|
||||
float dy = _ga_t0->getY()-_ga_t1->getY();
|
||||
float len = sqrtf(dx*dx+dy*dy);
|
||||
float dt = _ga_t0->time()-_ga_t1->time();
|
||||
|
||||
return (len>dt*velocity);
|
||||
}
|
||||
|
||||
|
||||
void TestManipulator::flushMouseEventStack()
|
||||
{
|
||||
_ga_t1 = NULL;
|
||||
_ga_t0 = NULL;
|
||||
}
|
||||
|
||||
|
||||
void TestManipulator::addMouseEvent(const GUIEventAdapter& ea)
|
||||
{
|
||||
_ga_t1 = _ga_t0;
|
||||
_ga_t0 = &ea;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TestManipulator::computeLocalDataFromCamera()
|
||||
{
|
||||
// maths from gluLookAt/osg::Matrix::makeLookAt
|
||||
osg::Vec3 f(_camera->getCenterPoint()-_camera->getEyePoint());
|
||||
f.normalize();
|
||||
osg::Vec3 s(f^_camera->getUpVector());
|
||||
s.normalize();
|
||||
osg::Vec3 u(s^f);
|
||||
u.normalize();
|
||||
|
||||
osg::Matrix rotation_matrix(s[0], u[0], -f[0], 0.0f,
|
||||
s[1], u[1], -f[1], 0.0f,
|
||||
s[2], u[2], -f[2], 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
_center = _camera->getCenterPoint();
|
||||
_distance = _camera->getLookDistance();
|
||||
_rotation.set(rotation_matrix);
|
||||
_rotation = _rotation.inverse();
|
||||
|
||||
}
|
||||
|
||||
void TestManipulator::computeCameraFromLocalData()
|
||||
{
|
||||
osg::Matrix new_rotation;
|
||||
new_rotation.makeRotate(_rotation);
|
||||
|
||||
osg::Vec3 up = osg::Vec3(0.0f,1.0f,0.0) * new_rotation;
|
||||
osg::Vec3 eye = (osg::Vec3(0.0f,0.0f,_distance) * new_rotation) + _center;
|
||||
|
||||
_camera->setLookAt(eye,_center,up);
|
||||
}
|
||||
|
||||
|
||||
bool TestManipulator::calcMovement()
|
||||
{
|
||||
|
||||
// return if less then two events have been added.
|
||||
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
|
||||
|
||||
float dx = _ga_t0->getX()-_ga_t1->getX();
|
||||
float dy = _ga_t0->getY()-_ga_t1->getY();
|
||||
|
||||
|
||||
// return if there is no movement.
|
||||
if (dx==0 && dy==0) return false;
|
||||
|
||||
unsigned int buttonMask = _ga_t1->getButtonMask();
|
||||
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
|
||||
{
|
||||
|
||||
// rotate camera.
|
||||
|
||||
float rx0 = (_ga_t0->getXmax()-_ga_t0->getXmin())/2.0f;
|
||||
|
||||
osg::Quat new_rotate;
|
||||
float xRot = dx / rx0;
|
||||
new_rotate.makeRotate(xRot / 5.0f, osg::Vec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
_rotation = _rotation*new_rotate;
|
||||
|
||||
computeCameraFromLocalData();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
|
||||
{
|
||||
|
||||
// pan model.
|
||||
|
||||
osg::Vec3 dv = osg::Vec3(0.0f, 0.0f, 1.0f) * dy;
|
||||
|
||||
_center += dv;
|
||||
|
||||
computeCameraFromLocalData();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
|
||||
{
|
||||
|
||||
osg::Vec3 uv = _camera->getUpVector();
|
||||
osg::Vec3 sv = _camera->getSideVector();
|
||||
osg::Vec3 fv = uv ^ sv;
|
||||
osg::Vec3 dv = fv*dy-sv*dx;
|
||||
|
||||
_center += dv;
|
||||
computeCameraFromLocalData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This size should really be based on the distance from the center of
|
||||
* rotation to the point on the object underneath the mouse. That
|
||||
* point would then track the mouse as closely as possible. This is a
|
||||
* simple example, though, so that is left as an Exercise for the
|
||||
* Programmer.
|
||||
*/
|
||||
const float TRACKBALLSIZE = 0.8f;
|
||||
|
||||
/*
|
||||
* Ok, simulate a track-ball. Project the points onto the virtual
|
||||
* trackball, then figure out the axis of rotation, which is the cross
|
||||
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
|
||||
* Note: This is a deformed trackball-- is a trackball in the center,
|
||||
* but is deformed into a hyperbolic sheet of rotation away from the
|
||||
* center. This particular function was chosen after trying out
|
||||
* several variations.
|
||||
*
|
||||
* It is assumed that the arguments to this routine are in the range
|
||||
* (-1.0 ... 1.0)
|
||||
*/
|
||||
void TestManipulator::trackball(osg::Vec3& axis,float& angle, float p1x, float p1y, float p2x, float p2y)
|
||||
{
|
||||
/*
|
||||
* First, figure out z-coordinates for projection of P1 and P2 to
|
||||
* deformed sphere
|
||||
*/
|
||||
|
||||
osg::Vec3 uv = _camera->getUpVector();
|
||||
osg::Vec3 sv = _camera->getSideVector();
|
||||
osg::Vec3 lv = _camera->getLookVector();
|
||||
|
||||
osg::Vec3 p1 = sv*p1x+uv*p1y-lv*tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y);
|
||||
osg::Vec3 p2 = sv*p2x+uv*p2y-lv*tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y);
|
||||
|
||||
/*
|
||||
* Now, we want the cross product of P1 and P2
|
||||
*/
|
||||
|
||||
axis = p2^p1;
|
||||
axis.normalize();
|
||||
|
||||
/*
|
||||
* Figure out how much to rotate around that axis.
|
||||
*/
|
||||
float t = (p2-p1).length() / (2.0*TRACKBALLSIZE);
|
||||
|
||||
/*
|
||||
* Avoid problems with out-of-control values...
|
||||
*/
|
||||
if (t > 1.0) t = 1.0;
|
||||
if (t < -1.0) t = -1.0;
|
||||
angle = inRadians(asin(t));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
|
||||
* if we are away from the center of the sphere.
|
||||
*/
|
||||
float TestManipulator::tb_project_to_sphere(float r, float x, float y)
|
||||
{
|
||||
float d, t, z;
|
||||
|
||||
d = sqrt(x*x + y*y);
|
||||
/* Inside sphere */
|
||||
if (d < r * 0.70710678118654752440)
|
||||
{
|
||||
z = sqrt(r*r - d*d);
|
||||
} /* On hyperbola */
|
||||
else
|
||||
{
|
||||
t = r / 1.41421356237309504880;
|
||||
z = t*t / d;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
|
||||
//Distributed under the terms of the GNU Library General Public License (LGPL)
|
||||
//as published by the Free Software Foundation.
|
||||
|
||||
#ifndef OSGGA_TESTMANIPULATOR
|
||||
#define OSGGA_TESTMANIPULATOR 1
|
||||
|
||||
#include <osgGA/CameraManipulator>
|
||||
|
||||
namespace osgGA{
|
||||
|
||||
class TestManipulator : public CameraManipulator
|
||||
{
|
||||
public:
|
||||
|
||||
TestManipulator();
|
||||
virtual ~TestManipulator();
|
||||
|
||||
/** Attach a node to the manipulator.
|
||||
Automatically detaches previously attached node.
|
||||
setNode(NULL) detaches previously nodes.
|
||||
Is ignored by manipulators which do not require a reference model.*/
|
||||
virtual void setNode(osg::Node*);
|
||||
|
||||
/** Return node if attached.*/
|
||||
virtual const osg::Node* getNode() const;
|
||||
|
||||
/** Return node if attached.*/
|
||||
virtual osg::Node* getNode();
|
||||
|
||||
/** Move the camera to the default position.
|
||||
May be ignored by manipulators if home functionality is not appropriate.*/
|
||||
virtual void home(const GUIEventAdapter& ea,GUIActionAdapter& us);
|
||||
|
||||
/** Start/restart the manipulator.*/
|
||||
virtual void init(const GUIEventAdapter& ea,GUIActionAdapter& us);
|
||||
|
||||
|
||||
/** handle events, return true if handled, false otherwise.*/
|
||||
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
|
||||
|
||||
private:
|
||||
|
||||
/** Reset the internal GUIEvent stack.*/
|
||||
void flushMouseEventStack();
|
||||
/** Add the current mouse GUIEvent to internal stack.*/
|
||||
void addMouseEvent(const GUIEventAdapter& ea);
|
||||
|
||||
void computeLocalDataFromCamera();
|
||||
|
||||
void computeCameraFromLocalData();
|
||||
|
||||
/** For the give mouse movement calculate the movement of the camera.
|
||||
Return true is camera has moved and a redraw is required.*/
|
||||
bool calcMovement();
|
||||
|
||||
void trackball(osg::Vec3& axis,float& angle, float p1x, float p1y, float p2x, float p2y);
|
||||
float tb_project_to_sphere(float r, float x, float y);
|
||||
|
||||
|
||||
/** Check the speed at which the mouse is moving.
|
||||
If speed is below a threshold then return false, otherwise return true.*/
|
||||
bool isMouseMoving();
|
||||
|
||||
// Internal event stack comprising last three mouse events.
|
||||
osg::ref_ptr<const GUIEventAdapter> _ga_t1;
|
||||
osg::ref_ptr<const GUIEventAdapter> _ga_t0;
|
||||
|
||||
osg::ref_ptr<osg::Node> _node;
|
||||
|
||||
float _modelScale;
|
||||
float _minimumZoomScale;
|
||||
|
||||
bool _thrown;
|
||||
|
||||
osg::Vec3 _center;
|
||||
osg::Quat _rotation;
|
||||
float _distance;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,304 +0,0 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Impostor>
|
||||
#include <osg/Material>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Quat>
|
||||
|
||||
#include <osgUtil/InsertImpostorsVisitor>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include "TestManipulator.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
// container storing all house nodes
|
||||
typedef osg::ref_ptr<osg::Node> NodePtr;
|
||||
typedef std::list<NodePtr> NodeContainer;
|
||||
typedef NodeContainer::iterator NodeIterator;
|
||||
|
||||
NodeContainer nodes;
|
||||
|
||||
//
|
||||
osg::Group * Root = 0;
|
||||
|
||||
const int HOUSES_SIZE = 25000; // total number of houses
|
||||
double XDim = 5000.0f; // area dimension +/- XDim
|
||||
double ZDim = 5000.0f; // area dimension +/- YDim
|
||||
|
||||
int GridX = 20; // number of grids in x direction
|
||||
int GridY = 20; // number of grids in y direction
|
||||
|
||||
bool UseImpostor = true; // use impostor (or do not use)
|
||||
|
||||
float Threshold = 3000.0f; // distance where impostor are shown
|
||||
|
||||
// create houses and store nodes in container
|
||||
void CreateHouses()
|
||||
{
|
||||
int i;
|
||||
|
||||
GLubyte indices[48] = {
|
||||
0, 2, 1,
|
||||
3, 2, 0,
|
||||
0, 4, 7,
|
||||
7, 3, 0,
|
||||
0, 1, 5,
|
||||
5, 4, 0,
|
||||
1, 6, 5,
|
||||
2, 6, 1,
|
||||
2, 3, 7,
|
||||
2, 7, 6,
|
||||
4, 8, 7,
|
||||
5, 6, 9,
|
||||
4, 5, 8,
|
||||
8, 5, 9,
|
||||
6, 7, 8,
|
||||
8, 9, 6
|
||||
};
|
||||
|
||||
// use the same color, normal and indices for all houses.
|
||||
osg::Vec4Array* colors = new osg::Vec4Array(1);
|
||||
(*colors)[0] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// normals
|
||||
osg::Vec3Array * normals = new osg::Vec3Array(16);
|
||||
(*normals)[0] = osg::Vec3( 0.0f, -0.0f, -1.0f);
|
||||
(*normals)[1] = osg::Vec3( 0.0f, -0.0f, -1.0f);
|
||||
(*normals)[2] = osg::Vec3( 0.0f, -1.0f, 0.0f);
|
||||
(*normals)[3] = osg::Vec3( 0.0f, -1.0f, 0.0f);
|
||||
(*normals)[4] = osg::Vec3( 1.0f, -0.0f, 0.0f);
|
||||
(*normals)[5] = osg::Vec3( 1.0f, -0.0f, 0.0f);
|
||||
(*normals)[6] = osg::Vec3( 0.0f, 1.0f, 0.0f);
|
||||
(*normals)[7] = osg::Vec3( 0.0f, 1.0f, 0.0f);
|
||||
(*normals)[8] = osg::Vec3(-1.0f, -0.0f, 0.0f);
|
||||
(*normals)[9] = osg::Vec3(-1.0f, -0.0f, 0.0f);
|
||||
(*normals)[10] = osg::Vec3( 0.0f, -0.928477f, 0.371391f);
|
||||
(*normals)[11] = osg::Vec3( 0.0f, 0.928477f, 0.371391f);
|
||||
(*normals)[12] = osg::Vec3( 0.707107f, 0.0f, 0.707107f);
|
||||
(*normals)[13] = osg::Vec3( 0.707107f, 0.0f, 0.707107f);
|
||||
(*normals)[14] = osg::Vec3(-0.707107f, 0.0f, 0.707107f);
|
||||
(*normals)[15] = osg::Vec3(-0.707107f, 0.0f, 0.707107f);
|
||||
|
||||
// coordIndices
|
||||
osg::UByteArray* coordIndices = new osg::UByteArray(48,indices);
|
||||
|
||||
// share the primtive set.
|
||||
osg::PrimitiveSet* primitives = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,48);
|
||||
|
||||
for (int q = 0; q < HOUSES_SIZE; q++)
|
||||
{
|
||||
float xPos = ((static_cast<double> (rand()) /
|
||||
static_cast<double> (RAND_MAX))
|
||||
* 2.0 * XDim) - XDim;
|
||||
|
||||
float yPos = ((static_cast<double> (rand()) /
|
||||
static_cast<double> (RAND_MAX))
|
||||
* 2 * ZDim) - ZDim;
|
||||
|
||||
float scale = 10.0f;
|
||||
|
||||
osg::Vec3 offset(xPos,yPos,0.0f);
|
||||
|
||||
// coords
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(10);
|
||||
(*coords)[0] = osg::Vec3( 0.5f, -0.7f, 0.0f);
|
||||
(*coords)[1] = osg::Vec3( 0.5f, 0.7f, 0.0f);
|
||||
(*coords)[2] = osg::Vec3(-0.5f, 0.7f, 0.0f);
|
||||
(*coords)[3] = osg::Vec3(-0.5f, -0.7f, 0.0f);
|
||||
(*coords)[4] = osg::Vec3( 0.5f, -0.7f, 1.0f);
|
||||
(*coords)[5] = osg::Vec3( 0.5f, 0.7f, 1.0f);
|
||||
(*coords)[6] = osg::Vec3(-0.5f, 0.7f, 1.0f);
|
||||
(*coords)[7] = osg::Vec3(-0.5f, -0.7f, 1.0f);
|
||||
(*coords)[8] = osg::Vec3( 0.0f, -0.5f, 1.5f);
|
||||
(*coords)[9] = osg::Vec3( 0.0f, 0.5f, 1.5f);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
(*coords)[i] = (*coords)[i] * scale + offset;
|
||||
}
|
||||
|
||||
|
||||
// create geometry
|
||||
osg::Geometry * geometry = new osg::Geometry();
|
||||
|
||||
geometry->addPrimitiveSet(primitives);
|
||||
|
||||
geometry->setVertexArray(coords);
|
||||
geometry->setVertexIndices(coordIndices);
|
||||
|
||||
geometry->setColorArray(colors);
|
||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geometry->setNormalArray(normals);
|
||||
geometry->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
||||
|
||||
osg::Geode * geode = new osg::Geode();
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
nodes.push_back(geode);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutAsGrid()
|
||||
{
|
||||
// calculate bounding box
|
||||
osg::BoundingBox bbox;
|
||||
for (NodeIterator node = nodes.begin(); node != nodes.end(); ++node)
|
||||
bbox.expandBy((*node)->getBound());
|
||||
|
||||
// setup grid information
|
||||
osg::Group ** groups = new osg::Group*[GridX * GridY];
|
||||
int i;
|
||||
for (i = 0; i < GridX * GridY; i++)
|
||||
groups[i] = new osg::Group();
|
||||
|
||||
float xGridStart = bbox.xMin();
|
||||
float xGridSize = (bbox.xMax() - bbox.xMin()) / GridX;
|
||||
|
||||
float yGridStart = bbox.yMin();
|
||||
float yGridSize = (bbox.yMax() - bbox.yMin()) / GridY;
|
||||
|
||||
// arrange buildings into right grid
|
||||
for (NodeIterator nodeIter = nodes.begin(); nodeIter != nodes.end(); ++nodeIter)
|
||||
{
|
||||
osg::Node * node = nodeIter->get();
|
||||
osg::Vec3 center = node->getBound().center();
|
||||
|
||||
int x = (int)floor((center.x() - xGridStart) / xGridSize);
|
||||
int z = (int)floor((center.y() - yGridStart) / yGridSize);
|
||||
|
||||
groups[z * GridX + x]->addChild(node);
|
||||
}
|
||||
|
||||
// add nodes to building root
|
||||
for (i = 0; i < GridX * GridY; i++)
|
||||
{
|
||||
osg::StateSet * stateset = new osg::StateSet();
|
||||
|
||||
osg::Material * material = new osg::Material();
|
||||
osg::Vec4 color = osg::Vec4(
|
||||
0.5f + (static_cast<double> (rand()) / (2.0*static_cast<double> (RAND_MAX))),
|
||||
0.5f + (static_cast<double> (rand()) / (2.0*static_cast<double> (RAND_MAX))),
|
||||
0.5f + (static_cast<double> (rand()) / ( 2.0*static_cast<double>(RAND_MAX))),
|
||||
1.0f);
|
||||
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK, color);
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK, color);
|
||||
stateset->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||
|
||||
groups[i]->setStateSet(stateset);
|
||||
|
||||
if (UseImpostor)
|
||||
{
|
||||
osg::Impostor * impostor = new osg::Impostor();
|
||||
impostor->setImpostorThreshold(static_cast<float> (Threshold));
|
||||
impostor->addChild(groups[i]);
|
||||
impostor->setRange(0, 0.0f, 1e7f);
|
||||
impostor->setCenter(groups[i]->getBound().center());
|
||||
Root->addChild(impostor);
|
||||
}
|
||||
else
|
||||
{
|
||||
Root->addChild(groups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] groups;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
glutInit( &argc, argv );
|
||||
|
||||
osgGLUT::Viewer viewer;
|
||||
viewer.setWindowTitle(argv[0]);
|
||||
|
||||
// create the commandline args.
|
||||
std::vector<std::string> arguments;
|
||||
for(int i=1;i<argc;++i) arguments.push_back(argv[i]);
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* model = osgDB::readNodeFiles(arguments);
|
||||
if (model)
|
||||
{
|
||||
// the osgUtil::InsertImpostorsVisitor used lower down to insert impostors
|
||||
// only operators on subclass of Group's, if the model top node is not
|
||||
// a group then it won't be able to insert an impostor. We therefore
|
||||
// manually insert an impostor above the model.
|
||||
if (dynamic_cast<osg::Group*>(model)==0)
|
||||
{
|
||||
const osg::BoundingSphere& bs = model->getBound();
|
||||
if (bs.valid())
|
||||
{
|
||||
|
||||
osg::Impostor* impostor = new osg::Impostor;
|
||||
|
||||
// standard LOD settings
|
||||
impostor->addChild(model);
|
||||
impostor->setRange(0,0.0f,1e7f);
|
||||
impostor->setCenter(bs.center());
|
||||
|
||||
// impostor specfic settings.
|
||||
impostor->setImpostorThresholdToBound(5.0f);
|
||||
|
||||
model = impostor;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// we insert an impostor node above the model, so we keep a handle
|
||||
// on the rootnode of the model, the is required since the
|
||||
// InsertImpostorsVisitor can add a new root in automatically and
|
||||
// we would know about it, other than by following the parent path
|
||||
// up from model. This is really what should be done, but I'll pass
|
||||
// on it right now as it requires a getRoots() method to be added to
|
||||
// osg::Node, and we're about to make a release so no new features!
|
||||
osg::Group* rootnode = new osg::Group;
|
||||
rootnode->addChild(model);
|
||||
|
||||
|
||||
// now insert impostors in the model using the InsertImpostorsVisitor.
|
||||
osgUtil::InsertImpostorsVisitor ov;
|
||||
|
||||
// traverse the model and collect all osg::Group's and osg::LOD's.
|
||||
// however, don't traverse the rootnode since we want to keep it as
|
||||
// the start of traversal, otherwise the insertImpostor could insert
|
||||
// and Impostor above the current root, making it nolonger a root!
|
||||
model->accept(ov);
|
||||
|
||||
// insert the Impostors above groups and LOD's
|
||||
ov.insertImpostors();
|
||||
}
|
||||
else
|
||||
{
|
||||
// no user model so we'll create our own world.
|
||||
model = Root = new osg::Group();
|
||||
CreateHouses();
|
||||
LayoutAsGrid();
|
||||
}
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport(model);
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TestManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglight.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglight
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglight.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglight
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,358 +0,0 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Node>
|
||||
|
||||
#include <osg/Light>
|
||||
#include <osg/LightSource>
|
||||
#include <osg/StateAttribute>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Point>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
// callback to make the loaded model oscilate up and down.
|
||||
class ModelTransformCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
ModelTransformCallback(const osg::BoundingSphere& bs)
|
||||
{
|
||||
_firstTime = 0.0;
|
||||
_period = 4.0f;
|
||||
_range = bs.radius()*0.5f;
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
|
||||
const osg::FrameStamp* frameStamp = nv->getFrameStamp();
|
||||
if (pat && frameStamp)
|
||||
{
|
||||
if (_firstTime==0.0)
|
||||
{
|
||||
_firstTime = frameStamp->getReferenceTime();
|
||||
}
|
||||
|
||||
double phase = (frameStamp->getReferenceTime()-_firstTime)/_period;
|
||||
phase -= floor(phase);
|
||||
phase *= (2.0 * osg::PI);
|
||||
|
||||
osg::Quat rotation;
|
||||
rotation.makeRotate(phase,1.0f,1.0f,1.0f);
|
||||
|
||||
pat->setAttitude(rotation);
|
||||
|
||||
pat->setPosition(osg::Vec3(0.0f,0.0f,sin(phase))*_range);
|
||||
}
|
||||
|
||||
// must traverse the Node's subgraph
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
double _firstTime;
|
||||
double _period;
|
||||
double _range;
|
||||
|
||||
};
|
||||
|
||||
|
||||
osg::Node* createLights(osg::BoundingBox& bb,osg::StateSet* rootStateSet)
|
||||
{
|
||||
osg::Group* lightGroup = new osg::Group;
|
||||
|
||||
float modelSize = bb.radius();
|
||||
|
||||
// create a spot light.
|
||||
osg::Light* myLight1 = new osg::Light;
|
||||
myLight1->setLightNum(0);
|
||||
myLight1->setPosition(osg::Vec4(bb.corner(4),1.0f));
|
||||
myLight1->setAmbient(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
|
||||
myLight1->setDiffuse(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
|
||||
myLight1->setSpotCutoff(20.0f);
|
||||
myLight1->setSpotExponent(50.0f);
|
||||
myLight1->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));
|
||||
|
||||
osg::LightSource* lightS1 = new osg::LightSource;
|
||||
lightS1->setLight(myLight1);
|
||||
lightS1->setLocalStateSetModes(osg::StateAttribute::ON);
|
||||
|
||||
lightS1->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
|
||||
lightGroup->addChild(lightS1);
|
||||
|
||||
|
||||
// create a local light.
|
||||
osg::Light* myLight2 = new osg::Light;
|
||||
myLight2->setLightNum(1);
|
||||
myLight2->setPosition(osg::Vec4(0.0,0.0,0.0,1.0f));
|
||||
myLight2->setAmbient(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
|
||||
myLight2->setDiffuse(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
|
||||
myLight2->setConstantAttenuation(1.0f);
|
||||
myLight2->setLinearAttenuation(2.0f/modelSize);
|
||||
myLight2->setQuadraticAttenuation(2.0f/osg::square(modelSize));
|
||||
|
||||
osg::LightSource* lightS2 = new osg::LightSource;
|
||||
lightS2->setLight(myLight2);
|
||||
lightS2->setLocalStateSetModes(osg::StateAttribute::ON);
|
||||
|
||||
lightS2->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
|
||||
|
||||
osg::MatrixTransform* mt = new osg::MatrixTransform();
|
||||
{
|
||||
// set up the animation path
|
||||
osg::AnimationPath* animationPath = new osg::AnimationPath;
|
||||
animationPath->insert(0.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
|
||||
animationPath->insert(1.0,osg::AnimationPath::ControlPoint(bb.corner(1)));
|
||||
animationPath->insert(2.0,osg::AnimationPath::ControlPoint(bb.corner(2)));
|
||||
animationPath->insert(3.0,osg::AnimationPath::ControlPoint(bb.corner(3)));
|
||||
animationPath->insert(4.0,osg::AnimationPath::ControlPoint(bb.corner(4)));
|
||||
animationPath->insert(5.0,osg::AnimationPath::ControlPoint(bb.corner(5)));
|
||||
animationPath->insert(6.0,osg::AnimationPath::ControlPoint(bb.corner(6)));
|
||||
animationPath->insert(7.0,osg::AnimationPath::ControlPoint(bb.corner(7)));
|
||||
animationPath->insert(8.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
|
||||
animationPath->setLoopMode(osg::AnimationPath::SWING);
|
||||
|
||||
mt->setUpdateCallback(new osg::AnimationPathCallback(animationPath));
|
||||
}
|
||||
|
||||
// create marker for point light.
|
||||
osg::Geometry* marker = new osg::Geometry;
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(osg::Vec3(0.0,0.0,0.0));
|
||||
marker->setVertexArray(vertices);
|
||||
marker->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,1));
|
||||
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
osg::Point* point = new osg::Point;
|
||||
point->setSize(4.0f);
|
||||
stateset->setAttribute(point);
|
||||
|
||||
marker->setStateSet(stateset);
|
||||
|
||||
osg::Geode* markerGeode = new osg::Geode;
|
||||
markerGeode->addDrawable(marker);
|
||||
|
||||
mt->addChild(lightS2);
|
||||
mt->addChild(markerGeode);
|
||||
|
||||
lightGroup->addChild(mt);
|
||||
|
||||
return lightGroup;
|
||||
}
|
||||
|
||||
osg::Geometry* createWall(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,osg::StateSet* stateset)
|
||||
{
|
||||
|
||||
// create a drawable for occluder.
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
geom->setStateSet(stateset);
|
||||
|
||||
unsigned int noXSteps = 100;
|
||||
unsigned int noYSteps = 100;
|
||||
|
||||
osg::Vec3Array* coords = new osg::Vec3Array;
|
||||
coords->reserve(noXSteps*noYSteps);
|
||||
|
||||
|
||||
osg::Vec3 dx = (v2-v1)/((float)noXSteps-1.0f);
|
||||
osg::Vec3 dy = (v3-v1)/((float)noYSteps-1.0f);
|
||||
|
||||
unsigned int row;
|
||||
osg::Vec3 vRowStart = v1;
|
||||
for(row=0;row<noYSteps;++row)
|
||||
{
|
||||
osg::Vec3 v = vRowStart;
|
||||
for(unsigned int col=0;col<noXSteps;++col)
|
||||
{
|
||||
coords->push_back(v);
|
||||
v += dx;
|
||||
}
|
||||
vRowStart+=dy;
|
||||
}
|
||||
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array(1);
|
||||
(*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
|
||||
geom->setColorArray(colors);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
for(row=0;row<noYSteps-1;++row)
|
||||
{
|
||||
osg::DrawElementsUShort* quadstrip = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
|
||||
quadstrip->reserve(noXSteps*2);
|
||||
for(unsigned int col=0;col<noXSteps;++col)
|
||||
{
|
||||
quadstrip->push_back((row+1)*noXSteps+col);
|
||||
quadstrip->push_back(row*noXSteps+col);
|
||||
}
|
||||
geom->addPrimitiveSet(quadstrip);
|
||||
}
|
||||
|
||||
// create the normals.
|
||||
osgUtil::SmoothingVisitor::smooth(*geom);
|
||||
|
||||
return geom;
|
||||
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createRoom(osg::Node* loadedModel)
|
||||
{
|
||||
// default scale for this model.
|
||||
osg::BoundingSphere bs(osg::Vec3(0.0f,0.0f,0.0f),1.0f);
|
||||
|
||||
osg::Group* root = new osg::Group;
|
||||
|
||||
if (loadedModel)
|
||||
{
|
||||
const osg::BoundingSphere& loaded_bs = loadedModel->getBound();
|
||||
|
||||
osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform();
|
||||
pat->setPivotPoint(loaded_bs.center());
|
||||
|
||||
pat->setUpdateCallback(new ModelTransformCallback(loaded_bs));
|
||||
pat->addChild(loadedModel);
|
||||
|
||||
bs = pat->getBound();
|
||||
|
||||
root->addChild(pat);
|
||||
|
||||
}
|
||||
|
||||
bs.radius()*=1.5f;
|
||||
|
||||
// create a bounding box, which we'll use to size the room.
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
|
||||
// create statesets.
|
||||
osg::StateSet* rootStateSet = new osg::StateSet;
|
||||
root->setStateSet(rootStateSet);
|
||||
|
||||
osg::StateSet* wall = new osg::StateSet;
|
||||
wall->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
osg::StateSet* floor = new osg::StateSet;
|
||||
floor->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
osg::StateSet* roof = new osg::StateSet;
|
||||
roof->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
|
||||
// create front side.
|
||||
geode->addDrawable(createWall(bb.corner(0),
|
||||
bb.corner(4),
|
||||
bb.corner(1),
|
||||
wall));
|
||||
|
||||
// right side
|
||||
geode->addDrawable(createWall(bb.corner(1),
|
||||
bb.corner(5),
|
||||
bb.corner(3),
|
||||
wall));
|
||||
|
||||
// left side
|
||||
geode->addDrawable(createWall(bb.corner(2),
|
||||
bb.corner(6),
|
||||
bb.corner(0),
|
||||
wall));
|
||||
// back side
|
||||
geode->addDrawable(createWall(bb.corner(3),
|
||||
bb.corner(7),
|
||||
bb.corner(2),
|
||||
wall));
|
||||
|
||||
// floor
|
||||
geode->addDrawable(createWall(bb.corner(0),
|
||||
bb.corner(1),
|
||||
bb.corner(2),
|
||||
floor));
|
||||
|
||||
// roof
|
||||
geode->addDrawable(createWall(bb.corner(6),
|
||||
bb.corner(7),
|
||||
bb.corner(4),
|
||||
roof));
|
||||
|
||||
root->addChild(geode);
|
||||
|
||||
root->addChild(createLights(bb,rootStateSet));
|
||||
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
|
||||
// create a room made of foor walls, a floor, a roof, and swinging light fitting.
|
||||
osg::Node* rootnode = createRoom(loadedModel);
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
osgUtil::SceneView* sv = viewer.getViewportSceneView(0);
|
||||
if (sv)
|
||||
{
|
||||
// switch off small feature culling to prevent the light points from being culled.
|
||||
sv->setCullingMode( sv->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
|
||||
sv->setCullingMode( 0);
|
||||
}
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglightpoint.cpp\
|
||||
|
||||
LIBS += -losgSim $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglightpoint
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglightpoint.cpp\
|
||||
|
||||
LIBS += -losgSim $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglightpoint
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,178 +0,0 @@
|
||||
#include <osg/GL>
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <osgSim/LightPointNode>
|
||||
|
||||
|
||||
#define INTERPOLATE(member) lp.member = start.member*rstart + end.member*rend;
|
||||
|
||||
void addToLightPointNode(osgSim::LightPointNode& lpn,osgSim::LightPoint& start,osgSim::LightPoint& end,unsigned int noSteps)
|
||||
{
|
||||
if (noSteps<=1)
|
||||
{
|
||||
lpn.addLightPoint(start);
|
||||
return;
|
||||
}
|
||||
|
||||
float rend = 0.0f;
|
||||
float rdelta = 1.0f/((float)noSteps-1.0f);
|
||||
|
||||
lpn._lightPointList.reserve(noSteps);
|
||||
|
||||
for(unsigned int i=0;i<noSteps;++i,rend+=rdelta)
|
||||
{
|
||||
float rstart = 1.0f-rend;
|
||||
osgSim::LightPoint lp(start);
|
||||
INTERPOLATE(_position)
|
||||
INTERPOLATE(_intensity);
|
||||
INTERPOLATE(_color);
|
||||
INTERPOLATE(_radius);
|
||||
//INTERPOLATE(_minPixelSize);
|
||||
//INTERPOLATE(_maxPixelSize);
|
||||
// INTERPOLATE(_maxVisibileDistance2);
|
||||
|
||||
lpn.addLightPoint(lp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef INTERPOLATE
|
||||
|
||||
osg::Node* createLightPointsDatabase()
|
||||
{
|
||||
osgSim::LightPoint start;
|
||||
osgSim::LightPoint end;
|
||||
|
||||
start._position.set(0.0f,0.0f,0.0f);
|
||||
start._color.set(1.0f,0.0f,0.0f,1.0f);
|
||||
|
||||
end._position.set(1000.0f,0.0f,0.0f);
|
||||
end._color.set(1.0f,1.0f,1.0f,1.0f);
|
||||
|
||||
osg::Transform* transform = new osg::Transform;
|
||||
|
||||
osg::Vec3 start_delta(0.0f,10.0f,0.0f);
|
||||
osg::Vec3 end_delta(0.0f,10.0f,1.0f);
|
||||
|
||||
int noStepsX = 100;
|
||||
int noStepsY = 100;
|
||||
|
||||
// osgSim::BlinkSequence* bs = new osgSim::BlinkSequence;
|
||||
// bs->addPulse(1.0,osg::Vec4(1.0f,0.0f,0.0f,1.0f));
|
||||
// bs->addPulse(0.5,osg::Vec4(0.0f,0.0f,0.0f,0.0f)); // off
|
||||
// bs->addPulse(1.5,osg::Vec4(1.0f,1.0f,0.0f,1.0f));
|
||||
// bs->addPulse(0.5,osg::Vec4(0.0f,0.0f,0.0f,0.0f)); // off
|
||||
// bs->addPulse(1.0,osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
// bs->addPulse(0.5,osg::Vec4(0.0f,0.0f,0.0f,0.0f)); // off
|
||||
|
||||
|
||||
// osgSim::Sector* sector = new osgSim::ConeSector(osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0),osg::inDegrees(45.0));
|
||||
// osgSim::Sector* sector = new osgSim::ElevationSector(-osg::inDegrees(45.0),osg::inDegrees(45.0),osg::inDegrees(45.0));
|
||||
// osgSim::Sector* sector = new osgSim::AzimSector(-osg::inDegrees(45.0),osg::inDegrees(45.0),osg::inDegrees(90.0));
|
||||
// osgSim::Sector* sector = new osgSim::AzimElevationSector(osg::inDegrees(180),osg::inDegrees(90), // azim range
|
||||
// osg::inDegrees(0.0),osg::inDegrees(90.0), // elevation range
|
||||
// osg::inDegrees(5.0));
|
||||
|
||||
for(int i=0;i<noStepsY;++i)
|
||||
{
|
||||
|
||||
// osgSim::BlinkSequence* local_bs = new osgSim::BlinkSequence(*bs);
|
||||
// local_bs->setSequenceGroup(new osgSim::BlinkSequence::SequenceGroup((double)i*0.1));
|
||||
// start._blinkSequence = local_bs;
|
||||
|
||||
// start._sector = sector;
|
||||
|
||||
osgSim::LightPointNode* lpn = new osgSim::LightPointNode;
|
||||
addToLightPointNode(*lpn,start,end,noStepsX);
|
||||
|
||||
start._position += start_delta;
|
||||
end._position += end_delta;
|
||||
|
||||
transform->addChild(lpn);
|
||||
}
|
||||
|
||||
osg::Group* group = new osg::Group;
|
||||
group->addChild(transform);
|
||||
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
osg::Group* rootnode = new osg::Group;
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
rootnode->addChild(osgDB::readNodeFiles(arguments));
|
||||
rootnode->addChild(createLightPointsDatabase());
|
||||
if (!rootnode)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglogo.cpp\
|
||||
|
||||
LIBS += -losgText $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglogo
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglogo.cpp\
|
||||
|
||||
LIBS += -losgText $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglogo
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,449 +0,0 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Material>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/ClearNode>
|
||||
|
||||
#include <osgUtil/Tesselator>
|
||||
#include <osgUtil/TransformCallback>
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <osgText/Text>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
static bool s_ProfessionalServices = false;
|
||||
|
||||
class MyBillboardTransform : public osg::PositionAttitudeTransform
|
||||
{
|
||||
public:
|
||||
|
||||
MyBillboardTransform():
|
||||
_axis(0.0f,0.0f,1.0f),
|
||||
_normal(0.0f,-1.0f,0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
|
||||
{
|
||||
osg::Quat billboardRotation;
|
||||
osgUtil::CullVisitor* cullvisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullvisitor)
|
||||
{
|
||||
osg::Vec3 eyevector = cullvisitor->getEyeLocal()-_position;
|
||||
eyevector.normalize();
|
||||
|
||||
osg::Vec3 side = _axis^_normal;
|
||||
side.normalize();
|
||||
|
||||
float angle = atan2(eyevector*_normal,eyevector*side);
|
||||
billboardRotation.makeRotate(osg::PI_2-angle,_axis);
|
||||
|
||||
}
|
||||
|
||||
|
||||
matrix.preMult(osg::Matrix::translate(-_pivotPoint)*
|
||||
osg::Matrix::rotate(_attitude)*
|
||||
osg::Matrix::rotate(billboardRotation)*
|
||||
osg::Matrix::translate(_position));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setAxis(const osg::Vec3& axis) { _axis = axis; }
|
||||
|
||||
void setNormal(const osg::Vec3& normal) { _normal = normal; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~MyBillboardTransform() {}
|
||||
|
||||
osg::Vec3 _axis;
|
||||
osg::Vec3 _normal;
|
||||
};
|
||||
|
||||
|
||||
osg::Geometry* createWing(const osg::Vec3& left, const osg::Vec3& nose, const osg::Vec3& right,float chordRatio,const osg::Vec4& color)
|
||||
{
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3 normal = (nose-right)^(left-nose);
|
||||
normal.normalize();
|
||||
|
||||
osg::Vec3 left_to_right = right-left;
|
||||
osg::Vec3 mid = (right+left)*0.5f;
|
||||
osg::Vec3 mid_to_nose = (nose-mid)*chordRatio*0.5f;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(left);
|
||||
//vertices->push_back(mid+mid_to_nose);
|
||||
|
||||
unsigned int noSteps = 40;
|
||||
for(unsigned int i=1;i<noSteps;++i)
|
||||
{
|
||||
float ratio = (float)i/(float)noSteps;
|
||||
vertices->push_back(left + left_to_right*ratio + mid_to_nose* (cosf((ratio-0.5f)*osg::PI*2.0f)+1.0f));
|
||||
}
|
||||
|
||||
vertices->push_back(right);
|
||||
vertices->push_back(nose);
|
||||
|
||||
geom->setVertexArray(vertices);
|
||||
|
||||
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(normal);
|
||||
geom->setNormalArray(normals);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
geom->setColorArray(colors);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,vertices->getNumElements()));
|
||||
|
||||
osgUtil::Tesselator tesselator;
|
||||
tesselator.retesselatePolygons(*geom);
|
||||
|
||||
return geom;
|
||||
|
||||
}
|
||||
|
||||
osg:: Node* createTextBelow(const osg::BoundingBox& bb)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
std::string font("fonts/arial.ttf");
|
||||
|
||||
osgText::Text* text = new osgText::Text;
|
||||
|
||||
text->setFont(font);
|
||||
text->setFontSize(64,64);
|
||||
text->setAlignment(osgText::Text::CENTER_CENTER);
|
||||
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||
text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
|
||||
text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
|
||||
text->setText("OpenSceneGraph");
|
||||
|
||||
geode->addDrawable( text );
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg:: Node* createTextLeft(const osg::BoundingBox& bb)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
|
||||
osg::StateSet* stateset = geode->getOrCreateStateSet();
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
|
||||
|
||||
//std::string font("fonts/times.ttf");
|
||||
std::string font("fonts/arial.ttf");
|
||||
|
||||
osgText::Text* text = new osgText::Text;
|
||||
|
||||
text->setFont(font);
|
||||
text->setFontSize(120,120);
|
||||
text->setAlignment(osgText::Text::RIGHT_CENTER);
|
||||
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||
text->setCharacterSize((bb.zMax()-bb.zMin())*0.8f);
|
||||
text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.3f));
|
||||
//text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's orignal OSG colour
|
||||
text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
|
||||
text->setText("OpenSceneGraph");
|
||||
|
||||
geode->addDrawable( text );
|
||||
|
||||
|
||||
if (s_ProfessionalServices)
|
||||
{
|
||||
//osgText::Text* subscript = new osgText::Text(new osgText::TextureFont(font,45));
|
||||
|
||||
osgText::Text* subscript = new osgText::Text;
|
||||
subscript->setFont(font);
|
||||
subscript->setText("Professional Services");
|
||||
subscript->setAlignment(osgText::Text::RIGHT_CENTER);
|
||||
subscript->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||
subscript->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin())*3.5f,-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.6f));
|
||||
subscript->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
|
||||
|
||||
geode->addDrawable( subscript );
|
||||
}
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg:: Node* createGlobe(const osg::BoundingBox& bb,float ratio)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
osg::StateSet* stateset = geode->getOrCreateStateSet();
|
||||
|
||||
osg::Image* image = osgDB::readImageFile("Images/land_shallow_topo_2048.jpg");
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
texture->setMaxAnisotropy(8);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
osg::Material* material = new osg::Material;
|
||||
stateset->setAttribute(material);
|
||||
|
||||
|
||||
// the globe
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(bb.center(),bb.radius()*ratio)));
|
||||
|
||||
|
||||
osg::MatrixTransform* xform = new osg::MatrixTransform;
|
||||
xform->setUpdateCallback(new osgUtil::TransformCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(30.0f)));
|
||||
xform->addChild(geode);
|
||||
|
||||
return xform;
|
||||
}
|
||||
|
||||
osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
|
||||
|
||||
// front faces.
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
|
||||
|
||||
// back faces
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
|
||||
|
||||
// front faces.
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
|
||||
|
||||
// back faces
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
|
||||
// osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
|
||||
// osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);
|
||||
|
||||
osg::Vec4 red(1.0f,0.12f,0.06f,1.0f);
|
||||
osg::Vec4 green(0.21f,0.48f,0.03f,1.0f);
|
||||
osg::Vec4 blue(0.20f,0.45f,0.60f,1.0f);
|
||||
|
||||
// front faces.
|
||||
geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));
|
||||
|
||||
geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
|
||||
{
|
||||
|
||||
|
||||
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3 normal = (corner-top)^(right-corner);
|
||||
normal.normalize();
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(top);
|
||||
vertices->push_back(corner);
|
||||
|
||||
vertices->push_back(right);
|
||||
vertices->push_back(right+(top-corner));
|
||||
|
||||
geom->setVertexArray(vertices);
|
||||
|
||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
||||
normals->push_back(normal);
|
||||
geom->setNormalArray(normals);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
geom->setColorArray(colors);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));
|
||||
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
geode->addDrawable(geom);
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg::Node* createLogo()
|
||||
{
|
||||
osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
|
||||
float chordRatio = 0.5f;
|
||||
float sphereRatio = 0.6f;
|
||||
|
||||
// create a group to hold the whole model.
|
||||
osg::Group* logo_group = new osg::Group;
|
||||
|
||||
osg::Quat r1,r2;
|
||||
r1.makeRotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f);
|
||||
r2.makeRotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f);
|
||||
|
||||
|
||||
MyBillboardTransform* xform = new MyBillboardTransform;
|
||||
xform->setPivotPoint(bb.center());
|
||||
xform->setPosition(bb.center());
|
||||
xform->setAttitude(r1*r2);
|
||||
|
||||
|
||||
// // create a transform to orientate the box and globe.
|
||||
// osg::MatrixTransform* xform = new osg::MatrixTransform;
|
||||
// xform->setDataVariance(osg::Object::STATIC);
|
||||
// xform->setMatrix(osg::Matrix::translate(-bb.center())*
|
||||
// osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
|
||||
// osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
|
||||
// osg::Matrix::translate(bb.center()));
|
||||
|
||||
// add the box and globe to it.
|
||||
//xform->addChild(createBox(bb,chordRatio));
|
||||
//xform->addChild(createBoxNo5(bb,chordRatio));
|
||||
xform->addChild(createBoxNo5No2(bb,chordRatio));
|
||||
// add the transform to the group.
|
||||
logo_group->addChild(xform);
|
||||
|
||||
logo_group->addChild(createGlobe(bb,sphereRatio));
|
||||
|
||||
// add the text to the group.
|
||||
//group->addChild(createTextBelow(bb));
|
||||
logo_group->addChild(createTextLeft(bb));
|
||||
|
||||
|
||||
// create the backdrop to render the shadow to.
|
||||
osg::Vec3 corner(-900.0f,150.0f,-100.0f);
|
||||
osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
|
||||
osg::Vec3 right(1100.0f,0.0f,0.0f); right += corner;
|
||||
|
||||
|
||||
// osg::Group* backdrop = new osg::Group;
|
||||
// backdrop->addChild(createBackdrop(corner,top,right));
|
||||
|
||||
osg::ClearNode* backdrop = new osg::ClearNode;
|
||||
backdrop->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
|
||||
//osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
|
||||
//osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);
|
||||
|
||||
osg::Group* scene = new osg::Group;
|
||||
|
||||
osg::StateSet* stateset = scene->getOrCreateStateSet();
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
|
||||
|
||||
scene->addChild(logo_group);
|
||||
scene->addChild(backdrop);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("ps","Render the Professional Services logo");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (arguments.find("ps")) s_ProfessionalServices = true;
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
osg::Node* node = createLogo();
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport( node );
|
||||
|
||||
// register trackball maniupulators.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgmultitexture.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgmultitexture
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgmultitexture.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgmultitexture
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,100 +0,0 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/TexGen>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(arguments);
|
||||
if (!rootnode)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
osg::Image* image = osgDB::readImageFile("Images/reflect.rgb");
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
|
||||
osg::TexGen* texgen = new osg::TexGen;
|
||||
texgen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
|
||||
osg::TexEnv* texenv = new osg::TexEnv;
|
||||
texenv->setMode(osg::TexEnv::BLEND);
|
||||
texenv->setColor(osg::Vec4(0.3f,0.3f,0.3f,0.3f));
|
||||
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
stateset->setTextureAttributeAndModes(1,texture,osg::StateAttribute::ON);
|
||||
stateset->setTextureAttributeAndModes(1,texgen,osg::StateAttribute::ON);
|
||||
stateset->setTextureAttribute(1,texenv);
|
||||
|
||||
rootnode->setStateSet(stateset);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"unable to load reflect map, model will not be mutlitextured"<<std::endl;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgoccluder.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgoccluder
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgoccluder.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgoccluder
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,359 +0,0 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/LineSegment>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <osgUtil/IntersectVisitor>
|
||||
|
||||
#include <osg/OccluderNode>
|
||||
#include <osg/Geometry>
|
||||
|
||||
|
||||
class OccluderEventHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
OccluderEventHandler(osgUtil::SceneView* sceneview,osg::Group* rootnode):_sceneview(sceneview),_rootnode(rootnode) {}
|
||||
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
|
||||
|
||||
virtual void accept(osgGA::GUIEventHandlerVisitor& v)
|
||||
{
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
void addPoint(const osg::Vec3& pos);
|
||||
|
||||
void endOccluder();
|
||||
|
||||
|
||||
osg::ref_ptr<osgUtil::SceneView> _sceneview;
|
||||
osg::ref_ptr<osg::Group> _rootnode;
|
||||
osg::ref_ptr<osg::Group> _occluders;
|
||||
osg::ref_ptr<osg::ConvexPlanarOccluder> _convexPlanarOccluder;
|
||||
};
|
||||
|
||||
bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
|
||||
{
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||
{
|
||||
if (ea.getKey()=='a')
|
||||
{
|
||||
|
||||
int x = ea.getX();
|
||||
int y = ea.getY();
|
||||
|
||||
osg::Vec3 near_point,far_point;
|
||||
if (!_sceneview->projectWindowXYIntoObject(x,ea.getYmax()-y,near_point,far_point))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::LineSegment> lineSegment = new osg::LineSegment;
|
||||
lineSegment->set(near_point,far_point);
|
||||
|
||||
osgUtil::IntersectVisitor iv;
|
||||
iv.addLineSegment(lineSegment.get());
|
||||
|
||||
_rootnode->accept(iv);
|
||||
|
||||
if (iv.hits())
|
||||
{
|
||||
|
||||
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(lineSegment.get());
|
||||
if (!hitList.empty())
|
||||
{
|
||||
|
||||
osgUtil::Hit& hit = hitList.front();
|
||||
addPoint(hit.getWorldIntersectPoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (ea.getKey()=='e')
|
||||
{
|
||||
endOccluder();
|
||||
return true;
|
||||
}
|
||||
else if (ea.getKey()=='O')
|
||||
{
|
||||
if (_occluders.valid())
|
||||
{
|
||||
std::cout<<"saving occluders to 'saved_occluders.osg'"<<std::endl;
|
||||
osgDB::writeNodeFile(*_occluders,"saved_occluders.osg");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"no occluders to save"<<std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OccluderEventHandler::addPoint(const osg::Vec3& pos)
|
||||
{
|
||||
std::cout<<"add point "<<pos<<std::endl;
|
||||
|
||||
if (!_convexPlanarOccluder.valid()) _convexPlanarOccluder = new osg::ConvexPlanarOccluder;
|
||||
|
||||
osg::ConvexPlanarPolygon& occluder = _convexPlanarOccluder->getOccluder();
|
||||
occluder.add(pos);
|
||||
|
||||
}
|
||||
|
||||
void OccluderEventHandler::endOccluder()
|
||||
{
|
||||
if (_convexPlanarOccluder.valid())
|
||||
{
|
||||
if (_convexPlanarOccluder->getOccluder().getVertexList().size()>=3)
|
||||
{
|
||||
osg::OccluderNode* occluderNode = new osg::OccluderNode;
|
||||
occluderNode->setOccluder(_convexPlanarOccluder.get());
|
||||
|
||||
if (!_occluders.valid())
|
||||
{
|
||||
_occluders = new osg::Group;
|
||||
_rootnode->addChild(_occluders.get());
|
||||
}
|
||||
_occluders->addChild(occluderNode);
|
||||
|
||||
std::cout<<"created occluder"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"Occluder requires at least 3 points to create occluder."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"No occluder points to create occluder with."<<std::endl;
|
||||
}
|
||||
|
||||
// reset current occluder.
|
||||
_convexPlanarOccluder = NULL;
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f)
|
||||
{
|
||||
// create and occluder which will site along side the loadmodel model.
|
||||
osg::OccluderNode* occluderNode = new osg::OccluderNode;
|
||||
|
||||
// create the convex planer occluder
|
||||
osg::ConvexPlanarOccluder* cpo = new osg::ConvexPlanarOccluder;
|
||||
|
||||
// attach it to the occluder node.
|
||||
occluderNode->setOccluder(cpo);
|
||||
occluderNode->setName("occluder");
|
||||
|
||||
// set the occluder up for the front face of the bounding box.
|
||||
osg::ConvexPlanarPolygon& occluder = cpo->getOccluder();
|
||||
occluder.add(v1);
|
||||
occluder.add(v2);
|
||||
occluder.add(v3);
|
||||
occluder.add(v4);
|
||||
|
||||
// create a whole at the center of the occluder if needed.
|
||||
if (holeRatio>0.0f)
|
||||
{
|
||||
// create hole.
|
||||
float ratio = holeRatio;
|
||||
float one_minus_ratio = 1-ratio;
|
||||
osg::Vec3 center = (v1+v2+v3+v4)*0.25f;
|
||||
osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio;
|
||||
osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio;
|
||||
osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio;
|
||||
osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio;
|
||||
|
||||
osg::ConvexPlanarPolygon hole;
|
||||
hole.add(v1dash);
|
||||
hole.add(v2dash);
|
||||
hole.add(v3dash);
|
||||
hole.add(v4dash);
|
||||
|
||||
cpo->addHole(hole);
|
||||
}
|
||||
|
||||
|
||||
// create a drawable for occluder.
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(occluder.getVertexList().begin(),occluder.getVertexList().end());
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array(1);
|
||||
(*colors)[0].set(1.0f,1.0f,1.0f,0.5f);
|
||||
geom->setColorArray(colors);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geom);
|
||||
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
|
||||
geom->setStateSet(stateset);
|
||||
|
||||
// add the occluder geode as a child of the occluder,
|
||||
// as the occluder can't self occlude its subgraph the
|
||||
// geode will never be occluder by this occluder.
|
||||
occluderNode->addChild(geode);
|
||||
|
||||
return occluderNode;
|
||||
|
||||
}
|
||||
|
||||
osg::Group* createOccludersAroundModel(osg::Node* model)
|
||||
{
|
||||
osg::Group* scene = new osg::Group;
|
||||
scene->setName("rootgroup");
|
||||
|
||||
|
||||
// add the loaded model into a the scene group.
|
||||
scene->addChild(model);
|
||||
model->setName("model");
|
||||
|
||||
// get the bounding volume of the model.
|
||||
const osg::BoundingSphere bs = model->getBound();
|
||||
|
||||
// create a bounding box around the sphere.
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
// front
|
||||
scene->addChild(createOccluder(bb.corner(0),
|
||||
bb.corner(1),
|
||||
bb.corner(5),
|
||||
bb.corner(4)));
|
||||
|
||||
// right side
|
||||
scene->addChild(createOccluder(bb.corner(1),
|
||||
bb.corner(3),
|
||||
bb.corner(7),
|
||||
bb.corner(5)));
|
||||
|
||||
// left side
|
||||
scene->addChild(createOccluder(bb.corner(2),
|
||||
bb.corner(0),
|
||||
bb.corner(4),
|
||||
bb.corner(6)));
|
||||
|
||||
// back side
|
||||
scene->addChild(createOccluder(bb.corner(3),
|
||||
bb.corner(2),
|
||||
bb.corner(6),
|
||||
bb.corner(7),
|
||||
0.5f)); // create a hole half the size of the occluder.
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-c","Mannually create occluders");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
bool manuallyCreateOccluders = false;
|
||||
while (arguments.read("-c")) { manuallyCreateOccluders = true; }
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedmodel = osgDB::readNodeFiles(arguments);
|
||||
if (!loadedmodel)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(loadedmodel);
|
||||
|
||||
// add the occluders to the loaded model.
|
||||
osg::Group* rootnode = NULL;
|
||||
|
||||
if (manuallyCreateOccluders)
|
||||
{
|
||||
rootnode = new osg::Group;
|
||||
rootnode->addChild(loadedmodel);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootnode = createOccludersAroundModel(loadedmodel);
|
||||
}
|
||||
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
if (manuallyCreateOccluders)
|
||||
{
|
||||
viewer.prependEventHandler(new OccluderEventHandler(viewer.getViewportSceneView(0),rootnode));
|
||||
}
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
@@ -1,369 +0,0 @@
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <osgParticle/Particle>
|
||||
#include <osgParticle/ParticleSystem>
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
#include <osgParticle/ModularEmitter>
|
||||
#include <osgParticle/ModularProgram>
|
||||
#include <osgParticle/RandomRateCounter>
|
||||
#include <osgParticle/SectorPlacer>
|
||||
#include <osgParticle/RadialShooter>
|
||||
#include <osgParticle/AccelOperator>
|
||||
#include <osgParticle/FluidFrictionOperator>
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// CUSTOM OPERATOR CLASS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This class demonstrates Operator subclassing. This way you can create
|
||||
// custom operators to apply your motion effects to the particles. See docs
|
||||
// for more details.
|
||||
class VortexOperator: public osgParticle::Operator {
|
||||
public:
|
||||
VortexOperator()
|
||||
: osgParticle::Operator(), center_(0, 0, 0), axis_(0, 0, 1), intensity_(0.1f) {}
|
||||
|
||||
VortexOperator(const VortexOperator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY)
|
||||
: osgParticle::Operator(copy, copyop), center_(copy.center_), axis_(copy.axis_), intensity_(copy.intensity_) {}
|
||||
|
||||
META_Object(osgParticle, VortexOperator);
|
||||
|
||||
void setCenter(const osg::Vec3 &c)
|
||||
{
|
||||
center_ = c;
|
||||
}
|
||||
|
||||
void setAxis(const osg::Vec3 &a)
|
||||
{
|
||||
axis_ = a / a.length();
|
||||
}
|
||||
|
||||
// this method is called by ModularProgram before applying
|
||||
// operators on the particle set via the operate() method.
|
||||
void beginOperate(osgParticle::Program *prg)
|
||||
{
|
||||
// we have to check whether the reference frame is relative to parents
|
||||
// or it's absolute; in the first case, we must transform the vectors
|
||||
// from local to world space.
|
||||
if (prg->getReferenceFrame() == osgParticle::Program::RELATIVE_TO_PARENTS) {
|
||||
// transform the center point (full transformation)
|
||||
xf_center_ = prg->transformLocalToWorld(center_);
|
||||
// transform the axis vector (only rotation and scale)
|
||||
xf_axis_ = prg->rotateLocalToWorld(axis_);
|
||||
} else {
|
||||
xf_center_ = center_;
|
||||
xf_axis_ = axis_;
|
||||
}
|
||||
}
|
||||
|
||||
// apply a vortex-like acceleration. This code is not optimized,
|
||||
// it's here only for demonstration purposes.
|
||||
void operate(osgParticle::Particle *P, double dt)
|
||||
{
|
||||
float l = xf_axis_ * (P->getPosition() - xf_center_);
|
||||
osg::Vec3 lc = xf_center_ + xf_axis_ * l;
|
||||
osg::Vec3 R = P->getPosition() - lc;
|
||||
osg::Vec3 v = (R ^ xf_axis_) * P->getMassInv() * intensity_;
|
||||
|
||||
// compute new position
|
||||
osg::Vec3 newpos = P->getPosition() + v * dt;
|
||||
|
||||
// update the position of the particle without modifying its
|
||||
// velocity vector (this is unusual, normally you should call
|
||||
// the Particle::setVelocity() or Particle::addVelocity()
|
||||
// methods).
|
||||
P->setPosition(newpos);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~VortexOperator() {}
|
||||
|
||||
private:
|
||||
osg::Vec3 center_;
|
||||
osg::Vec3 xf_center_;
|
||||
osg::Vec3 axis_;
|
||||
osg::Vec3 xf_axis_;
|
||||
float intensity_;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// SIMPLE PARTICLE SYSTEM CREATION
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
osgParticle::ParticleSystem *create_simple_particle_system(osg::Group *root)
|
||||
{
|
||||
|
||||
// Ok folks, this is the first particle system we build; it will be
|
||||
// very simple, with no textures and no special effects, just default
|
||||
// values except for a couple of attributes.
|
||||
|
||||
// First of all, we create the ParticleSystem object; it will hold
|
||||
// our particles and expose the interface for managing them; this object
|
||||
// is a Drawable, so we'll have to add it to a Geode later.
|
||||
|
||||
osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
|
||||
|
||||
// As for other Drawable classes, the aspect of graphical elements of
|
||||
// ParticleSystem (the particles) depends on the StateAttribute's we
|
||||
// give it. The ParticleSystem class has an helper function that let
|
||||
// us specify a set of the most common attributes: setDefaultAttributes().
|
||||
// This method can accept up to three parameters; the first is a texture
|
||||
// name (std::string), which can be empty to disable texturing, the second
|
||||
// sets whether particles have to be "emissive" (additive blending) or not;
|
||||
// the third parameter enables or disables lighting.
|
||||
|
||||
ps->setDefaultAttributes("", true, false);
|
||||
|
||||
// Now that our particle system is set we have to create an emitter, that is
|
||||
// an object (actually a Node descendant) that generate new particles at
|
||||
// each frame. The best choice is to use a ModularEmitter, which allow us to
|
||||
// achieve a wide variety of emitting styles by composing the emitter using
|
||||
// three objects: a "counter", a "placer" and a "shooter". The counter must
|
||||
// tell the ModularEmitter how many particles it has to create for the
|
||||
// current frame; then, the ModularEmitter creates these particles, and for
|
||||
// each new particle it instructs the placer and the shooter to set its
|
||||
// position vector and its velocity vector, respectively.
|
||||
// By default, a ModularEmitter object initializes itself with a counter of
|
||||
// type RandomRateCounter, a placer of type PointPlacer and a shooter of
|
||||
// type RadialShooter (see documentation for details). We are going to leave
|
||||
// these default objects there, but we'll modify the counter so that it
|
||||
// counts faster (more particles are emitted at each frame).
|
||||
|
||||
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
|
||||
|
||||
// the first thing you *MUST* do after creating an emitter is to set the
|
||||
// destination particle system, otherwise it won't know where to create
|
||||
// new particles.
|
||||
|
||||
emitter->setParticleSystem(ps);
|
||||
|
||||
// Ok, get a pointer to the emitter's Counter object. We could also
|
||||
// create a new RandomRateCounter object and assign it to the emitter,
|
||||
// but since the default counter is already a RandomRateCounter, we
|
||||
// just get a pointer to it and change a value.
|
||||
|
||||
osgParticle::RandomRateCounter *rrc =
|
||||
static_cast<osgParticle::RandomRateCounter *>(emitter->getCounter());
|
||||
|
||||
// Now set the rate range to a better value. The actual rate at each frame
|
||||
// will be chosen randomly within that range.
|
||||
|
||||
rrc->setRateRange(20, 30); // generate 20 to 30 particles per second
|
||||
|
||||
// The emitter is done! Let's add it to the scene graph. The cool thing is
|
||||
// that any emitter node will take into account the accumulated local-to-world
|
||||
// matrix, so you can attach an emitter to a transform node and see it move.
|
||||
|
||||
root->addChild(emitter);
|
||||
|
||||
// Ok folks, we have almost finished. We don't add any particle modifier
|
||||
// here (see ModularProgram and Operator classes), so all we still need is
|
||||
// to create a Geode and add the particle system to it, so it can be
|
||||
// displayed.
|
||||
|
||||
osg::Geode *geode = new osg::Geode;
|
||||
geode->addDrawable(ps);
|
||||
|
||||
// add the geode to the scene graph
|
||||
root->addChild(geode);
|
||||
|
||||
return ps;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// COMPLEX PARTICLE SYSTEM CREATION
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
osgParticle::ParticleSystem *create_complex_particle_system(osg::Group *root)
|
||||
{
|
||||
// Are you ready for a more complex particle system? Well, read on!
|
||||
|
||||
// Now we take one step we didn't before: create a particle template.
|
||||
// A particle template is simply a Particle object for which you set
|
||||
// the desired properties (see documentation for details). When the
|
||||
// particle system has to create a new particle and it's been assigned
|
||||
// a particle template, the new particle will inherit the template's
|
||||
// properties.
|
||||
// You can even assign different particle templates to each emitter; in
|
||||
// this case, the emitter's template will override the particle system's
|
||||
// default template.
|
||||
|
||||
osgParticle::Particle ptemplate;
|
||||
|
||||
ptemplate.setLifeTime(3); // 3 seconds of life
|
||||
|
||||
// the following ranges set the envelope of the respective
|
||||
// graphical properties in time.
|
||||
ptemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
|
||||
ptemplate.setAlphaRange(osgParticle::rangef(0.0f, 1.5f));
|
||||
ptemplate.setColorRange(osgParticle::rangev4(
|
||||
osg::Vec4(1, 0.5f, 0.3f, 1.5f),
|
||||
osg::Vec4(0, 0.7f, 1.0f, 0.0f)));
|
||||
|
||||
// these are physical properties of the particle
|
||||
ptemplate.setRadius(0.05f); // 5 cm wide particles
|
||||
ptemplate.setMass(0.05f); // 50 g heavy
|
||||
|
||||
// As usual, let's create the ParticleSystem object and set its
|
||||
// default state attributes. This time we use a texture named
|
||||
// "smoke.rgb", you can find it in the data distribution of OSG.
|
||||
// We turn off the additive blending, because smoke has no self-
|
||||
// illumination.
|
||||
osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
|
||||
ps->setDefaultAttributes("Images/smoke.rgb", false, false);
|
||||
|
||||
// assign the particle template to the system.
|
||||
ps->setDefaultParticleTemplate(ptemplate);
|
||||
|
||||
// now we have to create an emitter; this will be a ModularEmitter, for which
|
||||
// we define a RandomRateCounter as counter, a SectorPlacer as placer, and
|
||||
// a RadialShooter as shooter.
|
||||
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
|
||||
emitter->setParticleSystem(ps);
|
||||
|
||||
// setup the counter
|
||||
osgParticle::RandomRateCounter *counter = new osgParticle::RandomRateCounter;
|
||||
counter->setRateRange(60, 60);
|
||||
emitter->setCounter(counter);
|
||||
|
||||
// setup the placer; it will be a circle of radius 5 (the particles will
|
||||
// be placed inside this circle).
|
||||
osgParticle::SectorPlacer *placer = new osgParticle::SectorPlacer;
|
||||
placer->setCenter(8, 0, 10);
|
||||
placer->setRadiusRange(2.5, 5);
|
||||
placer->setPhiRange(0, 2 * osg::PI); // 360<36> angle to make a circle
|
||||
emitter->setPlacer(placer);
|
||||
|
||||
// now let's setup the shooter; we use a RadialShooter but we set the
|
||||
// initial speed to zero, because we want the particles to fall down
|
||||
// only under the effect of the gravity force. Since we se the speed
|
||||
// to zero, there is no need to setup the shooting angles.
|
||||
osgParticle::RadialShooter *shooter = new osgParticle::RadialShooter;
|
||||
shooter->setInitialSpeedRange(0, 0);
|
||||
emitter->setShooter(shooter);
|
||||
|
||||
// add the emitter to the scene graph
|
||||
root->addChild(emitter);
|
||||
|
||||
// WELL, we got our particle system and a nice emitter. Now we want to
|
||||
// simulate the effect of the earth gravity, so first of all we have to
|
||||
// create a Program. It is a particle processor just like the Emitter
|
||||
// class, but it allows to modify particle properties *after* they have
|
||||
// been created.
|
||||
// The ModularProgram class can be thought as a sequence of operators,
|
||||
// each one performing some actions on the particles. So, the trick is:
|
||||
// create the ModularProgram object, create one or more Operator objects,
|
||||
// add those operators to the ModularProgram, and finally add the
|
||||
// ModularProgram object to the scene graph.
|
||||
// NOTE: since the Program objects perform actions after the particles
|
||||
// have been emitted by one or more Emitter objects, all instances of
|
||||
// Program (and its descendants) should be placed *after* the instances
|
||||
// of Emitter objects in the scene graph.
|
||||
|
||||
osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
|
||||
program->setParticleSystem(ps);
|
||||
|
||||
// create an operator that simulates the gravity acceleration.
|
||||
osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
|
||||
op1->setToGravity();
|
||||
program->addOperator(op1);
|
||||
|
||||
// now create a custom operator, we have defined it before (see
|
||||
// class VortexOperator).
|
||||
VortexOperator *op2 = new VortexOperator;
|
||||
op2->setCenter(osg::Vec3(8, 0, 0));
|
||||
program->addOperator(op2);
|
||||
|
||||
// let's add a fluid operator to simulate air friction.
|
||||
osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
|
||||
op3->setFluidToAir();
|
||||
program->addOperator(op3);
|
||||
|
||||
// add the program to the scene graph
|
||||
root->addChild(program);
|
||||
|
||||
// create a Geode to contain our particle system.
|
||||
osg::Geode *geode = new osg::Geode;
|
||||
geode->addDrawable(ps);
|
||||
|
||||
// add the geode to the scene graph.
|
||||
root->addChild(geode);
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// MAIN SCENE GRAPH BUILDING FUNCTION
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void build_world(osg::Group *root)
|
||||
{
|
||||
|
||||
// In this function we are going to create two particle systems;
|
||||
// the first one will be very simple, based mostly on default properties;
|
||||
// the second one will be a little bit more complex, showing how to
|
||||
// create custom operators.
|
||||
// To avoid inserting too much code in a single function, we have
|
||||
// splitted the work into two functions which accept a Group node as
|
||||
// parameter, and return a pointer to the particle system they created.
|
||||
|
||||
osgParticle::ParticleSystem *ps1 = create_simple_particle_system(root);
|
||||
osgParticle::ParticleSystem *ps2 = create_complex_particle_system(root);
|
||||
|
||||
// Now that the particle systems and all other related objects have been
|
||||
// created, we have to add an "updater" node to the scene graph. This node
|
||||
// will react to cull traversal by updating the specified particles system.
|
||||
|
||||
osgParticle::ParticleSystemUpdater *psu = new osgParticle::ParticleSystemUpdater;
|
||||
psu->addParticleSystem(ps1);
|
||||
psu->addParticleSystem(ps2);
|
||||
|
||||
// add the updater node to the scene graph
|
||||
root->addChild(psu);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// main()
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
// initialize the GLUT
|
||||
glutInit(&argc, argv);
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer;
|
||||
//viewer.setWindowTitle(argv[0]);
|
||||
|
||||
osg::Group *root = new osg::Group;
|
||||
build_world(root);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport(root);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
#include <cassert>
|
||||
//#include <osgDB/ReadFile>
|
||||
|
||||
#include "RenderToTextureStage.h"
|
||||
|
||||
//using namespace osg;
|
||||
//using namespace osgUtil;
|
||||
|
||||
// register a RenderToTextureStage prototype with the RenderBin prototype list.
|
||||
//RegisterRenderBinProxy<RenderToTextureStage> s_registerRenderToTextureStageProxy;
|
||||
|
||||
MyRenderToTextureStage::MyRenderToTextureStage()
|
||||
{
|
||||
_pbuffer = 0L;
|
||||
}
|
||||
|
||||
MyRenderToTextureStage::~MyRenderToTextureStage()
|
||||
{
|
||||
}
|
||||
|
||||
void MyRenderToTextureStage::reset()
|
||||
{
|
||||
RenderStage::reset();
|
||||
}
|
||||
|
||||
void MyRenderToTextureStage::draw(osg::State& state, osgUtil::RenderLeaf*& previous)
|
||||
{
|
||||
if (_pbuffer && _texture.valid())
|
||||
{
|
||||
// Create pbuffer texture
|
||||
const unsigned int contextID = state.getContextID();
|
||||
GLuint& handle = _texture->getTextureObject(contextID);
|
||||
if (handle == 0)
|
||||
{
|
||||
// Create dynamic texture, subload callback required.
|
||||
_texture->apply(state);
|
||||
}
|
||||
|
||||
HDC hdc = ::wglGetCurrentDC();
|
||||
HGLRC hglrc = ::wglGetCurrentContext();
|
||||
|
||||
// Release pbuffer from "render to texture".
|
||||
_pbuffer->releaseTexImage();
|
||||
|
||||
// Make the p-buffer's context current.
|
||||
_pbuffer->makeCurrent();
|
||||
|
||||
// Render in p-buffer.
|
||||
RenderStage::draw(state,previous);
|
||||
|
||||
// restore window's context as current.
|
||||
if (!::wglMakeCurrent(hdc, hglrc))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (true /*_isRenderTextureSupported*/)
|
||||
{
|
||||
// transfer contents of p-buffer to texture
|
||||
_pbuffer->bindTexImage(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:
|
||||
// _pbuffer->copyTexImage(state);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderStage::draw(state,previous);
|
||||
|
||||
// now copy the rendered image to attached texture.
|
||||
if (_texture.valid())
|
||||
_texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
|
||||
|
||||
if (_image.valid())
|
||||
_image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),GL_RGBA,GL_UNSIGNED_BYTE);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
|
||||
//Distributed under the terms of the GNU Library General Public License (LGPL)
|
||||
//as published by the Free Software Foundation.
|
||||
|
||||
#ifndef RENDERTOTEXTURESTAGE
|
||||
#define RENDERTOTEXTURESTAGE 1
|
||||
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include <osgUtil/RenderStage>
|
||||
|
||||
#include "pbuffer.h"
|
||||
|
||||
// namespace osgUtil {
|
||||
|
||||
/**
|
||||
* RenderStage which copies the final image to an attached texture or image.
|
||||
* Generally used as a pre-rendering stage.
|
||||
*/
|
||||
class /*OSGUTIL_EXPORT*/ MyRenderToTextureStage : public osgUtil::RenderStage
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
MyRenderToTextureStage();
|
||||
|
||||
virtual osg::Object* cloneType() const { return new MyRenderToTextureStage(); }
|
||||
virtual osg::Object* clone(const osg::CopyOp&) const { return new MyRenderToTextureStage(); } // note only implements a clone of type.
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MyRenderToTextureStage*>(obj)!=0L; }
|
||||
virtual const char* libraryName() const { return ""; }
|
||||
virtual const char* className() const { return "MyRenderToTextureStage"; }
|
||||
|
||||
inline void setPBuffer(PBuffer* pbuffer) { _pbuffer = pbuffer; }
|
||||
|
||||
virtual void reset();
|
||||
|
||||
void setTexture(osg::Texture2D* texture) { _texture = texture; }
|
||||
osg::Texture2D* getTexture() { return _texture.get(); }
|
||||
|
||||
void setImage(osg::Image* image) { _image = image; }
|
||||
osg::Image* getImage() { return _image.get(); }
|
||||
|
||||
virtual void draw(osg::State& state,osgUtil::RenderLeaf*& previous);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~MyRenderToTextureStage();
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::ref_ptr<osg::Image> _image;
|
||||
PBuffer* _pbuffer;
|
||||
};
|
||||
|
||||
// }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,661 +0,0 @@
|
||||
#include <cassert>
|
||||
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Node>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/ColorMask>
|
||||
#include <osg/Depth>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/TransformCallback>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include "RenderToTextureStage.h"
|
||||
#include "pbuffer.h"
|
||||
|
||||
|
||||
PBuffer* g_pPixelBuffer;
|
||||
|
||||
|
||||
class MyUpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyUpdateCallback(osg::Node* subgraph):
|
||||
_subgraph(subgraph) {}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
// traverse the subgraph to update any nodes.
|
||||
if (_subgraph.valid()) _subgraph->accept(*nv);
|
||||
|
||||
// must traverse the Node's subgraph
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> _subgraph;
|
||||
};
|
||||
|
||||
class MyCullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyCullCallback(osg::Node* subgraph,osg::Texture2D* texture):
|
||||
_subgraph(subgraph),
|
||||
_texture(texture)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullVisitor && _texture.valid() && _subgraph.valid())
|
||||
doPreRender(*node,*cullVisitor);
|
||||
|
||||
// must traverse the subgraph
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);
|
||||
|
||||
osg::ref_ptr<osg::Node> _subgraph;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::ref_ptr<osg::StateSet> _localState;
|
||||
|
||||
};
|
||||
|
||||
|
||||
void MyCullCallback::doPreRender(osg::Node&, osgUtil::CullVisitor& cv)
|
||||
{
|
||||
const osg::BoundingSphere& bs = _subgraph->getBound();
|
||||
if (!bs.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// create the render to texture stage.
|
||||
osg::ref_ptr<MyRenderToTextureStage> rtts = new MyRenderToTextureStage;
|
||||
rtts->setPBuffer(g_pPixelBuffer);
|
||||
|
||||
// set up lighting.
|
||||
// currently ignore lights in the scene graph itself..
|
||||
// will do later.
|
||||
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage;
|
||||
|
||||
// set up the background color and clear mask.
|
||||
rtts->setClearColor(osg::Vec4(0.1f,0.9f,0.3f,1.0f));
|
||||
rtts->setClearMask(previous_stage->getClearMask());
|
||||
|
||||
// set up to charge the same RenderStageLighting is the parent previous stage.
|
||||
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
|
||||
|
||||
|
||||
// record the render bin, to be restored after creation
|
||||
// of the render to text
|
||||
osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();
|
||||
|
||||
// set the current renderbin to be the newly created stage.
|
||||
cv.setCurrentRenderBin(rtts.get());
|
||||
|
||||
float znear = 1.0f*bs.radius();
|
||||
float zfar = 3.0f*bs.radius();
|
||||
|
||||
// 2:1 aspect ratio as per flag geomtry below.
|
||||
float top = 0.25f*znear;
|
||||
float right = 0.5f*znear;
|
||||
|
||||
znear *= 0.9f;
|
||||
zfar *= 1.1f;
|
||||
|
||||
// set up projection.
|
||||
osg::RefMatrix* projection = new osg::RefMatrix;
|
||||
projection->makeFrustum(-right,right,-top,top,znear,zfar);
|
||||
|
||||
cv.pushProjectionMatrix(projection);
|
||||
|
||||
osg::RefMatrix* matrix = new osg::RefMatrix;
|
||||
matrix->makeLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
|
||||
|
||||
cv.pushModelViewMatrix(matrix);
|
||||
|
||||
if (!_localState) _localState = new osg::StateSet;
|
||||
|
||||
cv.pushStateSet(_localState.get());
|
||||
|
||||
{
|
||||
// traverse the subgraph
|
||||
_subgraph->accept(cv);
|
||||
}
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popModelViewMatrix();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popProjectionMatrix();
|
||||
|
||||
// restore the previous renderbin.
|
||||
cv.setCurrentRenderBin(previousRenderBin);
|
||||
|
||||
if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0)
|
||||
{
|
||||
// getting to this point means that all the subgraph has been
|
||||
// culled by small feature culling or is beyond LOD ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int height = 512;
|
||||
int width = 512;
|
||||
|
||||
|
||||
const osg::Viewport& viewport = *cv.getViewport();
|
||||
|
||||
// offset the impostor viewport from the center of the main window
|
||||
// viewport as often the edges of the viewport might be obscured by
|
||||
// other windows, which can cause image/reading writing problems.
|
||||
int center_x = viewport.x()+viewport.width()/2;
|
||||
int center_y = viewport.y()+viewport.height()/2;
|
||||
|
||||
osg::Viewport* new_viewport = new osg::Viewport;
|
||||
// new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
|
||||
new_viewport->setViewport(0,0,width,height);
|
||||
rtts->setViewport(new_viewport);
|
||||
|
||||
_localState->setAttribute(new_viewport);
|
||||
|
||||
// and the render to texture stage to the current stages
|
||||
// dependancy list.
|
||||
cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get());
|
||||
|
||||
// if one exist attach texture to the RenderToTextureStage.
|
||||
if (_texture.valid()) rtts->setTexture(_texture.get());
|
||||
|
||||
// if one exist attach image to the RenderToTextureStage.
|
||||
// if (_image.valid()) rtts->setImage(_image.get());
|
||||
|
||||
}
|
||||
|
||||
|
||||
// call back which cretes a deformation field to oscilate the model.
|
||||
class MyGeometryCallback :
|
||||
public osg::Drawable::UpdateCallback,
|
||||
public osg::Drawable::AttributeFunctor
|
||||
{
|
||||
public:
|
||||
|
||||
MyGeometryCallback(const osg::Vec3& o,
|
||||
const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z,
|
||||
double period,double xphase,double amplitude):
|
||||
_firstCall(true),
|
||||
_startTime(0.0),
|
||||
_time(0.0),
|
||||
_period(period),
|
||||
_xphase(xphase),
|
||||
_amplitude(amplitude),
|
||||
_origin(o),
|
||||
_xAxis(x),
|
||||
_yAxis(y),
|
||||
_zAxis(z) {}
|
||||
|
||||
virtual void update(osg::NodeVisitor* nv,osg::Drawable* drawable)
|
||||
{
|
||||
const osg::FrameStamp* fs = nv->getFrameStamp();
|
||||
double referenceTime = fs->getReferenceTime();
|
||||
if (_firstCall)
|
||||
{
|
||||
_firstCall = false;
|
||||
_startTime = referenceTime;
|
||||
}
|
||||
|
||||
_time = referenceTime-_startTime;
|
||||
|
||||
drawable->accept(*this);
|
||||
drawable->dirtyBound();
|
||||
|
||||
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
|
||||
if (geometry)
|
||||
{
|
||||
osgUtil::SmoothingVisitor::smooth(*geometry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
|
||||
{
|
||||
if (type == osg::Drawable::VERTICES)
|
||||
{
|
||||
const float TwoPI=2.0f*osg::PI;
|
||||
const float phase = -_time/_period;
|
||||
|
||||
osg::Vec3* end = begin+count;
|
||||
for (osg::Vec3* itr=begin;itr<end;++itr)
|
||||
{
|
||||
osg::Vec3 dv(*itr-_origin);
|
||||
osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);
|
||||
|
||||
local.z() = local.x()*_amplitude*
|
||||
sinf(TwoPI*(phase+local.x()*_xphase));
|
||||
|
||||
(*itr) = _origin +
|
||||
_xAxis*local.x()+
|
||||
_yAxis*local.y()+
|
||||
_zAxis*local.z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _firstCall;
|
||||
|
||||
double _startTime;
|
||||
double _time;
|
||||
|
||||
double _period;
|
||||
double _xphase;
|
||||
float _amplitude;
|
||||
|
||||
osg::Vec3 _origin;
|
||||
osg::Vec3 _xAxis;
|
||||
osg::Vec3 _yAxis;
|
||||
osg::Vec3 _zAxis;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Custom Texture subload callback, just acts the the standard subload modes in osg::Texture right now
|
||||
// but code be used to define your own style callbacks.
|
||||
class MyTextureSubloadCallback : public osg::Texture2D::SubloadCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyTextureSubloadCallback():
|
||||
_subloadMode(AUTO),
|
||||
_textureWidth(0),
|
||||
_textureHeight(0),
|
||||
_subloadTextureOffsetX(0),
|
||||
_subloadTextureOffsetY(0),
|
||||
_subloadImageOffsetX(0),
|
||||
_subloadImageOffsetY(0),
|
||||
_subloadImageWidth(0),
|
||||
_subloadImageHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
enum SubloadMode {
|
||||
OFF,
|
||||
AUTO,
|
||||
IF_DIRTY
|
||||
};
|
||||
|
||||
/** Set the texture subload mode. */
|
||||
inline void setSubloadMode(const SubloadMode mode) { _subloadMode = mode; }
|
||||
|
||||
/** Get the texture subload mode. */
|
||||
inline const SubloadMode getSubloadMode() const { return _subloadMode; }
|
||||
|
||||
/** Set the texture subload texture offsets. */
|
||||
inline void setSubloadTextureOffset(const int x, const int y)
|
||||
{
|
||||
_subloadTextureOffsetX = x;
|
||||
_subloadTextureOffsetY = y;
|
||||
}
|
||||
|
||||
/** Get the texture subload texture offsets. */
|
||||
inline void getSubloadTextureOffset(int& x, int& y) const
|
||||
{
|
||||
x = _subloadTextureOffsetX;
|
||||
y = _subloadTextureOffsetY;
|
||||
}
|
||||
|
||||
/** Set the texture subload width. If width or height are zero then
|
||||
* the repsective size value is calculated from the source image sizes. */
|
||||
inline void setSubloadTextureSize(const int width, const int height)
|
||||
{
|
||||
_textureWidth = width;
|
||||
_textureHeight = height;
|
||||
}
|
||||
|
||||
/** Get the texture subload width. */
|
||||
inline void getSubloadTextureSize(int& width, int& height) const
|
||||
{
|
||||
width = _textureWidth;
|
||||
height = _textureHeight;
|
||||
}
|
||||
|
||||
|
||||
/** Set the subload image offsets. */
|
||||
inline void setSubloadImageOffset(const int x, const int y)
|
||||
{
|
||||
_subloadImageOffsetX = x;
|
||||
_subloadImageOffsetY = y;
|
||||
}
|
||||
|
||||
/** Get the subload image offsets. */
|
||||
inline void getSubloadImageOffset(int& x, int& y) const
|
||||
{
|
||||
x = _subloadImageOffsetX;
|
||||
y = _subloadImageOffsetY;
|
||||
}
|
||||
|
||||
/** Set the image subload width. If width or height are zero then
|
||||
* the repsective size value is calculated from the source image sizes. */
|
||||
inline void setSubloadImageSize(const int width, const int height)
|
||||
{
|
||||
_subloadImageWidth = width;
|
||||
_subloadImageHeight = height;
|
||||
}
|
||||
|
||||
/** Get the image subload width. */
|
||||
inline void getSubloadImageSize(int& width, int& height) const
|
||||
{
|
||||
width = _subloadImageWidth;
|
||||
height = _subloadImageHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void load(const osg::Texture2D& texture,osg::State&) const
|
||||
{
|
||||
osg::notify(osg::INFO)<<"doing load"<<std::endl;
|
||||
/*
|
||||
static bool s_SGIS_GenMipmap = osg::isGLExtensionSupported("GL_SGIS_generate_mipmap");
|
||||
|
||||
if (s_SGIS_GenMipmap && (texture.getFilter(osg::Texture2D::MIN_FILTER) != osg::Texture2D::LINEAR && texture.getFilter(osg::Texture2D::MIN_FILTER) != osg::Texture2D::NEAREST))
|
||||
{
|
||||
texture.setNumMipmapLevels(1); // will leave this at one, since the mipmap will be created internally by OpenGL.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture.setNumMipmapLevels(1);
|
||||
}
|
||||
|
||||
|
||||
GLsizei width = (_subloadImageWidth>0)?_subloadImageWidth:texture.getImage()->s();
|
||||
GLsizei height = (_subloadImageHeight>0)?_subloadImageHeight:texture.getImage()->t();
|
||||
|
||||
|
||||
bool sizeChanged = false;
|
||||
if (_textureWidth==0)
|
||||
{
|
||||
// need to calculate texture dimension
|
||||
sizeChanged = true;
|
||||
_textureWidth = 1;
|
||||
for (; _textureWidth < (static_cast<GLsizei>(_subloadTextureOffsetX) + width); _textureWidth <<= 1) {}
|
||||
}
|
||||
|
||||
if (_textureHeight==0)
|
||||
{
|
||||
// need to calculate texture dimension
|
||||
sizeChanged = true;
|
||||
_textureHeight = 1;
|
||||
for (; _textureHeight < (static_cast<GLsizei>(_subloadTextureOffsetY) + height); _textureHeight <<= 1) {}
|
||||
}
|
||||
|
||||
if (sizeChanged)
|
||||
{
|
||||
texture.setTextureSize(_textureWidth, _textureHeight);
|
||||
}
|
||||
*/
|
||||
#if 0
|
||||
// reserve appropriate texture memory
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, texture.getInternalFormat(),
|
||||
_textureWidth, _textureHeight, 0,
|
||||
(GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(),
|
||||
NULL);
|
||||
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,texture.getImage()->s());
|
||||
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
_subloadTextureOffsetX, _subloadTextureOffsetY,
|
||||
width, height,
|
||||
(GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(),
|
||||
texture.getImage()->data(_subloadImageOffsetX,_subloadImageOffsetY));
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
|
||||
#else
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, texture.getInternalFormat(), _textureWidth, _textureHeight, 0, GL_RGB, GL_FLOAT, 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void subload(const osg::Texture2D& texture,osg::State&) const
|
||||
{
|
||||
osg::notify(osg::INFO)<<"doing subload"<<std::endl;
|
||||
#if 0
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,texture.getImage()->s());
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
_subloadTextureOffsetX, _subloadTextureOffsetY,
|
||||
(_subloadImageWidth>0)?_subloadImageWidth:texture.getImage()->s(), (_subloadImageHeight>0)?_subloadImageHeight:texture.getImage()->t(),
|
||||
(GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(),
|
||||
texture.getImage()->data(_subloadImageOffsetX,_subloadImageOffsetY));
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
SubloadMode _subloadMode;
|
||||
mutable GLsizei _textureWidth, _textureHeight;
|
||||
GLint _subloadTextureOffsetX, _subloadTextureOffsetY;
|
||||
GLint _subloadImageOffsetX, _subloadImageOffsetY;
|
||||
GLsizei _subloadImageWidth, _subloadImageHeight;
|
||||
};
|
||||
|
||||
|
||||
|
||||
osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
|
||||
{
|
||||
if (!subgraph) return 0;
|
||||
|
||||
// create the quad to visualize.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
polyGeom->setSupportsDisplayList(false);
|
||||
|
||||
osg::Vec3 origin(0.0f,0.0f,0.0f);
|
||||
osg::Vec3 xAxis(1.0f,0.0f,0.0f);
|
||||
osg::Vec3 yAxis(0.0f,0.0f,1.0f);
|
||||
osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
|
||||
float height = 100.0f;
|
||||
float width = 200.0f;
|
||||
int noSteps = 20;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
osg::Vec3 bottom = origin;
|
||||
osg::Vec3 top = origin; top.z()+= height;
|
||||
osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));
|
||||
|
||||
osg::Vec2Array* texcoords = new osg::Vec2Array;
|
||||
osg::Vec2 bottom_texcoord(0.0f,0.0f);
|
||||
osg::Vec2 top_texcoord(0.0f,1.0f);
|
||||
osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f);
|
||||
|
||||
for(int i=0;i<noSteps;++i)
|
||||
{
|
||||
vertices->push_back(top);
|
||||
vertices->push_back(bottom);
|
||||
top+=dv;
|
||||
bottom+=dv;
|
||||
|
||||
texcoords->push_back(top_texcoord);
|
||||
texcoords->push_back(bottom_texcoord);
|
||||
top_texcoord+=dv_texcoord;
|
||||
bottom_texcoord+=dv_texcoord;
|
||||
}
|
||||
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
polyGeom->setTexCoordArray(0,texcoords);
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
polyGeom->setColorArray(colors);
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size()));
|
||||
|
||||
// new we need to add the texture to the Drawable, we do so by creating a
|
||||
// StateSet to contain the Texture StateAttribute.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
// set up the texture.
|
||||
// osg::Image* image = new osg::Image;
|
||||
// image->setInternalTextureFormat(GL_RGBA);
|
||||
|
||||
// Dynamic texture filled with data from pbuffer.
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
//texture->setSubloadMode(osg::Texture::IF_DIRTY);
|
||||
texture->setInternalFormat(GL_RGB);
|
||||
texture->setTextureSize(512,512);
|
||||
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP);
|
||||
texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP);
|
||||
texture->setSubloadCallback(new MyTextureSubloadCallback());
|
||||
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
|
||||
|
||||
polyGeom->setStateSet(stateset);
|
||||
|
||||
polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));
|
||||
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
geode->addDrawable(polyGeom);
|
||||
|
||||
osg::Group* parent = new osg::Group;
|
||||
|
||||
parent->setUpdateCallback(new MyUpdateCallback(subgraph));
|
||||
|
||||
parent->setCullCallback(new MyCullCallback(subgraph,texture));
|
||||
|
||||
parent->addChild(geode);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
void write_usage(std::ostream& out,const std::string& name)
|
||||
{
|
||||
out << std::endl;
|
||||
out <<"usage:"<< std::endl;
|
||||
out <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
|
||||
out << std::endl;
|
||||
out <<"options:"<< std::endl;
|
||||
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
|
||||
out <<" i.e. -l osgdb_pfb"<< std::endl;
|
||||
out <<" Useful for loading reader/writers which can load"<< std::endl;
|
||||
out <<" other file formats in addition to its extension."<< std::endl;
|
||||
out <<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
|
||||
out <<" i.e. -e pfb"<< std::endl;
|
||||
out <<" Useful short hand for specifying full library name as"<< std::endl;
|
||||
out <<" done with -l above, as it automatically expands to"<< std::endl;
|
||||
out <<" the full library name appropriate for each platform."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stereo - switch on stereo rendering, using the default of,"<< std::endl;
|
||||
out <<" ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
|
||||
out <<" environmental variable. See doc/stereo.html for "<< std::endl;
|
||||
out <<" further details on setting up accurate stereo "<< std::endl;
|
||||
out <<" for your system. "<< std::endl;
|
||||
out <<" -stereo ANAGLYPHIC - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
|
||||
out <<" -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stencil - use a visual with stencil buffer enabled, this "<< std::endl;
|
||||
out <<" also allows the depth complexity statistics mode"<< std::endl;
|
||||
out <<" to be used (press 'p' three times to cycle to it)."<< std::endl;
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
|
||||
|
||||
if (!loadedModel)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create a transform to spin the model.
|
||||
osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
|
||||
loadedModelTransform->addChild(loadedModel);
|
||||
|
||||
osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
|
||||
loadedModelTransform->setUpdateCallback(nc);
|
||||
|
||||
osg::Group* rootNode = new osg::Group();
|
||||
// rootNode->addChild(loadedModelTransform);
|
||||
rootNode->addChild(createPreRenderSubGraph(loadedModelTransform));
|
||||
|
||||
|
||||
// add model to the viewer.
|
||||
viewer.addViewport( rootNode );
|
||||
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
g_pPixelBuffer = new PBuffer(512,512);
|
||||
g_pPixelBuffer->initialize();
|
||||
|
||||
viewer.run();
|
||||
|
||||
delete g_pPixelBuffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,446 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include "pbuffer.h"
|
||||
|
||||
namespace osg {
|
||||
bool isWGLExtensionSupported(const char *extension);
|
||||
}
|
||||
|
||||
|
||||
// WGL_ARB_pbuffer
|
||||
static WGLCreatePBufferProc wglCreatePBuffer;
|
||||
static WGLGetPBufferDCProc wglGetPBufferDC;
|
||||
static WGLReleasePBufferDCProc wglReleasePBufferDC;
|
||||
static WGLDestroyPBufferProc wglDestroyPBuffer;
|
||||
static WGLQueryPBufferProc wglQueryPBuffer;
|
||||
|
||||
// WGL_ARB_pixel_format
|
||||
static WGLGetPixelFormatAttribivProc wglGetPixelFormatAttribiv;
|
||||
static WGLGetPixelFormatAttribfvProc wglGetPixelFormatAttribfv;
|
||||
static WGLChoosePixelFormatProc wglChoosePixelFormat;
|
||||
|
||||
// WGL_ARB_render_texture
|
||||
static WGLBindTexImageProc wglBindTexImage;
|
||||
static WGLReleaseTexImageProc wglReleaseTexImage;
|
||||
static WGLSetPbufferAttribProc wglSetPbufferAttrib;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WGL_ARB_extensions_string
|
||||
#define WGL_ARB_extensions_string 1
|
||||
typedef const char * (WINAPI * WGLGetExtensionsStringProc) (HDC hDC);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
bool osg::isWGLExtensionSupported(const char *extension)
|
||||
{
|
||||
|
||||
typedef std::set<std::string> ExtensionSet;
|
||||
static ExtensionSet s_extensionSet;
|
||||
static const char* s_extensions = NULL;
|
||||
static WGLGetExtensionsStringProc wglGetExtensionsString = (WGLGetExtensionsStringProc)osg::getGLExtensionFuncPtr("wglGetExtensionsStringARB");
|
||||
if (wglGetExtensionsString == NULL) return false;
|
||||
if (s_extensions==NULL)
|
||||
{
|
||||
// get the extension list from OpenGL.
|
||||
s_extensions = (const char*)wglGetExtensionsString(::wglGetCurrentDC());
|
||||
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(osg::INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
|
||||
for(ExtensionSet::iterator itr=s_extensionSet.begin();
|
||||
itr!=s_extensionSet.end();
|
||||
++itr)
|
||||
{
|
||||
osg::notify(osg::INFO)<<" "<<*itr<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// true if extension found in extensionSet.
|
||||
bool result = s_extensionSet.find(extension)!=s_extensionSet.end();
|
||||
|
||||
if (result)
|
||||
osg::notify(osg::INFO)<<"OpenGL WGL extension '"<<extension<<"' is supported."<<std::endl;
|
||||
else
|
||||
osg::notify(osg::INFO)<<"OpenGL WGL extension '"<<extension<<"' is not supported."<<std::endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
PBuffer::PBuffer(const int width, const int height) :
|
||||
_width(width),
|
||||
_height(height),
|
||||
_hDC(NULL),
|
||||
_hGLcontext(NULL),
|
||||
_hPBuffer(NULL)
|
||||
{
|
||||
_doubleBuffer = false;
|
||||
_RGB = true;
|
||||
_shareLists = false;
|
||||
_minimumNumberDepthBits = 16;
|
||||
_minimumNumberAlphaBits = 8;
|
||||
_minimumNumberStencilBits = 0;
|
||||
_minimumNumberAccumulationBits = 0;
|
||||
}
|
||||
|
||||
PBuffer::~PBuffer()
|
||||
{
|
||||
if (_hPBuffer)
|
||||
{
|
||||
wglDeleteContext( _hGLcontext );
|
||||
wglReleasePBufferDC( _hPBuffer, _hDC );
|
||||
wglDestroyPBuffer( _hPBuffer );
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if the pbuffer was lost.
|
||||
// If it was lost, destroy it and then recreate it.
|
||||
void PBuffer::handleModeSwitch()
|
||||
{
|
||||
int lost = 0;
|
||||
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_LOST_ARB, &lost );
|
||||
|
||||
if ( lost )
|
||||
{
|
||||
this->~PBuffer();
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function actually does the creation of the p-buffer.
|
||||
// It can only be called once a window has already been created.
|
||||
void PBuffer::initialize()
|
||||
{
|
||||
setupGLExtenions();
|
||||
|
||||
HDC hdc = wglGetCurrentDC();
|
||||
HGLRC hglrc = wglGetCurrentContext();
|
||||
|
||||
// Query for a suitable pixel format based on the specified mode.
|
||||
std::vector<int> iattributes;
|
||||
std::vector<float> fattributes;
|
||||
|
||||
// P-buffer will be used with OpenGL
|
||||
iattributes.push_back(WGL_SUPPORT_OPENGL_ARB);
|
||||
iattributes.push_back(true);
|
||||
|
||||
// Since we are trying to create a pbuffer, the pixel format we
|
||||
// request (and subsequently use) must be "p-buffer capable".
|
||||
iattributes.push_back(WGL_DRAW_TO_PBUFFER_ARB);
|
||||
iattributes.push_back(true);
|
||||
|
||||
// Bind to texture
|
||||
iattributes.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
|
||||
iattributes.push_back(true);
|
||||
|
||||
//iattributes.push_back(WGL_ACCELERATION_ARB);
|
||||
//iattributes.push_back(WGL_FULL_ACCELERATION_ARB);
|
||||
|
||||
if (_RGB)
|
||||
{
|
||||
iattributes.push_back(WGL_PIXEL_TYPE_ARB);
|
||||
iattributes.push_back(WGL_TYPE_RGBA_ARB);
|
||||
|
||||
// We require a minimum of 8-bits for each R, G, B, and A.
|
||||
iattributes.push_back(WGL_RED_BITS_ARB);
|
||||
iattributes.push_back(8);
|
||||
iattributes.push_back(WGL_GREEN_BITS_ARB);
|
||||
iattributes.push_back(8);
|
||||
iattributes.push_back(WGL_BLUE_BITS_ARB);
|
||||
iattributes.push_back(8);
|
||||
if (_minimumNumberAlphaBits > 0)
|
||||
{
|
||||
iattributes.push_back(WGL_ALPHA_BITS_ARB);
|
||||
iattributes.push_back(_minimumNumberAlphaBits);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iattributes.push_back(WGL_PIXEL_TYPE_ARB);
|
||||
iattributes.push_back(WGL_TYPE_COLORINDEX_ARB);
|
||||
}
|
||||
|
||||
iattributes.push_back(WGL_DOUBLE_BUFFER_ARB);
|
||||
iattributes.push_back(_doubleBuffer);
|
||||
|
||||
if (_minimumNumberDepthBits > 0)
|
||||
{
|
||||
iattributes.push_back(WGL_DEPTH_BITS_ARB);
|
||||
iattributes.push_back(_minimumNumberDepthBits);
|
||||
}
|
||||
|
||||
if (_minimumNumberStencilBits > 0)
|
||||
{
|
||||
iattributes.push_back(WGL_STENCIL_BITS_ARB);
|
||||
iattributes.push_back(_minimumNumberStencilBits);
|
||||
}
|
||||
|
||||
if (_minimumNumberAccumulationBits > 0)
|
||||
{
|
||||
iattributes.push_back(WGL_ACCUM_BITS_ARB);
|
||||
iattributes.push_back(_minimumNumberAccumulationBits);
|
||||
}
|
||||
|
||||
// Terminate array
|
||||
iattributes.push_back(0);
|
||||
|
||||
|
||||
// Now obtain a list of pixel formats that meet these minimum requirements.
|
||||
int format;
|
||||
int pformat[MAX_PFORMATS];
|
||||
unsigned int nformats=0;
|
||||
if ( !wglChoosePixelFormat( hdc, &iattributes.front(), &fattributes.front(), MAX_PFORMATS, pformat, &nformats ) )
|
||||
{
|
||||
osg::notify(osg::FATAL)<< "pbuffer creation error: Couldn't find a suitable pixel format." <<std::endl;
|
||||
exit( -1 );
|
||||
}
|
||||
format = pformat[0];
|
||||
|
||||
|
||||
// Create the p-buffer.
|
||||
std::vector<int> pbattr;
|
||||
|
||||
// Texture format
|
||||
pbattr.push_back(WGL_TEXTURE_FORMAT_ARB);
|
||||
pbattr.push_back(WGL_TEXTURE_RGBA_ARB);
|
||||
#if 1
|
||||
// Texture target
|
||||
pbattr.push_back(WGL_TEXTURE_TARGET_ARB);
|
||||
pbattr.push_back(WGL_TEXTURE_2D_ARB);
|
||||
#else
|
||||
// Cubemap
|
||||
pbattr.push_back(WGL_TEXTURE_TARGET_ARB);
|
||||
pbattr.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
|
||||
|
||||
// Cubemap face
|
||||
pbattr.push_back(WGL_CUBE_MAP_FACE_ARB);
|
||||
pbattr.push_back(WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB);
|
||||
#endif
|
||||
// Terminate array
|
||||
pbattr.push_back(0);
|
||||
|
||||
iattributes[0] = 0;
|
||||
_hPBuffer = wglCreatePBuffer( hdc, format, _width, _height, &pbattr.front() );
|
||||
if ( !_hPBuffer )
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
osg::notify(osg::FATAL)<< "pbuffer creation error: wglCreatePBufferARB() failed\n" <<std::endl;
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_PIXEL_FORMAT:
|
||||
osg::notify(osg::FATAL)<< "error: ERROR_INVALID_PIXEL_FORMAT\n" <<std::endl;
|
||||
break;
|
||||
case ERROR_NO_SYSTEM_RESOURCES:
|
||||
osg::notify(osg::FATAL)<< "error: ERROR_NO_SYSTEM_RESOURCES\n" <<std::endl;
|
||||
break;
|
||||
case ERROR_INVALID_DATA:
|
||||
osg::notify(osg::FATAL)<< "error: ERROR_INVALID_DATA\n" <<std::endl;
|
||||
break;
|
||||
}
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
// Get the device context.
|
||||
_hDC = wglGetPBufferDC( _hPBuffer );
|
||||
if ( !_hDC )
|
||||
{
|
||||
osg::notify(osg::FATAL)<< "pbuffer creation error: wglGetPBufferDC() failed\n" << std::endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
// Create a gl context for the p-buffer.
|
||||
_hGLcontext = wglCreateContext( _hDC );
|
||||
if ( !_hGLcontext )
|
||||
{
|
||||
osg::notify(osg::FATAL)<< "pbuffer creation error: wglCreateContext() failed\n" << std::endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if( _shareLists )
|
||||
{
|
||||
if( !wglShareLists(hglrc, _hGLcontext) )
|
||||
{
|
||||
osg::notify(osg::FATAL)<< "pbuffer: wglShareLists() failed\n" << std::endl;
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the actual width and height we were able to create.
|
||||
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_width );
|
||||
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_height );
|
||||
|
||||
osg::notify(osg::INFO)<< "PBuffer created " << _width << " x " << _height << "pbuffer."<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
void PBuffer::releaseTexImage()
|
||||
{
|
||||
if(!wglReleaseTexImage( _hPBuffer, WGL_FRONT_LEFT_ARB ) )
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PBuffer::makeCurrent()
|
||||
{
|
||||
if ( !wglMakeCurrent( _hDC, _hGLcontext ) )
|
||||
{
|
||||
osg::notify(osg::FATAL)<< "PBuffer::makeCurrent() failed.\n"<< std::endl;
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PBuffer::bindTexImage(GLuint textureID)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
if(!::wglBindTexImage(_hPBuffer, WGL_FRONT_LEFT_ARB))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PBuffer::setupGLExtenions()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_isPBufferSupported = osg::isWGLExtensionSupported("WGL_ARB_pbuffer");
|
||||
if (_isPBufferSupported)
|
||||
{
|
||||
wglCreatePBuffer = (WGLCreatePBufferProc)osg::getGLExtensionFuncPtr("wglCreatePbufferARB");
|
||||
wglGetPBufferDC = (WGLGetPBufferDCProc)osg::getGLExtensionFuncPtr("wglGetPbufferDCARB");
|
||||
wglReleasePBufferDC = (WGLReleasePBufferDCProc)osg::getGLExtensionFuncPtr("wglReleasePbufferDCARB");
|
||||
wglDestroyPBuffer = (WGLDestroyPBufferProc)osg::getGLExtensionFuncPtr("wglDestroyPbufferARB");
|
||||
wglQueryPBuffer = (WGLQueryPBufferProc)osg::getGLExtensionFuncPtr("wglQueryPbufferARB");
|
||||
}
|
||||
|
||||
_isPixelFormatSupported = osg::isWGLExtensionSupported("WGL_ARB_pixel_format");
|
||||
if (_isPixelFormatSupported)
|
||||
{
|
||||
wglGetPixelFormatAttribiv = (WGLGetPixelFormatAttribivProc)osg::getGLExtensionFuncPtr("wglGetPixelFormatAttribivARB");
|
||||
wglGetPixelFormatAttribfv = (WGLGetPixelFormatAttribfvProc)osg::getGLExtensionFuncPtr("wglGetPixelFormatAttribfvARB");
|
||||
wglChoosePixelFormat = (WGLChoosePixelFormatProc)osg::getGLExtensionFuncPtr("wglChoosePixelFormatARB");
|
||||
}
|
||||
|
||||
_isRenderTextureSupported = osg::isWGLExtensionSupported("WGL_ARB_render_texture");
|
||||
if (_isRenderTextureSupported)
|
||||
{
|
||||
wglBindTexImage = (WGLBindTexImageProc)osg::getGLExtensionFuncPtr("wglBindTexImageARB");
|
||||
wglReleaseTexImage = (WGLReleaseTexImageProc)osg::getGLExtensionFuncPtr("wglReleaseTexImageARB");
|
||||
wglSetPbufferAttrib = (WGLSetPbufferAttribProc)osg::getGLExtensionFuncPtr("wglSetPbufferAttribARB");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if DEBUGGING
|
||||
fprintf( fp, "nformats = %d\n\n", nformats );
|
||||
int values[MAX_ATTRIBS];
|
||||
int iatr[MAX_ATTRIBS] = { WGL_PIXEL_TYPE_ARB, WGL_COLOR_BITS_ARB,
|
||||
WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB,
|
||||
WGL_ALPHA_BITS_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_ACCUM_BITS_ARB,
|
||||
WGL_DOUBLE_BUFFER_ARB, WGL_SUPPORT_OPENGL_ARB, WGL_ACCELERATION_ARB };
|
||||
int niatr = 12;
|
||||
for ( int j = 0; j < MAX_ATTRIBS; j++ )
|
||||
{
|
||||
values[j] = false;
|
||||
iattributes[j] = iattributes[2*j];
|
||||
}
|
||||
for ( unsigned int i = 0; i < nformats; i++ )
|
||||
{
|
||||
if ( !wglGetPixelFormatAttribivARB( hdc, pformat[i], 0, niatr, iatr, values ) )
|
||||
{
|
||||
fprintf( stderr, "pbuffer creation error: wglGetPixelFormatAttribiv() failed\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
fprintf( fp, "%d. pformat = %d\n", i, pformat[i] );
|
||||
fprintf( fp, "--------------------\n" );
|
||||
for ( int k = 0; k < niatr; k++ )
|
||||
{
|
||||
if ( iatr[k] == WGL_PIXEL_TYPE_ARB )
|
||||
{
|
||||
if ( values[k] == WGL_TYPE_COLORINDEX_ARB )
|
||||
fprintf( fp, " Pixel type = WGL_TYPE_COLORINDEX_ARB\n" );
|
||||
if ( values[k] == WGL_TYPE_RGBA_ARB )
|
||||
fprintf( fp, " Pixel type = WGL_TYPE_RGBA_ARB\n" );
|
||||
}
|
||||
if ( iatr[k] == WGL_COLOR_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " Color bits = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_RED_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " red %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_GREEN_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " green %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_BLUE_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " blue %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_ALPHA_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " alpha %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_DEPTH_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " Depth bits = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_STENCIL_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " Stencil bits = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_ACCUM_BITS_ARB )
|
||||
{
|
||||
fprintf( fp, " Accum bits = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_DOUBLE_BUFFER_ARB )
|
||||
{
|
||||
fprintf( fp, " Double Buffer = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_SUPPORT_OPENGL_ARB )
|
||||
{
|
||||
fprintf( fp, " Support OpenGL = %d\n", values[k] );
|
||||
}
|
||||
if ( iatr[k] == WGL_ACCELERATION_ARB )
|
||||
{
|
||||
if ( values[k] == WGL_FULL_ACCELERATION_ARB )
|
||||
fprintf( fp, " Acceleration = WGL_FULL_ACCELERATION_ARB\n" );
|
||||
if ( values[k] == WGL_GENERIC_ACCELERATION_ARB )
|
||||
fprintf( fp, " Acceleration = WGL_GENERIC_ACCELERATION_ARB\n" );
|
||||
}
|
||||
}
|
||||
fprintf( fp, "\n" );
|
||||
}
|
||||
fprintf( fp, "selected pformat = %d\n", format );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
#ifndef PBUFFERS_H
|
||||
#define PBUFFERS_H
|
||||
/*
|
||||
#include <windows.h>
|
||||
#include "GL/gl.h"
|
||||
#include <GL/glut.h>
|
||||
#include "GL/wglext.h"
|
||||
#include <GL/glext.h>
|
||||
*/
|
||||
|
||||
#include <osg/GL>
|
||||
|
||||
#if defined(WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WGL_ARB_pbuffer
|
||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
|
||||
#define WGL_ACCELERATION_ARB 0x2003
|
||||
#define WGL_NEED_PALETTE_ARB 0x2004
|
||||
#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
|
||||
#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
|
||||
#define WGL_SWAP_METHOD_ARB 0x2007
|
||||
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
|
||||
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
|
||||
#define WGL_TRANSPARENT_ARB 0x200A
|
||||
#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
|
||||
#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
|
||||
#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
|
||||
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
|
||||
#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
|
||||
#define WGL_SHARE_DEPTH_ARB 0x200C
|
||||
#define WGL_SHARE_STENCIL_ARB 0x200D
|
||||
#define WGL_SHARE_ACCUM_ARB 0x200E
|
||||
#define WGL_SUPPORT_GDI_ARB 0x200F
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||
#define WGL_STEREO_ARB 0x2012
|
||||
#define WGL_PIXEL_TYPE_ARB 0x2013
|
||||
#define WGL_COLOR_BITS_ARB 0x2014
|
||||
#define WGL_RED_BITS_ARB 0x2015
|
||||
#define WGL_RED_SHIFT_ARB 0x2016
|
||||
#define WGL_GREEN_BITS_ARB 0x2017
|
||||
#define WGL_GREEN_SHIFT_ARB 0x2018
|
||||
#define WGL_BLUE_BITS_ARB 0x2019
|
||||
#define WGL_BLUE_SHIFT_ARB 0x201A
|
||||
#define WGL_ALPHA_BITS_ARB 0x201B
|
||||
#define WGL_ALPHA_SHIFT_ARB 0x201C
|
||||
#define WGL_ACCUM_BITS_ARB 0x201D
|
||||
#define WGL_ACCUM_RED_BITS_ARB 0x201E
|
||||
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
|
||||
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
|
||||
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
|
||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
||||
#define WGL_AUX_BUFFERS_ARB 0x2024
|
||||
#define WGL_NO_ACCELERATION_ARB 0x2025
|
||||
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
|
||||
#define WGL_FULL_ACCELERATION_ARB 0x2027
|
||||
#define WGL_SWAP_EXCHANGE_ARB 0x2028
|
||||
#define WGL_SWAP_COPY_ARB 0x2029
|
||||
#define WGL_SWAP_UNDEFINED_ARB 0x202A
|
||||
#define WGL_TYPE_RGBA_ARB 0x202B
|
||||
#define WGL_TYPE_COLORINDEX_ARB 0x202C
|
||||
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
|
||||
#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
|
||||
#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
|
||||
#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
|
||||
#define WGL_PBUFFER_LARGEST_ARB 0x2033
|
||||
#define WGL_PBUFFER_WIDTH_ARB 0x2034
|
||||
#define WGL_PBUFFER_HEIGHT_ARB 0x2035
|
||||
#define WGL_PBUFFER_LOST_ARB 0x2036
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WGL_ARB_pbuffer
|
||||
#define WGL_ARB_pbuffer 1
|
||||
|
||||
DECLARE_HANDLE(HPBUFFERARB);
|
||||
|
||||
typedef HPBUFFERARB (WINAPI * WGLCreatePBufferProc) (
|
||||
HDC hDC,
|
||||
int iPixelFormat,
|
||||
int iWidth,
|
||||
int iHeight,
|
||||
const int *piAttribList);
|
||||
typedef HDC (WINAPI * WGLGetPBufferDCProc) (HPBUFFERARB hPbuffer);
|
||||
typedef int (WINAPI * WGLReleasePBufferDCProc) (
|
||||
HPBUFFERARB hPbuffer,
|
||||
HDC hDC);
|
||||
typedef BOOL (WINAPI * WGLDestroyPBufferProc) (HPBUFFERARB hPbuffer);
|
||||
typedef BOOL (WINAPI * WGLQueryPBufferProc) (
|
||||
HPBUFFERARB hPbuffer,
|
||||
int iAttribute,
|
||||
int *piValue);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WGL_ARB_pixel_format
|
||||
#define WGL_ARB_pixel_format 1
|
||||
typedef BOOL (WINAPI * WGLGetPixelFormatAttribivProc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
|
||||
typedef BOOL (WINAPI * WGLGetPixelFormatAttribfvProc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
|
||||
typedef BOOL (WINAPI * WGLChoosePixelFormatProc) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef WGL_ARB_render_texture
|
||||
#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
|
||||
#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
|
||||
#define WGL_TEXTURE_FORMAT_ARB 0x2072
|
||||
#define WGL_TEXTURE_TARGET_ARB 0x2073
|
||||
#define WGL_MIPMAP_TEXTURE_ARB 0x2074
|
||||
#define WGL_TEXTURE_RGB_ARB 0x2075
|
||||
#define WGL_TEXTURE_RGBA_ARB 0x2076
|
||||
#define WGL_NO_TEXTURE_ARB 0x2077
|
||||
#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
|
||||
#define WGL_TEXTURE_1D_ARB 0x2079
|
||||
#define WGL_TEXTURE_2D_ARB 0x207A
|
||||
#define WGL_NO_TEXTURE_ARB 0x2077
|
||||
#define WGL_MIPMAP_LEVEL_ARB 0x207B
|
||||
#define WGL_CUBE_MAP_FACE_ARB 0x207C
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
|
||||
#define WGL_FRONT_LEFT_ARB 0x2083
|
||||
#define WGL_FRONT_RIGHT_ARB 0x2084
|
||||
#define WGL_BACK_LEFT_ARB 0x2085
|
||||
#define WGL_BACK_RIGHT_ARB 0x2086
|
||||
#define WGL_AUX0_ARB 0x2087
|
||||
#define WGL_AUX1_ARB 0x2088
|
||||
#define WGL_AUX2_ARB 0x2089
|
||||
#define WGL_AUX3_ARB 0x208A
|
||||
#define WGL_AUX4_ARB 0x208B
|
||||
#define WGL_AUX5_ARB 0x208C
|
||||
#define WGL_AUX6_ARB 0x208D
|
||||
#define WGL_AUX7_ARB 0x208E
|
||||
#define WGL_AUX8_ARB 0x208F
|
||||
#define WGL_AUX9_ARB 0x2090
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_render_texture
|
||||
#define WGL_ARB_render_texture 1
|
||||
typedef BOOL (WINAPI * WGLBindTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * WGLReleaseTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * WGLSetPbufferAttribProc) (HPBUFFERARB hPbuffer, const int * piAttribList);
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_PFORMATS 256
|
||||
#define MAX_ATTRIBS 32
|
||||
|
||||
|
||||
|
||||
class PBuffer
|
||||
{
|
||||
private:
|
||||
|
||||
HDC _hDC; // Handle to a device context.
|
||||
HGLRC _hGLcontext; // Handle to a GL context.
|
||||
HPBUFFERARB _hPBuffer; // Handle to a pbuffer.
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
bool _doubleBuffer;
|
||||
bool _RGB;
|
||||
bool _shareLists;
|
||||
unsigned int _minimumNumberDepthBits;
|
||||
unsigned int _minimumNumberAlphaBits;
|
||||
unsigned int _minimumNumberStencilBits;
|
||||
unsigned int _minimumNumberAccumulationBits;
|
||||
|
||||
bool _isPBufferSupported;
|
||||
bool _isPixelFormatSupported;
|
||||
bool _isRenderTextureSupported;
|
||||
|
||||
public:
|
||||
|
||||
PBuffer(const int width, const int height );
|
||||
~PBuffer();
|
||||
void handleModeSwitch();
|
||||
void makeCurrent();
|
||||
void initialize();
|
||||
void bindTexImage(GLuint textureID);
|
||||
void releaseTexImage();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void setupGLExtenions();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgprerender.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgprerender
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgprerender.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgprerender
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,430 +0,0 @@
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Node>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/ColorMask>
|
||||
#include <osg/Depth>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/TransformCallback>
|
||||
#include <osgUtil/RenderToTextureStage>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
class MyUpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyUpdateCallback(osg::Node* subgraph):
|
||||
_subgraph(subgraph) {}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
// traverse the subgraph to update any nodes.
|
||||
if (_subgraph.valid()) _subgraph->accept(*nv);
|
||||
|
||||
// must traverse the Node's subgraph
|
||||
traverse(node,nv);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> _subgraph;
|
||||
};
|
||||
|
||||
class MyCullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyCullCallback(osg::Node* subgraph,osg::Texture2D* texture):
|
||||
_subgraph(subgraph),
|
||||
_texture(texture),
|
||||
_localState(new osg::StateSet) {}
|
||||
|
||||
MyCullCallback(osg::Node* subgraph,osg::Image* image):
|
||||
_subgraph(subgraph),
|
||||
_image(image),
|
||||
_localState(new osg::StateSet) {}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullVisitor && (_texture.valid()|| _image.valid()) && _subgraph.valid())
|
||||
{
|
||||
doPreRender(*node,*cullVisitor);
|
||||
|
||||
// must traverse the subgraph
|
||||
traverse(node,nv);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// must traverse the subgraph
|
||||
traverse(node,nv);
|
||||
}
|
||||
}
|
||||
|
||||
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);
|
||||
|
||||
osg::ref_ptr<osg::Node> _subgraph;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::ref_ptr<osg::Image> _image;
|
||||
osg::ref_ptr<osg::StateSet> _localState;
|
||||
|
||||
};
|
||||
|
||||
void MyCullCallback::doPreRender(osg::Node&, osgUtil::CullVisitor& cv)
|
||||
{
|
||||
const osg::BoundingSphere& bs = _subgraph->getBound();
|
||||
if (!bs.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create the render to texture stage.
|
||||
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;
|
||||
|
||||
// set up lighting.
|
||||
// currently ignore lights in the scene graph itself..
|
||||
// will do later.
|
||||
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage;
|
||||
|
||||
// set up the background color and clear mask.
|
||||
rtts->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,0.0f));
|
||||
rtts->setClearMask(previous_stage->getClearMask());
|
||||
|
||||
// set up to charge the same RenderStageLighting is the parent previous stage.
|
||||
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
|
||||
|
||||
|
||||
// record the render bin, to be restored after creation
|
||||
// of the render to text
|
||||
osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();
|
||||
|
||||
// set the current renderbin to be the newly created stage.
|
||||
cv.setCurrentRenderBin(rtts.get());
|
||||
|
||||
|
||||
float znear = 1.0f*bs.radius();
|
||||
float zfar = 3.0f*bs.radius();
|
||||
|
||||
// 2:1 aspect ratio as per flag geomtry below.
|
||||
float top = 0.25f*znear;
|
||||
float right = 0.5f*znear;
|
||||
|
||||
znear *= 0.9f;
|
||||
zfar *= 1.1f;
|
||||
|
||||
// set up projection.
|
||||
osg::RefMatrix* projection = new osg::RefMatrix;
|
||||
projection->makeFrustum(-right,right,-top,top,znear,zfar);
|
||||
|
||||
cv.pushProjectionMatrix(projection);
|
||||
|
||||
osg::RefMatrix* matrix = new osg::RefMatrix;
|
||||
matrix->makeLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
|
||||
|
||||
cv.pushModelViewMatrix(matrix);
|
||||
|
||||
cv.pushStateSet(_localState.get());
|
||||
|
||||
{
|
||||
|
||||
// traverse the subgraph
|
||||
_subgraph->accept(cv);
|
||||
|
||||
}
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popModelViewMatrix();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popProjectionMatrix();
|
||||
|
||||
// restore the previous renderbin.
|
||||
cv.setCurrentRenderBin(previousRenderBin);
|
||||
|
||||
if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0)
|
||||
{
|
||||
// getting to this point means that all the subgraph has been
|
||||
// culled by small feature culling or is beyond LOD ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int height = 256;
|
||||
int width = 512;
|
||||
|
||||
|
||||
const osg::Viewport& viewport = *cv.getViewport();
|
||||
|
||||
// offset the impostor viewport from the center of the main window
|
||||
// viewport as often the edges of the viewport might be obscured by
|
||||
// other windows, which can cause image/reading writing problems.
|
||||
int center_x = viewport.x()+viewport.width()/2;
|
||||
int center_y = viewport.y()+viewport.height()/2;
|
||||
|
||||
osg::Viewport* new_viewport = new osg::Viewport;
|
||||
new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
|
||||
rtts->setViewport(new_viewport);
|
||||
|
||||
_localState->setAttribute(new_viewport);
|
||||
|
||||
// and the render to texture stage to the current stages
|
||||
// dependancy list.
|
||||
cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get());
|
||||
|
||||
// if one exist attach texture to the RenderToTextureStage.
|
||||
if (_texture.valid()) rtts->setTexture(_texture.get());
|
||||
|
||||
// if one exist attach image to the RenderToTextureStage.
|
||||
if (_image.valid()) rtts->setImage(_image.get());
|
||||
|
||||
}
|
||||
|
||||
// call back which cretes a deformation field to oscilate the model.
|
||||
class MyGeometryCallback :
|
||||
public osg::Drawable::UpdateCallback,
|
||||
public osg::Drawable::AttributeFunctor
|
||||
{
|
||||
public:
|
||||
|
||||
MyGeometryCallback(const osg::Vec3& o,
|
||||
const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z,
|
||||
double period,double xphase,double amplitude):
|
||||
_firstCall(true),
|
||||
_startTime(0.0),
|
||||
_time(0.0),
|
||||
_period(period),
|
||||
_xphase(xphase),
|
||||
_amplitude(amplitude),
|
||||
_origin(o),
|
||||
_xAxis(x),
|
||||
_yAxis(y),
|
||||
_zAxis(z) {}
|
||||
|
||||
virtual void update(osg::NodeVisitor* nv,osg::Drawable* drawable)
|
||||
{
|
||||
const osg::FrameStamp* fs = nv->getFrameStamp();
|
||||
double referenceTime = fs->getReferenceTime();
|
||||
if (_firstCall)
|
||||
{
|
||||
_firstCall = false;
|
||||
_startTime = referenceTime;
|
||||
}
|
||||
|
||||
_time = referenceTime-_startTime;
|
||||
|
||||
drawable->accept(*this);
|
||||
drawable->dirtyBound();
|
||||
|
||||
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
|
||||
if (geometry)
|
||||
{
|
||||
osgUtil::SmoothingVisitor::smooth(*geometry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
|
||||
{
|
||||
if (type == osg::Drawable::VERTICES)
|
||||
{
|
||||
const float TwoPI=2.0f*osg::PI;
|
||||
const float phase = -_time/_period;
|
||||
|
||||
osg::Vec3* end = begin+count;
|
||||
for (osg::Vec3* itr=begin;itr<end;++itr)
|
||||
{
|
||||
osg::Vec3 dv(*itr-_origin);
|
||||
osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);
|
||||
|
||||
local.z() = local.x()*_amplitude*
|
||||
sinf(TwoPI*(phase+local.x()*_xphase));
|
||||
|
||||
(*itr) = _origin +
|
||||
_xAxis*local.x()+
|
||||
_yAxis*local.y()+
|
||||
_zAxis*local.z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _firstCall;
|
||||
|
||||
double _startTime;
|
||||
double _time;
|
||||
|
||||
double _period;
|
||||
double _xphase;
|
||||
float _amplitude;
|
||||
|
||||
osg::Vec3 _origin;
|
||||
osg::Vec3 _xAxis;
|
||||
osg::Vec3 _yAxis;
|
||||
osg::Vec3 _zAxis;
|
||||
|
||||
};
|
||||
|
||||
osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
|
||||
{
|
||||
if (!subgraph) return 0;
|
||||
|
||||
// create the quad to visualize.
|
||||
osg::Geometry* polyGeom = new osg::Geometry();
|
||||
|
||||
polyGeom->setSupportsDisplayList(false);
|
||||
|
||||
osg::Vec3 origin(0.0f,0.0f,0.0f);
|
||||
osg::Vec3 xAxis(1.0f,0.0f,0.0f);
|
||||
osg::Vec3 yAxis(0.0f,0.0f,1.0f);
|
||||
osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
|
||||
float height = 100.0f;
|
||||
float width = 200.0f;
|
||||
int noSteps = 20;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
osg::Vec3 bottom = origin;
|
||||
osg::Vec3 top = origin; top.z()+= height;
|
||||
osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));
|
||||
|
||||
osg::Vec2Array* texcoords = new osg::Vec2Array;
|
||||
osg::Vec2 bottom_texcoord(0.0f,0.0f);
|
||||
osg::Vec2 top_texcoord(0.0f,1.0f);
|
||||
osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f);
|
||||
|
||||
for(int i=0;i<noSteps;++i)
|
||||
{
|
||||
vertices->push_back(top);
|
||||
vertices->push_back(bottom);
|
||||
top+=dv;
|
||||
bottom+=dv;
|
||||
|
||||
texcoords->push_back(top_texcoord);
|
||||
texcoords->push_back(bottom_texcoord);
|
||||
top_texcoord+=dv_texcoord;
|
||||
bottom_texcoord+=dv_texcoord;
|
||||
}
|
||||
|
||||
|
||||
// pass the created vertex array to the points geometry object.
|
||||
polyGeom->setVertexArray(vertices);
|
||||
|
||||
polyGeom->setTexCoordArray(0,texcoords);
|
||||
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
polyGeom->setColorArray(colors);
|
||||
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size()));
|
||||
|
||||
// new we need to add the texture to the Drawable, we do so by creating a
|
||||
// StateSet to contain the Texture StateAttribute.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
|
||||
|
||||
polyGeom->setStateSet(stateset);
|
||||
|
||||
polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));
|
||||
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
geode->addDrawable(polyGeom);
|
||||
|
||||
osg::Group* parent = new osg::Group;
|
||||
|
||||
parent->setUpdateCallback(new MyUpdateCallback(subgraph));
|
||||
|
||||
parent->setCullCallback(new MyCullCallback(subgraph,texture));
|
||||
|
||||
parent->addChild(geode);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
if (!loadedModel)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create a transform to spin the model.
|
||||
osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
|
||||
loadedModelTransform->addChild(loadedModel);
|
||||
|
||||
osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
|
||||
loadedModelTransform->setUpdateCallback(nc);
|
||||
|
||||
osg::Group* rootNode = new osg::Group();
|
||||
// rootNode->addChild(loadedModelTransform);
|
||||
rootNode->addChild(createPreRenderSubGraph(loadedModelTransform));
|
||||
|
||||
|
||||
// add model to the viewer.
|
||||
viewer.addViewport( rootNode );
|
||||
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgreflect.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgreflect
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgreflect.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgreflect
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,368 +0,0 @@
|
||||
#include <osg/Node>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Stencil>
|
||||
#include <osg/ColorMask>
|
||||
#include <osg/Depth>
|
||||
#include <osg/ClipNode>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
#include <osgUtil/TransformCallback>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A simple demo demonstrating planar 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.
|
||||
|
||||
|
||||
osg::StateSet* createMirrorTexturedState(const std::string& filename)
|
||||
{
|
||||
osg::StateSet* dstate = new osg::StateSet;
|
||||
dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
|
||||
|
||||
// set up the texture.
|
||||
osg::Image* image = osgDB::readImageFile(filename.c_str());
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
dstate->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
|
||||
}
|
||||
|
||||
return dstate;
|
||||
}
|
||||
|
||||
|
||||
osg::Drawable* createMirrorSurface(float xMin,float xMax,float yMin,float yMax,float z)
|
||||
{
|
||||
|
||||
// set up the drawstate.
|
||||
|
||||
// set up the Geometry.
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(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);
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec3Array* norms = new osg::Vec3Array(1);
|
||||
(*norms)[0].set(0.0f,0.0f,1.0f);
|
||||
geom->setNormalArray(norms);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec2Array* tcoords = new osg::Vec2Array(4);
|
||||
(*tcoords)[0].set(0.0f,1.0f);
|
||||
(*tcoords)[1].set(0.0f,0.0f);
|
||||
(*tcoords)[2].set(1.0f,0.0f);
|
||||
(*tcoords)[3].set(1.0f,1.0f);
|
||||
geom->setTexCoordArray(0,tcoords);
|
||||
|
||||
osg::Vec4Array* colours = new osg::Vec4Array(1);
|
||||
(*colours)[0].set(1.0f,1.0f,1.0,1.0f);
|
||||
geom->setColorArray(colours);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
osg::Node* createMirroredScene(osg::Node* model)
|
||||
{
|
||||
|
||||
// calculate where to place the mirror according to the
|
||||
// loaded models bounding sphere.
|
||||
const osg::BoundingSphere& bs = model->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::MatrixTransform* rootNode = new osg::MatrixTransform;
|
||||
rootNode->setMatrix(osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f));
|
||||
|
||||
// make sure that the global color mask exists.
|
||||
osg::ColorMask* rootColorMask = new osg::ColorMask;
|
||||
rootColorMask->setMask(true,true,true,true);
|
||||
|
||||
// set up depth to be inherited by the rest of the scene unless
|
||||
// overrideen. this is overridden in bin 3.
|
||||
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(model);
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
// 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::ClipNode* clipNode = new osg::ClipNode;
|
||||
clipNode->addClipPlane(clipplane);
|
||||
|
||||
|
||||
osg::StateSet* dstate = clipNode->getOrCreateStateSet();
|
||||
dstate->setRenderBinDetails(4,"RenderBin");
|
||||
dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
|
||||
osg::Stencil* stencil = new osg::Stencil;
|
||||
stencil->setFunction(osg::Stencil::EQUAL,1,~0);
|
||||
stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
|
||||
dstate->setAttributeAndModes(stencil,osg::StateAttribute::ON);
|
||||
|
||||
osg::MatrixTransform* reverseMatrix = new osg::MatrixTransform;
|
||||
reverseMatrix->setStateSet(dstate);
|
||||
reverseMatrix->preMult(osg::Matrix::translate(0.0f,0.0f,-z)*
|
||||
osg::Matrix::scale(1.0f,1.0f,-1.0f)*
|
||||
osg::Matrix::translate(0.0f,0.0f,z));
|
||||
|
||||
reverseMatrix->addChild(model);
|
||||
|
||||
clipNode->addChild(reverseMatrix);
|
||||
|
||||
rootNode->addChild(clipNode);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 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::BlendFunc* trans = new osg::BlendFunc;
|
||||
trans->setFunction(osg::BlendFunc::ONE,osg::BlendFunc::ONE);
|
||||
|
||||
osg::StateSet* statesetBin5 = createMirrorTexturedState("Images/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);
|
||||
|
||||
}
|
||||
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
|
||||
|
||||
if (!loadedModel)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
|
||||
loadedModelTransform->addChild(loadedModel);
|
||||
|
||||
osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
|
||||
loadedModelTransform->setUpdateCallback(nc);
|
||||
|
||||
osg::Node* rootNode = createMirroredScene(loadedModelTransform);
|
||||
|
||||
// add model to the viewer.
|
||||
viewer.addViewport( rootNode );
|
||||
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
viewer.open();
|
||||
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgscribe.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgscribe
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgscribe.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgscribe
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,118 +0,0 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Material>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/LineStipple>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
|
||||
if (!loadedModel)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// to do scribe mode we create a top most group to contain the
|
||||
// original model, and then a second group contains the same model
|
||||
// but overrides various state attributes, so that the second instance
|
||||
// is rendered as wireframe.
|
||||
|
||||
osg::Group* rootnode = new osg::Group;
|
||||
|
||||
osg::Group* decorator = new osg::Group;
|
||||
|
||||
rootnode->addChild(loadedModel);
|
||||
|
||||
|
||||
rootnode->addChild(decorator);
|
||||
|
||||
decorator->addChild(loadedModel);
|
||||
|
||||
// set up the state so that the underlying color is not seen through
|
||||
// and that the drawing mode is changed to wireframe, and a polygon offset
|
||||
// is added to ensure that we see the wireframe itself, and turn off
|
||||
// so texturing too.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
osg::Material* material = new osg::Material;
|
||||
osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
|
||||
polyoffset->setFactor(-1.0f);
|
||||
polyoffset->setUnits(-1.0f);
|
||||
osg::PolygonMode* polymode = new osg::PolygonMode;
|
||||
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
|
||||
stateset->setAttributeAndModes(material,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
stateset->setAttributeAndModes(polyoffset,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
stateset->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
|
||||
|
||||
// osg::LineStipple* linestipple = new osg::LineStipple;
|
||||
// linestipple->setFactor(1);
|
||||
// linestipple->setPattern(0xf0f0);
|
||||
// stateset->setAttributeAndModes(linestipple,osg::StateAttribute::OVERRIDE_ON);
|
||||
|
||||
decorator->setStateSet(stateset);
|
||||
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgGA::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgsequence.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgsequence
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,11 +0,0 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgtexture.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgtexture
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
@@ -1,184 +0,0 @@
|
||||
// -*-c++-*-
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Sequence>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
//
|
||||
// A simple demo demonstrating usage of osg::Sequence.
|
||||
//
|
||||
|
||||
// simple event handler to start/stop sequences
|
||||
class MyEventHandler : public osgGA::GUIEventHandler {
|
||||
public:
|
||||
/// Constructor.
|
||||
MyEventHandler(std::vector<osg::Sequence*>* seq)
|
||||
{
|
||||
_seq = seq;
|
||||
}
|
||||
|
||||
/// Handle events.
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea,
|
||||
osgGA::GUIActionAdapter&)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)
|
||||
{
|
||||
const char keys[] = "!@#$%^&*()";
|
||||
for (unsigned int i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
|
||||
if (i < _seq->size() && ea.getKey() == keys[i])
|
||||
{
|
||||
// toggle sequence
|
||||
osg::Sequence* seq = (*_seq)[i];
|
||||
osg::Sequence::SequenceMode mode = seq->getMode();
|
||||
switch (mode) {
|
||||
case osg::Sequence::START:
|
||||
seq->setMode(osg::Sequence::PAUSE);
|
||||
break;
|
||||
case osg::Sequence::STOP:
|
||||
seq->setMode(osg::Sequence::START);
|
||||
break;
|
||||
case osg::Sequence::PAUSE:
|
||||
seq->setMode(osg::Sequence::RESUME);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
std::cerr << "Toggled sequence " << i << std::endl;
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
/// accept visits.
|
||||
virtual void accept(osgGA::GUIEventHandlerVisitor&) {}
|
||||
|
||||
private:
|
||||
std::vector<osg::Sequence*>* _seq;
|
||||
};
|
||||
|
||||
osg::Sequence* generateSeq(osg::Sequence::LoopMode mode,
|
||||
float speed, int nreps,
|
||||
std::vector<osg::Node*>& model)
|
||||
{
|
||||
osg::Sequence* seqNode = new osg::Sequence;
|
||||
|
||||
// add children, show each child for 1.0 seconds
|
||||
for (unsigned int i = 0; i < model.size(); i++) {
|
||||
seqNode->addChild(model[i]);
|
||||
seqNode->setTime(i, 1.0f);
|
||||
}
|
||||
|
||||
// interval
|
||||
seqNode->setInterval(mode, 0, -1);
|
||||
|
||||
// speed-up factor and number of repeats for entire sequence
|
||||
seqNode->setDuration(speed, nreps);
|
||||
|
||||
// stopped
|
||||
seqNode->setMode(osg::Sequence::STOP);
|
||||
|
||||
return seqNode;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getProgramName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// assumes any remaining parameters are models
|
||||
std::vector<osg::Node*> model;
|
||||
int i;
|
||||
for (i = 1; i < arguments.argc(); i++)
|
||||
{
|
||||
std::cerr << "Loading " << arguments[i] << std::endl;
|
||||
osg::Node* node = osgDB::readNodeFile(arguments[i]);
|
||||
if (node)
|
||||
model.push_back(node);
|
||||
}
|
||||
if (model.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// root
|
||||
osg::Group* rootNode = new osg::Group;
|
||||
|
||||
// create sequences
|
||||
std::vector<osg::Sequence*> seq;
|
||||
|
||||
const osg::Sequence::LoopMode mode[] = { osg::Sequence::LOOP,
|
||||
osg::Sequence::SWING,
|
||||
osg::Sequence::LOOP };
|
||||
const float speed[] = { 0.5f, 1.0f, 1.5f };
|
||||
const int nreps[] = { -1, 5, 1 };
|
||||
|
||||
float x = 0.0f;
|
||||
for (i = 0; i < (sizeof(speed) / sizeof(speed[0])); i++) {
|
||||
osg::Sequence* seqNode = generateSeq(mode[i], speed[i], nreps[i],
|
||||
model);
|
||||
if (!seqNode)
|
||||
continue;
|
||||
seq.push_back(seqNode);
|
||||
|
||||
// position sequence
|
||||
osg::Matrix matrix;
|
||||
matrix.makeTranslate(x, 0.0, 0.0);
|
||||
|
||||
osg::MatrixTransform* xform = new osg::MatrixTransform;
|
||||
xform->setMatrix(matrix);
|
||||
xform->addChild(seqNode);
|
||||
|
||||
rootNode->addChild(xform);
|
||||
|
||||
x += seqNode->getBound()._radius * 1.5f;
|
||||
}
|
||||
|
||||
// add model to viewer.
|
||||
viewer.addViewport(rootNode);
|
||||
|
||||
// register additional event handler
|
||||
viewer.prependEventHandler(new MyEventHandler(&seq), 0);
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
|
||||
viewer.open();
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/Material>
|
||||
#include <osg/LightSource>
|
||||
#include <osg/Geode>
|
||||
#include <osg/ShapeDrawable>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
#include <osgUtil/RenderToTextureStage>
|
||||
|
||||
#include "CreateShadowedScene.h"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
class CreateShadowTextureCullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit):
|
||||
_shadower(shadower),
|
||||
_position(position),
|
||||
_ambientLightColor(ambientLightColor),
|
||||
_unit(textureUnit),
|
||||
_shadowState(new osg::StateSet)
|
||||
{
|
||||
_texture = new osg::Texture2D;
|
||||
_texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullVisitor && (_texture.valid() && _shadower.valid()))
|
||||
{
|
||||
doPreRender(*node,*cullVisitor);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// must traverse the shadower
|
||||
traverse(node,nv);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);
|
||||
|
||||
osg::ref_ptr<osg::Node> _shadower;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::Vec3 _position;
|
||||
osg::Vec4 _ambientLightColor;
|
||||
unsigned int _unit;
|
||||
osg::ref_ptr<osg::StateSet> _shadowState;
|
||||
|
||||
// we need this to get round the order dependance
|
||||
// of eye linear tex gen...
|
||||
class MyTexGen : public TexGen
|
||||
{
|
||||
public:
|
||||
|
||||
void setMatrix(const osg::Matrix& matrix)
|
||||
{
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
||||
virtual void apply(osg::State& state) const
|
||||
{
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(_matrix.ptr());
|
||||
TexGen::apply(state);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
osg::Matrix _matrix;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv)
|
||||
{
|
||||
|
||||
const osg::BoundingSphere& bs = _shadower->getBound();
|
||||
if (!bs.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create the render to texture stage.
|
||||
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;
|
||||
|
||||
// set up lighting.
|
||||
// currently ignore lights in the scene graph itself..
|
||||
// will do later.
|
||||
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage;
|
||||
|
||||
// set up the background color and clear mask.
|
||||
rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
|
||||
rtts->setClearMask(previous_stage->getClearMask());
|
||||
|
||||
// set up to charge the same RenderStageLighting is the parent previous stage.
|
||||
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
|
||||
|
||||
|
||||
// record the render bin, to be restored after creation
|
||||
// of the render to text
|
||||
osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();
|
||||
|
||||
// set the current renderbin to be the newly created stage.
|
||||
cv.setCurrentRenderBin(rtts.get());
|
||||
|
||||
|
||||
float centerDistance = (_position-bs.center()).length();
|
||||
|
||||
float znear = centerDistance+bs.radius();
|
||||
float zfar = centerDistance-bs.radius();
|
||||
float zNearRatio = 0.001f;
|
||||
if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
|
||||
|
||||
|
||||
// 2:1 aspect ratio as per flag geomtry below.
|
||||
float top = (bs.radius()/centerDistance)*znear;
|
||||
float right = top;
|
||||
|
||||
// set up projection.
|
||||
osg::RefMatrix* projection = new osg::RefMatrix;
|
||||
projection->makeFrustum(-right,right,-top,top,znear,zfar);
|
||||
|
||||
cv.pushProjectionMatrix(projection);
|
||||
|
||||
osg::RefMatrix* matrix = new osg::RefMatrix;
|
||||
matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));
|
||||
|
||||
|
||||
osg::Matrix MV = cv.getModelViewMatrix();
|
||||
|
||||
// compute the matrix which takes a vertex from local coords into tex coords
|
||||
// will use this later to specify osg::TexGen..
|
||||
osg::Matrix MVPT =
|
||||
*matrix *
|
||||
*projection *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5f,0.5f,0.5f);
|
||||
|
||||
cv.pushModelViewMatrix(matrix);
|
||||
|
||||
// make the material black for a shadow.
|
||||
osg::Material* material = new osg::Material;
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK,_ambientLightColor);
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
|
||||
_shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE);
|
||||
|
||||
cv.pushStateSet(_shadowState.get());
|
||||
|
||||
{
|
||||
|
||||
// traverse the shadower
|
||||
_shadower->accept(cv);
|
||||
|
||||
}
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popModelViewMatrix();
|
||||
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popProjectionMatrix();
|
||||
|
||||
// restore the previous renderbin.
|
||||
cv.setCurrentRenderBin(previousRenderBin);
|
||||
|
||||
if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0)
|
||||
{
|
||||
// getting to this point means that all the shadower has been
|
||||
// culled by small feature culling or is beyond LOD ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int height = 256;
|
||||
int width = 256;
|
||||
|
||||
|
||||
const osg::Viewport& viewport = *cv.getViewport();
|
||||
|
||||
// offset the impostor viewport from the center of the main window
|
||||
// viewport as often the edges of the viewport might be obscured by
|
||||
// other windows, which can cause image/reading writing problems.
|
||||
int center_x = viewport.x()+viewport.width()/2;
|
||||
int center_y = viewport.y()+viewport.height()/2;
|
||||
|
||||
osg::Viewport* new_viewport = new osg::Viewport;
|
||||
new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
|
||||
rtts->setViewport(new_viewport);
|
||||
|
||||
_shadowState->setAttribute(new_viewport);
|
||||
|
||||
// and the render to texture stage to the current stages
|
||||
// dependancy list.
|
||||
cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get());
|
||||
|
||||
// if one exist attach texture to the RenderToTextureStage.
|
||||
if (_texture.valid()) rtts->setTexture(_texture.get());
|
||||
|
||||
|
||||
// set up the stateset to decorate the shadower with the shadow texture
|
||||
// with the appropriate tex gen coords.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
|
||||
MyTexGen* texgen = new MyTexGen;
|
||||
texgen->setMatrix(MV);
|
||||
texgen->setMode(osg::TexGen::EYE_LINEAR);
|
||||
texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0)));
|
||||
texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1)));
|
||||
texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2)));
|
||||
texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3)));
|
||||
|
||||
stateset->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON);
|
||||
stateset->setTextureAttribute(_unit,texgen);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
||||
|
||||
cv.pushStateSet(stateset);
|
||||
|
||||
// must traverse the shadower
|
||||
traverse(&node,&cv);
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// set up a light source with the shadower and shodower subgraphs below it
|
||||
// with the appropriate callbacks set up.
|
||||
osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit)
|
||||
{
|
||||
osg::LightSource* lightgroup = new osg::LightSource;
|
||||
|
||||
osg::Light* light = new osg::Light;
|
||||
light->setPosition(osg::Vec4(lightPosition,1.0f));
|
||||
light->setLightNum(0);
|
||||
|
||||
lightgroup->setLight(light);
|
||||
|
||||
osg::Vec4 ambientLightColor(0.1f,0.1f,0.1f,1.0f);
|
||||
|
||||
// add the shadower
|
||||
lightgroup->addChild(shadower);
|
||||
|
||||
// add the shadowed with the callback to generate the shadow texture.
|
||||
shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit));
|
||||
lightgroup->addChild(shadowed);
|
||||
|
||||
osg::Geode* lightgeode = new osg::Geode;
|
||||
lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));
|
||||
|
||||
lightgroup->addChild(lightgeode);
|
||||
|
||||
return lightgroup;
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef CREATESHADOWEDSCENE_H
|
||||
#define CREATESHADOWEDSCENE_H
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Vec3>
|
||||
|
||||
// function to create a lightsource which contain a shadower and showed subgraph,
|
||||
// the showadowed subgrph has a cull callback to fire off a pre render to texture
|
||||
// of the shadowed subgraph.
|
||||
extern osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user