2016-04-28 4 views
1

Я пытаюсь отобразить облако точек, состоящее из вершин и цвета с 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); 
} 

После того как я 'прилагается' геометрию, я пытаюсь обновить геометрию как этот

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), к сожалению, не является альтернативой, поскольку некоторые несовместимости с моим приложением.

Update: Когда я реплантация геометрии класса OSGWidget, вызова

this->attachGeometry(m_geometry) после

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

Я получаю мою точку облака видно, но эта процедура, безусловно, неправильно так как я теряю слишком высокую производительность и сбой драйвера дисплея.

ответ

2

Вы должны установить массив и добавить примитивный набор только один раз, после этого вы можете обновить вершины, как это:

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()
Если вам нужно вместо recompure ограничительной рамки геометрии, вызовите

m_geometry->dirtyBound() 

В случае, если количество точек изменений между обновления, вы можете нажать новые вершины в массив, если его размер слишком мал, и обновлять PrimitiveSet рассчитывать так:

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

Но это применимо только если число пикселей (nPixel) остается постоянным? –

+0

Несомненно @DanielR. Я был под этим предположением, я редактирую ответ, чтобы принять другой номер точки во внимание. – rickyviking

+0

Спасибо. Моим временным решением является сброс примитивов, вертекс и цветов. Но, как вы сказали, мне не нужно это делать –

Смежные вопросы