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

天行健 君子當自強而不息

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

新建網頁 1

cQuaternion類用來以四元數形式保存方位或角位移,在能應用到四元數上的完整數學運算集合中,只有那些對單位四元數有意義的運算才對保存角位移有用,這里沒有提供四元數的求負、加減、標量乘、對數操作。

Quaternion.h:

    #ifndef QUATERNION_H
   
#define QUATERNION_H
   
   
class cVector3;
   
class cEulerAngles;
   
    
//---------------------------------------------------------------------------
    // Implement a quaternion, for purposes of representing an angular
    // displacement (orientation) in 3D.
    //---------------------------------------------------------------------------
   
class cQuaternion
    {
   
public:
        
// The 4 values of the quaternion.  Normally, it will not be necessary to manipulate these 
        // directly.  However, we leave them public, since prohibiting direct access
        // makes some operations, such as file I/O, unnecessarily complicated.
   
    float    w, x, y, z;
   
   
public:
        
void identity()
        {
            w = 1.0f;
            x = y = z = 0.0f;
        }
   
        
// setup the quaternion to a specific rotation
   
    void set_to_rotate_about_x(float theta);
        
void set_to_rotate_about_y(float theta);
        
void set_to_rotate_about_z(float theta);
        
void set_to_rotate_about_axis(const cVector3& axis, float theta);
   
        
// setup to perform object<->inertial rotations, given orientation in Euler angle format.
   
    void set_to_rotate_object_to_inertial(const cEulerAngles& orientation);
        
void set_to_rotate_inertial_to_object(const cEulerAngles& orientation);
   
        
// cross product
   
    cQuaternion operator *(const cQuaternion& a) const;
   
        
// multiplication with assignment, as per c++ convention.
   
    cQuaternion& operator *=(const cQuaternion& a);
   
        
void normalize();
   
        
// extract and return the rotation angle and axis
   
    float     get_rotation_angle() const;
        cVector3 get_rotation_axis() 
const;
    };
   
   
extern const cQuaternion g_quat_identity;
   
   
float dot_product(const cQuaternion& a, const cQuaternion& b);
    cQuaternion slerp(
const cQuaternion& q0, const cQuaternion& q1, float t);
    cQuaternion conjugate(
const cQuaternion& q);
    cQuaternion pow(
const cQuaternion& q, float exponent);
   
   
#endif

為了創建一個代表特定角位移的四元數,需要使用set_to_xxx函數中的一個。set_to_rotate_object_to_inertial()set_to_rotate_inertial_to_object()用來將歐拉角轉換到四元數形式。第一個函數創建一個四元數,表達從物體空間到慣性空間的旋轉,后一個函數返回從慣性空間到物體空間的旋轉。

一般使用函數來操作角位移,角位移連接使用operator*()(習慣上,連接順序從左向右)。conjugate()函數返回一個四元數,該四元數代表的角位移與輸入四元數代表的角位移相反。

使用get_rotation_angle()get_rotation_axis()可從四元數中提取旋轉角和旋轉軸。

normalize()用來處理浮點數誤差擴大。如果要對同一四元數執行上百次連續運算,就可能需要調用這個方法。雖然歐拉角向四元數的轉換只產生單位化的四元數,避免了誤差擴大的可能。但是,矩陣和四元數間的轉換卻存在這一問題。

Quaternion.cpp:

    #include <assert.h>
    #include <math.h>
    #include "Quaternion.h"
    #include "MathUtil.h"
    #include "vector3.h"
    #include "EulerAngles.h"
   
   
// The global identity quaternion.  Notice that there are no constructors
    // to the Quaternion class, since we really don't need any.
   
const cQuaternion g_quat_identity = { 1.0f, 0.0f, 0.0f, 0.0f };
   
   
//---------------------------------------------------------------------------
    // Setup the quaternion to rotate about the specified axis
    //---------------------------------------------------------------------------
   

   
void cQuaternion::set_to_rotate_about_x(float theta)
    {
        
float half_theta = theta * 0.5f;
   
        w = cos(half_theta);
        x = sin(half_theta);
        y = 0.0f;
        z = 0.0f;
    }
   
   
void cQuaternion::set_to_rotate_about_y(float theta)
    {
        
float half_theta = theta * 0.5f;
   
        w = cos(half_theta);
        x = 0.0f;
        y = sin(half_theta);
        z = 0.0f;
    }
   
   
