青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

的筆記

隨時隨地編輯

Chase camera筆記

參考資料:
 - ogre1.72 character sample
 - Creating a simple first-person camera system
 - 3rd person camera system tutorial
 - Make A Character Look At The Camera         
   Using quaternions and SLERP to make a character look at a camera (or any other object for that matter) naturally, with constraints on head movement

I.character sample

本節(jié)是對ogre 1.72 sample character 的分析,源碼見本節(jié)尾的說明。

1.chase攝像頭的基本對象

對象關系圖
   
     
      goal作為pivot的子節(jié)點,放置在(0 ,0 , 15)處,也就是說goal永遠會在pivot的正后方,不離不棄,。pivot就是那美麗的月亮女神,goal是永遠的追隨者。camNode是獵殺者,只有取代goal的地位(postion,direct)才能贏得月亮女神。任何時刻camNode都在追逐goal這個目標。這也是chase攝像機的基本原理。
      這里將pivot放置在角色的肩膀處,在幀循環(huán)里同步這個位置永遠不變。


2.鼠標邏輯

MouseMove事件影響
pitch ---  只影響pivot的pitch。
yaw ---    只影響pivot的yaw。
zoom --- 只影響goal的local postion,決定了goal與pivot的z向距離。goal永遠在pivot的正后方,也就是只在pivot的z軸上移動。

      鼠標的移動只會造成pivot的yaw和pitch,以及goal的local-z的移動。同角色的移動是沒有關系的。
code:

void injectMouseMove(const OIS::MouseEvent& evt)
{
    
// update camera goal based on mouse movement
    updateCameraGoal(-0.05f * evt.state.X.rel, -0.05f * evt.state.Y.rel, -0.0005f * evt.state.Z.rel);
}


    
void updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom)
{
    mCameraPivot
->yaw(Degree(deltaYaw), Node::TS_WORLD);

    
// bound the pitch
    if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0&&
        
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0))
    
{
        mCameraPivot
->pitch(Degree(deltaPitch), Node::TS_LOCAL);
        mPivotPitch 
+= deltaPitch;
    }

    
    Real dist 
= mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
    Real distChange 
= deltaZoom * dist;

    
// bound the zoom
    if (!(dist + distChange < 8 && distChange < 0&&
        
!(dist + distChange > 25 && distChange > 0))
    
{
        mCameraGoal
->translate(00, distChange, Node::TS_LOCAL);
    }

}
      鼠標移動最終的結果是改變了goal在world中的position和direction,這個作為camera在幀循環(huán)中處理的唯一依據(jù)。

3.幀循環(huán)邏輯

更新角色
    取得按鍵方向矢量,根據(jù)這個矢量設置角色的positon,direction
更新攝相機
    將永遠的中心月亮女神pivot放到角色的肩膀上。(女神的圣斗士goal會永遠在pivot女神的正后方,,同時goal的獵殺者camNode也會死死緊逼)
    獵殺者camNode用自己的速度向goal前進一步
    獵殺者將視線對準月亮女神pivot(雖然postion是向goal逼近,但是方向卻向著永遠的中心月亮女神pivot)

至此chase攝像機的基本實現(xiàn)原理水落石出。無非就是女神的圣斗士被獵殺者時刻緊追,獵殺者死死的盯住女神用目光表示內(nèi)容,用行動追逐女神的斗士。

4.角色的移動

      按鍵事件決定了角色的移動方向,用keydirection表示角色在local中的移動方向,用goaldirection表示角色在world中的移動。在幀循環(huán)中根據(jù)這2個方向移動角色------用角色自己的速度移動。

按鍵決定了移動方向:
// player's local intended direction based on WASD keys
Vector3 mKeyDirection;
// actual intended direction in world-space
Vector3 mGoalDirection;

void injectKeyDown(const OIS::KeyEvent& evt)
{
    
// keep track of the player's intended direction
    if (evt.key == OIS::KC_W) mKeyDirection.z = -1;
    
else if (evt.key == OIS::KC_A) mKeyDirection.x = -1;
    
else if (evt.key == OIS::KC_S) mKeyDirection.z = 1;
    
else if (evt.key == OIS::KC_D) mKeyDirection.x = 1;
}


