如何正确更新几何

时间:2016-04-28 15:40:19

标签: c++ opengl openscenegraph

我正在尝试使用OSG显示由顶点和颜色组成的点云。使用此guide可以轻松显示静态点云。

但我无法更新这样的点云。我的目的是创建一个几何体并将其附加到我的观察器类一次。

这是提到的方法,在开始时调用一次。

OSGWidget强烈依赖于此OpenGLWidget based approach

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);
}

我附上&#39;几何,我试图像这样更新几何

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()));      
    }
}

我猜是

  

addPrimitiveSet(...)

每次更新几何图形时都不应调用。

或者它可以是几何的附件,所以我每次都要重新连接它?

遗憾的是,由于与我的应用程序不兼容,PointCloudlibrary(PCL)无法替代。

更新:当我将几何体重新连接到OSGWidget类时, 打电话

this->attachGeometry(m_geometry) 之后

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

我的点云可见,但这个程序绝对是错误的,因为我失去了太多的性能并且显示驱动程序崩溃。

2 个答案:

答案 0 :(得分:3)

您需要设置数组并仅添加一次原始图集,之后您可以像这样更新顶点:

osg::Vec3Array* vx = static_cast<osg::Vec3Array*>(m_vertices);
for (int i = 0; i < nPixel; i++)
{
   float x, y, z;

   // fill with your data...

   (*vx)[i].set(x, y, z);
}
m_vertices->dirty();

颜色和其他阵列也是如此 当您使用VBO时,您不需要调用dirtyDisplayList()
如果您需要重新编译几何体的边界框,请调用

m_geometry->dirtyBound()

如果更新之间的点数发生变化,如果数据的大小太小,可以将新顶点推入数组,并像这样更新PrimitiveSet计数:

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

答案 1 :(得分:0)

rickvikings解决方案有效 - 我只有一个问题......(OSX上的OSG 3.6.1)

我必须直接修改m_vertices数组,如果我使用上面的static_cast方法修改顶点数组,它会导致OSG崩溃:     osg :: Vec3Array * vx = static_cast(m_vertices); 出于某种原因,如果使用static_cast方法,OSG将不会在顶点数组类中创建缓冲区对象。