void cQuaternion::set_to_rotate_about_z(float theta)
    {
        
float half_theta = theta * 0.5f;
   
        w = cos(half_theta);
        x = 0.0f;
        y = 0.0f;
        z = sin(half_theta);
    }
   
   
void cQuaternion::set_to_rotate_about_axis(const cVector3& axis, float theta)
    {
        
// the axis of rotation must be normalized
   
    assert(fabs(vector_mag(axis) - 1.0f) < 0.01f);
   
        
// compute the half angle and its sin
   
    float half_theta = theta * 0.5f;
        
float sin_half_theta = sin(half_theta);
   
        w = cos(half_theta);
        x = axis.x * sin_half_theta;
        y = axis.y * sin_half_theta;
        z = axis.z * sin_half_theta;
    }
   
   
//---------------------------------------------------------------------------
    // Setup the quaternion to perform an object->inertial rotation, given the
    // orientation in Euler angle format.
    //
    //        | cos(h/2)cos(p/2)cos(b/2) + sin(h/2)sin(p/2)sin(b/2) |
    //    M = | cos(h/2)sin(p/2)cos(b/2) + sin(h/2)cos(p/2)sin(b/2) |
    //        | sin(h/2)cos(p/2)cos(b/2) - cos(h/2)sin(p/2)sin(b/2) |
    //        | cos(h/2)cos(p/2)sin(b/2) - sin(h/2)sin(p/2)cos(b/2) |
    //---------------------------------------------------------------------------
   
void cQuaternion::set_to_rotate_object_to_inertial(const cEulerAngles& orientation)
    {
        
// compute sine and cosine of the half angles
   

        
float sp, sb, sh;
        
float cp, cb, ch;
   
        sin_cos(&sp, &cp, orientation.pitch * 0.5f);
        sin_cos(&sb, &cb, orientation.bank * 0.5f);
        sin_cos(&sh, &ch, orientation.heading * 0.5f);
   
        w =  ch * cp * cb + sh * sp * sb;
        x =  ch * sp * cb + sh * cp * sb;
        y = -ch * sp * sb + sh * cp * cb;
        z = -sh * sp * cb + ch * cp * sb;
    }
   
   
//---------------------------------------------------------------------------
    // Setup the quaternion to perform an object->inertial rotation, given the
    // orientation in Euler angle format.
    //
    //        |  cos(h/2)cos(p/2)cos(b/2) + sin(h/2)sin(p/2)sin(b/2) |
    //    M = | -cos(h/2)sin(p/2)cos(b/2) - sin(h/2)cos(p/2)sin(b/2) |
    //        |  cos(h/2)sin(p/2)sin(b/2) - sin(h/2)cos(p/2)cos(b/2) |
    //        |  sin(h/2)sin(p/2)cos(b/2) - cos(h/2)cos(p/2)sin(b/2) |
    //---------------------------------------------------------------------------
   
void cQuaternion::set_to_rotate_inertial_to_object(const cEulerAngles& orientation)
    {
        
// compute sine and cosine of the half angles
   

        
float sp, sb, sh;
        
float cp, cb, ch;
   
        sin_cos(&sp, &cp, orientation.pitch * 0.5f);
        sin_cos(&sb, &cb, orientation.bank * 0.5f);
        sin_cos(&sh, &ch, orientation.heading * 0.5f);
   
        w =  ch * cp * cb + sh * sp * sb;
        x = -ch * sp * cb - sh * cp * sb;
        y =  ch * sp * sb - sh * cp * cb;
        z =  sh * sp * cb - ch * cp * sb;
    }
   
   
//---------------------------------------------------------------------------
    // Quaternion cross product, which concatenates multiple angular
    // displacements.  The order of multiplication, from left to right,
    // corresponds to the order that the angular displacements are
    // applied.  This is backwards from the *standard* definition of
    // quaternion multiplication. 
    //---------------------------------------------------------------------------
   
cQuaternion cQuaternion::operator *(const cQuaternion& a) const
    {
        cQuaternion result;
   
        result.w = w * a.w - x * a.x - y * a.y - z * a.z;
        result.x = w * a.x + x * a.w + z * a.y - y * a.z;
        result.y = w * a.y + y * a.w + x * a.z - z * a.x;
        result.z = w * a.z + z * a.w + y * a.x - x * a.y;
   
        
return result;
    }
     
   
