青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

3D中的方位和角位移的C++實現(1)

新建網頁 1

 

數學理論基礎請參閱3D中的方位和角位移。

處理變換是一件非常令人頭疼的事,矩陣更是棘手。如果你曾經編寫過關于矩陣的代碼并且沒有用設計良好的類,你會發現經常要處理負號、轉置矩陣或翻轉連接順序以使其能正常工作。

下面這幾個類正是為了消除在編程中經常遇到的這類問題而設計的。例如,很少需要直接訪問矩陣或四元數中的元素,因此特意限制了可用操作的數目以避免產生迷惑,再如,對cRotationMatrix類,沒有求逆和連接操作,因為如果按其本身的目的使用cRotationMatrix,這些操作是不應該出現或沒有意義的。

我們還使用了一系列簡單、常用的數學常數和實用工具函數,它們由MathUtil.hMathUtil.cpp提供。

MathUtil.h:

        #ifndef MATH_UTIL_H
    
#define MATH_UTIL_H
    
    #include <math.h>
    
    
    // declare a global constant for pi and a few multiples.
    

    
const float G_PI          = 3.14159265f;
    
const float G_2PI          = G_PI * 2.0f;
    
const float G_PI_OVER_2   = G_PI / 2.0f;
    
const float G_1_OVER_PI   = 1.0f / G_PI;
    
const float G_1_OVER_2PI  = 1.0f / G_2PI;
    
const float G_PI_OVER_180 = G_PI / 180.0f;
    
const float G_180_OVER_PI = 180.0f / G_PI;
    
    
float wrap_pi(float theta);
    
float safe_acos(float x);
    
    
    // convert between degrees and radians
    
inline float deg_to_rad(float deg)    { return deg * G_PI_OVER_180; }
    inline 
float rad_to_deg(float rad)    { return rad * G_180_OVER_PI; }
    
    
    // compute the sin and cosine of an angle. on some platforms, if we know that we need
    // both values, it can be computed faster than computing the two values seperately.
    
inline void sin_cos(float* ret_sin, float* ret_cos, float theta)
    {
        
// for simplicity, we will just use the normal trig functions.
        // note that on some platforms we may be able to do better.
    

        *ret_sin = sin(theta);
        *ret_cos = cos(theta);
    }
    
    
    // convert between "field of view" and "zoom", the fov angle is speficied in radians.
    
inline float fov_to_zoom(float fov)        { return 1.0f / tan(fov * 0.5f); }
    inline 
float zoom_to_fov(float zoom)    { return 2.0f * atan(1.0f / zoom); }
    
    
#endif

MathUtil.cpp:

關于類cVector3的實現細節請參閱一個3D向量類

        #include "MathUtil.h"
    #include "vector3.h"
    
    
const cVector3 g_zero_vector(0.0f, 0.0f, 0.0f);
    
    
float wrap_pi(float theta)
    {
        
// "wrap" an angle in range -pipi by adding the correct multiple of 2 pi
    

        theta += G_PI;
        theta -= floor(theta * G_1_OVER_2PI) * G_2PI;
        theta -= G_PI;
    
        
return theta;
    }
    
    
float safe_acos(float x)
    {
        
// Same as acos(x), but if x is out of range, it is "clamped" to the nearest valid value.
        // The value returned is in range 0pi, the same as the standard C acos() function.
    
        // check limit conditions
    

        
if(x <= -1.0f)
            
return G_PI;
    
        
if(x >= 1.0f)
            
return 0.0f;
    
        
// value is in the domain - use standard C function.
    
    return acos(x);
    }

cEulerAngles類:

cEulerAngles類用來以歐拉角形式保存方位,使用heading-pitch-bank約定。這個類非常直觀,為了簡單起見,我們沒有實現太多操作。特別沒有實現加、減、標量乘等運算。因為如果該類保存的不是方位而是角速度或變化率,那么這些運算才是有用的。

EulerAngles.h:

        #ifndef EULER_ANGLES_H
    
#define EULER_ANGLES_H
    
    
class cQuaternion;
    
class cMatrix4x3;
    
class cRotationMatrix;
    
    
    //---------------------------------------------------------------------------
    // This class represents a heading-pitch-bank Euler angle triple.
    //---------------------------------------------------------------------------
    
