zoukankan      html  css  js  c++  java
  • ogre3D学习基础12 --- 让机器人动起来(移动模型动画)

      学了那么长时间,才学会跑起来。My Ogre,动起来。

      第一,还是要把框架搭起来,这里我们用到双端队列deque,前面已经简单介绍过,头文件如下:

    #include  "ExampleApplication.h"
    #include "deque"
    using namespace std;

      第二,是我们的监听器,继承至ExampleFrameListener,构造函数我们使用五个参数,分别为渲染窗口,摄像机,场景节点,实体,行走路线上的位置坐标。

    1     MoveDemoListener(RenderWindow *win,Camera *cam,SceneNode *sn,Entity *ent,std::deque <Vector3> &walk) :ExampleFrameListener(win,cam,false,false),              mNode(sn),mEntity(ent),mWalkList(walk)
    2     {
    3 
    4         // Set default values for variables
    5         mWalkSpeed = 35.0f;//行走 速度设为每秒 35 个单位
    6         mDirection = Vector3::ZERO;//可用来判断机器人是否正在行走,为零时不走
    7 
    8     }

      第三,我们接着完善监听器首先成员函数添加了

     1     Real mDistance;//实体要移动的距离
     2     Vector3 mDirection;//方向
     3     Vector3 mDestination;//目的地
     4 
     5     AnimationState *mAnimationState;//物体的目前的动画状态
     6 
     7     Entity *mEntity;
     8     SceneNode *mNode;
     9     std::deque<Vector3> mWalkList;//要行走的点
    10     Real mWalkSpeed;//物体移动的速度

      然后添加一个函数,bool nextLocation();用来判断是否有下一个方位,确定下一步怎么走。如果返回行走的队列为空,返回false

     1    bool nextLocation()
     2     {
     3         if (mWalkList.empty())
     4             return false;
     5         mDestination = mWalkList.front(); // 取得队列的头部
     6         mWalkList.pop_front(); // 删除已走过的点
     7         mDirection = mDestination - mNode->getPosition();//距离由目的地减去当前位置得到
     8         mDistance = mDirection.normalise();//normalise()作用是将方向向量转换成单位向量,返回向量的原始长度
     9         return ture;
    10     }

       最后我们添加在每一帧前渲染的函数frameStarted(),这函数我们见了好多次,以后我们还会见面的。移动、转向操作等都在这里。

     1     bool frameStarted(const FrameEvent &evt)
     2     {
     3         if (mDirection == Vector3::ZERO)
     4         {
     5             if (nextLocation())//如果行走列表不为空
     6             {
     7                 // 设置行走的动画
     8                 mAnimationState = mEntity->getAnimationState("Walk");//设置动画为走动
     9                 mAnimationState->setLoop(true);//循环执行
    10                 mAnimationState->setEnabled(true);//激活
    11             }
    12         }
    13         else//开始 移动
    14         {
    15             Real move = mWalkSpeed * evt.timeSinceLastFrame;//速度*时间 = 移动距离
    16             mDistance -= move;//更新距离
    17             if (mDistance <= 0.0f)//小于0,说明已经走过目标地点
    18             {
    19                 mNode->setPosition(mDestination);//重新设置为目的地
    20                 mDirection = Vector3::ZERO;//方向为0,不走
    21                 if (! nextLocation())//如果行走列表为空,没有目的地
    22                 {// Set Idle animation
    23                     mAnimationState = mEntity->getAnimationState("Idle");//从网格动画的动画集(Idle)中获取当前的状态
    24                     mAnimationState->setLoop(true);//设置循环
    25                     mAnimationState->setEnabled(true);//激活
    26                 }
    27                 else    //继续走
    28                 {
    29                     Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;//获取实体的当前朝向,这里有向量的乘积,如果俩个向量方向相反,乘积就是-1
    30                     if ((1.0f + src.dotProduct(mDirection)) < 0.0001f)//如果要旋转180度
    31                     {
    32                         mNode->yaw(Degree(180));
    33                     }
    34                     else//如果不是要旋转180度
    35                     {
    36                         Ogre::Quaternion quat = src.getRotationTo(mDirection);//获取方向
    37                         mNode->rotate(quat);//旋转
    38                     } // else
    39                 }
    40             }
    41             else
    42             {
    43                 mNode->translate(mDirection * move);//移动一定距离
    44             } // else
    45         } // if
    46 
    47         mAnimationState->addTime(evt.timeSinceLastFrame);//更新动画状态
    48         return ExampleFrameListener::frameStarted(evt);
    49     }

      我已经把注释写的很详细了。这里说一下第29行Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;这里牵涉到向量乘积的问题,两个向量乘积有以下两种情况 

      向量的积分为数量积和向量积 数量积就是向量的点乘 向量积就是向量的叉乘
      设a(x,y,z) b(m,n,p)
      则 a点乘b=xm+yn+zp
      或 a点乘b=|a||b|*cos<a,b>
      设a=xi+yj+zk b=mi+nj+pk
      则叉乘 a×b=(yp-zn)i+(zm-xp)j+(xn-ym)k

      Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;//这个是点乘,结果是一个数,大小在-1,1之间。两个向量方向相反时,乘积为-1

      还有个老熟人createFrameListener(),我就不解释了,不懂,看前一章。

    void createFrameListener(void)
        {
            mFrameListener = new MoveDemoListener(mWindow,mCamera,mNode,mEntity,mWalkList);
            mFrameListener->showDebugOverlay(true);
            mRoot->addFrameListener(mFrameListener);
        }

      第四,创建场景,如下,都是一些简单的东西,不解释

     1 void createScene(void)
     2     {
     3         mSceneMgr->setAmbientLight( ColourValue( 1.0f, 1.0f, 1.0f ) );
     4         mEntity = mSceneMgr->createEntity( "Robot", "robot.mesh" );
     5         mNode = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "RobotNode", Vector3( 0.0f, 0.0f, 25.0f ) );
     6         mNode->attachObject( mEntity );
     7 
     8         // 创建走动列表
     9         mWalkList.push_back( Vector3( 550.0f, 0.0f, 50.0f ) );
    10         mWalkList.push_back( Vector3(-100.0f, 0.0f, -200.0f ) );
    11 
    12         Entity *ent;
    13         SceneNode *node;
    14         ent = mSceneMgr->createEntity( "Knot1", "knot.mesh" );
    15         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot1Node",Vector3( 0.0f, -10.0f, 25.0f ) );
    16         node->attachObject( ent );
    17         node->setScale( 0.1f, 0.1f, 0.1f );
    18         ent = mSceneMgr->createEntity( "Knot2", "knot.mesh" );
    19         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot2Node",Vector3( 550.0f, -10.0f, 50.0f ) );
    20         node->attachObject( ent );
    21         node->setScale( 0.1f, 0.1f, 0.1f );
    22         ent = mSceneMgr->createEntity( "Knot3", "knot.mesh" );
    23         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot3Node",Vector3(-100.0f, -10.0f,-200.0f ) );
    24         node->attachObject( ent );
    25         node->setScale( 0.1f, 0.1f, 0.1f );
    26 
    27         mCamera->setPosition( 90.0f, 280.0f, 535.0f );
    28         mCamera->pitch( Degree(-30.0f) );
    29         mCamera->yaw( Degree(-15.0f) );
    30     }

     

      好了,完整代码如下

      1 #include  "ExampleApplication.h"
      2 #include "deque"
      3 using namespace std;
      4 
      5 class MoveDemoListener : public ExampleFrameListener
      6 {
      7 public:
      8     MoveDemoListener(RenderWindow *win,Camera *cam,SceneNode *sn,Entity *ent,std::deque <Vector3> &walk)
      9         :ExampleFrameListener(win,cam,false,false),mNode(sn),mEntity(ent),mWalkList(walk)
     10     {    
     11         mWalkSpeed = 35.0f;//行走 速度设为每秒 35 个单位
     12         mDirection = Vector3::ZERO;//可用来判断机器人是否正在行走
     13     }
     14 
     15     bool nextLocation()
     16     {
     17         if (mWalkList.empty())
     18             return false;
     19         mDestination = mWalkList.front(); // 
     20         mWalkList.pop_front(); // 
     21         mDirection = mDestination - mNode->getPosition();
     22         mDistance = mDirection.normalise();
     23         return true;
     24     }
     25     bool frameStarted(const FrameEvent &evt)
     26     {
     27         if (mDirection == Vector3::ZERO)
     28         {
     29             if (nextLocation())//如果行走列表不为空
     30             {
     31                 // 设置行走的动画
     32                 mAnimationState = mEntity->getAnimationState("Walk");//设置动画为走动
     33                 mAnimationState->setLoop(true);//循环执行
     34                 mAnimationState->setEnabled(true);//激活
     35             }
     36         }
     37         else//开始 移动
     38         {
     39             Real move = mWalkSpeed * evt.timeSinceLastFrame;//速度*时间 = 移动距离
     40             mDistance -= move;//更新距离
     41             if (mDistance <= 0.0f)//小于0,说明已经走过目标地点
     42             {
     43                 mNode->setPosition(mDestination);//重新设置为目的地
     44                 mDirection = Vector3::ZERO;//方向为0,不走
     45                 if (! nextLocation())//如果行走列表为空,没有目的地
     46                 {
     47                     mAnimationState = mEntity->getAnimationState("Idle");//从网格动画的动画集(Idle)中获取当前的状态
     48                     mAnimationState->setLoop(true);//设置循环
     49                     mAnimationState->setEnabled(true);//激活
     50                 }
     51                 else    //继续走
     52                 {
     53                     Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;//获取实体的当前朝向,这里有向量的乘积,如果俩个向量方向相反,乘积就是-1
     54                     if ((1.0f + src.dotProduct(mDirection)) < 0.0001f)//如果要旋转180度
     55                     {
     56                         mNode->yaw(Degree(180));
     57                     }
     58                     else//如果不是要旋转180度
     59                     {
     60                         Ogre::Quaternion quat = src.getRotationTo(mDirection);//获取方向
     61                         mNode->rotate(quat);//旋转
     62                     } // else
     63                 }
     64             }
     65             else
     66             {
     67                 mNode->translate(mDirection * move);//移动一定距离
     68             } // else
     69         } // if
     70 
     71         mAnimationState->addTime(evt.timeSinceLastFrame);//更新动画状态
     72         return ExampleFrameListener::frameStarted(evt);
     73     }
     74 protected:
     75     Real mDistance;//实体要移动的距离
     76     Vector3 mDirection;//方向
     77     Vector3 mDestination;//目的地
     78 
     79     AnimationState *mAnimationState;//物体的目前的动画状态
     80 
     81     Entity *mEntity;
     82     SceneNode *mNode;
     83     std::deque<Vector3> mWalkList;//要行走的点
     84     Real mWalkSpeed;//物体移动的速度
     85 
     86 };
     87 
     88 class MoveDemoApplication:public ExampleApplication
     89 {
     90 public:
     91     MoveDemoApplication()
     92     {
     93 
     94     }
     95     ~MoveDemoApplication()
     96     {
     97 
     98     }
     99 protected:
    100     Entity *mEntity;
    101     SceneNode *mNode;
    102     std::deque<Vector3> mWalkList;
    103     void createScene(void)
    104     {
    105         mSceneMgr->setAmbientLight( ColourValue( 1.0f, 1.0f, 1.0f ) );
    106         mEntity = mSceneMgr->createEntity( "Robot", "robot.mesh" );
    107         mNode = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "RobotNode", Vector3( 0.0f, 0.0f, 25.0f ) );
    108         mNode->attachObject( mEntity );
    109 
    110         mWalkList.push_back( Vector3( 550.0f, 0.0f, 50.0f ) );
    111         mWalkList.push_back( Vector3(-100.0f, 0.0f, -200.0f ) );
    112 
    113         Entity *ent;
    114         SceneNode *node;
    115         ent = mSceneMgr->createEntity( "Knot1", "knot.mesh" );
    116         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot1Node",Vector3( 0.0f, -10.0f, 25.0f ) );
    117         node->attachObject( ent );
    118         node->setScale( 0.1f, 0.1f, 0.1f );
    119         ent = mSceneMgr->createEntity( "Knot2", "knot.mesh" );
    120         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot2Node",Vector3( 550.0f, -10.0f, 50.0f ) );
    121         node->attachObject( ent );
    122         node->setScale( 0.1f, 0.1f, 0.1f );
    123         ent = mSceneMgr->createEntity( "Knot3", "knot.mesh" );
    124         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Knot3Node",Vector3(-100.0f, -10.0f,-200.0f ) );
    125         node->attachObject( ent );
    126         node->setScale( 0.1f, 0.1f, 0.1f );
    127 
    128         mCamera->setPosition( 90.0f, 280.0f, 535.0f );
    129         mCamera->pitch( Degree(-30.0f) );
    130         mCamera->yaw( Degree(-15.0f) );
    131     }
    132 
    133     void createFrameListener(void)
    134     {
    135         mFrameListener = new MoveDemoListener(mWindow,mCamera,mNode,mEntity,mWalkList);
    136         mFrameListener->showDebugOverlay(true);
    137         mRoot->addFrameListener(mFrameListener);
    138     }
    139 
    140 
    141 };
    142 
    143 
    144 #include "windows.h"
    145 
    146 INT WINAPI WinMain(HINSTANCE hInstance,  HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT)
    147 {
    148     MoveDemoApplication app;
    149     app.go();
    150     return 0;
    151 }

      

  • 相关阅读:
    显示文件本地文件夹
    Select Dependencies选择依赖项
    搜索小技巧
    783. Minimum Distance Between BST Nodes BST节点之间的最小距离
    5. Longest Palindromic Substring 最长的回文子串
    12. Integer to Roman 整数转罗马数字
    3. Longest Substring Without Repeating Characters 最长的子串不重复字符
    539. Minimum Time Difference 最小时差
    43. Multiply Strings 字符串相乘
    445. Add Two Numbers II 两个数字相加2
  • 原文地址:https://www.cnblogs.com/songliquan/p/3317515.html
Copyright © 2011-2022 走看看