//---------------------------------------------------------------------------
    // Combined cross product and assignment, as per C++ convention.
    //---------------------------------------------------------------------------
   
cQuaternion& cQuaternion::operator *=(const cQuaternion& a)
    {
        *
this = *this * a;
   
        
return *this;
    }
   
   
//---------------------------------------------------------------------------
    // "Normalize" a quaternion.  Note that normally, quaternions
    // are always normalized (within limits of numerical precision).
    //
    // This function is provided primarily to combat floating point "error
    // creep," which can occur when many successive quaternion operations
    // are applied.
    //---------------------------------------------------------------------------
   
void cQuaternion::normalize()
    {
        
// compute magnitude of the quaternion
   
    float mag = sqrt(w * w + x * x + y * y + z * z);
   
        
// check for bogus length, to protect against divide by zero.
   
    if(mag > 0.0f)
        {
            
// normalize it
   

            
float one_over_mag = 1.0f / mag;
   
            w *= one_over_mag;
            x *= one_over_mag;
            y *= one_over_mag;
            z *= one_over_mag;
        }
        
else
        {
            
// houston, we have a problem.
   
        assert(false);
   
            
// in a release build, just slam it to something.
   
        identity();
        }
    }
   
   
//---------------------------------------------------------------------------
    // Return the rotation angle theta
    //---------------------------------------------------------------------------
   
float cQuaternion::get_rotation_angle() const
    {
        
// compute the half angle, remember that w = cos(theta / 2)
   
    float half_theta = safe_acos(w);
   
        
return half_theta * 2.0f;
    }
   
   
//---------------------------------------------------------------------------
    // Return the rotation axis
    //---------------------------------------------------------------------------
   
cVector3 cQuaternion::get_rotation_axis() const
    {
        
// compute sin^2(theta/2), remember that w = cos(theta/2), and sin^2(x) + cos^2(x) = 1.
   
    float sin_theta_square = 1.0f - w * w;
   
        
// protect against numerical imprecision
   
    if(sin_theta_square <= 0.0f)
        {
            
// identity quaterion, or numerical imprecision.
            // just return any valid vector, since it does not matter.
   
        return cVector3(1.0f, 0.0f, 0.0f);
        }
   
        
// compute 1 / sin(theta/2)
   
    float k = 1.0f / sqrt(sin_theta_square);
   
        
// return axis of rotation
   
    return cVector3(x * k, y * k, z * k);
    }
   
   
//////////////////////////////////////  Nonmember functions ////////////////////////////////////////
   

    
//---------------------------------------------------------------------------
    // Quaternion dot product.  We use a nonmember function so we can
    // pass quaternion expressions as operands without having "funky syntax"
    //---------------------------------------------------------------------------
   
float dot_product(const cQuaternion& a, const cQuaternion& b)
    {
        
return a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
    }
   
    
//---------------------------------------------------------------------------
    // Spherical linear interpolation.
    //---------------------------------------------------------------------------
   
cQuaternion slerp(const cQuaternion& q0, const cQuaternion& q1, float t)
    {
        
// check for out-of range parameter and return edge points if so
   
    if(t <= 0.0f)    return q0;
        
if(t >= 1.0f)    return q1;
   
        
// compute "cosine of angle between quaternions" using dot product
   
    float cos_omega = dot_product(q0, q1);
   
        
// If negative dot, use -q1.  Two quaternions q and -q
        // represent the same rotation, but may produce different slerp.  
        // We chose q or -q to rotate using the acute angle.
   

        
float q1w = q1.w;
        
float q1x = q1.x;
        
float q1y = q1.y;
        
float q1z = q1.z;
   
        
if(cos_omega < 0.0f)
        {
            q1w = -q1w;
            q1x = -q1x;
            q1y = -q1y;
            q1z = -q1z;
   
            cos_omega = -cos_omega;
        }
   
        
// we should have two unit quaternions, so dot should be <= 1.0
   
    assert(cos_omega < 1.1f);
   
        
// compute interpolation fraction, checking for quaternions almost exactly the same.
   

        
float k0, k1;
        
        
if(cos_omega > 0.9999f)
        {
            
// very close - just use linear interpolation, which will protect against a divide by zero.
   
        k0 = 1.0f - t;
            k1 = t;
        }
        
else
        {
            
// compute the sin of the angle using the trig identity sin^2(omega) + cos^2(omega) = 1
   
        float sin_omega = sqrt(1.0f - cos_omega * cos_omega);
   
            
// compute the angle from its sin and cosin
   
        float omega = atan2(sin_omega, cos_omega);
   
            
// compute inverse of denominator, so we only have to divice once.
   
        float k = 1.0f / sin_omega;
   
            
// compute interpolation perameters
   
            k0 = sin((1.0f - t) * omega) * k;
            k1 = sin(t * omega) * k;
        }
   
        cQuaternion result;
   
        result.x = k0 * q0.x + k1 * q1x;
        result.y = k0 * q0.y + k1 * q1y;
        result.z = k0 * q0.z + k1 * q1z;
        result.w = k0 * q0.w + k1 * q1w;
   
        
return result;
    }
   
   
