这回我们继续优化交互。使用轨迹球来使得模型转得更加人性化。

轨迹球可以理解为模型外部套一个球体,在我们鼠标拖动旋转模型时,能够准确地模拟出球体被拖动的感觉。

首先,我在这里放弃了透视投影,考虑透视投影的话太复杂了。(搞不出来,就很烦)

用简单的正交投影来做吧

glMatrixMode(GL_PROJECTION);//设置投影矩阵
glLoadIdentity();
glOrtho(-1500, 1500, -1500, 1500, 1, 10000);

这样,我们可以简单地算出球在窗口中的大小。(这里我的窗口大小为250,1500为正交投影规定的视景体的一半)

work_size = a*(R/1500.0)*250;//a为缩放比例,初始为1

接着我们换算一下鼠标回调函数得到的坐标,把它转化成球心为原点的坐标系(窗口中间)。因为鼠标回馈的坐标是以左上为原点,向右为x,向下为y。所以我们这么转化:

x -= 250;
y -= 250;
y = -y;

这样,可以算出我们点击的点的“坐标”A,这里是针对窗口里显示的球(work_size为半径)的中心的坐标系,朝外为Z正。

r_x1 = x;
r_y1 = y;
r_z1 = sqrt(work_size*work_size - x*x - y*y);

同样,在鼠标移动的回调函数里,我们会得到另外一个点B的坐标(r_x2,r_y2,r_z2)。

计算出OA X OB(叉乘)的值,即为旋转轴,记得要把长度缩放为1。

rx = r_y1*r_z2-r_z1*r_y2;
ry = r_z1*r_x2 - r_x1*r_z2;
rz = r_x1*r_y2 - r_y1*r_x2;
mod = sqrt(rx*rx + ry*ry + rz*rz);
rx /= mod;
ry /= mod;
rz /= mod;

计算旋转角度,l为两点之间的距离。

l = sqrt((r_x1 - r_x2)*(r_x1 - r_x2) + (r_y1 - r_y2)*(r_y1 - r_y2) + (r_z1 - r_z2)*(r_z1 - r_z2));
theta =-2*asin(l/(2.0*work_size));

参考https://www.cnblogs.com/graphics/archive/2012/08/10/2627458.html里的文章,我们可以得到对应的旋转矩阵如下

m2[0] = rx*rx + (1 - rx*rx)*cos(theta);
m2[1] = rx*ry*(1 - cos(theta)) - rz*sin(theta);
m2[2]= rx*rz*(1 - cos(theta)) + ry*sin(theta);
m2[4] = rx*ry*(1 - cos(theta)) + rz*sin(theta);
m2[5] = ry*ry + (1 - ry*ry)*cos(theta);
m2[6] = ry*rz*(1 - cos(theta)) - rx*sin(theta);
m2[8] = rx*rz*(1 - cos(theta)) - ry*sin(theta);
m2[9] = ry*rz*(1 - cos(theta)) + rx*sin(theta);
m2[10] = rz*rz + (1 - rz*rz)*cos(theta);
m2[15] = 1;

注意opengl中,矩阵为4X4,实际上接受的是一个一维数组指针,所以我们定义为m2[16]。因为opengl是一列一列存数据,和我们正常的一行一行的存不一样,所以注意下标的选择哦。

在我们放开鼠标左键之后,把这一次的旋转矩阵作用在m1上,使得m1代表所有历史旋转矩阵的综合作用。

glLoadMatrixd(m2);
glMultMatrixd(m1);
glGetDoublev(GL_MODELVIEW_MATRIX, m1);
glLoadIdentity();
glGetDoublev(GL_MODELVIEW_MATRIX, m2);

这里要注意的是,opengl是右乘,如果我们直接把m2乘进m1,得到的结果会是m1m2 V,我们实际上是希望在完成m1旋转之后进行m2旋转,所以才有了上面的倒来倒去的操作。

同样的,在绘制函数里,我们的绘制顺序也是

glMultMatrixd(m2);
glMultMatrixd(m1);

这样我们的旋转已经基本完成,接下来谈一下画球的问题,因为我们用的是光照模型,所以球画出来会有明暗的问题。但我们实际上不希望球的颜色会随着位置变化,所以我们调用如下函数设置球的自发光颜色,注意,这个光不会像光源一样影响其他物体的颜色。

glMaterialfv(GL_FRONT, GL_EMISSION, ball);

效果还不错。