class cEulerAngles
    {
    
public:
        
// store three angles, in radians.
    
    float heading;
        
float pitch;
        
float bank;
    
    
public:
        cEulerAngles()    {}
        
        cEulerAngles(
float h, float p, float b)
        {
            heading = h;
            pitch   = p;
            bank    = b;
        }
    
        
// set to identity triple (all zeors)
    
    void identity()
        {
            pitch = bank = heading = 0.0f;
        }
    
        
void canonize();
    
        
void from_object_to_inertial_quat(const cQuaternion& q);
        
void from_inertial_to_object_quat(const cQuaternion& q);
    
        
void from_object_to_world_matrix(const cMatrix4x3& m);
        
void from_world_to_object_matrix(const cMatrix4x3& m);
    
        
void from_rotation_matrix(const cRotationMatrix& m);
    };
    
    
extern const cEulerAngles g_euler_angles_identity;
    
    
#endif

cEulerAngles類的用法也很直觀,只有幾個地方需要加以詳細說明:

(1)canonize()函數的作用是確保歐拉角位于"限制集"中。

(2)from_object_to_inertial_quat()from_inertial_to_object_quat()函數根據四元數計算歐拉角,第一個函數的參數是代表從物體坐標系到慣性坐標系旋轉的四元數,第二個函數的參數是代表從慣性坐標系到物體坐標系旋轉的四元數。

(3)同樣,from_object_to_world_matrix()from_world_to_object_matrix()函數把矩陣的旋轉部分的方位轉換為歐拉角,假設這個被轉換的矩陣是正交的。


EulerAngles.cpp:

        #include <math.h>
    #include "EulerAngles.h"
    #include "Quaternion.h"
    #include "MathUtil.h"
    #include "Matrix4x3.h"
    #include "RotationMatrix.h"
    
    
const cEulerAngles g_euler_angles_identity(0.0f, 0.0f, 0.0f);
    
    
    //---------------------------------------------------------------------------
    // Set the Euler angle triple to its "canonical" value.  This does not change
    // the meaning of the Euler angles as a representation of Orientation in 3D,
    // but if the angles are for other purposes such as angular velocities, etc,
    // then the operation might not be valid.
    //---------------------------------------------------------------------------
    
void cEulerAngles::canonize()
    {
        
// first, wrap pitch in range -pi  pi
    
    pitch = wrap_pi(pitch);
    
        
// now, check for "the back side" of the matrix, pitch outside the canonical range
        // of -pi/2  pi/2
    
    if(pitch < -G_PI_OVER_2)
        {
            pitch     = -G_PI - pitch;
            heading += G_PI;
            bank    += G_PI;
        }
        
else if(pitch > G_PI_OVER_2)
        {
            pitch     = G_PI - pitch;
            heading += G_PI;
            bank    += G_PI;
        }
    
        
// ok, now check for the gimbel lock case (within a slight tolerance)    
    
    if(fabs(pitch) > G_PI_OVER_2 - 1e-4)
        {
            
// we are in gimbel lock, assign all rotation about the vertical axis to heading.
    
        heading += bank;
            bank     = 0.0f;
        }
        
else
        {
            
// not in gimbel lock, wrap the bank angle in canonical range.
    
        bank = wrap_pi(bank);
        }
    
        
// wrap heading in canonical range
    
    heading = wrap_pi(heading);
    }
    
    
    //---------------------------------------------------------------------------
    // Setup the Euler angles, given an object->inertial rotation quaternion.
    //
    // p = asin(-m23) = asin(-2(yz - wx))
    // 
    // h = atan2(m13, m33)  = atan2(xz + wy, 1/2 - x^2 - y^2)   cosp != 0
    // h = atan2(-m31, m11) = atan2(-xz + wy, 1/2 - y^2 - z^2)  cosp == 0
    //
    // b = atan2(m21, m22) = atan2(xy + wz, 1/2 - x^2 - z^2)    cosp != 0
    // b = 0                                                    cosp == 0
    //---------------------------------------------------------------------------
    
