《PCL点云库学习&VS2010(X64)》Part 47 鼠标选取点云坐标的计算原理

openGL从鼠标坐标转换到三维坐标转换的方法

利用鼠标获取的二维坐标,映射到三维点云中,查找出对应的三维坐标,是选点的基本算法步骤。
参考博文:
在opengl下从鼠标坐标转换到三维坐标的方法

基本原理:

1、利用鼠标的mousePress()函数找到鼠标坐标点;
2、屏幕坐标转换:将鼠标坐标转换到屏幕坐标;
3、glReadPixels()函数找到深度坐标winZ;
4、gluUnProject()找到对应投影坐标Z。

注:

1、openGL为左下角坐标系;
2、gluUnProject()函数得到的是模型坐标,用射线和要检测的目标求 交点,获取三维坐标。利用该原理可以实现影像与点云交互选点,详细解释见后面的参考链接。

一般用来拾取物体:

fPoint CMy3D_SurfaceView::Get_3D_pos(CPoint Tpoint)
{
    CMy3D_SurfaceDoc *pDoc=(CMy3D_SurfaceDoc*)GetDocument();

    fPoint Rp;//vcg::Point3f Rp;//pcl::PointXYZ Rp;
    GLint viewport[4];
    GLfloat TransVect[3];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat rotx,roty;
    GLfloat winX,winY,winZ;
    GLdouble posX,posY,posZ;
    GLfloat scalex,scaley.scalez;

    glPushMatrix();
    glTranslatef(TransVect[0],TransVect[1],TransVect[2]);
    if(pDoc->Init) roty=0.0f;
    glRotatef(roty+20.0f,0.0f,1.0f,0.0f);
    glScalef(scalx,scaly,scalz);

    glGetIntegerv(GL_VIEWPORT,viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
    glGetDoublev(GL_PROJECTION_MATRIX,projection);
    glPopMatrix();

    winX=(float)Tpoint.x;
    winY=viewport[3]-(float)Tpoint.y;//转换为屏幕坐标

    glReadPixels((int)winX,(int)winY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);//获取鼠标屏幕坐标处像素的深度Z
    gluUnProject(winX,winY,winZ,modelview,projection,viewport,&posX,&posY,&posZ);

    Rp.x=posX;
    Rp.y=posY;
    Rp.z=posZ;

    return Rp;
}

另一个例子(参考:gluUnProject()函数得到的是什么坐标):

void C3DSLoader::GetCoordinate(float x,float y,float z,float& resultx,float& resulty,float& resultz,int intMode)  
{  
 GLint viewport[4];    
 GLdouble modelview[16];    
 GLdouble projection[16];    
 GLfloat winX, winY, winZ;    
 GLdouble posX, posY, posZ;    
 GLdouble Point3f[3];       //  


 glMatrixMode(GL_MODELVIEW);  

 //glLoadIdentity();  
 //gluLookAt(0,0,0,  0,0,-10, 0,1,0);  
 //glLoadIdentity();  
 //gluLookAt(vertor3Eye.x,vertor3Eye.y,vertor3Eye.z,vertor3Center.x,  
     //vertor3Center.y,vertor3Center.z,vertor3Up.x,vertor3Up.y,vertor3Up.z);  
 glGetDoublev(GL_MODELVIEW_MATRIX, modelview);    
 glGetDoublev(GL_PROJECTION_MATRIX, projection);    
 glGetIntegerv(GL_VIEWPORT, viewport);    


 if(intMode==0)  
 {  
     winX = (float)x;  
     winY = (float)viewport[3] - (float)y;  
     glReadPixels(int(winX), int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);    
        gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);    
         resulty= (float)posY;  
 }  
 else if(intMode==1)  
 {  
     winX = x;  
     winY = y;  
     winZ=z;  
    // gluProject(winX, winY, winZ, modelview, projection, viewport, (GLdouble*)&resultx, (GLdouble*)&resulty, (GLdouble*)&resultz);    
    gluProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);    
    resulty=(float)viewport[3] - (float)posY;  
 }  

 resultx=(float)posX;  

 resultz=(float)posZ;  
 //Point3f[0] = posX;//*100;  
 //Point3f[1] = posY;//*100;   
 //Point3f[2] = posZ;//*100;  

 //QString strMessage=QString("X = %1,Y = %2,Z = %3s").arg(Point3f[0]).arg(Point3f[1]).arg(Point3f[2]);  
 //  
 //QMessageBox::warning(null,"",strMessage);  
}  

这个例子有两种模式:第一种是鼠标选中屏幕中二维点来计算三维点坐标,第二种是直接利用三维点计算出三维点,再将y坐标换算到屏幕坐标中,得到实际三维坐标(参考解释:用OpenGL实现射线拣取对象)。

dll函数接口: ////******** 初始化默认参数 ********// //extern "C" int __stdcall ZSY3DViewerInit(); //******** 读取历史数据到cloud ********// extern "C" int __stdcall ZSY3DReadHistoryData(char *file_dir); //******** 读取txt数据到cloud ********// extern "C" int __stdcall ZSY3DReadTxtData(char *file_dir); //******** 读取单个数据到cloud ********// extern "C" int __stdcall ZSY3DReadSingleData(float x, float y, float z); //******** 读取所有数据到cloud ********// extern "C" int __stdcall ZSY3DReadNowData(float *x, float *y, float *z, int count); //******** vtk读取txt文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_TXT(char *file_dir); //******** vtk读取obj文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_OBJ(char *file_dir); //******** vtk读取vtk文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_VTK(char *file_dir); //******** vtk读取ply文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_PLY(char *file_dir); //******** cloud下采样处理 ********// extern "C" int __stdcall ZSY3DDownSampling(float leaf_size); //******** cloud均匀采样处理 ********// extern "C" int __stdcall ZSY3DBalanceSampling(float radiusSearch = 0.01f); //******** cloud增采样处理 ********// extern "C" int __stdcall ZSY3DIncreaseSampling(float radius = 0.03f, float StepSize = 0.02f); //******** cloud直通滤波采样处理 ********// extern "C" int __stdcall ZSY3DStraightSampling(char *fieldName = "z", float limits_min = 0.0f, float limits_max = 0.1f, bool limitsNegative = true); //******** cloud统计滤波采样处理 ********// extern "C" int __stdcall ZSY3DStatisticsSampling(float meanK = 50.0f,float stddevMulThresh = 1.0f); //******** cloud半径滤波采样处理 ********// extern "C" int __stdcall ZSY3DRadiusSampling(float radiusSearch = 0.8f, float minNeighborsInRadius = 2.0f); //******** cloud数据进行渲染,并显示 ********// extern "C" int __stdcall ZSY3DShowPointCloud(); //******** cloud数据进行VTK三维重建(三角面绘制),并显示 ********// extern "C" int __stdcall ZSY3DDelaunayBuild(bool depth_color); //******** cloud数据进行VTK三维重建(曲面体绘制),并显示 ********// extern "C" int __stdcall ZSY3DSurfaceBu
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值