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