//---------------------------------------------------------------------------
    // Compute the quaternion conjugate.  This is the quaternian
    // with the opposite rotation as the original quaternian.
    //---------------------------------------------------------------------------
   
cQuaternion conjugate(const cQuaternion& q)
    {
        cQuaternion result;
   
        
// same rotation amount
   
    result.w = q.w;
   
        
// opposite axis of rotation
   
    result.x = -q.x;
        result.y = -q.y;
        result.z = -q.z;
        
        
return result;
    }
   
   
//---------------------------------------------------------------------------
    // Quaternion exponentiation.
    //---------------------------------------------------------------------------
   
cQuaternion pow(const cQuaternion& q, float exponent)
    {
        
// check for the case of an identity quaternion.
        // this will protect against divide by zero.
   

        
if(fabs(q.w) > 0.9999f)
            
return q;
   
        
// extract the half angle alpha (alpha = theta/2)
   
    float alpha = acos(q.w);
   
        
// compute new alpha value
   
    float new_alpha = alpha * exponent;
   
        
// compute new w value
   
    cQuaternion result;
        result.w = cos(new_alpha);
   
        
// compute new xyz values
   

        
float mult = sin(new_alpha) / sin(alpha);
   
        result.x = q.x * mult;
        result.y = q.y * mult;
        result.z = q.z * mult;
   
        
return result;
    }