void cEulerAngles::from_object_to_inertial_quat(const cQuaternion& q)
    {
        
// extract sin(pitch)
    
    float sin_pitch = -2.0f * (q.y * q.z - q.w * q.x);
    
        
// check for gimbel lock, giving slight tolerance for numerical imprecision.
    
    if(fabs(sin_pitch) > 0.9999f)
        {
            
// looking straight up or down
    
        pitch = G_PI_OVER_2 * sin_pitch;
    
            
// compute heading, slam bank to zero.
    
        heading = atan2(-q.x * q.z + q.w * q.y, 0.5f - q.y * q.y - q.z * q.z);
            bank = 0.0f;
        }
        
else
        {
            
// compute angles, we do not have to use the "safe" asin function because we already
            // checked for range errors when checking for gimbel lock.
    
        pitch    = asin(sin_pitch);
            heading = atan2(q.x * q.z + q.w * q.y, 0.5f - q.x * q.x - q.y * q.y);
            bank    = atan2(q.x * q.y + q.w * q.z, 0.5f - q.x * q.x - q.z * q.z);
        }
    }
    
    
    //---------------------------------------------------------------------------
    // Setup the Euler angles, given an inertial->object rotation quaternion.
    //
    // p = asin(-m23) = asin(-2(yz + wx))
    // 
    // h = atan2(m13, m33)  = atan2(xz - wy, 1/2 - x^2 - y^2)   cosp != 0
    // h = atan2(-m31, m11) = atan2(-xz - wy, 1/2 - y^2 - z^2)  cosp == 0
    //
    // b = atan2(m21, m22) = atan2(xy - wz, 1/2 - x^2 - z^2)    cosp != 0
    // b = 0                                                    cosp == 0
    //---------------------------------------------------------------------------
    
void cEulerAngles::from_inertial_to_object_quat(const cQuaternion& q)
    {
        
// extract sin(pitch)
    
    float sin_pitch = -2.0f * (q.y * q.z + q.w * q.x);
    
        
// check for gimbel lock, giving slight tolerance for numerical imprecision.
    
    if(fabs(sin_pitch) > 0.9999f)
        {
            
// looking straight up or down
    
        pitch = G_PI_OVER_2 * sin_pitch;
    
            
// compute heading, slam bank to zero.
    
        heading = atan2(-q.x * q.z - q.w * q.y, 0.5f - q.y * q.y - q.z * q.z);
            bank = 0.0f;
        }
        
else
        {
            
// compute angles, we do not have to use the "safe" asin function because we already
            // checked for range errors when checking for gimbel lock.
    
        pitch    = asin(sin_pitch);
            heading = atan2(q.x * q.z - q.w * q.y, 0.5f - q.x * q.x - q.y * q.y);
            bank    = atan2(q.x * q.y - q.w * q.z, 0.5f - q.x * q.x - q.z * q.z);
        }
    }
    
    
    //------------------------------------------------------------------------------------------------
    // Setup the Euler angles, given an object->world transformation matrix.
    // The matrix is assumed to be orthogonal.  The translation portion is ignored.
    //
    //     | cosh * cosb + sinh * sinp * sinb        sinb * cosp    -sinh * cosb + cosh * sinp * sinb |
    // M = | -cosh * sinb + sinh * sinp * cosb        cosb * cosp        sinb * sinh + cosh * sinp * cosb |
    //       | sinh * cosp                            -sinp            cosh * cosp                         |
    //
    // [1]: cosp != 0
    //
    // p = asin(-m32)
    // h = atan2(m31, m33)
    // b = atan2(m12, m22)
    //
    // [2]: cosp = 0, b = 0, sinb = 0, cosb = 1
    //
    //     | cosh            0        -sinh        |
    // M = | sinh * sinp    0        cosh * sinp |
    //       | 0                -sinp    0            |
    //
    // p = pi/2 * (-m32)
    // h = atan2(-m13, m11)
    // b = 0
    //------------------------------------------------------------------------------------------------
    
void cEulerAngles::from_object_to_world_matrix(const cMatrix4x3& m)
    {
        
// extract sin(pitch) from m32
    
    float sin_pitch = -m.m32;
    
        
// check for gimbel lock
    
    if(fabs(sin_pitch) > 0.99999f)
        {
            
// locking straight up or down
    
        pitch = G_PI_OVER_2 * sin_pitch;
    
            
// compute heading, slam bank to zero.
    
            heading = atan2(-m.m13, m.m11);
            bank = 0.0f;
        }
        
else
        {
            
// compute angles, we do not have to use the "safe" asin function because we already
            // checked for range errors when checking for gimbel lock.
    
            heading = atan2(m.m31, m.m33);
            pitch   = asin(sin_pitch);
            bank    = atan2(m.m12, m.m22);
        }
    }
    
    
    //-----------------------------------------------------------------------------------------------------
    // Setup the Euler angles, given a world->object transformation matrix.
    // The matrix is assumed to be orthogonal.  The translation portion is ignored.
    //
    //     | cosh * cosb + sinh * sinp * sinb      -cosh * sinb + sinh * sinp * cosb         sinh * cosp |
    // M = | sinb * cosp                            cosb * cosp                                 -sinp         |
    //       | -sinh * cosb + cosh * sinp * sinb        sinb * sinh + cosh * sinp * cosb        cosh * cosp  |
    //
    // [1]: cosp != 0
    //
    // p = asin(-m23)
    // h = atan2(m13, m33)
    // b = atan2(m21, m22)
    //
    // [2]: cosp = 0, b = 0, sinb = 0, cosb = 1
    //
    //        | cosh      sinh * sinp     0     |
    // M =  | 0            0                -sinp |
    //        | -sinh        cosh * sinp        0      |
    //
    // p = pi/2 * (-m23)
    // h = atan2(-m31, m11)
    // b = 0
    //-----------------------------------------------------------------------------------------------------
    