void injectKeyUp(const OIS::KeyEvent& evt)
{
    
// keep track of the player's intended direction
    if (evt.key == OIS::KC_W && mKeyDirection.z == -1) mKeyDirection.z = 0;
    
else if (evt.key == OIS::KC_A && mKeyDirection.x == -1) mKeyDirection.x = 0;
    
else if (evt.key == OIS::KC_S && mKeyDirection.z == 1) mKeyDirection.z = 0;
    
else if (evt.key == OIS::KC_D && mKeyDirection.x == 1) mKeyDirection.x = 0;
}

    幀循環(huán)中update角色的position和direction:

//! 在世界坐標系中,取得角色將要面對的方向
// calculate actually goal direction in world based on player's key directions
mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
mGoalDirection 
+= mKeyDirection.x * mCameraNode->getOrientation().xAxis();

mGoalDirection.y 
= 0;
mGoalDirection.normalise();

if((mKeyDirection != Vector3::ZERO))
{
    
//! 角色的正前方
    Vector3 charFront = mBodyNode->getOrientation().zAxis();
    Quaternion toGoal 
= charFront.getRotationTo(mGoalDirection);

    
// calculate how much the character has to turn to face goal direction
    Real yawToGoal = toGoal.getYaw().valueDegrees();
    
// this is how much the character CAN turn this frame
    Real yawAtSpeed = yawToGoal / Math::Abs(yawToGoal) * deltaTime * TURN_SPEED;
    
// reduce "turnability" if we're in midair
    if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;

    
//! 限制旋轉(zhuǎn)角度,不要旋轉(zhuǎn)過量
    
// turn as much as we can, but not more than we need to
    if (yawToGoal < 0
    
{
        yawToGoal 
= std::min<Real>(0, std::max<Real>(yawToGoal, yawAtSpeed)); 
        
//yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
    }

    
else if (yawToGoal > 0)
    
{
        yawToGoal 
= std::max<Real>(0, std::min<Real>(yawToGoal, yawAtSpeed)); 
        
//yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
    }

    
    
//! 角色yaw操作
    mBodyNode->yaw(Degree(yawToGoal));

    
//! 每次按鍵動作,角色都要用當前速度往正前方移動
    
// move in current body direction (not the goal direction)
    mBodyNode->translate(00, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),Node::TS_LOCAL);
}

 


5.各種坐標系變換總結

pivot的平移操作:
幀循環(huán)中,相機update操作時,將pivot設置到角色的肩膀處
pivot的yaw、pitch操作:
鼠標move事件中,根據(jù)鼠標的x、y坐標做yaw、pitch操作

goal的平移操作:
鼠標move事件中,根據(jù)鼠標的z坐標進行l(wèi)oca-z的平移
goal不會有l(wèi)ocal旋轉(zhuǎn)操作

相機的操作:
幀循環(huán),相機update時,相機相goal平移逼近,并lookat pivot

角色的平移:
角色的旋轉(zhuǎn),角色只會有yaw操作。角色從當前方向向按鍵和相機的矢量合成的目標方向逼近
角色在方向鍵keydirection不為0的時候,完成yaw操作后,向當前+z方向移動

6.修改到第一人稱視角

相機始終在角色的背后,正對角色。只需修改代碼中的updateCamera即可:
void SinbadCharacterController::updateCamera(Real deltaTime)
{
    
// place the camera pivot roughly at the character's shoulder
    mCameraPivot->setPosition(mBodyNode->getPosition() + Vector3::UNIT_Y * CAM_HEIGHT);
    
    
//! 將pivot對準角色的正前方,注意此時相機的+Z必須和角色的+Z相反,因為相機時從+Z看向-Z的
    
//! 這樣修改后,就完成了一個第一人稱的相機,和魔獸世界類似
    
//! W鍵始終讓角色往自身正前方走,而不是相機的正前方
    Vector3 front = mCameraPivot->getOrientation().zAxis();
    Vector3 goal  
= -mBodyNode->getOrientation().zAxis();
    Quaternion toGoal 
= front.getRotationTo(goal);
    Real yawToGoal 
= toGoal.getYaw().valueDegrees();
    mCameraPivot
->yaw(Degree(yawToGoal) , Node::TS_WORLD );

    
// move the camera smoothly to the goal
    Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();

    mCameraNode
->translate(goalOffset * deltaTime * 1.0f);
    
// always look at the pivot
    mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Node::TS_WORLD);
}
只是增加了幾行代碼,讓pivot的front與角色的front在一個平面,示意圖如下:

7.角色根據(jù)WASD方向與自身方向的合成移動,而不是與相機方向合成的移動

updateBody中方向合成的代碼
mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
mGoalDirection 
+= mKeyDirection.x * mCameraNode->getOrientation().xAxis();

本來以為將紅色字體處標識符替換為“mBodyNode”即可。運行時發(fā)現(xiàn)方向還算正常,但是角色會發(fā)生嚴重的角色抖動。不得其解。

本節(jié)完整源碼:https://3dlearn.googlecode.com/svn/trunk/Samples/Ogre/sinbad
此源碼來自ogre 1.72 sample character:https://bitbucket.org/sinbad/ogre/src/d1f2eab81f08/Samples/Character/

posted on 2011-06-15 12:15 的筆記 閱讀(2447) 評論(0)  編輯 收藏 引用


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


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久综合狠狠综合久久综青草| 久久精品99国产精品| 欧美交受高潮1| 91久久精品www人人做人人爽| 亚洲国产精品激情在线观看| 欧美成年人网| 日韩亚洲欧美高清| 亚洲欧美日韩成人高清在线一区| 国产乱码精品一区二区三区av| 午夜精品久久久久久久久久久久久 | 亚洲人成在线观看| 欧美日韩国产成人在线91| 一区二区三区国产在线观看| 欧美一区二区三区免费在线看 | 蜜臀a∨国产成人精品| 亚洲欧洲三级电影| 欧美系列精品| 久久精品在线播放| 亚洲国产欧美一区二区三区丁香婷| 99视频+国产日韩欧美| 国产精品成人一区二区三区夜夜夜| 亚洲一区二区三| 欧美成人免费播放| 国产精品99久久久久久久女警| 国产精品一区二区三区乱码| 久久综合电影一区| 一本色道久久综合亚洲精品按摩| 久久九九全国免费精品观看| 亚洲精品一区二区在线观看| 国产精品久久久久aaaa| 久久久青草婷婷精品综合日韩| 亚洲三级影片| 久久久久久久综合色一本| 日韩视频在线一区二区| 国产欧美日韩精品丝袜高跟鞋 | 久久综合999| 亚洲午夜国产一区99re久久| 欧美成人性网| 性欧美videos另类喷潮| 亚洲精品日韩久久| 国产真实久久| 国产精品久久久久久影院8一贰佰| 久久久五月天| 亚洲欧美日本伦理| 亚洲国产欧美另类丝袜| 六月婷婷一区| 欧美在线视频一区| 在线视频一区观看| 亚洲激情小视频| 国产一区深夜福利| 国产精品人人做人人爽| 欧美精品在线免费观看| 久久婷婷激情| 欧美专区在线播放| 亚洲永久精品国产| 在线午夜精品自拍| 99国内精品久久| 亚洲丰满在线| 男男成人高潮片免费网站| 欧美专区在线观看| 欧美一区日本一区韩国一区| 亚洲香蕉在线观看| 亚洲特级片在线| 日韩一区二区免费看| 91久久线看在观草草青青| 一区二区视频免费完整版观看| 国产目拍亚洲精品99久久精品 | 国产视频久久| 国产日韩欧美中文| 国产日韩欧美高清| 国产亚洲精品aa午夜观看| 国产精品美女久久福利网站| 国产精品成人v| 欧美午夜激情在线| 欧美视频手机在线| 国产精品看片你懂得| 国产精品久久久久久久久久久久久久| 欧美日韩视频在线| 国产精品a级| 国产精品区一区| 国产日韩欧美在线播放| 好看的日韩视频| 国语精品中文字幕| 亚洲第一中文字幕| 亚洲人成在线免费观看| 亚洲麻豆国产自偷在线| 日韩亚洲欧美在线观看| 亚洲一级网站| 久久国产精品高清| 麻豆av一区二区三区| 女仆av观看一区| 最近中文字幕mv在线一区二区三区四区 | 亚洲一区二区三区精品在线观看| 亚洲一区二区三区精品动漫| 亚洲在线一区| 久久精品一区二区三区中文字幕| 久久色中文字幕| 欧美激情精品久久久久久免费印度| 欧美极品一区二区三区| 国产精品毛片a∨一区二区三区|国| 国产麻豆日韩| 亚洲成人资源| 中文日韩电影网站| 久久激情视频| 亚洲高清在线观看| 在线亚洲自拍| 久久免费国产精品| 欧美日本一道本| 国产日产精品一区二区三区四区的观看方式| 国产在线拍偷自揄拍精品| 亚洲日本一区二区三区| 亚洲欧美日韩成人| 欧美freesex交免费视频| 亚洲九九精品| 久久精品国产清自在天天线| 欧美成人精品1314www| 国产精品卡一卡二| 亚洲高清一二三区| 亚洲性感激情| 你懂的国产精品| 亚洲少妇在线| 欧美波霸影院| 国产日产精品一区二区三区四区的观看方式| 亚洲第一级黄色片| 性欧美超级视频| 亚洲激情国产精品| 久久av资源网站| 国产精品h在线观看| 亚洲激情亚洲| 久久久久亚洲综合| 9久草视频在线视频精品| 久久人人爽人人爽爽久久| 国产精品久久久久久久免费软件| 亚洲高清成人| 久久精品国产清高在天天线| 日韩午夜在线观看视频| 久久久久久久久久久久久9999| 欧美午夜一区二区福利视频| 亚洲国产成人久久综合一区| 欧美一区二区三区视频在线观看| 亚洲欧洲在线视频| 久久全国免费视频| 国产日韩欧美黄色| 亚洲尤物视频网| 亚洲国产综合91精品麻豆| 久久久999精品免费| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲精品在线一区二区| 免费观看亚洲视频大全| 亚洲综合成人婷婷小说| 欧美日韩国产在线一区| 亚洲精品日产精品乱码不卡| 免费在线看一区| 久久国产精品一区二区三区| 国产精品久久久久久久久借妻 | 野花国产精品入口| 亚洲黄色在线观看| 美女主播一区| 在线看视频不卡| 蜜桃精品久久久久久久免费影院| 午夜一级久久| 国产欧美日韩在线观看| 欧美一区二粉嫩精品国产一线天| 一本色道久久综合| 欧美亚洲第一区| 亚洲欧美日韩国产综合在线| 亚洲伦理一区| 欧美午夜精品久久久久久孕妇| 亚洲美女av网站| 亚洲毛片在线观看.| 欧美区日韩区| 亚洲一区二区免费看| 9国产精品视频| 国产精品永久免费在线| 久久成人综合网| 久久精品国产第一区二区三区| 狠狠干综合网| 欧美大片在线观看一区| 欧美好骚综合网| 亚洲美女毛片| 一本色道久久综合亚洲精品不卡| 国产精品vip| 欧美伊久线香蕉线新在线| 久久国产天堂福利天堂| 欲香欲色天天天综合和网| 亚洲国产婷婷综合在线精品| 欧美少妇一区| 欧美中文字幕| 欧美1区2区| 亚洲图片在线观看| 欧美一级久久| 91久久国产自产拍夜夜嗨| 亚洲欧洲一级| 国产精品影视天天线| 美腿丝袜亚洲色图| 欧美精品情趣视频| 久久se精品一区二区| 麻豆精品视频在线| 亚洲欧美日本另类| 看欧美日韩国产|