OpenScenegraph sample code issue

Kobojunkie picture Kobojunkie · Jun 21, 2012 · Viewed 7k times · Source

The code below is from a book. When I try to run it, it fails on the line

osg::ref_ptr geom = new osg::Geometry();

and, the output window does not seem to contain much information on why it crashes, other than telling me that it did. Any idea what I may be doing wrong in the code below? Thanks in advance.

Here is the windows error popup when I try to run this in Visual Studio 2010(windows 7 64)

Windows has triggered a breakpoint in OSGPracticeLab.exe. This may be due to a corruption of the heap, which indicates a bug in OSGPracticeLab.exe or any of the DLLs it has loaded. This may also be due to the user pressing F12 while OSGPracticeLab.exe has focus. The output window may have more diagnostic information.

On attempting to debug the code, I was able to trace the problem to the new function call. In the code below, it seems the while loop is skipped over, and a null value is returned for p(no memory allocated, and so my Geometry object in the code below this, is not instantiated.

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
        {       // try to allocate size bytes
        void *p;
        while ((p = malloc(size)) == 0)
                if (_callnewh(size) == 0)
                {       // report no memory
                static const std::bad_alloc nomem;
                _RAISE(nomem);
                }

        return (p);
        }

Below is my Program to draw some shapes and display.

#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osgViewer/Viewer> 


int main()
{
    //An octahedron is a polyhedron having eight triangle faces. 
    //It is really a nice example to show why primitive indexing is important
    // we will sketch the octahedron structure now 

    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(6);
    //octahedron has six vertices, each shaed by four triangles.  
    //withe the help of an index array and the osg::DrawElementsUInt class, we can allocate
    //a vertex array with only six elements
    (*vertices)[0].set( 0.0f, 0.0f, 1.0f);
    (*vertices)[1].set(-0.5f,-0.5f, 0.0f);
    (*vertices)[2].set( 0.5f,-0.5f, 0.0f);
    (*vertices)[3].set( 0.5f, 0.5f, 0.0f);
    (*vertices)[4].set(-0.5f, 0.5f, 0.0f);
    (*vertices)[5].set( 0.0f, 0.0f,-1.0f);
    //The osg::DrawElementsUInt accepts a size parameter besides the drawing mode parameter, too. 
    //After that, we will specify the indices of vertices to describe all eight triangle faces.
    osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_TRIANGLES, 24);
    (*indices)[0] = 0; (*indices)[1] = 1; (*indices)[2] = 2;
    (*indices)[3] = 0; (*indices)[4] = 2; (*indices)[5] = 3;
    (*indices)[6] = 0; (*indices)[7] = 3; (*indices)[8] = 4;
    (*indices)[9] = 0; (*indices)[10]= 4; (*indices)[11]= 1;
    (*indices)[12]= 5; (*indices)[13]= 2; (*indices)[14]= 1;
    (*indices)[15]= 5; (*indices)[16]= 3; (*indices)[17]= 2;
    (*indices)[18]= 5; (*indices)[19]= 4; (*indices)[20]= 3;
    (*indices)[21]= 5; (*indices)[22]= 1; (*indices)[23]= 4;

    //To create a geometry with a default white color, we only set the vertex array 
    //and the osg::DrawElementsUInt primitive set. The normal array is also required but is not easy
    //to compute manually. We will use a smoothed normal calculator to automatically obtain it. This calculator
    //will be described in the next section, Using polygonal techniques.
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
    geom->setVertexArray( vertices.get() );
    geom->addPrimitiveSet( indices.get() );
    //osgUtil::SmoothingVisitor::smooth( *geom );
    //Add the geometry to an osg::Geode object and make it the scene root
    osg::ref_ptr<osg::Geode> root = new osg::Geode;
    root->addDrawable( geom.get() );
    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );
    return viewer.run();
}

