osg 点云概略坐标显示与精确坐标获取

习惯了绘图软件的坐标显示功能,想让点云软件也能实现不管鼠标在场景的哪里移动,总能知道坐标,即使不太精确也没关系。对于三维地形模型来说,随便一个求交器就能轻松实现,对点云就例外了。有了概略坐标就能估算相对位置和距离,可以满足大部分需求,但在点云配准时,必须要有精确坐标作为参考点。本文给出了使用osg获取点云的概略坐标和精确坐标的方法。

1、坐标显示

osgUtil中内置了线段求交器LineSegmentIntersector和多面体求交器PolytopeIntersector,但没有针对点的求交器。这两个默认的求交器只能对封闭区域求交,如三维地形。其原理都是射线求交。

基于OpenGL的反馈模式,可以利用屏幕坐标和深度值反算出三维坐标值,但这个值随着视距的远近其精度不一,越远精度越低。有深度值,意味着屏幕的该像素被渲染,故称之为像素求交。在给定较大的像素阈值(5pixel)的情况下,不需要太严格就能命中点云,并显示反馈的近似三维坐标。

2、精确获取点云坐标

有了上一步的粗略坐标,可以找到候选点集,再对该点集遍历,计算屏幕坐标,与实际屏幕坐标最接近的点云便是目标点云。

获取候选点集的方法有:NodeVisitor或者Intersector。这里练习一下Intersector的用法。

从LineSegmentIntersector派生一个PointLineSegmentIntersector点线求交器,在其内部对geom应用PrimitiveFunctor的模板派生类TemplatePrimitiveFunctor,语法如osg::drawable::accept(PrimitiveFunctor & )。TemplatePrimitiveFunctor 是一个能够访问点、线段、面片、点数组的类,它模拟openGL的绘制函数,功能上类似NodeVisitor,只是处理的粒度更细了,名字也改成了Functor,并增加了模板和多继承。

class PrimitiveFunctor

{

public:

    virtual ~PrimitiveFunctor() {}

    virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0;

    virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0;

    virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0;

    virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0;

    virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0;

    virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0;

    virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0;

    virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0;

    virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0;

    virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0;

    virtual void begin(GLenum mode) = 0;

    virtual void vertex(const Vec2& vert) = 0;

    virtual void vertex(const Vec3& vert) = 0;

    virtual void vertex(const Vec4& vert) = 0;

    virtual void vertex(float x,float y) = 0;

    virtual void vertex(float x,float y,float z) = 0;

virtual void vertex(float x,float y,float z,float w) = 0;

virtual void end() = 0;

    void useVertexCacheAsVertexArray()

    {

        setVertexArray(_vertexCache.size(),&_vertexCache.front());

    }

    std::vector<Vec3>   _vertexCache;

    bool                _treatVertexDataAsTemporary;

};

template<class T>

    class TemplatePrimitiveFunctor : public PrimitiveFunctor, public T

//T的样子,需实现下面几个被TemplatePrimitiveFunctor调用的函数

class PrimitiveHandler

{

public:

void operator()( const osg::Vec3& v1, bool treatVertexDataAsTemporary );

void operator()( const osg::Vec3& v1, const osg::Vec3& v2, bool treatVertexDataAsTemporary );

void operator()( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3,bool treatVertexDataAsTemporary );

void operator()( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3, const osg::Vec3& v4, bool treatVertexDataAsTemporary );

}

针对本主题,在向T传入鼠标反馈点,与顶点比较,距离在一定阈值的加入候选交集表。

有了候选交集表后,就可以从camera获取相机-视图-投影-窗口的变换矩阵matrixVPW,从而将模型坐标变换为窗口坐标,然后再与鼠标的窗口坐标比较,找出最近的点云。计算matrixVPW的方法为:

osg::Matrix matrixVPW(cam->getViewMatrix() * cam->getProjectionMatrix());

if (cam->getViewport())

         matrixVPW.postMult(cam->getViewport()->computeWindowMatrix());

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值