void cEulerAngles::from_world_to_object_matrix(const cMatrix4x3& m)
    {
        
// extract sin(pitch) from m23
    
    float sin_pitch = -m.m23;
    
        
// check for gimbel lock
    
    if(fabs(sin_pitch) > 0.99999f)
        {
            
// locking straight up or down
    
            pitch = G_PI_OVER_2 * sin_pitch;
    
            
// compute heading, slam bank to zero.
    
            heading = atan2(-m.m31, m.m11);
            bank = 0.0f;
        }
        
else
        {
            
// compute angles, we do not have to use the "safe" asin function because we already
            // checked for range errors when checking for gimbel lock.
    
            heading = atan2(m.m13, m.m33);
            pitch   = asin(sin_pitch);
            bank    = atan2(m.m21, m.m22);
        } 
    }
    
    
    //---------------------------------------------------------------------------
    // Setup the Euler angles, given a rotation matrix.
    //---------------------------------------------------------------------------
    
void cEulerAngles::from_rotation_matrix(const cRotationMatrix& m)
    {
        
// extract sin(pitch) from m23
    
    float sin_pitch = -m.m23;
    
        
// check for gimbel lock
    
    if(fabs(sin_pitch) > 0.99999f)
        {
            
// locking straight up or down
    
            pitch = G_PI_OVER_2 * sin_pitch;
    
            
// compute heading, slam bank to zero.
    
            heading = atan2(-m.m31, m.m11);
            bank = 0.0f;
        }
        
else
        {
            
// compute angles, we do not have to use the "safe" asin function because we already
            // checked for range errors when checking for gimbel lock.
    
            heading = atan2(m.m13, m.m33);
            pitch   = asin(sin_pitch);
            bank    = atan2(m.m21, m.m22);
        } 
    }

