Trackball詳解????

 

問題:後面的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)在視點座標系(XYZ)下的座標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個單位,這樣離物體更近*/

 

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章