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

天行健 君子當自強而不息

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久久免费看| 欧美a级在线| 欧美日韩91| 久久爱www久久做| 美女精品网站| 亚洲欧美日韩国产综合在线 | 亚洲精品乱码久久久久久蜜桃麻豆 | 久久女同精品一区二区| 亚洲国产欧美日韩| 夜夜夜久久久| 一区在线免费| 亚洲午夜激情在线| 狠狠色综合色区| 亚洲精品孕妇| 亚洲第一区在线观看| 国产精品美女久久久| 亚洲免费视频成人| 欧美午夜在线观看| 亚洲一区影音先锋| 久久久久久久波多野高潮日日| 欧美日韩一区二区在线观看视频| 亚洲精品在线免费观看视频| 99精品视频免费全部在线| avtt综合网| 欧美午夜不卡视频| 亚洲一区二区在线播放| 久久免费偷拍视频| 亚洲日本成人在线观看| 国产精品久久久久久福利一牛影视| 亚洲免费在线视频一区 二区| 亚洲高清一区二区三区| 国产精品日韩欧美| 亚洲每日更新| 欧美中文字幕第一页| 亚洲国产欧美精品| 久久成人在线| 午夜在线观看免费一区| 欧美精品三区| 男女av一区三区二区色多| 国产精品美女久久久久久2018| 欧美大片在线看免费观看| 国产一区自拍视频| 亚洲欧美福利一区二区| 亚洲一区二区3| 欧美精品系列| 亚洲国产精品久久久久久女王| 国产中文一区| 欧美一区二区三区婷婷月色| 午夜在线一区| 欧美色网一区二区| 99精品视频免费全部在线| 亚洲精品专区| 欧美久久99| 亚洲精品一区二| 夜久久久久久| 欧美日韩一区在线观看| 99re66热这里只有精品4| av不卡在线观看| 欧美激情一区二区三区成人| 欧美激情在线有限公司| 最新亚洲一区| 欧美成人精品三级在线观看| 欧美激情中文字幕在线| 亚洲福利久久| 免费不卡中文字幕视频| 亚洲电影观看| 一区二区三区成人精品| 欧美日韩情趣电影| 亚洲特级片在线| 欧美一区二区网站| 国产一区二区丝袜高跟鞋图片| 久久久91精品国产一区二区三区| 久久一区国产| 亚洲精品久久在线| 欧美日韩色一区| 亚洲综合三区| 蜜桃av一区二区在线观看| 亚洲国产成人porn| 欧美手机在线| 在线精品国产欧美| 男人天堂欧美日韩| 亚洲美洲欧洲综合国产一区| 亚洲一区成人| 黑人巨大精品欧美黑白配亚洲 | 一二三区精品| 国产热re99久久6国产精品| 久久本道综合色狠狠五月| 欧美黑人多人双交| 亚洲欧美日产图| 狠狠色伊人亚洲综合网站色| 欧美剧在线观看| 欧美一区二区三区精品| 亚洲欧洲综合| 久久精品盗摄| 一区二区三区国产| 韩国视频理论视频久久| 欧美日韩日本国产亚洲在线| 欧美一区免费| 夜夜夜久久久| 欧美激情中文字幕一区二区| 欧美一区二区日韩| 99在线精品观看| 在线精品观看| 国产一区二区三区久久| 欧美日韩精品免费看| 久久艳片www.17c.com| 香蕉久久夜色精品| 99国产精品视频免费观看一公开| 久久这里只有| 欧美一级专区| 亚洲欧美日韩国产中文| 亚洲美女中出| 亚洲国产精品一区制服丝袜| 国产亚洲欧美另类一区二区三区| 欧美天堂亚洲电影院在线观看| 美女脱光内衣内裤视频久久网站| 欧美一区二区精品| 亚洲午夜国产一区99re久久| 亚洲美女色禁图| 亚洲人成人一区二区三区| 欧美v亚洲v综合ⅴ国产v| 亚洲中午字幕| 亚洲综合电影一区二区三区| 99精品免费| 在线中文字幕不卡| 一本色道久久加勒比88综合 | 国产精品国产三级国产普通话三级| 米奇777在线欧美播放| 久久人人爽人人爽| 久久久五月天| 久久久青草青青国产亚洲免观| 亚久久调教视频| 午夜日韩激情| 欧美一区二区大片| 久久九九国产精品| 久久久久在线观看| 老牛嫩草一区二区三区日本 | 亚洲欧美国产另类| 午夜精品久久久久久久白皮肤| 亚洲伊人第一页| 欧美亚洲一区二区在线| 欧美一区二区在线观看| 久久精品视频免费播放| 另类春色校园亚洲| 欧美激情在线播放| 欧美午夜精品久久久久久浪潮| 欧美亚州一区二区三区| 国产精品美女999| 国产一区在线视频| 一区二区三区在线观看国产| 99亚洲精品| 欧美一区二区三区男人的天堂| 久久成人精品视频| 免费在线观看一区二区| 欧美日韩视频| 国产一二精品视频| 亚洲第一搞黄网站| aa成人免费视频| 欧美在线播放| 亚洲国产成人91精品| 在线视频欧美一区| 久久久久久尹人网香蕉| 欧美精品国产| 国产午夜精品视频| 亚洲精品一区二区三区蜜桃久| 亚洲视频在线免费观看| 久久精品夜色噜噜亚洲aⅴ| 欧美国产视频在线| 亚洲午夜电影网| 麻豆精品在线观看| 国产精品三级视频| 亚洲国产精品成人精品| 亚洲一区二区网站| 欧美成人午夜77777| 亚洲天堂免费观看| 久久深夜福利免费观看| 欧美亚洲成人免费| 亚洲国产清纯| 欧美一级片久久久久久久| 欧美黑人在线观看| 香蕉亚洲视频| 欧美日韩情趣电影| 亚洲高清久久网| 久久国产日韩欧美| 宅男精品视频| 欧美电影美腿模特1979在线看| 国产欧美日韩三区| 亚洲一区二区三区精品动漫| 亚洲第一天堂av| 久久亚洲色图| 国内伊人久久久久久网站视频|