附:对于在球外部的拖动,我们会希望变为Z轴方向的旋转。这里具体的讲解读者自己思考,我只放下我写的代码

                GLfloat theta,la,lb,lc;r_x2 = x;r_y2 = y;la = sqrt(r_x1*r_x1 + r_y1*r_y1);lb = sqrt(r_x2*r_x2 + r_y2*r_y2);lc = sqrt((r_x1 - r_x2)*(r_x1 - r_x2) + (r_y1 - r_y2)*(r_y1 - r_y2));theta = 180/PI*acos((la*la + lb*lb - lc*lc) / (2 * la*lb));//if (theta > 0.1)//{//  cout << endl;//}glLoadIdentity();if (r_x1*r_y2 - r_y1*r_x2>0)glRotated(theta, 0, 0, 1);elseglRotated(theta, 0, 0, -1);glGetDoublev(GL_MODELVIEW_MATRIX, m2);

opengl学习笔记Ⅴ——磨人的轨迹球真可爱相关推荐

  1. OpenGL MFC单文档 实现轨迹球

    OpenGL MFC单文档 实现轨迹球 前言:我是一个怀揣着伟大梦想的普通男生!结果就是,一有时间就幻想着自己的伟大梦想,忘了自己下一步该迈出左脚还是右脚.这不,只顾做梦了,时光可不管我,独自一个人走 ...

  2. C# 学习笔记(10)加速球

    C# 学习笔记(10)加速球 利用窗体透明和GIF透明背景,实现加速球类似效果(QQ宠物,老年人大概也知道) 本文参考C#仿PS异形启动界面设计https://www.bilibili.com/vid ...

  3. OpenGL学习笔记:矩阵变换

    文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...

  4. OpenGL学习笔记(一)绘制点线面及多面体

    OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...

  5. OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...

  6. 学习笔记之三人表决器FPGA

    学习笔记之三人表决器FPGA 新手入门,多多包涵,不足错误之处,望指出 三人表决器,顾名思义就是三人投票,只要达到两票以上,就取胜. 设a,b,c为三个投票的人,输出的为f,投为1,不投为0,两票以上 ...

  7. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  8. OPENGL学习笔记之八

    OPENGL学习笔记之八 2017/11/15 阅读材料来自learnopengl.com以及learnopengl-cn.github.io 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将 ...

  9. 【OpenGL学习笔记】地月系

    OpenGL学习笔记2-地月系 文章目录 OpenGL学习笔记2-地月系 前言 运行结果 纹理图片 一.TexturePool 1.**TexturePool.h** 2.**TexturePool. ...

最新文章

  1. Vue 兼容 ie9 的全面解决方案
  2. 来不及想标题了,我要去打包收藏了 | 本周值得读
  3. [转载] 使用Python编写打字训练小程序
  4. python软件测试面试题及答案_软件测试面试 | 一道大厂算法面试真题,你能答上来吗?(附答案)...
  5. C语言学习笔记---浮点函数modf()和fmod()
  6. 五分钟读懂UML类图(转)
  7. 运行PCL代码出现C2988,C2143,C2913等错误
  8. 信息系统项目管理师考试相关介绍
  9. html5时间插件mui,移动端时间控件 HTML5+ 的 pickDate 和 MUI 的 dtpicker 的使用与对比...
  10. 2015年河南省省赛部分题题解
  11. N款在线图片处理工具,让你的效率翻倍
  12. matlab hist 横坐标,matlab中hist函数的用法_matlab中hist函数 将EXCEL 中的日期 时间 导入到MATLAB坐标轴中...
  13. 应用计算机怎么弹ink,Win10不小心按W键结果弹出INK工作区的处理方法
  14. 笔记本每次启动都会先黑屏1分钟再启动问题解决
  15. 【VRP问题】基于NSGA算法求解多中心VRP问题matlab源码
  16. 3.4 学编程不拘于语言,学语言不限于平台——《逆袭大学》连载
  17. 计算机毕业设计基于VC的中小企业人事管理系
  18. 驰骋BPM工作流后台常用接口与前台常用方法
  19. 5.5 定积分应用——元素法
  20. 计算机图形学---颜色视觉知识点

热门文章

  1. 2019中国最佳创新公司50榜单发布
  2. 对于消纳问题 光伏领跑者有话说
  3. Photoshop中制作水中倒影
  4. hdu-2570 迷瘴(贪心水题)
  5. 布衣乐队的姑娘闪亮星光现场
  6. 机器学习中常用的线性回归问题
  7. Netty学习笔记(1) NIO基础-3
  8. 毕业论文调格式之页码,页眉页脚,目录页码右对齐
  9. 程序员需要了解的硬核知识之压缩算法
  10. 移动端芯片性能评测论文出炉