opengl学习笔记Ⅴ——磨人的轨迹球真可爱
这回我们继续优化交互。使用轨迹球来使得模型转得更加人性化。
轨迹球可以理解为模型外部套一个球体,在我们鼠标拖动旋转模型时,能够准确地模拟出球体被拖动的感觉。
首先,我在这里放弃了透视投影,考虑透视投影的话太复杂了。(搞不出来,就很烦)
用简单的正交投影来做吧
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学习笔记Ⅴ——磨人的轨迹球真可爱相关推荐
- OpenGL MFC单文档 实现轨迹球
OpenGL MFC单文档 实现轨迹球 前言:我是一个怀揣着伟大梦想的普通男生!结果就是,一有时间就幻想着自己的伟大梦想,忘了自己下一步该迈出左脚还是右脚.这不,只顾做梦了,时光可不管我,独自一个人走 ...
- C# 学习笔记(10)加速球
C# 学习笔记(10)加速球 利用窗体透明和GIF透明背景,实现加速球类似效果(QQ宠物,老年人大概也知道) 本文参考C#仿PS异形启动界面设计https://www.bilibili.com/vid ...
- OpenGL学习笔记:矩阵变换
文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...
- OpenGL学习笔记(一)绘制点线面及多面体
OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...
- OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用
原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...
- 学习笔记之三人表决器FPGA
学习笔记之三人表决器FPGA 新手入门,多多包涵,不足错误之处,望指出 三人表决器,顾名思义就是三人投票,只要达到两票以上,就取胜. 设a,b,c为三个投票的人,输出的为f,投为1,不投为0,两票以上 ...
- 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】
✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...
- OPENGL学习笔记之八
OPENGL学习笔记之八 2017/11/15 阅读材料来自learnopengl.com以及learnopengl-cn.github.io 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将 ...
- 【OpenGL学习笔记】地月系
OpenGL学习笔记2-地月系 文章目录 OpenGL学习笔记2-地月系 前言 运行结果 纹理图片 一.TexturePool 1.**TexturePool.h** 2.**TexturePool. ...
最新文章
- Vue 兼容 ie9 的全面解决方案
- 来不及想标题了,我要去打包收藏了 | 本周值得读
- [转载] 使用Python编写打字训练小程序
- python软件测试面试题及答案_软件测试面试 | 一道大厂算法面试真题,你能答上来吗?(附答案)...
- C语言学习笔记---浮点函数modf()和fmod()
- 五分钟读懂UML类图(转)
- 运行PCL代码出现C2988,C2143,C2913等错误
- 信息系统项目管理师考试相关介绍
- html5时间插件mui,移动端时间控件 HTML5+ 的 pickDate 和 MUI 的 dtpicker 的使用与对比...
- 2015年河南省省赛部分题题解
- N款在线图片处理工具,让你的效率翻倍
- matlab hist 横坐标,matlab中hist函数的用法_matlab中hist函数 将EXCEL 中的日期 时间 导入到MATLAB坐标轴中...
- 应用计算机怎么弹ink,Win10不小心按W键结果弹出INK工作区的处理方法
- 笔记本每次启动都会先黑屏1分钟再启动问题解决
- 【VRP问题】基于NSGA算法求解多中心VRP问题matlab源码
- 3.4 学编程不拘于语言,学语言不限于平台——《逆袭大学》连载
- 计算机毕业设计基于VC的中小企业人事管理系
- 驰骋BPM工作流后台常用接口与前台常用方法
- 5.5 定积分应用——元素法
- 计算机图形学---颜色视觉知识点