• <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>
            隨筆-379  評論-37  文章-0  trackbacks-0
            OgreOde創建一個會走動的角色

            原文http://www.game798.com/html/2007-12/5156.htm

            第一版 by SuperMegaMau

            這個教程包括的代碼和算法是作者自己的經驗,也許不正確或不怎么準確,如果發現問題請糾正。

             

            內容

            • 1 介紹
            • 2 創建物理模型  
              • 2.1 創建角色  
              • 2.2 獲取 AABB
              • 2.3 創建新空間  
              • 2.4 創建球  
              • 2.5 創建橢球  
              • 2.6 創建關節  
            • 3 移動角色  
              • 3.1 前后移動
              • 3.2 左右旋轉  
            • 4 讓角色爬起來
            • 5 問題

            介紹

            我相信我不是第一人自問如何用OgreOde創建一個運動角色。搜索論壇和wiki后,我意識到這是一個很有用的信息。這個教程解釋了如何創建一個可以在地形上行走的運動角色(包括其它meshes,如樹和房屋)。

            創建物理模型

            我按照在Monster的方法用下圖代表一個角色:

            下面,我假設你對OgreSceneNodes, meshes AlignedBoxes都有所了解,并且會用SceneManager創建地形。

            創建角色

            首先創建一個SceneNode來放角色的mesh,在這個例子中我用了Ogre例子中的忍者模型。創建兩個SceneNode并把它們連在一起。后面我會解釋為什么是兩個Node。

            Entity* ninja = mSceneMgr->createEntity("ninja","ninja.mesh");

            SceneNode* ninjaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ninja");

            SceneNode* modelNode = ninjaNode->createChildSceneNode("ninja_model");

            modelNode->attachObject(ninja);

            ninjaNode->setScale(0.05,0.05,0.05);

            RootSceneNode

            ninjaNode

            modelNode

            也許你已經注意到,ninjaNode被縮放得很小,這是因為如果mesh很大的話渲染的速度就變很慢(不知道為什么)。

            獲取 AABB(AxisAlignedBox, 軸對齊包圍盒)

            現在用AxisAlignedBox獲取mesh的大小。

            AxisAlignedBox aab = modelNode->getAttachedObject("ninja")->getBoundingBox();

            Ogre::Vector3 min = aab.getMinimum()*ninjaNode->getScale();

            Ogre::Vector3 max = aab.getMaximum()*ninjaNode->getScale();

            Ogre::Vector3 center = aab.getCenter()*ninjaNode->getScale();

            Ogre::Vector3 size(fabs(max.x-min.x),fabs(max.y-min.y),fabs(max.z-min.z));

            float radius = (size.x>size.z)?size.z/2.0f:size.x/2.0f;

             

            創建一個新空間

            我們需要創建一個新空間把角色放在其中,并且取消內部碰撞檢測。

            OgreOde::SimpleSpace* dollSpace = new OgreOde::SimpleSpace(_world->getDefaultSpace());

            dollSpace->setInternalCollisions(false);

            創建球體(腿部)

            現在有了兩個SceneNodes, "ninjaNode" "modelNode"。ninjaNode是代表你角色的節點,modelNode是你真正貼mesh的地方。這么做是因為mesh的中心總是在OgreOde::Body的中心,所以我們用ninjaNode來創建碰撞體的位置,然后根據ninjaNodeOgreOde::Body來獲得mesh的正確位置。

            左邊圖是用一個SceneNode所得到的效果,右邊是用兩個SceneNode。你可以注意到,左邊的角色懸浮在半空中。下面代碼創建了一個球體代表角色的腳部。我們需要一個SphereGeometry和一個TransformGeometry 將球體放到正確位置。

            譯注:注釋為我的猜想,具體不知道步驟這么復雜,歡迎糾正。

            (1)        創建一個碰撞體,命名為feet

            (2)        設置碰撞體為球形物體,半徑為AABB獲得的半徑

            (3)        SphereGeometry,半徑為AABB獲得的半徑

            (4)        TransformGeometry,空間為剛才創建的空間, TransformGeometry似乎是為了包含某特定形狀的幾何體

            (5)        改變modelNode相對于ninjiaNode的位置,以便讓腳占到地上

            (6)        TransformGeometry包含一個OgreOde::Body和一個幾何體

            (7)        Ogre::Body粘到ninjaNode

            懷疑創建SphereGeometry是否只是讓Ogre::Body具象化

             

            OgreOde::Body* dollFeetBody = new OgreOde::Body("feet");  

            dollFeetBody->setMass(OgreOde::SphereMass(70*2.5,radius));

            OgreOde::SphereGeometry* feetGeom = new OgreOde::SphereGeometry(radius);

            OgreOde::TransformGeometry* feetTrans = new OgreOde::TransformGeometry(dollSpace);

            modelNode->translate(Vector3(0,-radius/ninjaNode->getScale().y,0));

            feetTrans->setBody(dollFeetBody);

            feetTrans->setEncapsulatedGeometry(feetGeom);

            ninjaNode->attachObject(dollFeetBody);

            創建橢球體

            對于角色的上半身用一個橢球體來表示。

            譯注:和上面一樣。

            (1)        創建Ogre::Body

            (2)        設置Ogre::Body形狀,另外設置不被重力影響,

            (3)        創建TransformGeometry,空間為剛才創建的空間

            (4)        創建CapsuleGeometry,半徑為AABB獲得半徑

            (5)        設置CapsuleGeometry位置和方向和阻尼

            (6)        TransformGeometry包含Ogre::body

            (7)        TransformGeometry包含CapsuleGeometry

            (8)        Ogre::Body粘到ninjiaNode

            OgreOde::Body* dollTorsoBody = new OgreOde::Body("torso");

            dollTorsoBody->setMass(OgreOde::CapsuleMass(70*2.5,radius,Vector3::UNIT_Y,radius));

            dollTorsoBody->setAffectedByGravity(false);

            dollTorsoBody->setDamping(0,50000);

            OgreOde::TransformGeometry* torsoTrans = new OgreOde::TransformGeometry(dollSpace);

            OgreOde::CapsuleGeometry* torsoGeom = new OgreOde::CapsuleGeometry(radius,size.y-4*radius,dollSpace);

            torsoGeom->setPosition(Ogre::Vector3(0,size.y-((size.y-4*radius)/2+2*radius),0)); //can't find a good way to explain this

            torsoGeom->setOrientation(Quaternion(Degree(90),Vector3::UNIT_X));

            torsoTrans->setBody(dollTorsoBody);

            torsoTrans->setEncapsulatedGeometry(torsoGeom);

            ninjaNode->attachObject(dollTorsoBody);

            這個幾何體和腳的幾何體在同一個空間,所以我們要取消內部碰撞檢測。講阻尼設置高些,并且取消重力,不然它會從那個球體上掉下來。

            創建關節

            剩下的事情就是將兩個碰撞體連在一起了。一個絞連連接的代表是自行車前輪。

            OgreOde::HingeJoint* joint = new OgreOde::HingeJoint();

            joint->attach(dollTorsoBody,dollFeetBody);

            joint->setAxis(Ogre::Vector3::UNIT_X);      //set the rotation axis

            注意:不要忘記記錄所有碰撞體和連接的位置以便你之后能得到它們。你可以用ogre堆?;蛘邉摻阕约旱?。

            移動角色

            你可以通過不同方法移動或者旋轉你的角色,我決定通過改變碰撞體方向而不是施加力或者力矩。

            前后移動

            下面代碼可以放在按鍵響應里執行,象KC_UP。現在你需要獲取碰撞體,從堆棧或者hashTable中獲得,然后獲取它的方向。我用:

            譯注:猜想堆棧就是你為屏幕上所有物體所創建的Ogre::Body的一個列表。

            OgreOde::Body* torso = torsoBodies->getObject("ninja");

            Quaternion q = torso->getOrientation();

            然后賦予腳一個角速度。

            OgreOde::Body* feet = feetBodies->getObject("ninja");

            feet->wake();

            feet->setAngularVelocity(q*Ogre::Vector3(10*cos(1),0,10*sin(1)));

            10是我們用的角速度,必須乘以三角函數以便讓角色向正確的方向前進。

            左右轉動

            下面代碼同樣放在按鍵響應中執行,比如KC_RIGHT

            OgreOde::Body* torso = torsoBodies->getObject("ninja");

            Quaternion q1 = torso->getOrientation();

            Quaternion q2(Degree(-4),Ogre::Vector3::UNIT_Y);

            torso->setOrientation(q1*q2);

            Degree(-4)讓角色向右轉動,用正數向左轉動。也許你已經注意到,我總是從橢球體獲取或者設置方向。我沒有太多想,我想如果你從腳的球體來獲取和設置也應該沒有什么問題。

            注意:如果你松開按鍵,你必須把速度設置為0來停止運動。

            feetbody->setAngularVelocity(Vector3(0,0,0));

            feetBody->setLinearVelocity(Vector3(0,feetBody->getLinearVelocity().y,0));

            讓角色爬起來

            最后,我們要確定你的角色不摔倒,所以我們需要不時重新設定他的垂直方向。

            OgreOde::Body* torso = torsoBodies->getObject("ninja");

            Quaternion q = torso->getOrientation();                     

             

            Vector3 x = q.xAxis();

            Vector3 y = q.yAxis();

            Vector3 z = q.zAxis();

             

            torso->wake();

            torso->setOrientation(Quaternion(x,Vector3::UNIT_Y,z));

            問題

            部分代碼沒有我想象的那么好。我重新設定垂直方向會讓角色有奇怪的行為。雖然我設置了速度為0,但是角色在一些不規則的表面上仍然無法停下來。

            posted on 2009-01-02 04:56 小王 閱讀(1251) 評論(0)  編輯 收藏 引用 所屬分類: 游戲引擎
            久久免费美女视频| 国内精品久久久久久久97牛牛| 国产福利电影一区二区三区久久老子无码午夜伦不 | 亚洲国产成人久久综合一| 国产精品熟女福利久久AV| 久久久久亚洲AV片无码下载蜜桃 | 久久人人爽人人人人片av| 久久狠狠高潮亚洲精品| 久久亚洲2019中文字幕| 色婷婷综合久久久久中文一区二区| 9191精品国产免费久久| 亚洲精品无码专区久久久 | 波多野结衣久久精品| 狠狠88综合久久久久综合网 | 精品999久久久久久中文字幕| 亚洲国产成人久久综合野外| 国产精品久久波多野结衣| 免费精品久久天干天干| 日韩精品久久久久久| 99精品久久精品一区二区| 久久噜噜久久久精品66| 国产免费久久精品99久久| 潮喷大喷水系列无码久久精品| 亚洲综合日韩久久成人AV| 一本色道久久综合| 欧美大战日韩91综合一区婷婷久久青草 | 青青草原精品99久久精品66| 久久影视综合亚洲| 99久久免费国产精品| 久久成人国产精品二三区| 日韩精品久久无码中文字幕| 无码任你躁久久久久久老妇App| 欧美精品一区二区久久| 精品无码久久久久久国产| 岛国搬运www久久| 色综合久久最新中文字幕| 国产精品毛片久久久久久久| 99久久这里只有精品| 久久A级毛片免费观看| 国产欧美久久一区二区| 久久综合丁香激情久久|