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

天行健 君子當(dāng)自強(qiáng)而不息

3D中的方位和角位移的C++實(shí)現(xiàn)(1)

新建網(wǎng)頁 1

 

數(shù)學(xué)理論基礎(chǔ)請參閱3D中的方位和角位移

處理變換是一件非常令人頭疼的事,矩陣更是棘手。如果你曾經(jīng)編寫過關(guān)于矩陣的代碼并且沒有用設(shè)計(jì)良好的類,你會發(fā)現(xiàn)經(jīng)常要處理負(fù)號、轉(zhuǎn)置矩陣或翻轉(zhuǎn)連接順序以使其能正常工作。

下面這幾個類正是為了消除在編程中經(jīng)常遇到的這類問題而設(shè)計(jì)的。例如,很少需要直接訪問矩陣或四元數(shù)中的元素,因此特意限制了可用操作的數(shù)目以避免產(chǎn)生迷惑,再如,對cRotationMatrix類,沒有求逆和連接操作,因?yàn)槿绻雌浔旧淼哪康氖褂?/span>cRotationMatrix,這些操作是不應(yīng)該出現(xiàn)或沒有意義的。

我們還使用了一系列簡單、常用的數(shù)學(xué)常數(shù)和實(shí)用工具函數(shù),它們由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:

關(guān)于類cVector3的實(shí)現(xiàn)細(xì)節(jié)請參閱一個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約定。這個類非常直觀,為了簡單起見,我們沒有實(shí)現(xiàn)太多操作。特別沒有實(shí)現(xiàn)加、減、標(biāo)量乘等運(yùn)算。因?yàn)槿绻擃惐4娴牟皇欠轿欢墙撬俣然蜃兓剩敲催@些運(yùn)算才是有用的。

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類的用法也很直觀,只有幾個地方需要加以詳細(xì)說明:

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

(2)from_object_to_inertial_quat()from_inertial_to_object_quat()函數(shù)根據(jù)四元數(shù)計(jì)算歐拉角,第一個函數(shù)的參數(shù)是代表從物體坐標(biāo)系到慣性坐標(biāo)系旋轉(zhuǎn)的四元數(shù),第二個函數(shù)的參數(shù)是代表從慣性坐標(biāo)系到物體坐標(biāo)系旋轉(zhuǎn)的四元數(shù)。

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


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


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲理论在线| 最新中文字幕亚洲| 久久国产精彩视频| 你懂的视频一区二区| 亚洲人成人77777线观看| 欧美激情久久久| 中国成人黄色视屏| 久久精品五月| 亚洲精品午夜精品| 国产精品久久久久aaaa樱花| 性欧美精品高清| 欧美国产在线观看| 亚洲视频在线播放| 国内精品久久久| 欧美—级在线免费片| 亚洲免费网站| 亚洲电影成人| 亚洲欧美中文日韩v在线观看| 红桃视频亚洲| 欧美体内she精视频| 久久久久久久国产| 99视频有精品| 欧美电影在线免费观看网站| 亚洲在线观看视频网站| 伊人影院久久| 国产精品一区在线播放| 性欧美在线看片a免费观看| 国内精品福利| 国产精品老女人精品视频| 久久久久久尹人网香蕉| 中文久久精品| 亚洲国产美女| 久久久国产成人精品| 一本色道久久综合亚洲精品不| 国产网站欧美日韩免费精品在线观看| 欧美成年人视频网站欧美| 欧美一区二区三区啪啪| 亚洲美女av网站| 欧美成人精品一区| 欧美在线影院在线视频| 这里是久久伊人| 亚洲成人在线观看视频| 国产伦精品一区二区三区免费| 欧美a级一区二区| 欧美一区二区视频网站| 99视频一区二区三区| 亚洲第一免费播放区| 久久久久成人精品免费播放动漫| 亚洲一区在线观看视频| 亚洲精品久久久久久久久久久久 | 蜜桃av一区二区三区| 欧美亚洲一区| 亚洲欧美久久久| 亚洲精品一区二区三区在线观看 | 欧美国产日韩一区二区三区| 久久精品夜色噜噜亚洲a∨| 亚洲午夜在线观看| 亚洲精品中文字幕女同| 亚洲国产精品一区二区尤物区 | 一本大道久久精品懂色aⅴ | 另类图片国产| 久久婷婷久久一区二区三区| 久久se精品一区二区| 性欧美在线看片a免费观看| 亚洲欧美日本在线| 亚洲午夜一区二区| 亚洲影院污污.| 亚洲一区免费视频| 亚洲一区日本| 午夜一区不卡| 欧美影院午夜播放| 久久国产直播| 久久婷婷av| 蜜臀99久久精品久久久久久软件| 玖玖综合伊人| 欧美黄色影院| 亚洲区国产区| 一区二区三区高清不卡| 亚洲一区二区三区高清| 一本色道久久综合| 亚洲一卡二卡三卡四卡五卡| 亚洲一区二区av电影| 新狼窝色av性久久久久久| 欧美一级专区免费大片| 久久久久国产精品厨房| 免费在线亚洲欧美| 亚洲第一黄网| 一区二区三区欧美亚洲| 性色一区二区| 久久综合999| 欧美人妖在线观看| 国产精品海角社区在线观看| 国产精品综合视频| 精品成人国产| 妖精视频成人观看www| 亚洲影音一区| 久久一区二区三区超碰国产精品| 久久久久久久精| 欧美激情欧美激情在线五月| 99re66热这里只有精品4| 亚洲一区二区在线观看视频| 久久久久久久网站| 欧美日韩久久| 狠狠色丁香久久婷婷综合_中| 亚洲精品欧美日韩专区| 亚洲综合色网站| 久久亚洲精选| 一区二区三区久久| 久久久久久久久综合| 欧美日韩国产综合在线| 国产日韩在线播放| 亚洲乱码精品一二三四区日韩在线 | 国产精品素人视频| 亚洲第一精品久久忘忧草社区| 日韩视频在线一区二区| 欧美在线影院| 亚洲日本成人网| 欧美自拍偷拍| 欧美色欧美亚洲另类七区| 国内精品久久久久久| 一区二区三区你懂的| 久久久免费精品| 一区二区三区日韩欧美| 久久中文在线| 国产欧美日韩亚洲| 这里只有精品视频| 欧美高清视频www夜色资源网| 亚洲中午字幕| 欧美日韩精品一区视频| 亚洲国产成人av在线| 欧美永久精品| 在线一区二区三区四区五区| 毛片基地黄久久久久久天堂| 国产欧美一区二区三区沐欲| 在线视频一区观看| 亚洲国产美女精品久久久久∴| 欧美影院成人| 国产伦精品一区二区三区视频黑人 | 欧美一区二区三区免费在线看| 最新国产拍偷乱拍精品 | 国产亚洲一区二区三区在线观看 | 亚洲激情视频| 美国成人毛片| 一区在线影院| 久久中文字幕一区二区三区| 亚洲免费中文| 国产精品久久久久久亚洲调教| 一区二区三区www| 亚洲国产国产亚洲一二三| 久久精品理论片| 海角社区69精品视频| 欧美与黑人午夜性猛交久久久| 亚洲午夜电影| 国产精品成人va在线观看| 亚洲深夜av| av成人国产| 欧美午夜视频一区二区| 中文在线资源观看网站视频免费不卡| 欧美a级一区| 米奇777在线欧美播放| 亚洲国产综合在线| 欧美激情综合色| 欧美成人免费视频| 99精品视频免费观看视频| 亚洲日本中文字幕| 欧美午夜精品久久久| 亚洲一区免费看| 亚洲欧美在线另类| 国产一区二区三区四区五区美女 | 欧美一区午夜精品| 国产一区二区三区久久久久久久久| 欧美在线视频二区| 欧美中文字幕视频| 亚洲国产日韩欧美一区二区三区| 欧美成人午夜剧场免费观看| 欧美顶级大胆免费视频| 国产精品99久久99久久久二8| 亚洲色图综合久久| 国产欧美精品一区aⅴ影院| 久久午夜精品一区二区| 另类国产ts人妖高潮视频| 日韩视频国产视频| 亚洲一区影院| 1000部精品久久久久久久久| 最新国产成人av网站网址麻豆 | 一区二区三区欧美日韩| 亚洲尤物影院| 伊人久久噜噜噜躁狠狠躁| 亚洲国产欧美精品| 欧美性片在线观看| 玖玖玖免费嫩草在线影院一区| 欧美不卡高清| 午夜精品视频一区| 久久先锋资源| 亚洲午夜国产一区99re久久| 久久国产夜色精品鲁鲁99| 亚洲精品中文字幕有码专区| 亚洲在线视频免费观看| 亚洲国产乱码最新视频| 亚洲一二三四区|