問題:後面的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個單位,這樣離物體更近*/
}
}