posted on 2008-02-18 10:49 lovedday 閱讀(1134) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国外视频精品毛片| 欧美成人网在线| 亚洲免费激情| 狂野欧美一区| 午夜精品视频网站| 亚洲美女黄色| 亚洲成人资源网| 国产亚洲网站| 国产精品一区一区三区| 欧美日韩精品二区| 欧美搞黄网站| 久久视频一区二区| 久久超碰97人人做人人爱| 亚洲视频在线观看视频| 亚洲日本一区二区| 欧美a级一区| 久久夜色精品亚洲噜噜国产mv| 亚洲欧美日韩国产精品| 一区二区三区四区国产| 最新精品在线| 亚洲国产高清自拍| 在线成人av网站| 狠狠色狠狠色综合日日91app| 国产精品综合色区在线观看| 欧美视频在线观看视频极品| 欧美伦理视频网站| 欧美日韩大片| 欧美日韩一区二区视频在线| 欧美日韩成人在线播放| 欧美另类在线播放| 欧美精品一区二区精品网| 欧美α欧美αv大片| 欧美.www| 欧美国产精品专区| 欧美激情女人20p| 欧美激情91| 欧美日韩亚洲另类| 欧美日韩在线免费| 国产精品久99| 国产亚洲观看| 伊人夜夜躁av伊人久久| 亚洲高清资源| 妖精视频成人观看www| 中文国产成人精品| 亚洲欧美欧美一区二区三区| 性做久久久久久免费观看欧美| 欧美一区二区三区免费大片| 久久久久久久综合色一本| 久久婷婷综合激情| 欧美91大片| 亚洲精品一区二区三区蜜桃久| 99成人在线| 亚洲永久视频| 久久久久亚洲综合| 欧美夫妇交换俱乐部在线观看| 欧美日韩国产一区二区三区地区 | 欧美母乳在线| 国产精品国产成人国产三级| 国产区亚洲区欧美区| 国语自产精品视频在线看一大j8 | 午夜精品在线观看| 久久久久久国产精品一区| 欧美高清一区| 国产精品久久午夜| 尤物九九久久国产精品的分类| 日韩亚洲精品电影| 午夜伦欧美伦电影理论片| 久久在线免费观看视频| 亚洲精品日韩综合观看成人91| 亚洲在线观看视频| 葵司免费一区二区三区四区五区| 欧美精品一区二区三区四区| 国产精品一区二区久久国产| 亚洲成色www8888| 亚洲一区在线直播| 久久婷婷av| 一区二区三区国产| 久久精品国产第一区二区三区最新章节 | 麻豆成人在线播放| 国产精品久久久久久福利一牛影视| 国产一区二区三区在线观看免费 | 亚洲夜晚福利在线观看| 久久青草久久| 一区二区三区久久网| 久久久久久久精| 国产精品成人v| 亚洲国产欧美另类丝袜| 亚洲欧美变态国产另类| 欧美成人乱码一区二区三区| 亚洲新中文字幕| 欧美成人午夜激情| 国内精品免费在线观看| 亚洲午夜精品久久久久久浪潮| 巨乳诱惑日韩免费av| 亚洲资源在线观看| 欧美精品在线一区二区| 伊人久久大香线| 午夜精品福利在线| 亚洲人成亚洲人成在线观看图片| 欧美一区二区在线免费播放| 欧美午夜视频在线| 日韩视频在线一区| 可以看av的网站久久看| 亚洲欧美国产精品va在线观看 | 免费人成网站在线观看欧美高清| 国产欧美一区二区精品婷婷| 亚洲一区精品视频| 亚洲人成人77777线观看| 久久久国产成人精品| 国产日韩精品久久久| 亚洲午夜一区二区| 91久久视频| 欧美成人精品在线播放| 曰韩精品一区二区| 久久婷婷丁香| 欧美在线播放一区二区| 国产精品人人做人人爽| 亚洲一区二区三区三| 亚洲精品日韩一| 欧美精品一区三区在线观看| 亚洲国产日韩一区二区| 能在线观看的日韩av| 久久久久久久综合狠狠综合| 红桃视频国产一区| 久久艳片www.17c.com| 久久国产手机看片| 极品尤物一区二区三区| 麻豆成人91精品二区三区| 久久精品国产v日韩v亚洲| 国自产拍偷拍福利精品免费一| 久久久久久久性| 久久99在线观看| 伊人天天综合| 欧美黄色精品| 欧美精品久久久久久久免费观看 | 国产一区二区三区日韩| 久久久水蜜桃av免费网站| 久久激情五月激情| 在线观看国产成人av片| 蜜臀99久久精品久久久久久软件| 久久香蕉国产线看观看av| 亚洲国产精品电影在线观看| 亚洲电影毛片| 欧美日韩伦理在线免费| 亚洲欧美不卡| 久久国产精品第一页| 在线精品观看| 亚洲日本久久| 国产精品美女黄网| 久久久亚洲午夜电影| 欧美69视频| 亚洲一区二区三区中文字幕在线| 亚洲免费视频一区二区| 国语自产精品视频在线看抢先版结局 | 国产欧美一区二区白浆黑人| 久久免费视频这里只有精品| 久久先锋影音| 亚洲视频欧美视频| 亚洲欧美日韩直播| 亚洲狠狠婷婷| 中文亚洲欧美| 在线观看日韩精品| 9l视频自拍蝌蚪9l视频成人| 国产日韩一区二区三区| 欧美大片一区二区三区| 欧美天堂亚洲电影院在线观看 | 久久精品亚洲热| 亚洲毛片av在线| 亚洲免费网址| 91久久黄色| 亚洲一区国产视频| 亚洲激情欧美激情| 亚洲一区二区三区四区在线观看 | 久久免费国产| 亚洲午夜视频在线| 久久久噜久噜久久综合| 亚洲天堂黄色| 久久伊伊香蕉| 午夜精品久久久久久99热| 麻豆精品精华液| 性欧美xxxx大乳国产app| 另类av导航| 久久激情中文| 欧美日韩xxxxx| 美女免费视频一区| 国产精品久久久久一区| 亚洲第一在线综合网站| 亚洲午夜免费视频| 午夜亚洲福利在线老司机| 亚洲乱码国产乱码精品精可以看| 欧美亚洲视频在线看网址| 一本一本久久a久久精品牛牛影视| 欧美一区二区三区免费大片| 在线综合亚洲欧美在线视频| 久久亚洲欧美| 久久久久成人精品| 国产精品成人一区| 欧美激情第一页xxx| 狠狠色丁香婷婷综合久久片| 亚洲视频在线一区|