[osg-users] How to properly update a Geometry

995 views
Skip to first unread message

Daniel Neos

unread,
Apr 29, 2016, 5:55:19 AM4/29/16
to osg-...@lists.openscenegraph.org
Greetings everyone,

I am trying to display a point cloud, consisting of vertices and color with OpenSceneGraph. A static point cloud to display is rather easy with this guide.
But I am not capable of updating such a point cloud. My intention is to create a geometry and attach it to my viewer class once.
This is the mentioned method which is called once in the beginning.

The OSGWidget strongly depends on this OpenGLWidget based approach.


Code:

void OSGWidget::attachGeometry(osg::ref_ptr<osg::Geometry> geom)
{
osg::Geode* geode = new osg::Geode;

geom->setDataVariance(osg::Object::DYNAMIC);
geom->setUseDisplayList(false);
geom->setUseVertexBufferObjects(true);
bool addDrawSuccess = geode->addDrawable(geom.get()); // Adding Drawable Shape to the geometry node


if (!addDrawSuccess)
{
throw "Adding Drawable failed!";
}

osg::StateSet* stateSet = geode->getOrCreateStateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);


float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());

// Setting up the camera
osg::Camera* camera = new osg::Camera;
camera->setViewport(0, 0, this->width(), this->height());
camera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 1.f)); // Kind of Backgroundcolor, clears the buffer and sets the default color (RGBA)
camera->setProjectionMatrixAsPerspective(30.f, aspectRatio, 1.f, 1000.f); // Create perspective projection
camera->setGraphicsContext(graphicsWindow_); // embed

osgViewer::View* view = new osgViewer::View;
view->setCamera(camera); // Set the defined camera
view->setSceneData(geode); // Set the geometry
view->addEventHandler(new osgViewer::StatsHandler);


osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator;
manipulator->setAllowThrow(false);

view->setCameraManipulator(manipulator);

///////////////////////////////////////////////////
// Set the viewer
//////////////////////////////////////////////////
viewer_->addView(view);
viewer_->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
viewer_->realize();

this->setFocusPolicy(Qt::StrongFocus);
this->setMinimumSize(100, 100);

this->setMouseTracking(true);
}





This method gets set once and shall set up the camera, interactor settings and the overall scene which only consists of one geode containing the geometry which shall be updated continiously.
And after I have 'attached' the geometry, I am trying to update the geometry like this


Code:

void PointCloudViewOSG::processData(DepthDataSet depthData)
{
if (depthData.points()->empty())
{
return; // empty cloud, cannot do anything
}

const DepthDataSet::IndexPtr::element_type& index = *depthData.index();
const size_t nPixel = depthData.points().get()->points.size();

if (depthData.intensity().isValid() && !index.empty() )
{
for (int i = 0; i < nPixel; i++)
{
float x = depthData.points().get()->points[i].x;
float y = depthData.points().get()->points[i].y;
float z = depthData.points().get()->points[i].z;
m_vertices->push_back(osg::Vec3(x
, y
, z));

// 32 bit integer variable containing the rgb (8 bit per channel) value
uint32_t rgb_val_;
memcpy(&rgb_val_, &(depthData.points().get()->points[i].rgb), sizeof(uint32_t));

uint32_t red, green, blue;
blue = rgb_val_ & 0x000000ff;

rgb_val_ = rgb_val_ >> 8;
green = rgb_val_ & 0x000000ff;

rgb_val_ = rgb_val_ >> 8;
red = rgb_val_ & 0x000000ff;

m_colors->push_back(
osg::Vec4f((float)red / 255.0f,
(float)green / 255.0f,
(float)blue / 255.0f,
1.0f)
);
}

m_geometry->setVertexArray(m_vertices.get());

m_geometry->setColorArray(m_colors.get());

m_geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

m_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, m_vertices->size()));
}
}




(Apperantly the code tag can somehow not handle the whitespaces but i will let it be since it is more readable than if everything is aligned)

So my guess is that the addPrimitiveSet(...) shall not be called everytime I update the geometry, since it will push_back
the primitive set everytime the geometry gets updated?

Do I have to reattach my geometry after every update? Or do I have to rewrite my update method?
So it boils down to the question What steps are necessary to update my underlying geometry with new vertices and colors

I have read the basic tutorials and looked for similar questions in this forum
and the only thing that I could adapt is the use of VBO for performance gain

PointCloudlibrary (PCL) is unfortunately not an alternative since of some incompatibilities with my application.




Thank you!

Cheers,
Daniel

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=67011#67011





_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Glenn Waldron

unread,
Apr 29, 2016, 8:26:21 AM4/29/16
to OpenSceneGraph Users
If you're just updating an existing array, you don't need to call setVertexArray (etc); but you need to mark it dirty by calling

  m_vertices->dirty();

That applies also to your other buffer objects (color array, elements, etc.)


Glenn Waldron

Daniel Neos

unread,
Apr 29, 2016, 11:48:18 AM4/29/16
to osg-...@lists.openscenegraph.org

gwaldron wrote:
> If you're just updating an existing array, you don't need to call setVertexArray (etc); but you need to mark it dirty by calling
>
>   m_vertices->dirty();
>
>
> That applies also to your other buffer objects (color array, elements, etc.)
>
>
>
> Glenn Waldron
>
>


Hi Glenn,

thanks for your solution, I somehow came up with a solution which calls setVertexArray() anyway,
because I am not feeling confident when updating a geometry with dynamically changing
size of vertices each frame.

In my numbercrunching class, I create a geometry which I pass to
the visiualization class.


Code:

osg::ref_ptr<osg::Vec3Array> vertices(new osg::Vec3Array());
osg::ref_ptr<osg::Vec4Array> colors(new osg::Vec4Array());

for (int i = 0; i < nPixel; i++)
{

// Fill in vertices and colors...
// ....
//
}

m_geometry->setVertexArray(vertices.get());
m_geometry->setColorArray(colors.get());
m_geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
if (firstTimecall)
{
m_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertices->size()));
this->attachGeometry(m_geometry);
}
else
{
this->updateGeometry(m_geometry, nPixel);
}


Then I update the geometry of my visualization class like this


Code:

void OSGWidget::updateGeometry(osg::ref_ptr<osg::Geometry> geometry, const int nPixel)
{
m_geometry->setVertexArray(geometry->getVertexArray());
m_geometry->setColorArray(geometry->getColorArray());

osg::DrawArrays* drawArrays = static_cast<osg::DrawArrays*>(m_geometry->getPrimitiveSet(0));
drawArrays->setCount(nPixel);
drawArrays->dirty();

// ensures update of scene
this->update();
}


This seems to work, but eventually there is a more efficient and elegant solution to exchange/ update vertice and colors.
I hope my issue is clear and small piece of samplecode will be appreciated. Thanks!

Cheers,
Daniel Neos

------------------
Read this topic online here:

http://forum.openscenegraph.org/viewtopic.php?p=67028#67028

Reply all
Reply to author
Forward
0 new messages