• <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)  編輯 收藏 引用 所屬分類: 游戲引擎
            久久久久久久久波多野高潮| 中文字幕成人精品久久不卡| 国产精品久久久久久搜索| 精品多毛少妇人妻AV免费久久| 国产91久久综合| 超级碰久久免费公开视频| 99久久这里只有精品| 久久精品人人槡人妻人人玩AV| 久久无码人妻一区二区三区| 日产精品久久久久久久性色| 国产精品一区二区久久不卡| 久久久久久久综合日本亚洲| 久久亚洲国产欧洲精品一| 国内精品久久久久久久coent | 久久精品国产清自在天天线| 国产毛片欧美毛片久久久| 国产成人精品久久综合| 国产成人精品久久亚洲高清不卡| 99久久99久久精品国产片| 久久亚洲av无码精品浪潮| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 99久久成人国产精品免费| 91精品国产91久久久久久| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | yy6080久久| 久久综合给合久久狠狠狠97色| 久久精品国产99久久无毒不卡| 精品国产福利久久久| 久久91这里精品国产2020| 色综合久久夜色精品国产| 国产精品久久99| 伊人久久大香线蕉AV一区二区| 亚洲女久久久噜噜噜熟女| 日本精品久久久中文字幕| 欧美国产成人久久精品| 久久精品成人国产午夜| 无码乱码观看精品久久| 日本精品久久久中文字幕| 亚洲AV乱码久久精品蜜桃| 精品水蜜桃久久久久久久| 久久婷婷五月综合色奶水99啪|