opengl编程 : 利用鼠标的位置跟踪一条在世界坐标系中的射线

如何用鼠标与三维世界的物体交互呢?

想了一种方法:将鼠标在二维屏幕的位置转化为三维世界坐标系的位置,记该位置为pm(mouse position)。我们在窗口中看到的内容都是基于观察坐标系的,

鼠标的位置可以看作是观察坐标系中,投影可见体的前平面中的一个位置,如何找到这样的一个位置呢?

可以肯定,pm·.z的值就是近平面的值,这点是没有疑问的,因为pm·就在近平面上。

我们假定投影平面和窗口有相同的宽高比,这些不会有失真出现。

接下来找pm·.x和pm·.y

1.将屏幕 0 - window_height-1变换到 1 到 -1

将屏幕 0 - window_width-1变换到 -1 到  1

2.找到投影平面的宽度,和投影平面的高度,可以这样计算 h = tan(Fov)*near  ,  w = ar*h;       (ar为宽高比,一般是事先定义好的,Fov为观察角度)

1 到 -1变化为 h 到 -h

-1到   1 变化 为-w 到 w

        float scale_h = tanf(Fov)*Near;   //投影窗口高度的一半
        float scale_w = ar*scale_h;

        Vector3f<GLfloat> aim = Vector3f<GLfloat>(scale_w*(static_cast<float>(m_mousePos_x) / static_cast<float>(m_windowWidth)*2.f - 1.f),
            scale_h*(1.f-static_cast<float>(m_mousePos_y) / static_cast<float>(m_windowHeight)*2.f), Near);

如上代码变可以找到2维鼠标在3维投影平面的位置pm`

接下来要将pm`由观察坐标系变化到世界坐标系,通过乘以观察矩阵的逆就ok了,接下来贴出观察矩阵的逆的计算过程

    void SetView(const Vector3f<T> & eye, const Vector3f<T> & z_target, const Vector3f<T> & up, Mat4<T>& ViewTranspose)
    {
        Vector3f<T> N = z_target;
        N.Normalize();
        Vector3f<T> U = up;
        U.Normalize();
        U = U.Cross(z_target);
        Vector3f<T> V = N.Cross(U);

        /*以下四行是坐标系旋转矩阵,将物体先进行坐标系平移,再进行坐标系旋转*/
        data[0][0] = U._Vector3f.x;  data[0][1] = U._Vector3f.y;  data[0][2] = U._Vector3f.z; data[0][3] = 0.0f;
        data[1][0] = V._Vector3f.x;  data[1][1] = V._Vector3f.y;  data[1][2] = V._Vector3f.z; data[1][3] = 0.0f;
        data[2][0] = N._Vector3f.x;  data[2][1] = N._Vector3f.y;  data[2][2] = N._Vector3f.z; data[2][3] = 0.0f;
        data[3][0] = 0.0f; data[3][1] = 0.0f; data[3][2] = 0.0f; data[3][3] = 1.0f;

        Mat4<T> trans;
        trans.SetTranlate(Vector3f<T>( -eye._Vector3f.x, -eye._Vector3f.y, -eye._Vector3f.z));//坐标系平移矩阵

        Mat4<T> transTranspose;
        transTranspose.SetTranlate(Vector3f<T>(eye._Vector3f.x, eye._Vector3f.y, eye._Vector3f.z));//坐标系平移矩阵的逆
        Mat4<T> vi = *this;
        vi.transpose();//生成坐标系旋转矩阵的逆

        ViewTranspose = transTranspose*vi; //观察矩阵的逆 view-1 = (view)-1 = (trans*(*this))-1 = (*this)-1*(trans)-1

        *this = *this*trans;//观察矩阵
    }

将pm`应用观察矩阵的逆就可以得到鼠标在世界坐标系中的坐标了。

眼睛在世界坐标中的位置已经是知道的了,那么眼睛和鼠标的位置一起就可以构成一条射线,应用这条射线与世界中的物体求交,这样就可以方便交互了.

类似上图的效果,移动鼠标可以实时地显示在哪个方格上。

时间: 2024-12-15 09:46:55

opengl编程 : 利用鼠标的位置跟踪一条在世界坐标系中的射线的相关文章

OpenGL编程 基础篇(四)与鼠标的交互

当用户按下或释放鼠标按钮.按下按钮时移动鼠标或按下和松开键盘按键时,就会产生一个相关事件.程序员可以用每类事件注册一个回调函数,例如使用如下函数: glutMouseFunc(myMouse):利用按下或释放鼠标按钮时发生的事件来注册myMouse glutMotionFunc(myMovedMouse):利用按下按钮同时移动鼠标的事件来注册myMovedMouse glutKeyboardFunc(myKeyboard):利用按下和松开键盘按键的事件来注册myKeyboard 1.用鼠标交互

Qt编程获取鼠标移动事件

想做下面一个效果:想当鼠标移动到按钮上的时候,按钮就变大,图标换个大的,鼠标不在按钮上的时候,按钮就变小,图标也换成小的,感觉比较Cool 实现原理:为每个按钮设置监听属性 void MainHomeForm::init() { //为按钮注册事件 ui->SystemSetButton->installEventFilter(this); ui->ZoneSetButton->installEventFilter(this); } //系统监听器监听按钮对象 bool MainH

在Win7(64位)使用VS2015运行《OpenGL编程指南》第八版第一章程序的方法

前言:笔者第一次用vs2015来实现<OpenGL编程指南>第八版第一个程序时确实花费了不少时间,按照网上教程,尝试了各种方法,最终花费了两个上午加一个下午的时间, 成功运行了程序,花了这么多时间,确实让人懊恼,现在把运行程序的步骤记录下来,以便查阅. 1.第一步,下载oglpg-8th-edith. 如果去书本上的官网下载,下载的是第九版的,而不是第八版的源码. 去其他网站下载,下载的这个包里面没有第一章的源码,可以网上黏贴其他人的代码,建议下第八版源码,下载网址:链接:http://pan

MFC中状态栏显示鼠标坐标位置

原文:MFC中状态栏显示鼠标坐标位置,蝈蝈 1,利用MFC向导创建一个应用工程ewq. 2,打开ResourceView,右击Menu菜单,插入Menu,在空白处双击,Caption中填入Point. 3,为Point设置下拉菜单,ID为ID_INDICATOR_POINT:Caption为point:Prompt为X:XXXX,Y:YYYY. 4,打开MainFrm.cpp,在indicators数组中的第二个位置添加ID_INDICATOR_POINT. 5,将MainFrm中的成员变量m_

在 Mac OS X Yosemite 10.10.5 上配置 OpenGL 编程环境

这个教程主要参考了youtube上的视频 Getting Started in OpenGL with GLFW/GLEW in Xcode 6 ,这个视频有点问题,不能照搬.本人通过自己摸(瞎)索(猫)加(碰)下(死)方(耗)的(子)评论,现在给出一种可能安装成功的方案,至于能不能成功,看各位的造化了. 首先,你的 mac 需要有最新的 Xcode,Command line tool, 这些都是最基础的,估计各位已经具备条件了.其次,下载安装 CMake (https://cmake.org/

Range对象理解,浏览器兼容性,获取鼠标光标位置

一.关于浏览器的兼容性 目前主要有3种关于range的类似的对象,分别是W3C range 对象,Mozzlia selection ,ie TextRange 关于这三种的区别,请查看文档 http://www.quirksmode.org/dom/w3c_range.html 这里面对这三个是说的很清楚的 可以看出 Mozilla 的 range 是一个selection对象 ,而在ie下 range 是一个 text Range 这个和Mozilla是完全不同的,所以需要为这两种类型的ra

【翻译】利用加速度求解位置的算法——三轴传感器

摘要 此文档描述并使用MMA7260QT三轴加速计和低功耗的9S08QG8八位单片机实现求解位置的算法 . 在今天先进的电子市场,有不少增加了许多特性和智能的多功能的产品.定位和游戏只是得益于获取到的位置信息的一部分市场.一个获取这种信息的可选方案是通过使用惯性传感器.从这些传感器中取得的信号需要进行一些处理,因为在加速度和位置之间没有一种直接转换. 为了获得位置,需要对加速度进行二次积分.本文介绍一种简单的算法实现加速度的二重积分.为了获取加速度的二重积分,一个简单的积分要进行两次,因为这样也

利用鼠标点击绘制出三棱锥

作者:feiquan 出处:http://www.cnblogs.com/feiquan/ 版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 大家写文都不容易,请尊重劳动成果~ 这里谢谢大家啦(*/ω\*) 大家可以先看下我的上一篇文章:对于单个模型(长方体为例)进行面投影时的消隐           http://www.cnblogs.com/feiquan/p/8213875.html 这两篇有相

MFC控件编程之鼠标消息

MFC控件编程之鼠标消息 在MFC中鼠标消息.键盘消息我们很常用.所以说一下. 鼠标消息分为客户区消息.跟非客户区消息. 一丶客户区消息 我们可以处理消息.来进行我们相应的函数即可. MFC添加消息的话.可以自己在消息映射表中添加 .可以自己使用工具直接添加. 消息映射表添加 学习过MFC原理的应该知道.这里可以添加消息. 自己可以手动添加.我们也可以使用向导来添加. void CCDCDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO