<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 第十七課: 旋轉 # 第十七課:旋轉 雖然本課有些超出OpenGL的范圍,但是解決了一個常見問題:怎樣表示旋轉? 《第三課:矩陣》中,我們了解到矩陣可以讓點繞某個軸旋轉。矩陣可以簡潔地表示頂點的變換,但使用難度較大:例如,從最終結果中獲取旋轉軸就很麻煩。 本課將展示兩種最常見的表示旋轉的方法:歐拉角(Euler angles)和四元數(Quaternion)。最重要的是,本課將詳細解釋為何要盡量使用四元數。 ![](https://box.kancloud.cn/2015-11-02_5636f30af1552.png) ## 旋轉與朝向(orientation) 閱讀有關旋轉的文獻時,你可能會為其中的術語感到困惑。本課中: - “朝向”是狀態:該物體的朝向為…… - “旋轉”是操作:旋轉該物體 也就是說,當實施旋轉操作時,就改變了物體的朝向。 兩者形式相同,因此容易混淆。閑話少敘,開始進入正題…… ## 歐拉角 歐拉角是表示朝向的最簡方法,只需存儲繞X、Y、Z軸旋轉的角度,非常容易理解。你可以用vec3來存儲一個歐拉角: ``` <pre class="calibre16">``` vec3 <span class="token3">EulerAngles</span><span class="token1">(</span> RotationAroundXInRadians<span class="token1">,</span> RotationAroundYInRadians<span class="token1">,</span> RotationAroundZInRadians<span class="token1">)</span><span class="token1">;</span> ``` ``` 這三個旋轉是依次施加的,通常的順序是:Y-Z-X(但并非一定要按照這種順序)。順序不同,產生的結果也不同。 一個歐拉角的簡單應用就是用于設置角色的朝向。通常,游戲角色不會繞X和Z軸旋轉,僅僅繞豎直的Y軸旋轉。因此,無需處理三個朝向,只需用一個float型變量表示方向即可。 另外一個使用歐拉角的例子是FPS相機:用一個角度表示頭部朝向(繞Y軸),一個角度表示俯仰(繞X軸)。參見`common/controls.cpp`的示例。 不過,面對更加復雜的情況時,歐拉角就顯得力不從心了。例如: - 對兩個朝向進行插值比較困難。簡單地對X、Y、Z角度進行插值得到的結果不太理想。 - 實施多次旋轉很復雜且不精確:必須計算出最終的旋轉矩陣,然后據此推測書歐拉角。 - “臭名昭著”的“萬向節死鎖”(Gimbal Lock)問題有時會讓旋轉“卡死”。其他一些奇異狀態還會導致模型方向翻轉。 - 不同的角度可產生同樣的旋轉(例如-180°和180°) - 容易出錯——如上所述,一般的旋轉順序是YZX,如果用了非YZX順序的庫,就有麻煩了。 - 某些操作很復雜:如繞指定的軸旋轉N角度。 四元數是表示旋轉的好工具,可解決上述問題。 ## 四元數 四元數由4個數\[x y z w\]構成,表示了如下的旋轉: ``` <pre class="calibre16">``` <span class="token2">// RotationAngle is in radians</span> x <span class="token">=</span> RotationAxis<span class="token1">.</span>x <span class="token">*</span> <span class="token3">sin</span><span class="token1">(</span>RotationAngle <span class="token">/</span> <span class="token6">2</span><span class="token1">)</span> y <span class="token">=</span> RotationAxis<span class="token1">.</span>y <span class="token">*</span> <span class="token3">sin</span><span class="token1">(</span>RotationAngle <span class="token">/</span> <span class="token6">2</span><span class="token1">)</span> z <span class="token">=</span> RotationAxis<span class="token1">.</span>z <span class="token">*</span> <span class="token3">sin</span><span class="token1">(</span>RotationAngle <span class="token">/</span> <span class="token6">2</span><span class="token1">)</span> w <span class="token">=</span> <span class="token3">cos</span><span class="token1">(</span>RotationAngle <span class="token">/</span> <span class="token6">2</span><span class="token1">)</span> ``` ``` `RotationAxis`,顧名思義即旋轉軸。`RotationAngle`是旋轉的角度。 ![](https://box.kancloud.cn/2015-11-02_5636f30b242c1.png) 因此,四元數實際上存儲了一個旋轉軸和一個旋轉角度。這讓旋轉的組合變簡單了。 ## 解讀四元數 四元數的形式當然不如歐拉角直觀,不過還是能看懂的:xyz分量大致代表了各個軸上的旋轉分量,而w=acos(旋轉角度/2)。舉個例子,假設你在調試器中看到了這樣的值\[ 0.7 0 0 0.7 \]。x=0.7,比y、z的大,因此主要是在繞X軸旋轉;而2\*acos(0.7) = 1.59弧度,所以旋轉角度應該是90°。 同理,\[0 0 0 1\] (w=1)表示旋轉角度 = 2*acos(1) = 0,因此這是一個*單位四元數\*(unit quaternion),表示沒有旋轉。 ## 基本操作 不必理解四元數的數學原理:這種表示方式太晦澀了,因此我們一般通過一些工具函數進行計算。如果對這些數學原理感興趣,可以參考[實用工具和鏈接](http://www.opengl-tutorial.org/miscellaneous/useful-tools-links/)中的數學書籍。 ### 怎樣用C++創建四元數? ``` <pre class="calibre16">``` <span class="token2">// Don't forget to #include <glm/gtc/quaternion.hpp> and <glm/gtx/quaternion.hpp></span> <span class="token2">// Creates an identity quaternion (no rotation)</span> quat MyQuaternion<span class="token1">;</span> <span class="token2">// Direct specification of the 4 components</span> <span class="token2">// You almost never use this directly</span> MyQuaternion <span class="token">=</span> <span class="token3">quat</span><span class="token1">(</span>w<span class="token1">,</span>x<span class="token1">,</span>y<span class="token1">,</span>z<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Conversion from Euler angles (in radians) to Quaternion</span> vec3 <span class="token3">EulerAngles</span><span class="token1">(</span><span class="token6">90</span><span class="token1">,</span> <span class="token6">45</span><span class="token1">,</span> <span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> MyQuaternion <span class="token">=</span> <span class="token3">quat</span><span class="token1">(</span>EulerAngles<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Conversion from axis-angle</span> <span class="token2">// In GLM the angle must be in degrees here, so convert it.</span> MyQuaternion <span class="token">=</span> gtx<span class="token1">:</span><span class="token1">:</span>quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">angleAxis</span><span class="token1">(</span><span class="token3">degrees</span><span class="token1">(</span>RotationAngle<span class="token1">)</span><span class="token1">,</span> RotationAxis<span class="token1">)</span><span class="token1">;</span> ``` ``` ### 怎樣用GLSL創建四元數? 不要在shader中創建四元數。應該把四元數轉換為旋轉矩陣,用于模型矩陣中。頂點會一如既往地隨著MVP矩陣的變化而旋轉。 某些情況下,你可能確實需要在shader中使用四元數。例如,GPU骨骼動畫。GLSL中沒有四元數類型,但是可以將四元數存在vec4變量中,然后在shader中計算。 ### 怎樣把四元數轉換為矩陣? ``` <pre class="calibre16">``` mat4 RotationMatrix <span class="token">=</span> quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">toMat4</span><span class="token1">(</span>quaternion<span class="token1">)</span><span class="token1">;</span> ``` ``` 這下可以像往常一樣建立模型矩陣了: ``` <pre class="calibre16">``` mat4 RotationMatrix <span class="token">=</span> quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">toMat4</span><span class="token1">(</span>quaternion<span class="token1">)</span><span class="token1">;</span> <span class="token1">.</span><span class="token1">.</span><span class="token1">.</span> mat4 ModelMatrix <span class="token">=</span> TranslationMatrix <span class="token">*</span> RotationMatrix <span class="token">*</span> ScaleMatrix<span class="token1">;</span> <span class="token2">// You can now use ModelMatrix to build the MVP matrix</span> ``` ``` ## 那究竟該用哪一個呢? 在歐拉角和四元數之間作選擇還真不容易。歐拉角對于美工來說顯得很直觀,因此如果要做一款3D編輯器,請選用歐拉角。但對程序員來說,四元數卻是最方便的。所以在寫3D引擎內核時應該選用四元數。 一個普遍的共識是:在程序內部使用四元數,在需要和用戶交互的地方就用歐拉角。 這樣,在處理各種問題時,你才能得心應手(至少會輕松一點)。如果確有必要(如上文所述的FPS相機,設置角色朝向等情況),不妨就用歐拉角,附加一些轉換工作。 ## 其他資源 1. [實用工具和鏈接](http://www.opengl-tutorial.org/miscellaneous/useful-tools-links/)中的書籍 2. 老是老了點,《游戲編程精粹1》(Game Programming Gems I)有幾篇關于四元數的好文章。也許網絡上就有這份資料。 1. 一個關于旋轉的\[GDC報告\][http://www.essentialmath.com/GDC2012/GDC2012\_JMV\_Rotations.pdf](http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf) 1. The Game Programing Wiki [Quaternion tutorial](http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation) 2. Ogre3D [FAQ on quaternions](http://www.ogre3d.org/tikiwiki/Quaternion+and+Rotation+Primer)。 第二部分大多是針對OGRE的。 3. Ogre3D [Vector3D.h](https://bitbucket.org/sinbad/ogre/src/3cbd67467fab3fef44d1b32bc42ccf4fb1ccfdd0/OgreMain/include/OgreVector3.h?at=default)和[Quaternion.cpp](https://bitbucket.org/sinbad/ogre/src/3cbd67467fab3fef44d1b32bc42ccf4fb1ccfdd0/OgreMain/src/OgreQuaternion.cpp?at=default) ## 速查手冊 ## 怎樣判斷兩個四元數是否相同? 向量點積是兩向量夾角的余弦值。若該值為1,那么這兩個向量同向。判斷兩個四元數是否相同的方法與之十分相似: ``` <pre class="calibre16">``` float matching <span class="token">=</span> quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">dot</span><span class="token1">(</span>q1<span class="token1">,</span> q2<span class="token1">)</span><span class="token1">;</span> <span class="token4">if</span> <span class="token1">(</span> <span class="token3">abs</span><span class="token1">(</span>matching<span class="token">-</span><span class="token6">1.0</span><span class="token1">)</span> <span class="token"><</span> <span class="token6">0.001</span> <span class="token1">)</span><span class="token1">{</span> <span class="token2">// q1 and q2 are similar</span> <span class="token1">}</span> ``` ``` 由點積的acos值還可以得到q1和q2間的夾角。 ## 怎樣旋轉一個點? 方法如下: ``` <pre class="calibre16">``` rotated_point <span class="token">=</span> orientation_quaternion <span class="token">*</span> point<span class="token1">;</span> ``` ``` ……但如果想計算模型矩陣,你得先將其轉換為矩陣。注意,旋轉的中心始終是原點。如果想繞別的點旋轉: ``` <pre class="calibre16">``` rotated_point <span class="token">=</span> origin <span class="token">+</span> <span class="token1">(</span>orientation_quaternion <span class="token">*</span> <span class="token1">(</span>point<span class="token">-</span>origin<span class="token1">)</span><span class="token1">)</span><span class="token1">;</span> ``` ``` ## 怎樣對兩個四元數插值? SLERP意為球面線性插值(Spherical Linear intERPolation)、可以用GLM中的`mix`函數進行SLERP: ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>quat interpolatedquat <span class="token">=</span> quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">mix</span><span class="token1">(</span>quat1<span class="token1">,</span> quat2<span class="token1">,</span> <span class="token6">0.5</span>f<span class="token1">)</span><span class="token1">;</span> <span class="token2">// or whatever factor</span> ``` ``` ## 怎樣累積兩個旋轉? 只需將兩個四元數相乘即可。順序和矩陣乘法一致。亦即逆序相乘: ``` <pre class="calibre16">``` quat combined_rotation <span class="token">=</span> second_rotation <span class="token">*</span> first_rotation<span class="token1">;</span> ``` ``` ## 怎樣計算兩向量之間的旋轉? (也就是說,四元數得把v1旋轉到v2) 基本思路很簡單: - 兩向量間的夾角很好找:由點積可知其cos值。 - 旋轉軸很好找:兩向量的叉乘積。 如下的算法就是依照上述思路實現的,此外還處理了一些特例: ``` <pre class="calibre16">``` quat <span class="token3">RotationBetweenVectors</span><span class="token1">(</span>vec3 start<span class="token1">,</span> vec3 dest<span class="token1">)</span><span class="token1">{</span> start <span class="token">=</span> <span class="token3">normalize</span><span class="token1">(</span>start<span class="token1">)</span><span class="token1">;</span> dest <span class="token">=</span> <span class="token3">normalize</span><span class="token1">(</span>dest<span class="token1">)</span><span class="token1">;</span> float cosTheta <span class="token">=</span> <span class="token3">dot</span><span class="token1">(</span>start<span class="token1">,</span> dest<span class="token1">)</span><span class="token1">;</span> vec3 rotationAxis<span class="token1">;</span> <span class="token4">if</span> <span class="token1">(</span>cosTheta <span class="token"><</span> <span class="token">-</span><span class="token6">1</span> <span class="token">+</span> <span class="token6">0.001</span>f<span class="token1">)</span><span class="token1">{</span> <span class="token2">// special case when vectors in opposite directions:</span> <span class="token2">// there is no "ideal" rotation axis</span> <span class="token2">// So guess one; any will do as long as it's perpendicular to start</span> rotationAxis <span class="token">=</span> <span class="token3">cross</span><span class="token1">(</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f<span class="token1">)</span><span class="token1">,</span> start<span class="token1">)</span><span class="token1">;</span> <span class="token4">if</span> <span class="token1">(</span>gtx<span class="token1">:</span><span class="token1">:</span>norm<span class="token1">:</span><span class="token1">:</span><span class="token3">length2</span><span class="token1">(</span>rotationAxis<span class="token1">)</span> <span class="token"><</span> <span class="token6">0.01</span> <span class="token1">)</span> <span class="token2">// bad luck, they were parallel, try again!</span> rotationAxis <span class="token">=</span> <span class="token3">cross</span><span class="token1">(</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">1.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">)</span><span class="token1">,</span> start<span class="token1">)</span><span class="token1">;</span> rotationAxis <span class="token">=</span> <span class="token3">normalize</span><span class="token1">(</span>rotationAxis<span class="token1">)</span><span class="token1">;</span> <span class="token4">return</span> gtx<span class="token1">:</span><span class="token1">:</span>quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">angleAxis</span><span class="token1">(</span><span class="token6">180.0</span>f<span class="token1">,</span> rotationAxis<span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> rotationAxis <span class="token">=</span> <span class="token3">cross</span><span class="token1">(</span>start<span class="token1">,</span> dest<span class="token1">)</span><span class="token1">;</span> float s <span class="token">=</span> <span class="token3">sqrt</span><span class="token1">(</span> <span class="token1">(</span><span class="token6">1</span><span class="token">+</span>cosTheta<span class="token1">)</span><span class="token">*</span><span class="token6">2</span> <span class="token1">)</span><span class="token1">;</span> float invs <span class="token">=</span> <span class="token6">1</span> <span class="token">/</span> s<span class="token1">;</span> <span class="token4">return</span> <span class="token3">quat</span><span class="token1">(</span> s <span class="token">*</span> <span class="token6">0.5</span>f<span class="token1">,</span> rotationAxis<span class="token1">.</span>x <span class="token">*</span> invs<span class="token1">,</span> rotationAxis<span class="token1">.</span>y <span class="token">*</span> invs<span class="token1">,</span> rotationAxis<span class="token1">.</span>z <span class="token">*</span> invs <span class="token1">)</span><span class="token1">;</span> <span class="token1">}</span> ``` ``` (可在`common/quaternion_utils.cpp`中找到該函數) ## 我需要一個類似gluLookAt的函數。怎樣旋轉物體使之朝向某點? 調用`RotationBetweenVectors`函數! ``` <pre class="calibre16">``` <span class="token2">// Find the rotation between the front of the object (that we assume towards +Z,</span> <span class="token2">// but this depends on your model) and the desired direction</span> quat rot1 <span class="token">=</span> <span class="token3">RotationBetweenVectors</span><span class="token1">(</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f<span class="token1">)</span><span class="token1">,</span> direction<span class="token1">)</span><span class="token1">;</span> ``` ``` 現在,你也許想讓物體保持豎直: ``` <pre class="calibre16">``` <span class="token2">// Recompute desiredUp so that it's perpendicular to the direction</span> <span class="token2">// You can skip that part if you really want to force desiredUp</span> vec3 right <span class="token">=</span> <span class="token3">cross</span><span class="token1">(</span>direction<span class="token1">,</span> desiredUp<span class="token1">)</span><span class="token1">;</span> desiredUp <span class="token">=</span> <span class="token3">cross</span><span class="token1">(</span>right<span class="token1">,</span> direction<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Because of the 1rst rotation, the up is probably completely screwed up.</span> <span class="token2">// Find the rotation between the "up" of the rotated object, and the desired up</span> vec3 newUp <span class="token">=</span> rot1 <span class="token">*</span> <span class="token3">vec3</span><span class="token1">(</span><span class="token6">0.0</span>f<span class="token1">,</span> <span class="token6">1.0</span>f<span class="token1">,</span> <span class="token6">0.0</span>f<span class="token1">)</span><span class="token1">;</span> quat rot2 <span class="token">=</span> <span class="token3">RotationBetweenVectors</span><span class="token1">(</span>newUp<span class="token1">,</span> desiredUp<span class="token1">)</span><span class="token1">;</span> ``` ``` 組合到一起: ``` <pre class="calibre16">``` quat targetOrientation <span class="token">=</span> rot2 <span class="token">*</span> rot1<span class="token1">;</span> <span class="token2">// remember, in reverse order.</span> ``` ``` 注意,“direction”僅僅是方向,并非目標位置!你可以輕松計算出方向:`targetPos – currentPos`。 得到目標朝向后,你很可能想對`startOrientation`和`targetOrientation`進行插值 (可在`common/quaternion_utils.cpp`中找到此函數。) ## 怎樣使用LookAt且限制旋轉速度? 基本思想是采用SLERP(用`glm::mix`函數),但要控制插值的幅度,避免角度偏大。 ``` <pre class="calibre16">``` float mixFactor <span class="token">=</span> maxAllowedAngle <span class="token">/</span> angleBetweenQuaternions<span class="token1">;</span> quat result <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span>gtc<span class="token1">:</span><span class="token1">:</span>quaternion<span class="token1">:</span><span class="token1">:</span><span class="token3">mix</span><span class="token1">(</span>q1<span class="token1">,</span> q2<span class="token1">,</span> mixFactor<span class="token1">)</span><span class="token1">;</span> ``` ``` 如下是更為復雜的實現。該實現處理了許多特例。注意,出于優化的目的,代碼中并未使用`mix`函數。 ``` <pre class="calibre16">``` quat <span class="token3">RotateTowards</span><span class="token1">(</span>quat q1<span class="token1">,</span> quat q2<span class="token1">,</span> float maxAngle<span class="token1">)</span><span class="token1">{</span> <span class="token4">if</span><span class="token1">(</span> maxAngle <span class="token"><</span> <span class="token6">0.001</span>f <span class="token1">)</span><span class="token1">{</span> <span class="token2">// No rotation allowed. Prevent dividing by 0 later.</span> <span class="token4">return</span> q1<span class="token1">;</span> <span class="token1">}</span> float cosTheta <span class="token">=</span> <span class="token3">dot</span><span class="token1">(</span>q1<span class="token1">,</span> q2<span class="token1">)</span><span class="token1">;</span> <span class="token2">// q1 and q2 are already equal.</span> <span class="token2">// Force q2 just to be sure</span> <span class="token4">if</span><span class="token1">(</span>cosTheta <span class="token">></span> <span class="token6">0.9999</span>f<span class="token1">)</span><span class="token1">{</span> <span class="token4">return</span> q2<span class="token1">;</span> <span class="token1">}</span> <span class="token2">// Avoid taking the long path around the sphere</span> <span class="token4">if</span> <span class="token1">(</span>cosTheta <span class="token"><</span> <span class="token6">0</span><span class="token1">)</span><span class="token1">{</span> q1 <span class="token">=</span> q1<span class="token">*</span><span class="token">-</span><span class="token6">1.0</span>f<span class="token1">;</span> cosTheta <span class="token">*</span><span class="token">=</span> <span class="token">-</span><span class="token6">1.0</span>f<span class="token1">;</span> <span class="token1">}</span> float angle <span class="token">=</span> <span class="token3">acos</span><span class="token1">(</span>cosTheta<span class="token1">)</span><span class="token1">;</span> <span class="token2">// If there is only a 2° difference, and we are allowed 5°,</span> <span class="token2">// then we arrived.</span> <span class="token4">if</span> <span class="token1">(</span>angle <span class="token"><</span> maxAngle<span class="token1">)</span><span class="token1">{</span> <span class="token4">return</span> q2<span class="token1">;</span> <span class="token1">}</span> float fT <span class="token">=</span> maxAngle <span class="token">/</span> angle<span class="token1">;</span> angle <span class="token">=</span> maxAngle<span class="token1">;</span> quat res <span class="token">=</span> <span class="token1">(</span><span class="token3">sin</span><span class="token1">(</span><span class="token1">(</span><span class="token6">1.0</span>f <span class="token">-</span> fT<span class="token1">)</span> <span class="token">*</span> angle<span class="token1">)</span> <span class="token">*</span> q1 <span class="token">+</span> <span class="token3">sin</span><span class="token1">(</span>fT <span class="token">*</span> angle<span class="token1">)</span> <span class="token">*</span> q2<span class="token1">)</span> <span class="token">/</span> <span class="token3">sin</span><span class="token1">(</span>angle<span class="token1">)</span><span class="token1">;</span> res <span class="token">=</span> <span class="token3">normalize</span><span class="token1">(</span>res<span class="token1">)</span><span class="token1">;</span> <span class="token4">return</span> res<span class="token1">;</span> <span class="token1">}</span> ``` ``` 可以這樣用`RotateTowards`函數: ``` <pre class="calibre16">``` CurrentOrientation <span class="token">=</span> <span class="token3">RotateTowards</span><span class="token1">(</span>CurrentOrientation<span class="token1">,</span> TargetOrientation<span class="token1">,</span> <span class="token6">3.14</span>f <span class="token">*</span> deltaTime <span class="token1">)</span><span class="token1">;</span> ``` ``` (可在`common/quaternion_utils.cpp`中找到此函數) ## 怎樣……
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看