博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
摄像机与绕任意轴旋转
阅读量:6162 次
发布时间:2019-06-21

本文共 2462 字,大约阅读时间需要 8 分钟。

I 摄像机类

我们先用gluLookAt来实现摄像机,稍后会给出世界坐标到相机坐标的变换矩阵。

关于gluLookAt的描述

void gluLookAt(    GLdouble eyeX,

     GLdouble eyeY,
     GLdouble eyeZ,
     GLdouble centerX,
     GLdouble centerY,
     GLdouble centerZ,
     GLdouble upX,
     GLdouble upY,
     GLdouble upZ);
Parameters

eyeX, eyeY, eyeZ

Specifies the position of the eye point.

centerX, centerY, centerZ

Specifies the position of the reference point.

upX, upY, upZ

Specifies the direction of the up vector.

Description

gluLookAt creates a viewing matrix derived from an eye point, a reference point indicating the center of the scene, and an UP vector.

针对摄像机需要用三个向量来定义,视点坐标m_View,上向量m_Up决定摆动幅度,位置向量m_Position决定空间中的位置

 

要让摄像机能在游戏世界中漫游的话 需要支持移动和改变朝向。

移动拆解为左右移动和前后移动,我们把垂直于朝向向量和上向量形的向量叫作左向量,左右移动即是沿左向量正负方向的移动。前后移动则是沿朝向向量正负方向的移动。

 

改变朝向的方法比较复杂,我们需要这样一个接口void rotateView(float angle,float x,float y,float z);来计算摄像机的视点绕任意轴旋转后的新位置

II 点绕任意轴旋转的公式推导

已知一点P坐标 以及轴A 求P绕轴A旋转后的新坐标P’

rotateView函数中的参数 x y z即为轴A向量 它的长度对我们没有意义 只需要知道方向就行了 也就是A的单位向量(在上面加^符号表示)

最后推导出来的公式应该只包含P向量 ,A的单位向量和旋转角度

III 旋转方法的实现

接下来的事情就简单了 只需要拿朝向向量计算旋转后的每个分量的值 再更新视点坐标就行了

 

III 世界坐标转换为相机坐标

gluLookAt可以用矩阵变换实现,只要推导出世界坐标转换为相机坐标的矩阵Tcaml。网上搜了下有用glTranslate和glRotate实现的,但是那是用的欧拉坐标系的方式,原理是根据绕XYZ绕转的角度来推导Tcam,比较麻烦。既然我们用的上向量,左向量,视点向量的方式表示摄像机,用UVN坐标系变换的方式顺理成章。

摄像机的上向量u,左向量v,方向向量n 相互正交,线性无关,可扩展成R3空间,即可做为三维空间的基。世界坐标到相机坐标的变换即是将世界坐标中的向量(a1,a2,a3) ,即关于 xyz坐标轴基向量的线性组合 a1X+a2Y+a3Z 变换为 基(u,v,n)的线性组合 c1U+c2V+c3N

注意推导过程是用的行向量右乘矩阵,与一般线性代数的教材列向量有点不同。u,v,n向量都是经过Normalize的单位向量。过程很简单,即用(u,v,n)向量表示出线性变换矩阵M(uvn坐标到世界坐标的变换),然后求M的逆矩阵。还有一种方法是对x向量的uvn线性组合,两边都点乘上u,由于u和v,u和n正交,所以dot(u,v),dot(u,n)都等于0,从而求出x向量与u向量的共线度,即为u坐标c1,同理可求c2,c3。

代码

void Camera::setLook()

{       
        /*gluLookAt(m_Position.x,m_Position.y,m_Position.z,
                    m_View.x,m_View.y,m_View.z,
                    m_Up.x,m_Up.y,m_Up.z);*/

        glMatrixMode(GL_MODELVIEW);

        glLoadIdentity();
        buildMatrixUVN();
        glMultMatrixf((GLfloat*)m_Camera.M);
}

void Camera::buildMatrixUVN()
{       
        VECTOR4D u;
        VECTOR4D v;
        VECTOR4D n;

        VECTOR4D_Sub(&m_View,&m_Position,&n);       

//这里之所以要对方向向量反向,是因为opengl采用的右手坐标系

        n.x = -n.x;
        n.y = -n.y;
        n.z = -n.z;

        VECTOR4D_INITXYZ(&v,0,1,0);

        VECTOR4D_Cross(&v,&n,&u);

        VECTOR4D_Cross(&n,&u,&v);
       
        VECTOR4D_Normalize(&v);
        VECTOR4D_Normalize(&u);
        VECTOR4D_Normalize(&n);       

        //uvn变换

        Mat_Init_4X4(&m_Camera,u.x,v.x,n.x,0,
                                                    u.y,v.y,n.y,0,
                                                    u.z,v.z,n.z,0,
                                                    0,0,0,1);

//坐标变换,还需要叠加上相机位置的移动向量

        MATRIX4X4 mt_postion;
        Mat_Init_4X4(&mt_postion,1,0,0,0,
                                                          0,1,0,0,
                                                          0,0,1,0,
                                                          -m_Position.x,-m_Position.y,-m_Position.z,1);

        Mat_Mul_4X4(&mt_postion,&m_Camera,&m_Camera);

}

转载于:https://www.cnblogs.com/lambdal/p/3638684.html

你可能感兴趣的文章
《代码敲不队》第四次作业:项目需求调研与分析
查看>>
菜鸡互啄队—— 团队合作
查看>>
HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法...
查看>>
SparseArray
查看>>
第二章
查看>>
android背景选择器selector用法汇总
查看>>
[转]Paul Adams:为社交设计
查看>>
showdialog弹出窗口刷新问题
查看>>
java
查看>>
Vue.js连接后台数据jsp页面  ̄▽ ̄
查看>>
关于程序的单元测试
查看>>
mysql内存优化
查看>>
都市求生日记第一篇
查看>>
Java集合---HashMap源码剖析
查看>>
SQL优化技巧
查看>>
thead 固定,tbody 超出滚动(附带改变滚动条样式)
查看>>
Dijkstra算法
查看>>
css 动画 和 响应式布局和兼容性
查看>>
csrf 跨站请求伪造相关以及django的中间件
查看>>
MySQL数据类型--与MySQL零距离接触2-11MySQL自动编号
查看>>