posted on 2008-02-18 19:31 lovedday 閱讀(747) 評論(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>
            亚洲巨乳在线| 欧美日韩亚洲一区二区三区在线 | 夜夜嗨网站十八久久| 麻豆精品国产91久久久久久| 亚洲自拍偷拍网址| 午夜精品久久久久久99热| 亚洲美女毛片| 亚洲自拍偷拍网址| 久久综合给合久久狠狠狠97色69| 久久亚洲综合网| 欧美日韩精品一二三区| 国产精品视频免费| 一区二区三区我不卡| 亚洲国产毛片完整版| 中国成人亚色综合网站| 久久成人羞羞网站| 亚洲第一视频| 亚洲精品在线看| 欧美亚洲一区| 欧美日韩1区| 激情欧美一区二区三区在线观看| 日韩视频一区| 欧美影院成人| 亚洲黄色免费电影| 欧美一区激情| 欧美性天天影院| 亚洲国产精品一区制服丝袜| 在线亚洲免费| 欧美国产乱视频| 亚欧美中日韩视频| 国产精品videosex极品| 亚洲成人中文| 久久漫画官网| 午夜精品福利一区二区蜜股av| 欧美成人精品福利| 精品不卡在线| 久久福利视频导航| 亚洲午夜国产一区99re久久 | 亚洲六月丁香色婷婷综合久久| 先锋a资源在线看亚洲| 亚洲激情国产精品| 噜噜噜久久亚洲精品国产品小说| 国产精一区二区三区| 一区二区不卡在线视频 午夜欧美不卡在 | 1024亚洲| 久久亚洲一区二区三区四区| 亚洲视频在线观看三级| 欧美日韩一卡| 在线视频你懂得一区| 欧美黄在线观看| 美女福利精品视频| 久久嫩草精品久久久精品一| 久久欧美中文字幕| 午夜一区二区三区在线观看| 欧美日韩中文字幕精品| 日韩视频在线观看免费| 亚洲成色最大综合在线| 久久精品视频免费播放| 狠狠色丁香婷综合久久| 久久九九国产精品怡红院| 午夜精品网站| 国产在线观看精品一区二区三区| 久久成人av少妇免费| 亚洲欧美日韩精品综合在线观看 | 欧美高清视频免费观看| 亚洲激情国产精品| 91久久夜色精品国产九色| 欧美激情一区在线| 中国成人黄色视屏| 亚洲香蕉在线观看| 国产亚洲人成a一在线v站| 久久久久九九九九| 久久午夜精品一区二区| 91久久精品一区二区别| 亚洲第一伊人| 欧美日韩精品免费在线观看视频| 一区二区三区你懂的| 一区二区三区日韩| 国产网站欧美日韩免费精品在线观看 | 欧美日韩中文字幕精品| 亚洲性线免费观看视频成熟| 亚洲无吗在线| 狠狠色综合播放一区二区| 亚洲成在人线av| 国产精品一区二区久久久| 米奇777超碰欧美日韩亚洲| 欧美国产日本在线| 欧美伊人影院| 欧美精品在线一区| 久久激情视频| 欧美成人一品| 久久精品亚洲乱码伦伦中文| 免费不卡中文字幕视频| 亚洲午夜精品国产| 久久久免费精品| 亚洲一区3d动漫同人无遮挡| 午夜精品久久久久久99热软件| 最近看过的日韩成人| 亚洲一区二区久久| 亚洲人成人99网站| 欧美在线观看天堂一区二区三区 | 国产精品久久久久免费a∨| 六月婷婷久久| 国产精品久久久久永久免费观看| 狼人社综合社区| 亚洲午夜在线| 欧美色网一区二区| 欧美插天视频在线播放| 国产精品av免费在线观看| 欧美大片国产精品| 国产真实精品久久二三区| 亚洲精品乱码久久久久久蜜桃麻豆| 国产欧美日韩精品一区| 亚洲毛片播放| 91久久综合亚洲鲁鲁五月天| 欧美一级大片在线免费观看| 中文欧美日韩| 欧美日韩ab| 亚洲国产精品久久精品怡红院| 黄色国产精品一区二区三区| 亚洲一区精品在线| 亚洲欧美精品在线| 欧美日韩国产综合视频在线观看中文| 久久久久久有精品国产| 国产农村妇女精品一二区| 中文网丁香综合网| 亚洲一区二区三区777| 欧美精品在线观看91| 亚洲国产精品日韩| 亚洲毛片在线观看| 欧美激情网友自拍| 亚洲三级国产| 亚洲视频网站在线观看| 欧美日韩国产欧| 一本久道久久综合狠狠爱| 日韩午夜一区| 欧美午夜视频一区二区| 中文亚洲字幕| 久久国产手机看片| 激情欧美一区| 欧美成人第一页| 日韩一级片网址| 午夜精品久久久久99热蜜桃导演| 欧美四级在线| 亚洲欧美在线看| 麻豆国产va免费精品高清在线| 国内综合精品午夜久久资源| 久久精品国亚洲| 亚洲黄色尤物视频| 亚洲视频久久| 国产日韩久久| 美女亚洲精品| 99精品视频免费观看| 欧美一级成年大片在线观看| 国产欧美精品一区二区三区介绍 | 欧美成人精精品一区二区频| 亚洲黄色三级| 新片速递亚洲合集欧美合集| 国产日韩欧美在线观看| 久久久久久久久久久久久女国产乱| 免费观看一级特黄欧美大片| 亚洲伦理自拍| 国产伦理一区| 免费日本视频一区| 亚洲伊人色欲综合网| 欧美 亚欧 日韩视频在线| 在线一区二区日韩| 国产在线观看精品一区二区三区| 美国三级日本三级久久99| 99热这里只有精品8| 久久久精品性| 亚洲在线日韩| 91久久精品www人人做人人爽| 国产精品国产三级国产普通话三级 | 久久夜色精品| 日韩网站在线看片你懂的| 国产精品视频一二| 欧美成人免费在线| 亚洲欧美在线网| 亚洲人成网站精品片在线观看| 性欧美精品高清| 日韩亚洲成人av在线| 国产亚洲永久域名| 欧美午夜电影完整版| 久色婷婷小香蕉久久| 亚洲一区美女视频在线观看免费| 欧美不卡在线| 久久综合久久综合久久综合| 一区二区三区四区五区精品| 影音先锋一区| 国产一区二区剧情av在线| 欧美涩涩网站| 欧美精品一区二区高清在线观看| 欧美资源在线观看| 亚洲专区一二三| 亚洲视频在线观看视频| 日韩香蕉视频| 99国产精品视频免费观看| 亚洲国产精品一区| 亚洲第一狼人社区|