Hi Dimi,

I have merged your changes for copying the data and refactored the
main() of the example so that it uses osg::ArgumentParser to read
command line arguments which then control which implementation is
used.  I cleaned up the awkward swap mechanism and renamed the file to
vbotest.cpp to better reflect what we are trying to test.

Now for the follow combinations I get:

  ./vbotest               # no arguments, just straight pointer swap
of the VertexArray - fails
  ./vobtest --ct-dirty  # dirty the colour and texture coord arrays - works
  ./vobtest --copy     # copy the data to the vertex array and dirty it - works

The new main loop code looks like:

    bool data_copy = arguments.read("--copy");
    bool ct_dirty = arguments.read("--ct-dirty");

    unsigned numFrameTillSwap=60;
    osg::Vec3Array* previousVertexArray = data_copy ? 0 :
dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());

    while(!viewer.done())
    {
        bool chooseFirst = ((viewer.getFrameStamp()->getFrameNumber()
/ numFrameTillSwap) % 2) == 0;
        osg::Vec3Array* newVertexArray = chooseFirst ? v2 : v3;

        if (previousVertexArray!=newVertexArray)
        {
            previousVertexArray = newVertexArray;

            if (data_copy)
            {
                OSG_NOTICE<<"copying data array from array
"<<newVertexArray<<std::endl;
                for (uint j = 0; j < v->size (); j++)
                {
                    v->at(j) = newVertexArray->at (j);
                }
                v->dirty();
            }
            else
            {
                OSG_NOTICE<<"swapping to array "<<newVertexArray<<std::endl;
                geom->setVertexArray(newVertexArray);
                newVertexArray->dirty();
            }

            if (ct_dirty)
            {
                c->dirty();
                t->dirty();
            }
        }

        viewer.frame();
    }

    return 0;
}


As to what is specifically wrong I haven't started digging into
osg::Geometry and the VBO support so can't say, but I suspect it's an
issue with management of the VBO and which arrays are assigned to
them.   Now I have a concise example that reproduces the problem I
should be able to find out what is specifically amiss.

Robert.
cmake_minimum_required(VERSION 2.6)

PROJECT(vbotest)

SET(CMAKE_MODULE_PATH "${vbotest_SOURCE_DIR};${CMAKE_MODULE_PATH}")

FIND_PACKAGE(OpenThreads)
FIND_PACKAGE(osg)
FIND_PACKAGE(osgDB)
FIND_PACKAGE(osgViewer)

SET(SOURCES
    vbotest.cpp
)

INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR} ${OSG_INCLUDE_DIR})

LINK_DIRECTORIES(${OSG_LIB_DIR})

ADD_EXECUTABLE(vbotest ${SOURCES})

TARGET_LINK_LIBRARIES(vbotest ${OSG_LIBRARY} ${OSGVIEWER_LIBRARY} 
${OPENTHREADS_LIBRARY})
// GPU,CPU Moprhing example. Dimi Christopoulos, Mai 2010
//
// Example programm of a morphing cube with option to do the morphing using Vertex Buffer Objects (VBO) either on the CPU or on the GPU (GLSL).
// Shows how to setup and pass vertex attributes to GLSL in OSG and setup VBO geometry for GLSL (GPU) moprhing.
// Shows how to setup VBO and do updates for CPU morphing.
// Use the #define USE_GLSL further down to compile the example for CPU or GPU morphing.
//
// For CPU morphing 2 arrays are created which hold the 2 morph shapes. These are interpolated using C++ and afterwards
// copied to the geometry vertexArray and uploaded to Gfx memory using VBOs.
//
// For GPU morphing one morph shape array is assigned as a GLSL geometry vertex attribute and the second
// morph shape is stored directly in the geometry vertexArray. The actual interpolation occurs in the vertex GLSL shader, 
// which mixes the two arrays and passes the new vertices down the pipeline. Again VBos are used to store the geometry on the Gfx card.

#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/CullFace>
#include <osg/Image>
#include <osg/Texture>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/StateSetManipulator>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>


// Set USE_GLSL to 1 to do interpolation on the GPU
// Set USE_GLSL to 0 to do interpolation on the CPU
#define USE_GLSL 0

// This is the number of the attribute channel used
// to pass the second vertex attributes for morphing.
// According to NVidia spec not all channels are free,
// but number 6 is guaranteed to be free. 
#define VERTEXBIND 6

// Global vars for holding the GLSL Uniform timer 
// and pointers to the vertex arrays for morphing needed 
// when doing the interpolation on the GPU 
osg::ref_ptr<osg::Uniform> fractionUniform;
osg::ref_ptr<osg::Vec3Array> v, v2, v3;
 
osg::ref_ptr<osg::Geometry> geom;
osg::ref_ptr<osg::Vec4Array> c;
osg::ref_ptr<osg::Vec2Array> t;