int drawShapeUsingVertices()
{
    //Create the vertex array and push the four corner points to the back of the array by using vector like operations:
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
    vertices->push_back( osg::Vec3(0.0f, 0.0f, 0.0f) );
    vertices->push_back( osg::Vec3(1.0f, 0.0f, 0.0f) );
    vertices->push_back( osg::Vec3(1.0f, 0.0f, 1.0f) );
    vertices->push_back( osg::Vec3(0.0f, 0.0f, 1.0f) );
    //We have to indicate the normal of each vertex; otherwise OpenGL will use a default (0, 0, 1) normal vector
    //and the lighting equation calculation may be incorrect. The four vertices actually face the same direction,
    //so a single normal vector is enough. We will also set the setNormalBinding() method to BIND_OVERALL later.
    osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; 
    normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );
    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    //here We will indicate a unique color value to each vertex and make them colored. By default, 
    //OpenGL will use smooth coloring and blend colors at each vertex together:
    colors->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
    colors->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
    colors->push_back( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
    colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
    //Next, we create the osg::Geometry object and set the prepared vertex, normal, and color arrays to it. 
    //We also indicate that the single normal should be bound to the entire geometry and that the colors
    //should be bound per vertex:
    osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
    quad->setVertexArray( vertices.get() );
    quad->setNormalArray( normals.get() );
    quad->setNormalBinding( osg::Geometry::BIND_OVERALL );
    quad->setColorArray( colors.get() );
    quad->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

    //The last step required to finish a geometry and add it to the scene graph is to specify the primitive set.
    //A newly allocated osg::DrawArrays instance with the drawing mode set to GL_QUADS is used here, in order to
    //render the four vertices as quad corners in a counter-clockwise order:
    quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );
    //Add the geometry to an osg::Geode object and render it in the scene viewer:
    osg::ref_ptr<osg::Geode> root = new osg::Geode;
    root->addDrawable( quad.get() );
    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );
    return viewer.run();
}

Answer

Nav picture Nav · Jul 4, 2012

I didn't have any problems with the code. Took it from the beginners guide and it works fine:

#include <osg/Geometry>
#include <osg/Geode>
#include <osgViewer/Viewer>

int main()
{
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
    vertices->push_back( osg::Vec3(0.0f, 0.0f, 0.0f) );
    vertices->push_back( osg::Vec3(1.0f, 0.0f, 0.0f) );
    vertices->push_back( osg::Vec3(1.0f, 0.0f, 1.0f) );
    vertices->push_back( osg::Vec3(0.0f, 0.0f, 1.0f) );

    osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
    normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );

    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
    colors->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
    colors->push_back( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
    colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );

    osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
    quad->setVertexArray( vertices.get() );
    quad->setNormalArray( normals.get() );
    quad->setNormalBinding( osg::Geometry::BIND_OVERALL );
    quad->setColorArray( colors.get() );
    quad->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

    quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );

    osg::ref_ptr<osg::Geode> root = new osg::Geode;
    root->addDrawable( quad.get() );
    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );
    return viewer.run();
}  

I recommend you check your project properties.

Have you included additional include directories: $(OSG_ROOT)\include;$(OSG_SOURCE)\include;$(OSG_ROOT)\include\osg;
If you're in Debug mode, do you have this in your preprocessor definitions? _DEBUG;WIN32;
Did you specify your linker additional directory: $(OSG_ROOT)\lib
Did you specify linker additional dependencies?: osgWidgetd.lib;osgVolumed.lib;osgViewerd.lib;osgUtild.lib;osgTextd.lib;osgTerraind.lib;osgSimd.lib;osgShadowd.lib;osgPresentationd.lib;osgParticled.lib;osgManipulatord.lib;osgGAd.lib;osgFXd.lib;osgDBd.lib;osgd.lib;osgAnimationd.lib;OpenThreadsd.lib;;;;;;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
Have you specified Configuration properties > debugging > Working directory as: $(OSG_ROOT)\bin

If an extreme case, it may be because your Visual Studio installation is corrupted. Try reinstalling Visual Studio and if the OSG installation was corrupted, then reinstall OSG (build from source). Mentioning this because a friend of mine had problems running OSG because his Visual Studio was corrupted. Reinstalling fixed it.