本文采用两种方式,在OpenGL中实现放大缩小功能:
方式一. 改变“视点”与模型之间的距离【改变模型视点变换矩阵】
对于这种方式存在三个问题需要解决:
① 缩放过程过渡平滑
② 当模型放大或缩小到一定程度,减慢其缩放速度,以免视点很快地贴近模型或消失在场景中
③ 防止视点进入模型内部
解决方案:
使用反正切函数:y=0.5*arctan(0.1*x)+0.25*PI,函数图像如下图:
当模型放大时,x--, y减小
当模型缩小时,x++, y增大
y减小时,即∠APM变小,视点A向M点移动(由于y>0,所以A永远不会到达M点)
y增大时,即∠APM变大,视点A远离M点
视点与物体中心的距离由三部分组成【AM+MN+NO】,这样可以保证无论模型处于什么姿态,都可以保证物体不会跨越近裁截面(问题③)
1 void setEyeAndRadius()
2 {
3 double angle = 0.5*atan(0.1*x)+0.25*PI;
4 // AM=tan(angle) MN=0.1 NO=sqrt(3.0)
5 radius = tan(angle)+sqrt(3.0)+0.1;
6
7 // 从聚焦点指向视点的向量 OA向量
8 vector3dd a(eye-target);
9
10 // 将其单位化
11 a.normailize();
12
13 eye = a*radius+target;
14 }
方式二. 改变投影变换的fovy夹角【改变投影变换矩阵】
fovy越小,模型越大;fovy越大,模型越小。
使用反正切函数:y=arctan(0.1*x)+0.5*PI,函数图像如下图:
当模型放大时,x--, y减小(fovy减少)
当模型缩小时,x++, y增大 (fovy增大)
1 void setFovy()
2 {
3 camFovy = 180.0/PI*(atan(0.1*x)+0.5*PI);
4 }
对于模型浏览而言,第二种方式更简洁,也易于理解,不用考虑视点会进入模型的情况。
效果图如下:
原图:
放大:
缩小: