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

            的筆記

            隨時(shí)隨地編輯

            Ogre骨骼動(dòng)畫分析

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

            歡迎指出文中錯(cuò)誤

            1  前言

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

            下頁(yè)示意圖少兒不宜.

             

             

             

             

            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)建一個(gè)骨骼魔法

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

            一個(gè)骨骼文件看起來(lái)像這樣:

             

             

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

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

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

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

             

             

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

             

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

            q1+(q2-q1)*k

             

             

            4.2  更新動(dòng)畫時(shí)間

            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  骨骼動(dòng)畫的核心玩法(更新骨骼)

            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)聽(tīng),再更新實(shí)體

            OgreMain_d.dll!Ogre::Root::renderOneFrame

            OgreMain_d.dll!Ogre::Root::startRendering

            AnalyzeAnimation.exe!BaseApplication::go

            AnalyzeAnimation.exe!WinMain

             

            TransformKeyFrame 看做一個(gè)全變換.

             

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

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

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

             

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

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

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

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

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

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

            對(duì)節(jié)點(diǎn)施加一個(gè)縮放buffer

             

             

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

             

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

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

             

             

             

            5  蒙皮

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

             

            V=M4*V

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

             

             

            處理軟件索引頂點(diǎn)混合,本意是用于骨骼動(dòng)畫,但是也可用于其他用途.

             

             

             

            const VertexData*

            sourceVertexData

             

            const VertexData*

            targetVertexData

             

            const Matrix4* const*

            blendMatrices

             

            size_t

            numMatrices,

             

            bool

            blendNormals

             

             

            sourceVertexData

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

             

            targetVertexData

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

             

            blendMatrices

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

             

            numMatrices

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

             

            blendNormals

            true表示法線也同頂點(diǎn)一起混合.

             

             

             

             

            srcElemPos

            源頂點(diǎn)

             

            srcElemNorm

            源法線

             

            srcElemBlendIndices

            源混合索引

             

            srcElemBlendWeights

            源混合權(quán)重

             

             

             

             

             

             

             

            srcPosBuf      

            源頂點(diǎn)緩存

             

            srcIdxBuf      

            源索引緩存

             

            srcWeightBuf 

            源權(quán)重緩存

             

            srcNormBuf

            源法線緩存

             

            destElemPos

            目頂點(diǎn)

             

            destElemNorm

            目法線

             

                  

             

             

            destPosStride

            目法線跨步

             

             

             

             

             

             

             

            5.2  蒙皮核心算法

            核心算法如下

             

             

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

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

            ü 用這個(gè)值索引出混合矩陣M4

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

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

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

             

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

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

            評(píng)論

            # re: Ogre骨骼動(dòng)畫分析 2013-05-09 22:55 eryar

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

            # re: Ogre骨骼動(dòng)畫分析 2013-10-28 11:08 渣漿泵

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

            # re: Ogre骨骼動(dòng)畫分析[未登錄](méi) 2014-09-02 16:58 albert

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


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


            亚洲AV日韩精品久久久久久| 亚洲乱码中文字幕久久孕妇黑人| 色狠狠久久综合网| 国产精品美女久久久久av爽| 日本欧美久久久久免费播放网| 一本久久免费视频| 久久夜色精品国产噜噜亚洲a| 国产一区二区精品久久凹凸| 色综合久久88色综合天天| 99久久人妻无码精品系列蜜桃| 77777亚洲午夜久久多喷| 欧美日韩精品久久久免费观看| 中文字幕无码久久精品青草 | 久久人做人爽一区二区三区| 久久精品一区二区影院| 久久精品国产国产精品四凭| 99久久99久久精品国产片果冻| 亚洲综合婷婷久久| 很黄很污的网站久久mimi色| 久久精品成人欧美大片| 久久99精品久久久久久野外| 国内精品欧美久久精品| 精品久久久久久久久久久久久久久| 亚洲国产精品久久| 久久综合久久伊人| 国产色综合久久无码有码| 国产精品99久久99久久久| 国产一区二区三区久久精品| 欧美精品一区二区精品久久| 国产精品伊人久久伊人电影| 久久久久久国产精品无码下载| 伊人久久五月天| 亚洲中文字幕无码久久2020| 丰满少妇人妻久久久久久| 欧美亚洲另类久久综合| 欧美久久亚洲精品| 亚洲av成人无码久久精品| 久久国产乱子伦精品免费强| 久久se精品一区二区影院| 波多野结衣久久精品| 精品综合久久久久久97超人 |