Opengl二维坐标转三维坐标

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014531567/article/details/53488195

        由于项目的功能需求,需要通过点击屏幕来获取屏幕中物体的三维坐标(屏幕中显示的是一个3D球)。之前看过一篇文章说每件事情都是经过:学习、尝试、失败、灵感、成功的过程。没错,不过我在第二步和第三步差点陷入死循环。就如同网上说的,自从学了3D数学,从懵逼到无限懵逼。由于刚开始接触opengl,很多东西都不熟悉。后面接触后,个人觉得最重要的还是矩阵变换和shader的使用吧。

网上第一种方法:

         

        我不知道这个方法到底可不可以用,反正我是失败了。代码中最主要的是利用glreadpixels()函数来获取z坐标的深度,但是我获取不到(希望知道的大神指导一下,找了网上很久没找到),因为对opengl不太熟。然后我在网上一直查找,到目前为止还不是很清楚,不过既然有这个功能,那么肯定能用吧!

    我使用的是第二种方法(借用下别的博主的图哈):

              

 GLint    viewport[4]; 
 GLdouble modelview[16]; 
 GLdouble projection[16]; 
 glGetIntegerv(GL_VIEWPORT, viewport); // 得到的是最后一个设置视口的参数
 glGetDoublev(GL_MODELVIEW_MATRIX, modelview); 
 glGetDoublev(GL_PROJECTION_MATRIX, projection); 
 winX = point.x; 
 winY = screenHeight - point.y; 
//获取像素对应的前裁剪面的点坐标
 bool bResult = gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ); 
 FPoint3 nearPoint;
 nearPoint.x = posX; nearPoint.y = posY; nearPoint.z = posZ;
 //获取像素对应的后裁剪面的点坐标
 bResult = gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ); 
 FPoint3 farPoint;
 farPoint.x = posX; farPoint.y = posY; farPoint.z = posZ;

   网上基本上说的都是这种方法。以上就是该种方法的核心步骤了。通过获得MVP矩阵和视口矩阵,然后利用gluUnproject()函数来获取近裁剪面和远裁剪面的坐标,从而得到一条射线,然后射线再和三维物体相交求坐标。因为我的对象是个球,所以求交比较简单,解方程就可以了。

 

得到球坐标(水平坐标和垂直坐标):



旋转后原位置的球坐标:


效果还是蛮不错的。

 

另附Opengl编程一些低级错误:



没有glDisable(GL_TEXTURE_2D),导致基本几何作图全部失败。
2.镜头位置没调好,导致所有物体不可见.
3.物体位置数据错误,导致物体大大超出镜头显示范围.
4.纹理没有GL_CLAMP导致边界拼接出现缝线.
5.纹理没有GL_REPEAT导致使用超出1.0纹理坐标技巧失败,显示单色插值.
6.没有glEnable(GL_TEXTURE_2D)导致全白纹理.
7.glEnable(GL_TEXTURE_2D)后没有使用纹理顶点导致如glColor效果的纯单色.
8.应该在作图循环设置灯光位置,因为The position is transformed by the modelview matrix when glLight is called (just as if it were a point), and it is stored in eye coordinates. 
9.灯光位置应该是4个float,3个float程序不出错,但结果完全扭曲。
10.打开灯光却没设置顶点法线,到头一场空。
11.Window Class没有CS_OWNDC,导致glDrawPixels失败,如在子窗口View上进行象素写入操作.
12.没有设置PIXELFORMATDESCRIPTOR的cAlphaBits,导致glReadPixels读取alpha通道数据失败,统统为0.
13.手动实现的多层纹理闪烁,出现线带,没有使用glPolygonOffset.
14.glDrawPixels格式GL_RGB或GL_BGR_EXT的数据时崩溃,且数据有效,没有使用glPixelStorei(GL_UNPACK_ALIGNMENT, 1);导致图像行默认4字节对齐,导致OpenGL数据读取越界崩溃.相应的要为glReadPixels设置glPixelStorei(GL_PACK_ALIGNMENT, 1);
15.glReadPixel读取被覆盖的OpenGL窗口部分的图像数据时,读出数据混乱无效,OpenGL Pixel Ownership检测导致,标准如此.使用PixelBuffer,或强制置前OpenGL窗口解决.
16.glReadPixels读取总是从FrameBuffer的左下往右上读取,毫无参数可设置改变方向,真是笨到家了.载入图像一般还是从上到下比较容易理解.
17.使用glDepthMask(GL_FALSE)后不打开,glClear无法清除深度缓冲,导致现象:场景起始静止正常,一旦移动出现不规则的透明无渲染区域,深度缓存逻辑混乱.
18. gluPerspective(45.0f, (GLfloat)cxPixels/(GLfloat)cyPixels, 0.1f, 2000.0f);这里的0.1f将导致物体和地面的相交处闪烁,原因待查,至少取1.0f.
19.没有显示定义shiniess或shiniess为0,在shader中对gl_FrontMaterial.shininess使用pow计算,结果不可测,黑色条带闪烁,quite not understand.
20.纹理出现白色点状闪烁,没有Mipmap过滤导致!
21.任何初装的Windows系统,多好的机器,一开始对OpenGL只支持1.1,连多重纹理都没有,需要警惕这种机器,装着DX9,微软真恶心,::SwapBuffer直接崩溃,故需要检测显卡至少支持了1.2标准,否则要求更新显卡驱动程序.
22.3D和2D,透视和正射模式混合时,2D模式的渲染覆盖不了3D的渲染,原因深度测试失败,
      a.2D下渲染时所取点深度确实大于3D点的深度.
      b.glOrtho参数错误,导致2D渲染所得深度值错误,如zNear被取负数!
      c.使用glDisable(GL_DEPTH_TEST);
23.glDrawElements崩溃,
      a.glXXXPointer设置的缓冲错误,顶点索引越界引用顶点数组.
      b.当前glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer);硬件缓冲和内存缓冲混淆.
24.画面上出现方块形背景色,原因,渲染一次后,在glClear时glDepthMask没有打开,glClear没能clear掉depth,但clear掉颜色缓冲,depth值持续到下一次render,导致depth test没通过,颜色画不上.
25.树叶挡在物体前,树叶间隙或蛀洞本应该透明却呈现背景色.原因,没有启用Alpha过滤.一般不可能用几何形状勾勒出叶子的形状,只用较大的多边形包围叶子,用Alpha过滤掉空隙.此时不启用Alpha过滤,出现Alpha为0的三角面也被渲染,但得到的是背景图像,并且由于Alpha为0的三角面离视点近,后面的物体渲染无法通过深度测试补上透明的空隙区域.
26.atlgdi.h里有#pragma comment(lib, "opengl32.lib"),导致无源无故链接opengl32.lib失败.

阅读更多

没有更多推荐了,返回首页