在有些使用场景中,我们需要用到
1. 3dsMax
1.1外参数的导出
选中相机,点击菜单栏动画->保存动画->选择路径保存,用记事本打开这个 .xaf 文件,然后里面就会有相机的运动 变换矩阵T(R ,t),这里的R t是3dmax特有的格式,导出来的格式如下:
.........
.........
其中,可以组成3dmax的变换矩阵:T,前半部分是R(3*3),后半部分是t(3*1),对于变换矩阵,3dmax的API文档定义为Matrix3 类型,其原文如下:
http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/index.html?url=files/GUID-14497600-0839-4225-BA52-B571FCC8AEBF.htm,topicNumber=d30e24647
A Matrix3 can also be used to specify an axis system. For example, the INode method Rotate() is used to rotate a node about a specified axis system. One of the arguments to this method is a Matrix3 that specifies this axis system. Essentially, a matrix is just an axis system.
For example, if you think of an axis tripod in a viewport, this is basically all the information a matrix has. The axis tripod has three vectors (the directions of the axes: X, Y, Z) and a position in space (the point where the axes converge). A transformation matrix holds this same information. The 0th row of a matrix is the X vector, the 1st row of the matrix is the Y vector, the 2nd row of the matrix is the Z vector, and the 3rd row of the matrix is the position.
翻译过来就是这个矩阵是一个轴系统,对于矩阵中第一行是指定的X轴朝向,矩阵的第0行是X向量,矩阵的第1行是Y向量,矩阵的第2行是Z向量,矩阵的第3行是位置。
因此我猜测3dmax应该是按行存储的,由于3dmax和OpenGL一样是使用右手系的,因此,这里和计算及图形学定义的旋转与平移矩阵就匹配起来了,我们可以将导出的v=" ........."按行存入R,t中,而这里的R(3*3) 可以作为当前相机的观察坐标系,当前的t(3*1)可以作为当前观察坐标系原点,那么根据上面的定义我们可以计算出被拍摄物体转换到当前坐标系下面的变换矩阵,具体公式见书本吧。
1.2 内参数的计算
设相机输出画幅为 Width*Hight
镜头焦距为 F(图中的Lens) ,水平视角为 a(图中的 横向FOV )) ,则 Film Back Size (w)= 2*F*Tan(a/2)
而内参数Fx,Fy = 缩放尺度( 像素/m ) * F( m )
则 Fx = Width / Film Back Size * F
= Width / (2*F*Tan(a/2))*F
= Width / (2*Tan(a/2))
1.3 外参数转换,变换世界坐标系转换到观察坐标系(相机坐标系)
根据计算机图形学的世界坐标系到观察坐标系的转换公式,T(4*4)=R(4*4)*T(4*4)(具体公式见书本),计算出变换矩阵之后,就可以将被拍摄物体通过变换矩阵转换到观测的坐标系下了,此时设为Pc(x,y,z)。
2. 3dmax转换到OpenCV
由于这里3dmax的相机默认情况下是在世界坐标系原点朝向z轴负方向的,
参考:http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/index.html?url=files/GUID-14497600-0839-4225-BA52-B571FCC8AEBF.htm,topicNumber=d30e24647
此时观测坐标系的正方向是Y轴朝上,X轴朝向右边,Z轴朝屏幕外,根据OpenCV坐标系正方向,OpenCV坐标系相当于3dmax 的观测坐标系绕X轴旋转180度,那么将得到的坐标整体左乘以旋转矩阵{1,0,0,0,-1,0,0,0,-1},即得到OpenCV下的相机坐标,对此坐标进行归一化得到Pc(x/|z|,y/|z|,1),用内参K乘以Pc(x/|z|,y/|z|,1),得到像素坐标Puv(u,v,1),取前两位转换为像素坐标之后就可以直接显到屏幕上了。
3. 3dmax转换到OpenGL
3.1 modelViewMatrix计算
如果自己写 LookAt函数:
3dmax的相机默认朝向和OpenGL的默认朝向是一样的,因此,ModelViewMatrix就为上面的T,ProjectMatrix按照书本上的公式计算就OK了。
如果用glm::lookAt 函数需要一个位置、目标和上向量。它会创建一个和3.1的一样的观察矩阵
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
3.2 ProjectionMatrix计算
先挖个坑,其他地方好像有蛮多类似教程,不重复造轮子了
3.3 模型使用
3.3.1 导入
3dsMax选中模型,删除动画,旋转量归零,平移量归零,导出,只要顶点和面
然后用meshlab转换一下,不知道为什么,不转一下,好像显示不出来
3.3.2 控制
给模型设置好动画之后,选中模型,动画->保存动画,这里的模型RT导出来的格式为行优先,前三行为R,后一行为T,由于3dsMax的控制方式为先旋转,后平移,所以这里的使用的方法是T={R|t};
然后在渲染物体之前首先glMultMatrixd(T),就可以将物体转换到当前位置了