Tuesday, March 14, 2017

Building Geometry Model



The osg::Geode class corresponds to the leaf node of scene graph. It has no child nodes, but always contains geometry information for rendering. Its name Geode is short for geometry node.

The geometry data to be drawn are stored in a set of osg::Drawable objects managed by osg::Geode . The non-instantiatable osg::Drawable class is defined as a pure virtual class. It has several subclasses for rendering models, images, and texts to the OpenGL pipeline. These renderable elements are collectively called drawables.

Please open your CodeBlocks and create new project. Copy paste code below into your main.cpp file to implement basic geometry then build (you can download the code here ). If you are confuse on how to set OpenSceneGraph environment, please refer to this guidance for OSG CodeBlock or OSG Netbean C++ or OSG Visual Studio 2010.


#include <osg/Node>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osgDB/ReadFile> 
#include <osgViewer/Viewer>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
int main()
{
    osgViewer::Viewer viewer;
    osg::Group* root = new osg::Group();
    osg::Geode* pyramidGeode = new osg::Geode();
    osg::Geometry* pyramidGeometry = new osg::Geometry();

    //Associate the pyramid geometry with the pyramid geode
    //   Add the pyramid geode to the root node of the scene graph.

    pyramidGeode->addDrawable(pyramidGeometry);
    root->addChild(pyramidGeode);

    //Declare an array of vertices. Each vertex will be represented by
    //a triple -- an instances of the vec3 class. An instance of
    //osg::Vec3Array can be used to store these triples. Since
    //osg::Vec3Array is derived from the STL vector class, we can use the
    //push_back method to add array elements. Push back adds elements to
    //the end of the vector, thus the index of first element entered is
    //zero, the second entries index is 1, etc.
    //Using a right-handed coordinate system with 'z' up, array
    //elements zero..four below represent the 5 points required to create
    //a simple pyramid.

    osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
    pyramidVertices->push_back( osg::Vec3( 0, 0, 0) ); // front left
    pyramidVertices->push_back( osg::Vec3(10, 0, 0) ); // front right
    pyramidVertices->push_back( osg::Vec3(10,10, 0) ); // back right
    pyramidVertices->push_back( osg::Vec3( 0,10, 0) ); // back left
    pyramidVertices->push_back( osg::Vec3( 5, 5,10) ); // peak

    //Associate this set of vertices with the geometry associated with the
    //geode we added to the scene.

    pyramidGeometry->setVertexArray( pyramidVertices );

    //Next, create a primitive set and add it to the pyramid geometry.
    //Use the first four points of the pyramid to define the base using an
    //instance of the DrawElementsUint class. Again this class is derived
    //from the STL vector, so the push_back method will add elements in
    //sequential order. To ensure proper backface cullling, vertices
    //should be specified in counterclockwise order. The arguments for the
    //constructor are the enumerated type for the primitive
    //(same as the OpenGL primitive enumerated types), and the index in
    //the vertex array to start from.

    osg::DrawElementsUInt* pyramidBase =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidBase->push_back(3);
    pyramidBase->push_back(2);
    pyramidBase->push_back(1);
    pyramidBase->push_back(0);
    pyramidGeometry->addPrimitiveSet(pyramidBase);

    //Repeat the same for each of the four sides. Again, vertices are
    //specified in counter-clockwise order.

    osg::DrawElementsUInt* pyramidFaceOne =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceOne->push_back(0);
    pyramidFaceOne->push_back(1);
    pyramidFaceOne->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceOne);

    osg::DrawElementsUInt* pyramidFaceTwo =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceTwo->push_back(1);
    pyramidFaceTwo->push_back(2);
    pyramidFaceTwo->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);

    osg::DrawElementsUInt* pyramidFaceThree =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceThree->push_back(2);
    pyramidFaceThree->push_back(3);
    pyramidFaceThree->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceThree);

    osg::DrawElementsUInt* pyramidFaceFour =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceFour->push_back(3);
    pyramidFaceFour->push_back(0);
    pyramidFaceFour->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceFour);

    //Declare and load an array of Vec4 elements to store colors.

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red
    colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //index 1 green
    colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //index 2 blue
    colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 3 white
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 4 red

    //The next step is to associate the array of colors with the geometry,
    //assign the color indices created above to the geometry and set the
    //binding mode to _PER_VERTEX.

    pyramidGeometry->setColorArray(colors);
    pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

    //Now that we have created a geometry node and added it to the scene
    //we can reuse this geometry. For example, if we wanted to put a
    //second pyramid 15 units to the right of the first one, we could add
    //this geode as the child of a transform node in our scene graph.

    // Declare and initialize a transform node.
    osg::PositionAttitudeTransform* pyramidTwoXForm =
        new osg::PositionAttitudeTransform();

    // Use the 'addChild' method of the osg::Group class to
    // add the transform as a child of the root node and the
    // pyramid node as a child of the transform.

    root->addChild(pyramidTwoXForm);
    pyramidTwoXForm->addChild(pyramidGeode);

    // Declare and initialize a Vec3 instance to change the
    // position of the model in the scene

    osg::Vec3 pyramidTwoPosition(15,0,0);
    pyramidTwoXForm->setPosition( pyramidTwoPosition );

    // switch off lighting as we haven't assigned any normals.
    root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    //The final step is to set up and enter a simulation loop.

    viewer.setSceneData( root );
    //viewer.run();

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    viewer.realize();

    while( !viewer.done() )
    {
        viewer.frame();
    }

    return 0;
}


Result

No comments:

Post a Comment