diff --git a/src/Demos/osggeometry/osggeometry.cpp b/src/Demos/osggeometry/osggeometry.cpp index 6a9bb0fd9..971ab4b9c 100644 --- a/src/Demos/osggeometry/osggeometry.cpp +++ b/src/Demos/osggeometry/osggeometry.cpp @@ -11,150 +11,330 @@ #include -// ---------------------------------------------------------------------- -// Global variables - this is basically the stuff wh ich will be animated -// ---------------------------------------------------------------------- -class MyTransformCallback : public osg::NodeCallback{ +// 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! - public: +// 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(). - MyTransformCallback(osg::Transform* node,float angularVelocity) - { - _nodeToOperateOn = node; - _angular_velocity = angularVelocity; - _previousTraversalNumber = -1; - _orig_t = _timer.tick(); - } - - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv) - { - if (nv) - { - if (_nodeToOperateOn && node==_nodeToOperateOn) - { - // ensure that we do not operate on this node more than - // once during this traversal. This is an issue since node - // can be shared between multiple parents. - if (nv->getTraversalNumber()!=_previousTraversalNumber) - { - osg::Timer_t new_t = _timer.tick(); - float delta_angle = _angular_velocity*_timer.delta_s(_orig_t,new_t); - - osg::Matrix matrix; - matrix.makeRotate(delta_angle,1.0f,1.0f,1.0f); - matrix *= osg::Matrix::translate(1.0f,0.0f,0.0f); - matrix *= osg::Matrix::rotate(delta_angle,0.0f,0.0f,1.0f); - - _nodeToOperateOn->setMatrix(matrix); - - _previousTraversalNumber = nv->getTraversalNumber(); - - } - } - } - - // must continue subgraph traversal. - traverse(node,nv); - - } - - protected: - - osg::Transform* _nodeToOperateOn; - float _angular_velocity; - - int _previousTraversalNumber; - osg::Timer _timer; - osg::Timer_t _orig_t; - -}; - -osg::Geode* createGeometryCube() +osg::Geode* createScene() { + // create the Geode (Geometry Node) to contain all our osg::Geometry objects. osg::Geode* geode = new osg::Geode(); - // ------------------------------------------- - // Set up a new Geometry which will be our cube - // ------------------------------------------- - osg::Geometry* cube = new osg::Geometry(); + // follows are seperate 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. - // set up the primitives + + // 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,1.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->addPrimitive(new osg::DrawArrays(osg::Primitive::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,1.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->addPrimitive(new osg::DrawArrays(osg::Primitive::LINES,0,8)); + + + // add the points geomtry to the geode. + geode->addDrawable(linesGeom); + } - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,0,4)); - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,4,4)); - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,8,4)); - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,12,4)); - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,16,4)); - cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,20,4)); - - - // set up coords. - osg::Vec3Array* coords = new osg::Vec3Array; - coords->resize(24); - - (*coords)[0].set( -1.0000f, 1.0000f, -1.000f ); - (*coords)[1].set( 1.0000f, 1.0000f, -1.0000f ); - (*coords)[2].set( 1.0000f, -1.0000f, -1.0000f ); - (*coords)[3].set( -1.0000f, -1.0000f, -1.000 ); - - (*coords)[4].set( 1.0000f, 1.0000f, -1.0000f ); - (*coords)[5].set( 1.0000f, 1.0000f, 1.0000f ); - (*coords)[6].set( 1.0000f, -1.0000f, 1.0000f ); - (*coords)[7].set( 1.0000f, -1.0000f, -1.0000f ); - - (*coords)[8].set( 1.0000f, 1.0000f, 1.0000f ); - (*coords)[9].set( -1.0000f, 1.0000f, 1.000f ); - (*coords)[10].set( -1.0000f, -1.0000f, 1.000f ); - (*coords)[11].set( 1.0000f, -1.0000f, 1.0000f ); - - (*coords)[12].set( -1.0000f, 1.0000f, 1.000 ); - (*coords)[13].set( -1.0000f, 1.0000f, -1.000 ); - (*coords)[14].set( -1.0000f, -1.0000f, -1.000 ); - (*coords)[15].set( -1.0000f, -1.0000f, 1.000 ); - - (*coords)[16].set( -1.0000f, 1.0000f, 1.000 ); - (*coords)[17].set( 1.0000f, 1.0000f, 1.0000f ); - (*coords)[18].set( 1.0000f, 1.0000f, -1.0000f ); - (*coords)[19].set( -1.0000f, 1.0000f, -1.000f ); - - (*coords)[20].set( -1.0000f, -1.0000f, 1.000f ); - (*coords)[21].set( -1.0000f, -1.0000f, -1.000f ); - (*coords)[22].set( 1.0000f, -1.0000f, -1.0000f ); - (*coords)[23].set( 1.0000f, -1.0000f, 1.0000f ); + // 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,1.0f,1.0f)); + linesGeom->setColorArray(colors); + linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL); - cube->setVertexArray( coords ); - - - // set up the normals. - osg::Vec3Array* cubeNormals = new osg::Vec3Array; - cubeNormals->resize(6); - - (*cubeNormals)[0].set(0.0f,0.0f,-1.0f); - (*cubeNormals)[1].set(1.0f,0.0f,0.0f); - (*cubeNormals)[2].set(0.0f,0.0f,1.0f); - (*cubeNormals)[3].set(-1.0f,0.0f,0.0f); - (*cubeNormals)[4].set(0.0f,1.0f,0.0f); - (*cubeNormals)[5].set(0.0f,-1.0f,0.0f); - - cube->setNormalArray( cubeNormals ); - cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE ); + // set 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); - // --------------------------------------- - // Set up a StateSet to make the cube red - // --------------------------------------- - osg::StateSet* cubeState = new osg::StateSet(); - osg::Material* redMaterial = new osg::Material(); - osg::Vec4 red( 1.0f, 0.0f, 0.0f, 1.0f ); - redMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, red ); - cubeState->setAttribute( redMaterial ); - cube->setStateSet( cubeState ); + // This time we simply use primitive, and hardwire the number of coords to use + // since we know up front, + linesGeom->addPrimitive(new osg::DrawArrays(osg::Primitive::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,1.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->addPrimitive(new osg::DrawArrays(osg::Primitive::LINE_LOOP,0,numCoords)); + + + // add the points geomtry to the geode. + geode->addDrawable(linesGeom); + } + + + + + // now we'll stop creating seperate 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 shared_colors = new osg::Vec4Array; + shared_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + + // same trick for shared normal. + osg::ref_ptr shared_normals = new osg::Vec3Array; + shared_normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f)); + + + + // 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. + osg::Vec3 myCoords[] = + { + osg::Vec3(-0.980488, -2.15188e-09, -0.094753), + osg::Vec3(-0.766264, -2.15188e-09, -0.0576758), + osg::Vec3(-0.807461, -2.15188e-09, -0.181267), + osg::Vec3(-1.0258, -2.15188e-09, -0.26778), + osg::Vec3(-1.0464, 9.18133e-09, -0.193626) + }; + + 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->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,0,numCoords)); + + + // 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(); + + osg::Vec3 myCoords[] = + { + osg::Vec3(-0.222464, 9.18133e-09, -0.13183), + osg::Vec3(-0.160668, 9.18133e-09, -0.0453167), + osg::Vec3(0.0247182, 9.18133e-09, -0.00823939), + osg::Vec3(0.0247182, 9.18133e-09, -0.156548), + + osg::Vec3(0.13595, -2.15188e-09, -0.255421), + osg::Vec3(0.164788, 9.18133e-09, -0.0453167), + osg::Vec3(0.333696, 9.18133e-09, 0.0329576), + osg::Vec3(0.238942, -2.15188e-09, -0.251302) + }; + + 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->addPrimitive(new osg::DrawArrays(osg::Primitive::QUADS,0,numCoords)); + + + // add the points geomtry to the geode. + geode->addDrawable(polyGeom); + } - geode->addDrawable( cube ); - return geode; } @@ -174,15 +354,9 @@ int main( int argc, char **argv ) // configure the viewer from the commandline arguments, and eat any // parameters that have been matched. viewer.readCommandLine(commandLine); - - osg::Transform* myTransform = new osg::Transform(); - myTransform->addChild( createGeometryCube() ); - - // move node in a circle at 90 degrees a sec. - myTransform->setAppCallback(new MyTransformCallback(myTransform,osg::inDegrees(90.0f))); // add model to viewer. - viewer.addViewport( myTransform ); + viewer.addViewport( createScene() ); // register trackball maniupulators. viewer.registerCameraManipulator(new osgGA::TrackballManipulator);