osg::ref_ptr<osg::Node>
createSceneGraph()
{
    // Create an object to store geometry in.
    geom = new osg::Geometry;

#if 1
    // Disable Display lists and setup Vertex Buffer Objects
    geom->setUseDisplayList (false);
    geom->setUseVertexBufferObjects(true);

    // Set VBO to STREAMING since attributes are changing per frame
    osg::VertexBufferObject* df = geom->getOrCreateVertexBufferObject();
    df->setUsage (GL_STREAM_DRAW);
#endif

    // Create 3 vertex arrays
    v = new osg::Vec3Array;
    v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
    v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );

    v->push_back( osg::Vec3( -1.f, 2.f, -1.f ) );
    v->push_back( osg::Vec3( -1.f, 2.f, 1.f ) );
    v->push_back( osg::Vec3( 1.f, 2.f, 1.f ) );
    v->push_back( osg::Vec3( 1.f, 2.f, -1.f ) );

    v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
    v->push_back( osg::Vec3( 1.f, 2.f, -1.f ) );
    v->push_back( osg::Vec3( 1.f, 2.f, 1.f ) );

    v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( 1.f, 2.f, 1.f ) );
    v->push_back( osg::Vec3( -1.f, 2.f, 1.f ) );

    v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );
    v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );
    v->push_back( osg::Vec3( -1.f, 2.f, 1.f ) );
    v->push_back( osg::Vec3( -1.f, 2.f, -1.f ) );

    v->push_back( osg::Vec3( 1.f, 2.f, -1.f ) );
    v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
    v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );
    v->push_back( osg::Vec3( -1.f, 2.f, -1.f ) );


    v2 = new osg::Vec3Array;
    for (int i=0; i<v->size(); i++)
        v2->push_back (v->at(i)*0.7);

    v3 = new osg::Vec3Array;
    for (int i=0; i<v->size(); i++)
        v3->push_back (v->at(i)*0.3);

    geom->setVertexArray( v.get() );

    v->setDataVariance(osg::Object::DYNAMIC);
    v2->setDataVariance(osg::Object::DYNAMIC);
    v3->setDataVariance(osg::Object::DYNAMIC);


    // Create an color array
    c = new osg::Vec4Array;
    geom->setColorArray( c.get() );
    geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );

    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );

    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );

    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );

    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );

    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) ); 

    // Create an texcoord array
    t = new osg::Vec2Array;
    geom->setTexCoordArray(0, t.get());
    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );

    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );

    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );

    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );

    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );

    t->push_back( osg::Vec2( 0.f, 0.f) );
    t->push_back( osg::Vec2( 0.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 1.f) );
    t->push_back( osg::Vec2( 1.f, 0.f) );



    // Add primitiveset to draw a cube
    geom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 24 ) );

    // Add the Geometry (Drawable) to a Geode.
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable (geom.get());

    // Enable Face Culling, disable lighting
    osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
    stateset->setAttributeAndModes (new osg::CullFace()); 
    stateset->setMode (GL_LIGHTING, osg::StateAttribute::OFF); 

    // Set up the texture.
    osg::Image* img = osgDB::readImageFile("Images/purpleFlowers.png");
    osg::Texture2D* texture = new osg::Texture2D;
    texture->setImage(img);
    stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

    
    return geode.get();
}


int
main( int argc, char** argv )
{

    osg::ArgumentParser arguments(&argc, argv);
    
    osgViewer::Viewer viewer(arguments);

    // Create and setup geometry for morphing
    osg::ref_ptr<osg::Node> root = createSceneGraph();
   
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    if (!root.valid())
    {
        osg::notify(osg::FATAL) << "Failed in createSceneGraph()." << std::endl;
        return 1;
    }

    viewer.setSceneData (root.get());
    viewer.realize();

    // code for timing
    float frac=0, inc=0.75;
    osg::Timer_t startTick = osg::Timer::instance()->tick();

    viewer.addEventHandler( new osgGA::StateSetManipulator( viewer.getCamera()->getOrCreateStateSet() ) );

    bool data_copy = arguments.read("--copy");
    bool ct_dirty = arguments.read("--ct-dirty");

    unsigned numFrameTillSwap=60;
    osg::Vec3Array* previousVertexArray = data_copy ? 0 : dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
    
    while(!viewer.done())
    {
        bool chooseFirst = ((viewer.getFrameStamp()->getFrameNumber() / numFrameTillSwap) % 2) == 0;
        osg::Vec3Array* newVertexArray = chooseFirst ? v2 : v3;

        if (previousVertexArray!=newVertexArray)
        {
            previousVertexArray = newVertexArray;

            if (data_copy)
            {
                OSG_NOTICE<<"copying data array from array "<<newVertexArray<<std::endl;
                for (uint j = 0; j < v->size (); j++)
                {
                    v->at(j) = newVertexArray->at (j);
                }
                v->dirty();
            }
            else
            {
                OSG_NOTICE<<"swapping to array "<<newVertexArray<<std::endl;
                geom->setVertexArray(newVertexArray);
                newVertexArray->dirty();
            }

            if (ct_dirty)
            {
                c->dirty();
                t->dirty();
            }
        }
        
        viewer.frame();
    }

    return 0;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to