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

天行健 君子當自強而不息

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 閱讀(1128) 評論(0)  編輯 收藏 引用

公告

導航

統計

常用鏈接

隨筆分類(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>
            香蕉久久久久久久av网站| 日韩一级在线| 免费在线播放第一区高清av| 免费欧美在线视频| 欧美日韩成人综合| 国产精品久久看| 中文av一区特黄| 最新国产拍偷乱拍精品| 欧美日韩国产综合一区二区| 国产一区日韩二区欧美三区| 亚洲国产视频一区二区| 激情综合色综合久久综合| 久久一区精品| 欧美另类综合| 亚洲欧洲一区二区在线观看| 国产精品国产三级国产专区53 | 欧美一区二区三区四区在线观看 | 午夜精品av| 久久久精品动漫| 另类专区欧美制服同性| 亚洲一区二区三区精品视频 | 久久精品夜色噜噜亚洲aⅴ| 久久一区视频| 一本色道久久综合狠狠躁篇的优点 | 久久九九热re6这里有精品| 亚洲三级毛片| 一区二区三区视频免费在线观看| 亚洲第一成人在线| 欧美一区91| 久久久精品tv| 国产一区二区视频在线观看| 午夜天堂精品久久久久| 亚洲深夜福利网站| 欧美精品国产| 一区二区三区黄色| 欧美伊人久久大香线蕉综合69| 国产精品美女999| 这里是久久伊人| 欧美一区二区黄| 国产欧美1区2区3区| 亚洲一级片在线观看| 亚洲国产精品123| 国产精品美女视频网站| 欧美在线不卡视频| 亚洲在线1234| 亚洲欧美日本精品| 日韩一二三在线视频播| 99精品黄色片免费大全| 美女免费视频一区| 亚洲天堂免费观看| 久久久久91| 欧美一区二区三区免费视频| 亚洲精品国产精品乱码不99| 国产婷婷色一区二区三区| 另类av导航| 亚洲在线观看免费| 亚洲毛片播放| 亚洲人成网站在线播| 亚洲激情视频在线观看| 永久域名在线精品| 国产欧美精品一区二区色综合| 欧美久久久久久| 欧美jizz19性欧美| 欧美亚洲日本国产| 性欧美大战久久久久久久免费观看 | 老牛嫩草一区二区三区日本| 亚洲综合电影| 亚洲免费一在线| 一本久久综合亚洲鲁鲁五月天| 亚洲国产成人av| 久久一综合视频| 欧美成人一区二区在线| 亚洲第一精品夜夜躁人人躁| 欧美肥婆在线| 欧美精品v国产精品v日韩精品| 亚洲日韩视频| 99精品国产在热久久婷婷| 亚洲美女av黄| 亚洲欧美日韩区 | 国内精品久久久久伊人av| 国产无遮挡一区二区三区毛片日本| 国产欧美精品日韩精品| 国产综合18久久久久久| 亚洲夫妻自拍| 久久国产精品一区二区三区四区| 久久免费黄色| 一本色道久久综合| 久久综合九色综合欧美就去吻 | 亚洲天堂av图片| 久久综合99re88久久爱| 99这里有精品| 亚洲美女中出| 亚洲人成啪啪网站| 久久精品国产亚洲精品| 亚洲人www| 老司机67194精品线观看| 国产精品日韩在线播放| 亚洲欧洲日韩在线| 久热精品视频| 亚洲综合视频1区| 欧美性猛交视频| 中文亚洲字幕| 中文在线资源观看网站视频免费不卡| 久久久亚洲成人| 国产主播一区二区| 久久九九热免费视频| 亚洲欧美国产日韩中文字幕| 欧美色欧美亚洲另类二区| 亚洲伦理中文字幕| 日韩一级在线观看| 欧美色精品在线视频| 99爱精品视频| 欧美不卡激情三级在线观看| 国产精品素人视频| 久久久人成影片一区二区三区| 欧美亚洲三级| 最新日韩在线视频| 日韩视频免费观看| 国产精品久久久久99| 久久国产精品亚洲va麻豆| 久久亚洲精品网站| 亚洲视频视频在线| 新狼窝色av性久久久久久| 亚洲国产一区二区a毛片| 欧美激情视频一区二区三区不卡| 欧美日韩一区二区三区免费看| 性欧美精品高清| 免费91麻豆精品国产自产在线观看| 日韩视频在线观看免费| 欧美亚洲综合网| 亚洲视频中文字幕| 欧美ed2k| 亚洲欧美怡红院| 一本色道久久综合亚洲精品不卡| 久久久综合香蕉尹人综合网| 欧美国产日韩二区| 久久国产日韩| 欧美性事免费在线观看| 亚洲电影在线免费观看| 国产欧美日韩亚洲一区二区三区| 亚洲人成在线播放| 亚洲国产精品第一区二区三区 | 国产网站欧美日韩免费精品在线观看 | 久久精品色图| 老司机精品视频网站| 欧美精品久久久久久久久老牛影院| 久久精品国产清高在天天线| 国产精品美女在线观看| 一区二区三区久久网| 亚洲精品永久免费精品| 欧美久久久久久| 一本色道久久综合亚洲精品按摩| 亚洲一区bb| 国产精品腿扒开做爽爽爽挤奶网站| 在线视频欧美日韩精品| 午夜视频在线观看一区| 欧美视频中文在线看| 亚洲免费影院| 欧美成人一区二区| 午夜精品久久久久99热蜜桃导演| 国产精品高潮呻吟久久av黑人| 亚洲女人天堂av| 欧美大片免费| 欧美在线一级va免费观看| 精品不卡在线| 欧美体内谢she精2性欧美| 亚洲一区二区三区在线播放| 久久久www成人免费毛片麻豆| 国内成人在线| 欧美日韩一区在线观看视频| 久久久久久精| 亚洲欧美综合一区| 亚洲精品在线看| 欧美激情一区在线| 亚洲一区二区成人在线观看| 亚洲亚洲精品三区日韩精品在线视频| 欧美午夜免费电影| 欧美成人亚洲成人| 久久aⅴ国产紧身牛仔裤| 亚洲作爱视频| 91久久国产综合久久| 欧美一区二区免费| 亚洲天堂av图片| 亚洲一区二区免费在线| 宅男精品视频| 亚洲视频在线观看网站| 亚洲国产乱码最新视频| 亚洲精品国产精品国自产在线| 国产女人aaa级久久久级| 国产精品乱码妇女bbbb| 欧美性久久久| 国内精品一区二区| 国产在线欧美日韩| 激情校园亚洲| 伊人夜夜躁av伊人久久| 精品成人一区二区三区| 亚洲欧洲偷拍精品| 99热在线精品观看| 亚洲一区二三| 欧美国产日韩二区|