问题:后面的TrackballManipulator::tb_project_to_sphere()?????
void TrackballManipulator::computePosition(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up)
{ osg::Vec3 lv(center-eye);
osg::Vec3 f(lv);
f.normalize();
osg::Vec3 s(f^up);
s.normalize();
osg::Vec3 u(s^f);
u.normalize();
osg::Matrix rotation_matrix(s[0], u[0], -f[0], 0.0f,
s[1], u[1], -f[1], 0.0f,
s[2], u[2], -f[2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
//矩阵rotation_matrix相当于把“倾斜”的uvn坐标系变为“正”的opengl标准坐标系,下面的_rotation是rotation_matrix的逆矩阵,相当于把“正”的opengl标准坐标系变为“倾斜”的uvn坐标系
_center = center;
_distance = lv.length();
_rotation = rotation_matrix.getRotate().inverse();
}
---------
//将视点及其局部坐标系由opengl标准世界坐标系变换到最终“倾斜”的uvn坐标系。
osg::Matrixd TrackballManipulator::getMatrix() consts
{
return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::translate(_center);
}//改变视点坐标系,实质相当于改变视点坐标和旋转矩阵(R*T),它其实也相当于是把坐标系先平移(T)再旋转(R):
osg::Matrixd::rotate(_rotation )* osg::Matrixd::translate(_homeEye),但注意,这只是有时候成立,因为TrackballManipulator中鼠标操作是以改变_center为主的。
TrackballManipulator::getMatrix()相当于对视点及其局部坐标系进行变换:①先平移到_center。②将局部坐标系旋转成为“倾斜”的uvn坐标系。③将局部坐标系沿Z轴(即n轴)平移_distance的距离。如下图:
注意:对视点的变换是在opengl坐标系下,而不是在OSG坐标系下。
――――――――――
视图矩阵MV=TrackballManipulator::getInverseMatrix()。
――――――――――
void TrackballManipulator::setByMatrix(const osg::Matrixd& matrix)
{
_center = osg::Vec3(0.0f,0.0f,-_distance)*matrix;
_rotation = matrix.getRotate();
}
其中matrix是把视点及其局部坐标系变换为最终的视点及局部坐标系(uvn)。这样,(0.0f,0.0f,-_distance)表示在该uvn坐标系下z=-_distance的点,看上图的视点E及其uvn坐标系,可知该点是参考点_center。matrix.getRotate();就是将opengl标准世界坐标系变换到最终“倾斜”的uvn坐标系。
总之,可以看成是对局部坐标系的操作(进行一系列平移或旋转变换)。
――――――――――
用鼠标旋转轨迹球时:TrackballManipulator::calcMovement()中:
_rotation = _rotation*new_rotate;
它是在原来_rotation的基础上右乘的,为什么不左乘?原因如下(参考下图):在以_center为中心的opengl的XYZ坐标系(X朝右,Z朝屏幕外)下,视点v(0,0,_distance)在视点坐标系(X’Y’Z’)下的坐标v0=v*_rotation,而当用鼠标旋转轨迹球时,坐标v0应该绕opengl的XYZ坐标系下的某个轴n旋转一角度(设矩阵为R),此时新视点v1在opengl的XYZ坐标系下的坐标v1=v0*R,即v1=v*_rotation*R,即新的旋转矩阵为_rotation*R。
TrackballManipulator::calcMovement()
{……
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))//在与视线垂直的平面上平移相机
{ // pan model.
float scale = -0.3f*_distance;
osg::Matrix rotation_matrix;
rotation_matrix.makeRotate(_rotation);
osg::Vec3 dv(dx*scale,dy*scale,0.0f);
_center += dv*rotation_matrix;
return true;
}
/* dv*rotation_matrix相当于uvn坐标系中(dx*scale,dy*scale,0.0f)的向量,_center += dv*rotation_matrix即将参考点_center 在uvn坐标系的uv平面(或xy平面)上移动,相当于在与视线垂直的平面上平移相机*/
……
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{//缩放模型,即将参考点沿视线方向前进
float scale = -fd;
osg::Matrix rotation_matrix(_rotation);
osg::Vec3 dv = (osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix)*(dy*scale);
_center += dv;
/*(0.0f,0.0f,-1.0f)*rotation_matrix相当于uvn坐标系中的z=-1的向量(值是世界坐标值),_center += dv表示将参考点_center 向n轴负向平移1个单位,这样离物体更近*/
}
}