• <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>

            的筆記

            隨時隨地編輯

            Ogre骨骼動畫分析

            http://3dlearn.googlecode.com/files/ogre skeleton animation.pdf

            歡迎指出文中錯誤

            1  前言

            骨骼蒙皮動畫分兩步驟進(jìn)行:根據(jù)時間插值更新骨骼、然后根據(jù)骨骼更新每骨骼上的頂點。為了好玩,暫且這樣看:在每一個時間點,對每一個骨骼,我們創(chuàng)建一個骨骼魔法,并將骨骼魔法施放到每一個骨頭上;有個這些骨骼然后我們開始蒙皮,我們找出每一寸皮膚(一個頂點),并從骨堆里找出這塊皮需要依附的骨頭,當(dāng)然骨頭的數(shù)量都是有限的,一般就十幾或翻倍的數(shù)量級,所以骨頭還是比價好找的。我們將皮貼到骨頭上,貼完所有的皮,我們就得到了一個骨頭人鳥。看起來很形象:
             

            下頁示意圖少兒不宜.

             

             

             

             

            2  類圖

             <只能看pdf>

             

            3  邏輯切片

            不解釋.

             

            渲染

            Root::renderOneFrame()

            ->Root::_updateAllRenderTargets

            ->RenderSystem::_updateAllRenderTargets()

            ->RenderWindow::update()

            ->D3D9RenderWindow::update(bool swap)

            ->RenderTarget::update()

            ->Viewport::update()

            ->Camera::_renderScene()

            ->SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)

             

            4  更新骨骼

            只考慮線性插值更新骨骼的情況.

            4.1  創(chuàng)建一個骨骼魔法

            創(chuàng)建一根骨頭需要的魔法。言歸正傳,其實就是創(chuàng)建一個TransformKeyFrame對象,看做一個全變換,一個變換只能應(yīng)用到一個骨骼上。當(dāng)前動作有24根骨頭,在每幀里,你需要對著24根骨頭施加24次骨骼魔法,如果美術(shù)認(rèn)為男人應(yīng)該是23根骨頭少畫了一根,可以不用糾結(jié),知道這不是bug就行。

            一個骨骼文件看起來像這樣:

             

             

            左邊定義的是骨頭,右邊定義的是動作。恩,這里只有18根骨頭,可以認(rèn)為這個不是人類骨骼數(shù)據(jù)。在程序?qū)崿F(xiàn)上,事實上考慮的術(shù)語叫joint,看起來像只是一個質(zhì)點,可以這樣理解,一個joint是一個空間射線,它表示了一個空間變化,也即一次旋轉(zhuǎn)縮放平移。當(dāng)然,它是一個矩陣,可以分解成一個平移和一個四元素變換。這時候似乎沒有骨骼的長度,可以認(rèn)為這個joint表示的只是骨頭的關(guān)節(jié)處,骨頭的長度隱藏在2個關(guān)節(jié)之間了。

            右邊描述的是動作,一個動作是所有的joint在時間軸上的一個個切片組成的。恩,為了便于組織數(shù)據(jù),ogrejoint分類關(guān)鍵時間。其實也可以用關(guān)鍵時間來分類joint。恩,這其實也是一個很好的優(yōu)化方式,如果關(guān)鍵幀分類下省略了joint,就表示這個joint不需要變換,其對應(yīng)的頂點都不需要進(jìn)行重新蒙皮計算了。例如一個人在揮手,假設(shè)全身只有手在揮舞,當(dāng)然這動作應(yīng)看起來像個僵尸。按ogre現(xiàn)在的實現(xiàn),這個wave下的所有24(為了男女平等考慮男人和女人都是24根骨頭)joint都必須有關(guān)鍵時間,就算關(guān)鍵時間少幾處,也會將所有的joint進(jìn)行插值。這個時候避開某個joint被蒙皮,只有在這個動作下刪掉某個joint了。這徹頭徹尾就是個機器人鳥。如果用改進(jìn)的分類方式,在某個關(guān)鍵字里,可以省略一些joint,這樣一個人邊揮手邊輕邊擺頭還是可以實現(xiàn)的。

                   創(chuàng)建一個骨頭魔法分兩步,第一部是取到當(dāng)前時間點在關(guān)鍵幀中的插值系數(shù),第二部是根據(jù)這個插值系數(shù)對這個骨頭進(jìn)行插值。

            t=(i-k1)/(k2-k1)

             

             

            可以看到移動和縮放非常好理解,都是進(jìn)行的一次線性插值。只有旋轉(zhuǎn)使用了四元素的歸一化線性插值。兩個旋轉(zhuǎn)的插值似乎也只能用四元素插值,矩陣插值聽說有這樣那樣的問題。這個插值有誤差,并且不是恒速插值。

             

            核心算法也是基本的線性插值公式,灰常神奇

            q1+(q2-q1)*k

             

             

            4.2  更新動畫時間

            AnalyzeAnimation.exe!AnalyzeAnimation::frameRenderingQueued

            OgreMain_d.dll!Ogre::Root::_fireFrameRenderingQueued

            OgreMain_d.dll!Ogre::Root::_fireFrameRenderingQueued

            OgreMain_d.dll!Ogre::Root::_updateAllRenderTargets

            OgreMain_d.dll!Ogre::Root::renderOneFrame

            OgreMain_d.dll!Ogre::Root::startRendering

            AnalyzeAnimation.exe!BaseApplication::go

            AnalyzeAnimation.exe!WinMain

             

            4.3  骨骼動畫的核心玩法(更新骨骼)

            OgreMain_d.dll!Ogre::NodeAnimationTrack::applyToNode

            OgreMain_d.dll!Ogre::Animation::apply

            OgreMain_d.dll!Ogre::Skeleton::setAnimationState

            OgreMain_d.dll!Ogre::Entity::cacheBoneMatrices

            OgreMain_d.dll!Ogre::Entity::updateAnimation

            OgreMain_d.dll!Ogre::Entity::_updateRenderQueue

            OgreMain_d.dll!Ogre::RenderQueue::processVisibleObject

            OgreMain_d.dll!Ogre::SceneNode::_findVisibleObjects

            OgreMain_d.dll!Ogre::SceneNode::_findVisibleObjects

            OgreMain_d.dll!Ogre::SceneManager::_findVisibleObjects

            OgreMain_d.dll!Ogre::SceneManager::_renderScene

            OgreMain_d.dll!Ogre::Camera::_renderScene

            OgreMain_d.dll!Ogre::Viewport::update

            OgreMain_d.dll!Ogre::RenderTarget::_updateViewport

            RenderSystem_Direct3D9_d.dll

            OgreMain_d.dll!Ogre::RenderTarget::_updateAutoUpdatedViewports

            OgreMain_d.dll!Ogre::RenderTarget::updateImpl

            OgreMain_d.dll!Ogre::RenderTarget::update

            OgreMain_d.dll!Ogre::RenderSystem::_updateAllRenderTargets

            OgreMain_d.dll!Ogre::Root::_updateAllRenderTargets              --->先更新幀監(jiān)聽,再更新實體

            OgreMain_d.dll!Ogre::Root::renderOneFrame

            OgreMain_d.dll!Ogre::Root::startRendering

            AnalyzeAnimation.exe!BaseApplication::go

            AnalyzeAnimation.exe!WinMain

             

            TransformKeyFrame 看做一個全變換.

             

            對骨骼(bone/node)進(jìn)行變換的流程

            輸入:節(jié)點、時間(省略權(quán)值和縮放)

            輸出:節(jié)點的全變換

             

            構(gòu)造出插值關(guān)鍵幀全變換buffer(TransformKeyFrame kf)

            從關(guān)鍵幀buffer釋放一個平移buffer

            對節(jié)點施加平移buffer (省略權(quán)值與縮放)

            從關(guān)鍵幀buffer釋放一個旋轉(zhuǎn)buffer

            對節(jié)點施加旋轉(zhuǎn)buffer

            從關(guān)鍵幀buffer釋放一個縮放buffer

            對節(jié)點施加一個縮放buffer

             

             

            每幀對每一個骨骼(這里蛻化成node)4個關(guān)鍵幀buffer,正是骨骼動畫的核心玩法。

             

            4.3.1  釋放一個關(guān)鍵幀魔法

            關(guān)鍵幀魔法需要創(chuàng)建一個特殊的buffer,即關(guān)鍵幀全變換buffer(TransformKeyFrame).

             

             

             

            5  蒙皮

            Ogre蒙皮算法的核心是對每頂點進(jìn)行對應(yīng)骨骼的全變換。

             

            V=M4*V

            分兩步進(jìn)行,第一步在Mesh::softwareVertexBlend中準(zhǔn)備好計算數(shù)據(jù)結(jié)構(gòu)的上下文,第二步在softwareVertexSkinning中進(jìn)行每頂點的蒙皮計算。

             

             

            處理軟件索引頂點混合,本意是用于骨骼動畫,但是也可用于其他用途.

             

             

             

            const VertexData*

            sourceVertexData

             

            const VertexData*

            targetVertexData

             

            const Matrix4* const*

            blendMatrices

             

            size_t

            numMatrices,

             

            bool

            blendNormals

             

             

            sourceVertexData

            頂點,法線,混合索引,混合權(quán)重

             

            targetVertexData

            目標(biāo)的頂點,混合版本的法線緩存.需要注意向量的歸一化.

             

            blendMatrices

            指向一個用于混合的矩陣數(shù)組,sourceVertexData的混合指數(shù)索引.

             

            numMatrices

            blendMatrices中矩陣數(shù)組的數(shù)量

             

            blendNormals

            true表示法線也同頂點一起混合.

             

             

             

             

            srcElemPos

            源頂點

             

            srcElemNorm

            源法線

             

            srcElemBlendIndices

            源混合索引

             

            srcElemBlendWeights

            源混合權(quán)重

             

             

             

             

             

             

             

            srcPosBuf      

            源頂點緩存

             

            srcIdxBuf      

            源索引緩存

             

            srcWeightBuf 

            源權(quán)重緩存

             

            srcNormBuf

            源法線緩存

             

            destElemPos

            目頂點

             

            destElemNorm

            目法線

             

                  

             

             

            destPosStride

            目法線跨步

             

             

             

             

             

             

             

            5.2  蒙皮核心算法

            核心算法如下

             

             

            首先對頂點進(jìn)行計算

            ü 找到當(dāng)前的混合索引值

            ü 用這個值索引出混合矩陣M4

            ü M4左乘以頂點V1(*)得到V2

            ü V2進(jìn)行加權(quán)計算得到V3(=V2*weight)

            ü V3歸一處理得到V4(=V3.normalized)

             

            然后對法線進(jìn)行同樣過程的計算,只是上面流程中的(*) 處的V1換成法線.如果一個頂點存在多個權(quán)重值,需要對每一個權(quán)值重復(fù)上面的14步驟進(jìn)行累積計算到V3.一次頂點計算完成,即對下一個頂點進(jìn)行同樣的計算過程.所有頂點計算完成,即完成了骨骼蒙皮.

            posted on 2012-07-25 23:42 的筆記 閱讀(4797) 評論(3)  編輯 收藏 引用

            評論

            # re: Ogre骨骼動畫分析 2013-05-09 22:55 eryar

            Good!
            Mark...  回復(fù)  更多評論   

            # re: Ogre骨骼動畫分析 2013-10-28 11:08 渣漿泵

            扔下太久了,看著好累  回復(fù)  更多評論   

            # re: Ogre骨骼動畫分析[未登錄] 2014-09-02 16:58 albert

            內(nèi)容看的有些懂了,不過作者很有意思  回復(fù)  更多評論   


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


            久久久久久亚洲精品不卡 | 日韩久久无码免费毛片软件| 无码人妻少妇久久中文字幕蜜桃 | 欧美亚洲另类久久综合婷婷| 久久亚洲精品视频| 国产精品久久久久无码av| 久久久久亚洲av无码专区导航| 久久人人爽人人爽人人片AV不| 人人狠狠综合88综合久久| 久久青青草原亚洲av无码| 久久精品国产欧美日韩| 久久精品国产亚洲5555| 色偷偷91久久综合噜噜噜噜| 久久精品无码专区免费| 日韩久久久久中文字幕人妻| 一日本道伊人久久综合影| 久久亚洲sm情趣捆绑调教| 中文字幕久久波多野结衣av| 久久久一本精品99久久精品88 | 国产成人无码久久久精品一| 97久久精品无码一区二区| 久久精品国产秦先生| 国产福利电影一区二区三区久久久久成人精品综合 | 久久强奷乱码老熟女网站| 国产成人精品综合久久久| 色综合久久无码五十路人妻| 久久精品人人槡人妻人人玩AV | 激情久久久久久久久久| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 久久99精品国产自在现线小黄鸭| 国产欧美一区二区久久| 久久精品国产福利国产琪琪| 国内精品伊人久久久影院| 99久久99久久| 久久天天躁狠狠躁夜夜av浪潮| 久久人人爽人人爽人人片AV东京热 | 亚洲国产成人精品无码久久久久久综合 | 99久久国产综合精品五月天喷水 | 99久久精品免费国产大片| 色8激情欧美成人久久综合电| 无码精品久久久天天影视|