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

            第三人稱攝象機系統(tǒng)例子

            Posted on 2008-07-09 15:42 RichardHe 閱讀(453) 評論(0)  編輯 收藏 引用 所屬分類: OGRE

            第三人稱攝象機系統(tǒng)例子

            Translator:自由騎士篤志(王宏張)

            Data2008-5-14

            l        前言

            Ogre是一款優(yōu)秀的3D圖形渲染引擎,在國內(nèi),很多前輩從04年甚至更早就對它有了深入的了解,并留了許多譯文和心得,極大的便利了我的學習。雖然我起步比較晚,但仍希望自己學習間的這些記錄和翻譯能夠幫助到他人,如您對Ogre有所心得和資料,望提供至Ogre中文Wiki http://ogre3d.cn/wiki中大家共享交流。

            因能力所限,翻譯和整理難免有錯誤之處,歡迎各位指正。

            Blog http:\\hi.baidu.com\freedomknightduzhi

            E-mail duzhi5368@163.com

            大部分譯文來自 http://www.ogre3d.org ,如原文內(nèi)無說明,不再額外查證來源以及原作者名稱。

             

            l        想法來源

            這個第三人稱攝象機系統(tǒng)的想法來源于我玩的一款游戲《寂靜嶺2》,在其中有一些圖象上的BUG,我甚至能從其中發(fā)現(xiàn)一些不正常的“線”,如果你也看過,你會明白我說的情況。

                   一般情況下,該系統(tǒng)中同一時刻內(nèi)整個場景中有且僅有一個攝象機。和其他的第一/三人稱攝象機系統(tǒng)不同的是,我的這套系統(tǒng)中,攝象機是完全獨立與整個場景的(除根結(jié)點Root以外 --- 它是程序的核心)。

                   這個系統(tǒng)能使我們獲得非常優(yōu)秀的特效和軟件環(huán)境,也提供了我們一個非常友好的方式來查看整個場景。

                   概括來說,這個核心攝象機ExtendedCamera由 兩個場景結(jié)點共同組成,它們分別是“攝象機管理器”和“攝象機的對象”。攝象機管理器用來保證攝象機永遠朝向攝象機的對象。如果我們移動“對象”,攝象機 將會平移。如果我們移動“管理器”,則會使攝象機圍繞著“對象”進行旋轉(zhuǎn)。當然,我們也可以兩者一起移動獲得更多的情況。

                   上面是對整個系統(tǒng)的一個簡單功能的說明。我們還可以為攝象機增加一些震動特效,也可以通過虛擬攝象機實現(xiàn)一些電影效果等等。

                   下面,我將講述如何在一個Demo中實現(xiàn)三種攝象機模式。

            l         可旋轉(zhuǎn)第三人稱攝象機

            首先,我們有一個主角,它有三重性質(zhì)。首先,它本身是一個重要的場景結(jié)點(主角),又是一個可見的結(jié)點(我們的攝象機的目標結(jié)點),還是一個可旋轉(zhuǎn)的攝象機結(jié)點(主角的眼睛本身可以進行旋轉(zhuǎn)和觀察)。還有很多方法可以實現(xiàn)同樣的功能,但是我認為這種方法比較簡單。

                   我們接下來要做的就是,使它本身“可見的結(jié)點”這一特性結(jié)點做為我們“攝象機的目標”,而“可旋轉(zhuǎn)的攝象機結(jié)點”這一特性結(jié)點做為攝象機本身。

                   “可見的結(jié)點”意味著主角大部分時間應該處于屏幕的中心,但當主角處于“調(diào)查”狀態(tài)時,它自身就變成了一個攝象機,這時它能夠獲得更寬闊的視野。

                   (譯者:還不理解的朋友可以玩玩單機的《零》系列或射擊類游戲。通常為第三人稱,一旦開啟瞄準鏡時,就變成了第一人稱,即作者所說的“主角成為了一個攝象機結(jié)點”。)

            l         綁定的第三人稱攝象機

            這種類型的攝象機非常常見,例如《寂靜嶺》……(譯者:- -看來作者是SH的粉絲……)這種攝象機意味著攝象機永遠鎖定主角,但僅鎖定一個方面。(譯者:簡單來說即永遠無法旋轉(zhuǎn)攝象機看到主角的正面。)

            這種類型的攝象機與可旋轉(zhuǎn)的第三人稱攝象機類似。

            l         第一人稱攝象機

            我們使用主角的位置作為攝象機的位置。在該模式下,我們將攝象機的“目標結(jié)點”設置為空,同時也將以主角結(jié)點為目標的攝象機隱藏起來。

            以上,就是三種攝象機的區(qū)別。

            l        需要緊記的一些事情

            l         調(diào)整系統(tǒng)

            如果攝象機受到場景中的一些對象影響,我們則需要對攝象機進行一些調(diào)整。

            l         攝象機移動

            攝象機以及攝象機目標點可以這樣移動:我們計算攝象機坐標和目標點之間的差距,最終得到一個矩陣,讓它作用于攝象機使其移動至目標點。

            l         緊密器

            按照我們上面說的移動方式,我們會感覺到攝象機的移動很生硬,不夠平滑。所以這個“移動緊密器”的概念就出來了。這個緊密器因素是一個0,0 – 1.0之間的值,我們在計算出攝象機的移動轉(zhuǎn)換矩陣時,用它來進行影響。

                   1:若該因素為1.0,則表明當目標單元移動,攝象機同樣移動。

                   2:若該因素為0.0,則當目標單元移動時,攝象機完全不動。

                   3:該因素在0.0 – 1.0之間時,將會對攝象機的變換矩陣做出影響。

            l        源代碼以及說明

            你可以從http://www.ugr.es/local/agsh/ogre/ExtendedCameraSample.zip這里下載Alberts的這套代碼。

                   首先,我們包含OGRE的例子框架文件頭。

             

                   // 攝象機系統(tǒng)例子 By Kencho

                   #include “ExampleApplication.h”

             

                   接下來,我們定義一個角色類。這個類中將定義一個對象所處的多種特性屬性(即是攝象機又是攝象機的目標對象)。當然,在一個游戲中,你需要為角色類定義更多的屬性。 :)

             

                   // 普通角色類

                   Class Charater

            {

                   Protected:

                          SceneNode *mMainNode;      // 主角結(jié)點

                          SceneNode *mSightNode;      // 可見結(jié)點,主角應當一直看著這里

                          SceneNode *mCameraNode;  // 鎖定攝象機結(jié)點,該結(jié)點圍繞主角移動和旋轉(zhuǎn)

                          Entity *mEntity;                   // 角色實體

                          SceneManager *mSceneMgr;

                   Public:

                          // 更新主角狀態(tài)(如移動等……)

                          Virtual void update (Real elapsedTime, InputReader *input) = 0;

                          // 下面兩個方法返回攝象機結(jié)點指針

                          SceneNode *getSightNode(){ return mSightNode ;}

                          SceneNode *getCameraNode(){ return mCameraNode; }

                          // 返回主角當前坐標(第一人稱攝象機時需要)

                          Vector3 getWorldPosition(){ return mMainNode->getWorldPosition(); }

            };

             

            接下來,我們對角色類特化實現(xiàn)一下。我認為在Demo弄一個漂浮的食人魔腦袋做主角挺不錯。所以我們寫一個實例化的類。

             

                   // 特殊的實例化角色類 我們可愛的Ogre

                   Class OgreCharater : public Character

            {

            Protected:

                   String mName;

            Public:

                   OgreCharater(String name, SceneManager *sceneMgr)

            {

                   // 保存類成員變量

                   mName = name;

                   mSceneMgr = sceneMgr;

                   // 創(chuàng)建節(jié)點用來存放綁定第三人稱的攝象機

            mMainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(mName);

                mSightNode = mMainNode-> createChildSceneNode(mName + “_sight”, Vector3(0, 0, 100));

                mCameraNode = mMainNode-> createChildSceneNode(mName + “_camera”, Vector3(0, 50, -100));

                // 為角色綁定一個實體

                mEntity = mSceneMgr->createEntity(mName, “OgreHead.mesh”);

                mMainNode->attachObject(mEntity);

            }

             

            Void update(Real elapsedTime, InputReader *input)

            {

                   // 移動

                   If (input->isKeyDown(KC_W))

            {

                   mMainNode->translate(mMainNode->getOrientation() * Vector3(0, 0, 100 * elapsedTime));

            }

                   If (input->isKeyDown(KC_S))

            {

                   mMainNode->translate(mMainNode->getOrientation() * Vector3(0, 0, -50 * elapsedTime));

            }

                   If (input->isKeyDown(KC_A))

            {

                   mMainNode->yaw(Radian(2 * elapsedTime));;

            }

                   If (input->isKeyDown(KC_D))

            {

                   mMainNode->yaw(Radian(-2 * elapsedTime));;

            }

            }

             

            // 設置自身是否可見,這對于第一人稱視角很有用。

            Void setVisible(bool visible)

            {

                   mMainNode->setVisible(visible);

            }

            };

             

            為了保證代碼簡單,我這里不再寫一些關于主角的模型動畫,控制等函數(shù)。

                   現(xiàn)在,進入有趣的部分:擴展的攝象機類。它就如我之前所說明的思路一樣去設計的,所以,如果你對本部分代碼有什么疑問,你可以看一下先前我的講述。

                  

                   // 我們的擴展攝象機類

                   Class ExtendedCamera

                   {

                   Protected:

                          SceneNode *mTargetNode;    // 攝象機目標結(jié)點

                          SceneNode *mCameraNode;  // 攝象機自身結(jié)點

                          Camera *mCamera;              // Ogre攝象機

                          SceneManager *mSceneMgr;

                          String mName;

                          Bool mOwnCamera;             // 判斷是否是本類創(chuàng)建的攝象機,或是類外傳入的攝象機

                          Real mTightness;                  // 攝象機捆綁緊密度。1.0表示攝象機與目標的移動保持完全一致。0.0表示攝象機不移動,完全不受目標移動的影響。

                   Public:

                          ExtendedCamera(String name, SceneManager *sceneMgr, Camera *camera = 0)

            {

                   mName = name;

                   mSceneMgr = sceneMgr;

                   // 創(chuàng)建攝象機結(jié)點結(jié)構(gòu)

                   mCamreaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(mName);

                   mTargetNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(mName + “_target”);

                   // 攝象機永遠朝向目標結(jié)點

            mCameraNode->setAutoTracking(true, mTargetNode);

            // 因為需要自動跟蹤,所以該項要設為true

            mCameraNode->setFixedYawAxis(true);

             

            // 假如沒有從參數(shù)獲得一個攝象機,我們則自己創(chuàng)建

            If (camera == 0)

            {

                   mCamera = mSceneMgr->createCamera(mName);

                   mOwnCamera = true;

            }else

            {

                   mCamera = camera;

                   mOwnCamera = false;

            }

            // 為攝象機結(jié)點綁定一個Ogre攝象機

            mCameraNode->attachObject(mCamera);

            // 默認的攝象機捆綁緊密系數(shù)

            mTightness = 0.01f;

            }

             

            ~ExtendedCamera()

            {

                   mCameraNode->detachAllObjects();

                   if (mOwnCamera)

                          delete mCamera;

                   mSceneMgr->destroySceneNode(mName);

                   mSceneMgr-> destroySceneNode(mName + “_target”);

            }

             

            Void setTightness(Real tightness)

            {

                   mTightness = tightness;

            }

             

            Real getTightness()

            {

                   Return mTightness;

            }

             

            Vector3 getCameraPosition()

            {

                   Return mCameraNode->getPosition();

            }

             

            Void instantUpdate(Vertor3 cameraPosition, Vector3 targetPosition)

            {

                   mCameraNode->setPosition(cameraPosition);

            mTargetNode->setPosition(targetPosition);

            }

             

            Void update(Real elapsedTime, Vector3 cameraPosition, Vector3 targetPositon)

            {

                   // 管理移動

                   Vector3 displacement;

                   Displacement = (cameraPosition – mCameraNode->getPosition()) * mTightness;

                   mCameraNode->translate( displacement );

                   Displacement = (targetPosition – mTargetNode->getPosition()) * mTightness;

                   mTargetNode ->translate( displacement );   

            }

            };

             

            在每一楨的楨監(jiān)聽中,更變攝象機,角色和攝象機模式。

             

                   Class SampleListener : public ExampleFrameListener

                   {

                   Protected:

                          Character *mChar;

                          ExtendedCamera *mExCamera;

                          Unsigned int mMode;    // 攝象機模式,現(xiàn)在支持第一人稱,綁定的第三人稱攝象機和動態(tài)捕捉第三人稱攝象機

                   Public:

                          SampleListener(RenderWindow *win, Camera *cam) : ExampleFrameListener(win, cam)

                          {

                                 mChar = 0;

                                 mExCamera = 0;

                                 mMode = 0;

            }

             

            Void setCharacter(Character * character)

            {

                   mChar = character;

            }

             

            Void setExtendedCamera(ExtendedCamera *cam)

            {

                   mExCamera = cam;

            }

             

            Bool frameStarted( const FrameEvent& evt )

            {

                   mInputDevice->capture();

             

                   if (mChar)

                   {

                          mChar->update(evt.timeSinceLastFrame, mInputDevice);

                          if (mExCamera)

                          {

                                 Switch(mMode)

                                 {

                                        // 動態(tài)捕捉型第三人稱攝象機

                                        case 0:

            mExCamera->update(evt.timeSinceLastFrame, mChar->getCameraNode()->getWorldPosition(), mChar->getSightNode()->getWorldPosition());

            break;

                                                      // 綁定的第三人稱攝象機

                                                      case 1:

                                                             mExCamera->update(evt.timeSinceLastFrame, Vector3(0, 200, 0), mChar->getSightNode()->getWorldPosition());

                                                             break;

                                                      // 第一人稱攝象機

                                                      case 2:

                                                             mExCamera->update(evt.timeSinceLastFrame, mChar->getWorldPosition(), mChar->getSightNode()->getWorldPosition());

                                                             break;

            }

            }

            }

            // F1鍵切換為動態(tài)捕捉型第三人稱攝象機

            If (mInputDevice->isKeyDown(KC_F1))

            {

                   mMode = 0;

                   if (mChar)

                          static_cast<OgreCharacter* >(mChar)->setVisible(true);

                   if (mExCamera)

                   {

                          If (mChar)

                          {

            mExCamera->instantUpdate(mChar->getCameraNode()->getWorldPosition(), mChar->getSightNode()->getWorldPosition());

            }     

                          mExCamera->setTightness(0.01f);      

            }

            }

            //  F2切換為綁定的第三人稱攝象機

            If( mInputDevice->isKeyDown(KC_F2))

            {

                   mMode = 1;

                   if (mChar)

                          static_cast<OgreCharacter*>(mChar)->setVisible(true);

                   if (mExCamera)

                   {

                          If (mChar)

                                 mExCamera->instanceUpdate(Vector3(0, 200, 0), mChar->getSightNode()->getWorldPosition());

                          mExCamera->setTightness(0.01f);

            }

            }

             

            // F3鍵切換為第一人稱攝象機

            If (mInputDevice->isKeyDown(KC_F3))

            {

                   mMode = 2;

                   if (mChar)

                          static_cast<OgreCharacter*>(mChar)->setVisible(true);

                   if(mExCamera)

            {

                          If (mChar)

                          {

            mExCamera->instantUpdate(mChar->getWorldPosition(), mChar->getSightNode()->getWorldPosition());

            }     

                          mExCamera->setTightness(1.0f); 

            }

            }

            // 若按下ESC就退出

            If (mInputDevice->isKeyDown(KC_ESCAPE))

                   Return false;

             

            Return true;

            }

            };

             

            下面是一個App程序的樣本,如果你不理解這段代碼,你可以看一下其他的Ogre文章。

             

            Class SampleApplication : public ExampleApplication

            {

                   Public:

                          SampleApplication(){}

                          ~ SampleApplication(){}

                   Protected:

                          // 創(chuàng)建場景

                          Void createScene(void)

                          {

                                 // 設置環(huán)境光

                                 mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));

                                 // 創(chuàng)建一個點光源

                                 Light* l = mSceneMgr->createLight(“MainLight”);

                                 // 這個點光源使用默認設置

                                 l->setType(Light::LT_DIRECTIONAL);

                                 l->setDirection(-0.5, -0.5, 0);

                                 // 攝象機位置

                                 mCamera->setPosition(0, 0, 0);

                                 // 為場景添加一些實體對象

                                 SceneNode* razorNode;

                                 Entity* razorEntity;

                                 For (unsigned int i = 0; i< 30; ++i)

                                 {

                                        razorNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(StringConverter::toString(i), Vector3(Mesh::RangeRandom(-1000, 1000), 0, Math::RangeRandom(-1000, 1000)));

                                        razorEntity = mSceneMgr->createEntity(StringConverter::toString(i), “razor.mesh”);

                                        rezorNode->attachObject(razorEntity);

            }

             

            // 主角

            OgreCharacter *ogre = new OgreCharacter(“Ogre 1”, mSceneMgr);

            ExtendedCamera *exCamera = new ExtendedCamera(“Extended Camera”, mSceneMgr, mCamera);

            // 楨監(jiān)聽器用來管理主角和攝象機的更新和不同攝象機模式間的切換

            mFrameListener = new SampleListener(mWindow, mCamera);

            static_cast<SampleListener*>( mFrameListener)->setCharacter(ogre);

            static_cast<SampleListener*>( mFrameListener)->setExtendedCamera(exCamera);

            }

             

            Void destroyScene(void){}

            Void createFrameListener(void)

            {

                   // 放棄實例化我們自己的楨監(jiān)聽器

                   // mFrameListener = new SampleListener(mWindow, mCamera);

                   mRoot->addFrameListener(mFrameListener);

            }

            };

             

            注意:在createFrameListener()函數(shù)中,我們并沒有構(gòu)造創(chuàng)建楨監(jiān)聽器,所以不會有兩個監(jiān)聽器。這是非常重要的,若我們創(chuàng)建兩個楨監(jiān)聽器,這個程序?qū)敊C。

             

            #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

            #define WIN32_LEAN_AND_MEAN

            #include “windows,h”

             

            INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)

            #else

            Int main(int argc, char** argv)

            #endif

            {

                   // 創(chuàng)建APP實例

                   SampleApplication app;

            Try

            { app.go(); }

            Catch( Exception & e)

            {

                          #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

                   MessageBox( NULL, e.getFullDescription().c_str(), “An Exception has occurred!”, MB_OK | MB_ICONERROR );

                   #else

                   Fprintf(stderr, “An Exception has occurred: %s\n”, e.getFullDescription().c_str());

                   #endif

            }

            Return 0;

            }

             

            l        結(jié)束語

            希望這篇文章對你有用處,我會之后再更新它來進行更多的解釋說明。感謝您的閱讀。

            Kencho

            posts - 94, comments - 138, trackbacks - 0, articles - 94

            Copyright © RichardHe

            国产精品久久国产精品99盘| AV色综合久久天堂AV色综合在| 亚洲欧洲中文日韩久久AV乱码| 亚洲人AV永久一区二区三区久久| 久久精品无码一区二区app| 亚洲欧洲久久av| 国产精品久久久久久久| 久久久精品久久久久久| 亚洲精品无码成人片久久| 久久99精品久久久久久秒播| 久久夜色精品国产网站| 久久久99精品一区二区| 99久久成人国产精品免费| 2019久久久高清456| 国产精品美女久久久久AV福利| 中文字幕无码av激情不卡久久| 日本福利片国产午夜久久| 久久妇女高潮几次MBA| 久久天天日天天操综合伊人av| 国产高潮国产高潮久久久| 欧美日韩久久中文字幕| 久久亚洲av无码精品浪潮| 婷婷综合久久中文字幕| 久久婷婷五月综合国产尤物app| 久久这里只精品99re66| 午夜精品久久影院蜜桃| 国产精品美女久久久免费| 青青青国产成人久久111网站| 久久婷婷成人综合色综合| 狠狠色综合网站久久久久久久高清 | 精品久久久久久国产潘金莲| 尹人香蕉久久99天天拍| 久久久中文字幕日本| 久久国产成人午夜AV影院| 久久不见久久见免费影院www日本| 欧美亚洲另类久久综合| 色综合久久88色综合天天| 欧美一区二区精品久久| 国产99久久九九精品无码| 99久久精品无码一区二区毛片 | 亚洲午夜无码AV毛片久久|