Ported osgGLUT based src/Demos across to being osgProducer based, and placed
them in the new examples/ directory.
This commit is contained in:
parent
2ca505b3d8
commit
7083773b64
@ -18,7 +18,7 @@ SRC_DIRS = \
|
||||
osgSim\
|
||||
osgPlugins\
|
||||
../examples\
|
||||
src/Demos
|
||||
# src/Demos
|
||||
|
||||
|
||||
################################################################
|
||||
@ -86,14 +86,45 @@ endif
|
||||
# Directories traversed in the TOPDIR/examples directory
|
||||
|
||||
EXAMPLE_DIRS = \
|
||||
osganimate\
|
||||
osgbillboard\
|
||||
osgcallback\
|
||||
osgcameragroup\
|
||||
osgviewer\
|
||||
osgclip\
|
||||
osgconv\
|
||||
osgcopy\
|
||||
osgcubemap\
|
||||
osggeodemo\
|
||||
osggeometry\
|
||||
osghangglide\
|
||||
osghud\
|
||||
osgtext\
|
||||
osgimpostor\
|
||||
osglight\
|
||||
osglightpoint\
|
||||
osglogo\
|
||||
osgmultitexture\
|
||||
osgoccluder\
|
||||
osgparticle\
|
||||
osgprerender\
|
||||
osgreflect\
|
||||
osgscribe\
|
||||
osgsequence\
|
||||
osgshadowtexture\
|
||||
osgshape\
|
||||
osgstereoimage\
|
||||
osgstereoimage\
|
||||
osgteapot\
|
||||
osgtext\
|
||||
osgtexture1D\
|
||||
osgtexture2D\
|
||||
osgtexture3D\
|
||||
osgunittests\
|
||||
osgversion\
|
||||
osgvertexprogram\
|
||||
osgviewer\
|
||||
|
||||
# comment in you want to compile the cluster demo.
|
||||
# EXAMPLE_DIRS += osgcluster
|
||||
|
||||
################################################################
|
||||
# Directories traversed in the TOPDIR/src/Demos directory
|
||||
|
19
examples/osganimate/GNUmakefile
Normal file
19
examples/osganimate/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osganimate.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osganimate
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
14
examples/osganimate/GNUmakefile.inst
Normal file
14
examples/osganimate/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osganimate.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osganimate
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
262
examples/osganimate/osganimate.cpp
Normal file
262
examples/osganimate/osganimate.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgProducer/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.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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);
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(rootnode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgbillboard/GNUmakefile
Normal file
19
examples/osgbillboard/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgbillboard.cpp
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgbillboard
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
15
examples/osgbillboard/GNUmakefile.inst
Normal file
15
examples/osgbillboard/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgbillboard.cpp
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
|
||||
EXEC = osgbillboard
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
224
examples/osgbillboard/osgbillboard.cpp
Normal file
224
examples/osgbillboard/osgbillboard.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
#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 <osgProducer/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.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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();
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(rootNode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgcallback/GNUmakefile
Normal file
19
examples/osgcallback/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcallback.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcallback
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osgcallback/GNUmakefile.inst
Normal file
15
examples/osgcallback/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcallback.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcallback
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
201
examples/osgcallback/osgcallback.cpp
Normal file
201
examples/osgcallback/osgcallback.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
#include <osgProducer/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.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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);
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(rootnode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgcameragroup.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
|
@ -4,12 +4,11 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgcameragroup.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcameragroup
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
18
examples/osgclip/GNUmakefile
Normal file
18
examples/osgclip/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgclip.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgclip
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgclip/GNUmakefile.inst
Normal file
14
examples/osgclip/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgclip.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgclip
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
201
examples/osgclip/osgclip.cpp
Normal file
201
examples/osgclip/osgclip.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
#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 <osgProducer/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.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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);
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(rootnode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
23
examples/osgcluster/GNUmakefile
Normal file
23
examples/osgcluster/GNUmakefile
Normal file
@ -0,0 +1,23 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
broadcaster.cpp\
|
||||
osgcluster.cpp\
|
||||
receiver.cpp\
|
||||
|
||||
HEADERFILES =\
|
||||
broadcaster.h\
|
||||
receiver.h\
|
||||
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(SOCKET_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
$(HEADERFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcluster
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
13
examples/osgcluster/GNUmakefile.inst
Normal file
13
examples/osgcluster/GNUmakefile.inst
Normal file
@ -0,0 +1,13 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
broadcaster.cpp\
|
||||
osgcluster.cpp\
|
||||
receiver.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(SOCKET_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcluster
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
188
examples/osgcluster/broadcaster.cpp
Normal file
188
examples/osgcluster/broadcaster.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
#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
|
||||
|
||||
}
|
||||
|
55
examples/osgcluster/broadcaster.h
Normal file
55
examples/osgcluster/broadcaster.h
Normal file
@ -0,0 +1,55 @@
|
||||
#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
|
408
examples/osgcluster/osgcluster.cpp
Normal file
408
examples/osgcluster/osgcluster.cpp
Normal file
@ -0,0 +1,408 @@
|
||||
#ifdef USE_MEM_CHECK
|
||||
#include <mcheck.h>
|
||||
#endif
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgProducer/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 )
|
||||
{
|
||||
|
||||
// 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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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::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);
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(mySceneView.get());
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
145
examples/osgcluster/receiver.cpp
Normal file
145
examples/osgcluster/receiver.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#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
|
||||
}
|
||||
|
51
examples/osgcluster/receiver.h
Normal file
51
examples/osgcluster/receiver.h
Normal file
@ -0,0 +1,51 @@
|
||||
#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
|
@ -17,5 +17,4 @@ INSTFILES = \
|
||||
|
||||
EXEC = osgconv
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
@ -13,4 +13,7 @@ INSTFILES =\
|
||||
$(CXXFILES)\
|
||||
Makefile.inst=Makefile
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
18
examples/osgcopy/GNUmakefile
Normal file
18
examples/osgcopy/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcopy.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcopy
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgcopy/GNUmakefile.inst
Normal file
14
examples/osgcopy/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcopy.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcopy
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
243
examples/osgcopy/osgcopy.cpp
Normal file
243
examples/osgcopy/osgcopy.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
#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 <osgProducer/Viewer>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
// 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 osg::Referenced* operator() (const osg::Referenced* ref) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Referenced "<<ref<<std::endl;
|
||||
moveIn();
|
||||
osg::Referenced* ret_ref = CopyOp::operator()(ref);
|
||||
moveOut();
|
||||
return ret_ref;
|
||||
}
|
||||
|
||||
virtual osg::Object* operator() (const osg::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 osg::Node* operator() (const osg::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 osg::Drawable* operator() (const osg::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 osg::StateSet* operator() (const osg::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 osg::StateAttribute* operator() (const osg::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 osg::Texture* operator() (const osg::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 osg::Image* operator() (const osg::Image* image) const
|
||||
{
|
||||
writeIndent(); std::cout << "copying Image "<<image;
|
||||
if (image) std::cout<<" "<<image->className();
|
||||
std::cout<<std::endl;
|
||||
moveIn();
|
||||
osg::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.
|
||||
osgProducer::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 -------------------------------------------------------
|
||||
|
||||
// set the scene to render
|
||||
viewer.setSceneData(rootnode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgcubemap/GNUmakefile
Normal file
19
examples/osgcubemap/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcubemap.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgcubemap
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osgcubemap/GNUmakefile.inst
Normal file
15
examples/osgcubemap/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcubemap.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcubemap
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
140
examples/osgcubemap/osgcubemap.cpp
Normal file
140
examples/osgcubemap/osgcubemap.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData(rootnode);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osggeodemo/GNUmakefile
Normal file
19
examples/osggeodemo/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeodemo.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osggeodemo
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osggeodemo/GNUmakefile.inst
Normal file
15
examples/osggeodemo/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeomdemo.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osggeomdemo
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
185
examples/osggeodemo/osggeodemo.cpp
Normal file
185
examples/osggeodemo/osggeodemo.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
// Geo demo written by Geoff Michel, November 2002.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <osgProducer/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 "../../src/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("--fov <float>","Set the Field of View");
|
||||
|
||||
float camera_fov=-1;
|
||||
while (arguments.read("--fov",camera_fov)) {}
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
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.getEventHandlerList().push_front(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.getEventHandlerList().push_front(ghand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osggeometry/GNUmakefile
Normal file
18
examples/osggeometry/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeometry.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osggeometry
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osggeometry/GNUmakefile.inst
Normal file
14
examples/osggeometry/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osggeometry.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osggeometry
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
708
examples/osggeometry/osggeometry.cpp
Normal file
708
examples/osggeometry/osggeometry.cpp
Normal file
@ -0,0 +1,708 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( root );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
33
examples/osghangglide/GNUmakefile
Normal file
33
examples/osghangglide/GNUmakefile
Normal file
@ -0,0 +1,33 @@
|
||||
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 += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
$(HEADERFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osghangglide
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
22
examples/osghangglide/GNUmakefile.inst
Normal file
22
examples/osghangglide/GNUmakefile.inst
Normal file
@ -0,0 +1,22 @@
|
||||
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 += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osghangglide
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
241
examples/osghangglide/GliderManipulator.cpp
Normal file
241
examples/osghangglide/GliderManipulator.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
#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;
|
||||
}
|
65
examples/osghangglide/GliderManipulator.h
Normal file
65
examples/osghangglide/GliderManipulator.h
Normal file
@ -0,0 +1,65 @@
|
||||
#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
|
||||
|
78
examples/osghangglide/base.cpp
Normal file
78
examples/osghangglide/base.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#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;
|
||||
}
|
150
examples/osghangglide/hat.cpp
Normal file
150
examples/osghangglide/hat.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#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;
|
||||
}
|
4
examples/osghangglide/hat.h
Normal file
4
examples/osghangglide/hat.h
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef __HAT_H
|
||||
#define __HAT_H
|
||||
extern float Hat( float x, float y, float z );
|
||||
#endif
|
168
examples/osghangglide/osghangglide.cpp
Normal file
168
examples/osghangglide/osghangglide.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
unsigned int pos = viewer.addCameraManipulator(new GliderManipulator());
|
||||
viewer.selectCameraManipulator(pos);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
124
examples/osghangglide/sky.cpp
Normal file
124
examples/osghangglide/sky.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#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;
|
||||
}
|
166
examples/osghangglide/tank.cpp
Normal file
166
examples/osghangglide/tank.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#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;
|
||||
}
|
128
examples/osghangglide/terrain.cpp
Normal file
128
examples/osghangglide/terrain.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
// #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;
|
||||
}
|
1528
examples/osghangglide/terrain_coords.h
Normal file
1528
examples/osghangglide/terrain_coords.h
Normal file
File diff suppressed because it is too large
Load Diff
4421
examples/osghangglide/terrain_normals.h
Normal file
4421
examples/osghangglide/terrain_normals.h
Normal file
File diff suppressed because it is too large
Load Diff
2936
examples/osghangglide/terrain_texcoords.h
Normal file
2936
examples/osghangglide/terrain_texcoords.h
Normal file
File diff suppressed because it is too large
Load Diff
273
examples/osghangglide/trees.cpp
Normal file
273
examples/osghangglide/trees.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
#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;
|
||||
}
|
@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osghud.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
|
@ -4,12 +4,11 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osghud.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osghud
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
19
examples/osgimpostor/GNUmakefile
Normal file
19
examples/osgimpostor/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
TestManipulator.cpp\
|
||||
osgimpostor.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgimpostor
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgimpostor/GNUmakefile.inst
Normal file
14
examples/osgimpostor/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgimpostor.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgimpostor
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
382
examples/osgimpostor/TestManipulator.cpp
Normal file
382
examples/osgimpostor/TestManipulator.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
#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;
|
||||
}
|
80
examples/osgimpostor/TestManipulator.h
Normal file
80
examples/osgimpostor/TestManipulator.h
Normal file
@ -0,0 +1,80 @@
|
||||
//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>
|
||||
|
||||
class TestManipulator : public osgGA::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 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);
|
||||
|
||||
private:
|
||||
|
||||
/** Reset the internal GUIEvent stack.*/
|
||||
void flushMouseEventStack();
|
||||
/** Add the current mouse GUIEvent to internal stack.*/
|
||||
void addMouseEvent(const osgGA::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 osgGA::GUIEventAdapter> _ga_t1;
|
||||
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
|
||||
|
||||
osg::ref_ptr<osg::Node> _node;
|
||||
|
||||
float _modelScale;
|
||||
float _minimumZoomScale;
|
||||
|
||||
bool _thrown;
|
||||
|
||||
osg::Vec3 _center;
|
||||
osg::Quat _rotation;
|
||||
float _distance;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
344
examples/osgimpostor/osgimpostor.cpp
Normal file
344
examples/osgimpostor/osgimpostor.cpp
Normal file
@ -0,0 +1,344 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Impostor>
|
||||
#include <osg/Material>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Quat>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <osgUtil/InsertImpostorsVisitor>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgProducer/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 )
|
||||
{
|
||||
// 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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// add local test manipulator more suitable for testing impostors.
|
||||
unsigned int pos = viewer.addCameraManipulator(new TestManipulator);
|
||||
viewer.selectCameraManipulator(pos);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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 = 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.setSceneData(model);
|
||||
|
||||
// register trackball, flight and drive.
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osglight/GNUmakefile
Normal file
19
examples/osglight/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglight.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglight
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osglight/GNUmakefile.inst
Normal file
15
examples/osglight/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglight.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglight
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
379
examples/osglight/osglight.cpp
Normal file
379
examples/osglight/osglight.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
#include <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
// set all the sceneview's up so that their left and right add cull masks are set up.
|
||||
for(osgProducer::OsgCameraGroup::SceneHandlerList::iterator itr=viewer.getSceneHandlerList().begin();
|
||||
itr!=viewer.getSceneHandlerList().end();
|
||||
++itr)
|
||||
{
|
||||
osgUtil::SceneView* sceneview = *itr;
|
||||
// switch off small feature culling to prevent the light points from being culled.
|
||||
sceneview->setCullingMode( sceneview->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
|
||||
//sceneview->setCullingMode( 0);
|
||||
}
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osglightpoint/GNUmakefile
Normal file
19
examples/osglightpoint/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglightpoint.cpp\
|
||||
|
||||
LIBS += -losgSim -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglightpoint
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osglightpoint/GNUmakefile.inst
Normal file
15
examples/osglightpoint/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglightpoint.cpp\
|
||||
|
||||
LIBS += -losgSim -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglightpoint
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
189
examples/osglightpoint/osglightpoint.cpp
Normal file
189
examples/osglightpoint/osglightpoint.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
#include <osg/GL>
|
||||
#include <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osglogo/GNUmakefile
Normal file
18
examples/osglogo/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglogo.cpp\
|
||||
|
||||
LIBS += -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osglogo
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osglogo/GNUmakefile.inst
Normal file
14
examples/osglogo/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osglogo.cpp\
|
||||
|
||||
LIBS += -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osglogo
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
465
examples/osglogo/osglogo.cpp
Normal file
465
examples/osglogo/osglogo.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (arguments.read("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.setSceneData( node );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgmultitexture/GNUmakefile
Normal file
19
examples/osgmultitexture/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgmultitexture.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgmultitexture
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osgmultitexture/GNUmakefile.inst
Normal file
15
examples/osgmultitexture/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgmultitexture.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgmultitexture
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
112
examples/osgmultitexture/osgmultitexture.cpp
Normal file
112
examples/osgmultitexture/osgmultitexture.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgoccluder/GNUmakefile
Normal file
19
examples/osgoccluder/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgoccluder.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgoccluder
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osgoccluder/GNUmakefile.inst
Normal file
15
examples/osgoccluder/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgoccluder.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgoccluder
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
370
examples/osgoccluder/osgoccluder.cpp
Normal file
370
examples/osgoccluder/osgoccluder.cpp
Normal file
@ -0,0 +1,370 @@
|
||||
#include <osgProducer/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.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
bool manuallyCreateOccluders = false;
|
||||
while (arguments.read("-c")) { manuallyCreateOccluders = true; }
|
||||
|
||||
// register trackball, flight and drive.
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
if (manuallyCreateOccluders)
|
||||
{
|
||||
osgUtil::SceneView* sceneview = viewer.getSceneHandlerList()[0];
|
||||
|
||||
viewer.getEventHandlerList().push_front(new OccluderEventHandler(sceneview,rootnode));
|
||||
}
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/osgparticle/GNUmakefile
Normal file
19
examples/osgparticle/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
16
examples/osgparticle/GNUmakefile.inst
Normal file
16
examples/osgparticle/GNUmakefile.inst
Normal file
@ -0,0 +1,16 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
405
examples/osgparticle/osgparticle.cpp
Normal file
405
examples/osgparticle/osgparticle.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
#include <osgProducer/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° 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)
|
||||
{
|
||||
// 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] image_file_left_eye image_file_right_eye");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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 *root = new osg::Group;
|
||||
build_world(root);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.setSceneData(root);
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osgprerender/GNUmakefile
Normal file
18
examples/osgprerender/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgprerender.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgprerender
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgprerender/GNUmakefile.inst
Normal file
14
examples/osgprerender/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgprerender.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgprerender
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
444
examples/osgprerender/osgprerender.cpp
Normal file
444
examples/osgprerender/osgprerender.cpp
Normal file
@ -0,0 +1,444 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootNode );
|
||||
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgreflect.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
|
@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgviewer.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgviewer
|
||||
|
||||
@ -12,4 +12,7 @@ INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
18
examples/osgscribe/GNUmakefile
Normal file
18
examples/osgscribe/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgscribe.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgscribe
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgscribe/GNUmakefile.inst
Normal file
14
examples/osgscribe/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgscribe.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgscribe
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
129
examples/osgscribe/osgscribe.cpp
Normal file
129
examples/osgscribe/osgscribe.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#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 <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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.setSceneData( rootnode );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osgsequence/GNUmakefile
Normal file
18
examples/osgsequence/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgsequence.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgsequence
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgsequence/GNUmakefile.inst
Normal file
14
examples/osgsequence/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgtexture.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgtexture
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
201
examples/osgsequence/osgsequence.cpp
Normal file
201
examples/osgsequence/osgsequence.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
// -*-c++-*-
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Sequence>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgProducer/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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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;
|
||||
for (int 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 (unsigned int j = 0; j < (sizeof(speed) / sizeof(speed[0])); j++) {
|
||||
osg::Sequence* seqNode = generateSeq(mode[j], speed[j], nreps[j],
|
||||
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.setSceneData(rootNode);
|
||||
|
||||
// register additional event handler
|
||||
viewer.getEventHandlerList().push_front(new MyEventHandler(&seq));
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
274
examples/osgshadowtexture/CreateShadowedScene.cpp
Normal file
274
examples/osgshadowtexture/CreateShadowedScene.cpp
Normal file
@ -0,0 +1,274 @@
|
||||
#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;
|
||||
}
|
||||
|
12
examples/osgshadowtexture/CreateShadowedScene.h
Normal file
12
examples/osgshadowtexture/CreateShadowedScene.h
Normal file
@ -0,0 +1,12 @@
|
||||
#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
|
19
examples/osgshadowtexture/GNUmakefile
Normal file
19
examples/osgshadowtexture/GNUmakefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
CreateShadowedScene.cpp\
|
||||
osgshadowtexture.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgshadowtexture
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
15
examples/osgshadowtexture/GNUmakefile.inst
Normal file
15
examples/osgshadowtexture/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
CreateShadowedScene.cpp\
|
||||
osgshadowtexture.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgshadowtexture
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
240
examples/osgshadowtexture/osgshadowtexture.cpp
Normal file
240
examples/osgshadowtexture/osgshadowtexture.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
|
||||
#include <osgProducer/Viewer>
|
||||
|
||||
|
||||
// include the call which creates the shadowed subgraph.
|
||||
#include "CreateShadowedScene.h"
|
||||
|
||||
|
||||
// for the grid data..
|
||||
#include "../osghangglide/terrain_coords.h"
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
|
||||
// set up the texture of the base.
|
||||
osg::StateSet* stateset = new osg::StateSet();
|
||||
osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
geode->setStateSet( stateset );
|
||||
|
||||
|
||||
osg::Grid* grid = new osg::Grid;
|
||||
grid->allocateGrid(38,39);
|
||||
grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f));
|
||||
grid->setXInterval(radius*2.0f/(float)(38-1));
|
||||
grid->setYInterval(radius*2.0f/(float)(39-1));
|
||||
|
||||
float minHeight = FLT_MAX;
|
||||
float maxHeight = -FLT_MAX;
|
||||
|
||||
|
||||
unsigned int r;
|
||||
for(r=0;r<39;++r)
|
||||
{
|
||||
for(unsigned int c=0;c<38;++c)
|
||||
{
|
||||
float h = vertex[r+c*39][2];
|
||||
if (h>maxHeight) maxHeight=h;
|
||||
if (h<minHeight) minHeight=h;
|
||||
}
|
||||
}
|
||||
|
||||
float hieghtScale = radius*0.5f/(maxHeight-minHeight);
|
||||
float hieghtOffset = -(minHeight+maxHeight)*0.5f;
|
||||
|
||||
for(r=0;r<39;++r)
|
||||
{
|
||||
for(unsigned int c=0;c<38;++c)
|
||||
{
|
||||
float h = vertex[r+c*39][2];
|
||||
grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale);
|
||||
}
|
||||
}
|
||||
|
||||
geode->addDrawable(new osg::ShapeDrawable(grid));
|
||||
|
||||
osg::Group* group = new osg::Group;
|
||||
group->addChild(geode);
|
||||
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
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* 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,2.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::Vec3 lightPosition(center+osg::Vec3(0.0f,0.0f,radius));
|
||||
|
||||
// the shadower model
|
||||
osg::Node* shadower = createMovingModel(center,radius*0.5f);
|
||||
|
||||
// the shadowed model
|
||||
osg::Node* shadowed = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.25),radius);
|
||||
|
||||
// combine the models together to create one which has the shadower and the shadowed with the required callback.
|
||||
osg::Group* root = createShadowedScene(shadower,shadowed,lightPosition,radius/100.0f,1);
|
||||
|
||||
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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// comment out optimization over the scene graph right now as it optimizers away the shadow... will look into this..
|
||||
//osgUtil::Optimizer optimzer;
|
||||
//optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.setSceneData( model );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osgshape/GNUmakefile
Normal file
18
examples/osgshape/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgshape.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgshape
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgshape/GNUmakefile.inst
Normal file
14
examples/osgshape/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgshape.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgshape
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
143
examples/osgshape/osgshape.cpp
Normal file
143
examples/osgshape/osgshape.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Material>
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgProducer/Viewer>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osg/Math>
|
||||
|
||||
// for the grid data..
|
||||
#include "../osghangglide/terrain_coords.h"
|
||||
|
||||
osg::Geode* createShapes()
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// ---------------------------------------
|
||||
// Set up a StateSet to texture the objects
|
||||
// ---------------------------------------
|
||||
osg::StateSet* stateset = new osg::StateSet();
|
||||
|
||||
osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
geode->setStateSet( stateset );
|
||||
|
||||
float radius = 0.8f;
|
||||
float height = 1.0f;
|
||||
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)));
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.0f,0.0f,0.0f),2*radius)));
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height)));
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height)));
|
||||
|
||||
osg::Grid* grid = new osg::Grid;
|
||||
grid->allocateGrid(38,39);
|
||||
grid->setXInterval(0.28f);
|
||||
grid->setYInterval(0.28f);
|
||||
|
||||
for(unsigned int r=0;r<39;++r)
|
||||
{
|
||||
for(unsigned int c=0;c<38;++c)
|
||||
{
|
||||
grid->setHeight(c,r,vertex[r+c*39][2]);
|
||||
}
|
||||
}
|
||||
geode->addDrawable(new osg::ShapeDrawable(grid));
|
||||
|
||||
osg::ConvexHull* mesh = new osg::ConvexHull;
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array(4);
|
||||
(*vertices)[0].set(7.0+0.0f,-1.0f+2.0f,-1.0f+0.0f);
|
||||
(*vertices)[1].set(7.0+1.0f,-1.0f+0.0f,-1.0f+0.0f);
|
||||
(*vertices)[2].set(7.0+2.0f,-1.0f+2.0f,-1.0f+0.0f);
|
||||
(*vertices)[3].set(7.0+1.0f,-1.0f+1.0f,-1.0f+2.0f);
|
||||
osg::UByteArray* indices = new osg::UByteArray(12);
|
||||
(*indices)[0]=0;
|
||||
(*indices)[1]=2;
|
||||
(*indices)[2]=1;
|
||||
(*indices)[3]=0;
|
||||
(*indices)[4]=1;
|
||||
(*indices)[5]=3;
|
||||
(*indices)[6]=1;
|
||||
(*indices)[7]=2;
|
||||
(*indices)[8]=3;
|
||||
(*indices)[9]=2;
|
||||
(*indices)[10]=0;
|
||||
(*indices)[11]=3;
|
||||
mesh->setVertices(vertices);
|
||||
mesh->setIndices(indices);
|
||||
geode->addDrawable(new osg::ShapeDrawable(mesh));
|
||||
|
||||
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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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::Node* node = createShapes();
|
||||
|
||||
// add model to viewer.
|
||||
viewer.setSceneData( node );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
examples/osgteapot/GNUmakefile
Normal file
18
examples/osgteapot/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgteapot.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgteapot
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
14
examples/osgteapot/GNUmakefile.inst
Normal file
14
examples/osgteapot/GNUmakefile.inst
Normal file
@ -0,0 +1,14 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgcube.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgcube
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
374
examples/osgteapot/osgteapot.cpp
Normal file
374
examples/osgteapot/osgteapot.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
#include <osgProducer/Viewer>
|
||||
|
||||
|
||||
// The classic OpenGL teapot... taken form glut-3.7/lib/glut/glut_teapot.c
|
||||
|
||||
/* Copyright (c) Mark J. Kilgard, 1994. */
|
||||
|
||||
/**
|
||||
(c) Copyright 1993, Silicon Graphics, Inc.
|
||||
|
||||
ALL RIGHTS RESERVED
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that
|
||||
both the copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Silicon
|
||||
Graphics, Inc. not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission.
|
||||
|
||||
THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
|
||||
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
|
||||
OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
|
||||
EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
|
||||
ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
|
||||
CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
|
||||
INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
|
||||
SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
|
||||
NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
|
||||
OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
US Government Users Restricted Rights
|
||||
|
||||
Use, duplication, or disclosure by the Government is subject to
|
||||
restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||
(c)(1)(ii) of the Rights in Technical Data and Computer
|
||||
Software clause at DFARS 252.227-7013 and/or in similar or
|
||||
successor clauses in the FAR or the DOD or NASA FAR
|
||||
Supplement. Unpublished-- rights reserved under the copyright
|
||||
laws of the United States. Contractor/manufacturer is Silicon
|
||||
Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
|
||||
94039-7311.
|
||||
|
||||
OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||
*/
|
||||
|
||||
|
||||
/* Rim, body, lid, and bottom data must be reflected in x and
|
||||
y; handle and spout data across the y axis only. */
|
||||
|
||||
static int patchdata[][16] =
|
||||
{
|
||||
/* rim */
|
||||
{102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15},
|
||||
/* body */
|
||||
{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27},
|
||||
{24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36,
|
||||
37, 38, 39, 40},
|
||||
/* lid */
|
||||
{96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101,
|
||||
101, 0, 1, 2, 3,},
|
||||
{0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112,
|
||||
113, 114, 115, 116, 117},
|
||||
/* bottom */
|
||||
{118, 118, 118, 118, 124, 122, 119, 121, 123, 126,
|
||||
125, 120, 40, 39, 38, 37},
|
||||
/* handle */
|
||||
{41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
||||
53, 54, 55, 56},
|
||||
{53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
28, 65, 66, 67},
|
||||
/* spout */
|
||||
{68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83},
|
||||
{80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
|
||||
92, 93, 94, 95}
|
||||
};
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
static float cpdata[][3] =
|
||||
{
|
||||
{0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
|
||||
-0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
|
||||
{0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
|
||||
0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
|
||||
2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
|
||||
2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
|
||||
{1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
|
||||
1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
|
||||
{0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
|
||||
0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
|
||||
0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
|
||||
{1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
|
||||
{1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
|
||||
-1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
|
||||
-0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
|
||||
2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
|
||||
2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
|
||||
2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
|
||||
{-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
|
||||
-0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
|
||||
1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
|
||||
-0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
|
||||
1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
|
||||
0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
|
||||
0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
|
||||
{2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
|
||||
-0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
|
||||
2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
|
||||
{3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
|
||||
{3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
|
||||
{2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
|
||||
3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
|
||||
3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
|
||||
-0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
|
||||
2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
|
||||
2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
|
||||
2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
|
||||
{0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
|
||||
-0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
|
||||
0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
|
||||
{0.84, -1.5, 0.075}
|
||||
};
|
||||
|
||||
static float tex[2][2][2] =
|
||||
{
|
||||
{ {0, 0},
|
||||
{1, 0}},
|
||||
{ {0, 1},
|
||||
{1, 1}}
|
||||
};
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
teapot(GLint grid, GLenum type)
|
||||
{
|
||||
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
|
||||
long i, j, k, l;
|
||||
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
|
||||
glEnable(GL_AUTO_NORMAL);
|
||||
glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_MAP2_VERTEX_3);
|
||||
glEnable(GL_MAP2_TEXTURE_COORD_2);
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
for (l = 0; l < 3; l++) {
|
||||
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
||||
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
||||
if (l == 1)
|
||||
q[j][k][l] *= -1.0;
|
||||
if (i < 6) {
|
||||
r[j][k][l] =
|
||||
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
||||
if (l == 0)
|
||||
r[j][k][l] *= -1.0;
|
||||
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
||||
if (l == 0)
|
||||
s[j][k][l] *= -1.0;
|
||||
if (l == 1)
|
||||
s[j][k][l] *= -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2,
|
||||
&tex[0][0][0]);
|
||||
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
|
||||
&p[0][0][0]);
|
||||
glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
|
||||
glEvalMesh2(type, 0, grid, 0, grid);
|
||||
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
|
||||
&q[0][0][0]);
|
||||
glEvalMesh2(type, 0, grid, 0, grid);
|
||||
if (i < 6) {
|
||||
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
|
||||
&r[0][0][0]);
|
||||
glEvalMesh2(type, 0, grid, 0, grid);
|
||||
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
|
||||
&s[0][0][0]);
|
||||
glEvalMesh2(type, 0, grid, 0, grid);
|
||||
}
|
||||
}
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
// Now the OSG wrapper for the above OpenGL code, the most complicated bit is computing
|
||||
// the bounding box for the above example, normally you'll find this the easy bit.
|
||||
class Teapot : public osg::Drawable
|
||||
{
|
||||
public:
|
||||
Teapot() {}
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
Teapot(const Teapot& teapot,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
osg::Drawable(teapot,copyop) {}
|
||||
|
||||
META_Object(myTeapotApp,Teapot)
|
||||
|
||||
|
||||
// the draw immediate mode method is where the OSG wraps up the drawing of
|
||||
// of OpenGL primitives.
|
||||
virtual void drawImplementation(osg::State&) const
|
||||
{
|
||||
// teapot(..) doens't use vertex arrays at all so we don't need to toggle their state
|
||||
// if we did we'd need to something like following call
|
||||
// state.disableAllVertexArrays(), see src/osg/Geometry.cpp for the low down.
|
||||
|
||||
// just call the OpenGL code.
|
||||
teapot(14,GL_FILL);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~Teapot() {}
|
||||
|
||||
// we need to set up the bounding box of the data too, so that the scene graph knows where this
|
||||
// objects is, for both positioning the camera at start up, and most importantly for culling.
|
||||
virtual bool computeBound() const
|
||||
{
|
||||
_bbox.init();
|
||||
|
||||
// follow is some truely horrible code required to calculate the
|
||||
// bounding box of the teapot. Have used the original code above to do
|
||||
// help compute it.
|
||||
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
|
||||
long i, j, k, l;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
|
||||
for (l = 0; l < 3; l++) {
|
||||
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
||||
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
||||
if (l == 1)
|
||||
q[j][k][l] *= -1.0;
|
||||
|
||||
if (i < 6) {
|
||||
r[j][k][l] =
|
||||
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
|
||||
if (l == 0)
|
||||
r[j][k][l] *= -1.0;
|
||||
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
|
||||
if (l == 0)
|
||||
s[j][k][l] *= -1.0;
|
||||
if (l == 1)
|
||||
s[j][k][l] *= -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
_bbox.expandBy(osg::Vec3(p[j][k][0],p[j][k][1],p[j][k][2]));
|
||||
_bbox.expandBy(osg::Vec3(q[j][k][0],q[j][k][1],q[j][k][2]));
|
||||
|
||||
if (i < 6)
|
||||
{
|
||||
_bbox.expandBy(osg::Vec3(r[j][k][0],r[j][k][1],r[j][k][2]));
|
||||
_bbox.expandBy(osg::Vec3(s[j][k][0],s[j][k][1],s[j][k][2]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bbox_computed = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
osg::Geode* createTeapot()
|
||||
{
|
||||
osg::Geode* geode = new osg::Geode();
|
||||
|
||||
// add the teapot to the geode.
|
||||
geode->addDrawable( new Teapot );
|
||||
|
||||
// add a reflection map to the teapot.
|
||||
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::StateSet* stateset = new osg::StateSet;
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
stateset->setTextureAttributeAndModes(0,texgen,osg::StateAttribute::ON);
|
||||
|
||||
geode->setStateSet(stateset);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
// construct the viewer.
|
||||
osgProducer::Viewer viewer(arguments);
|
||||
|
||||
// set up the value with sensible default event handlers.
|
||||
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
|
||||
|
||||
// get details on keyboard and mouse bindings used by the viewer.
|
||||
viewer.getUsage(*arguments.getApplicationUsage());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// add model to viewer.
|
||||
viewer.setSceneData( createTeapot() );
|
||||
|
||||
// create the windows and run the threads.
|
||||
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
|
||||
|
||||
while( !viewer.done() )
|
||||
{
|
||||
// wait for all cull and draw threads to complete.
|
||||
viewer.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
viewer.update();
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
viewer.frame();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgtext.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
|
@ -4,12 +4,11 @@ include $(TOPDIR)/Make/makedefs
|
||||
CXXFILES =\
|
||||
osgtext.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText $(OSG_LIBS) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgtext
|
||||
|
||||
INC += $(PRODUCER_INCLUDE_DIR)
|
||||
LDFLAGS += $(PRODUCER_LIB_DIR)
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user