剑痴乎

  • 首页
  • 文章分类
    • 音视频
    • WebRTC
    • 编程之美
    • Linux
    • Windows
    • 生活点滴
    • 校园生活
  • 参考
    • API参考
    • 实用工具
    • 测试音视频
    • 文档
  • 留言板
  • 关于
剑痴乎
代码为剑,如痴如醉
  1. 首页
  2. 编程之美
  3. 正文

Ogre中移植Sample_Character到Advanced Ogre Framework

2014年4月5日 2002点热度 0人点赞 5条评论

刚开始学习Ogre的时候,用的是BaseApplication这个框架,但是该框架不能满足更大规模的开发需求,比如不能进行游戏场景切换,游戏状态切换,后来我用了Advanced Ogre Framework,这是一个很不错的游戏框架,总共包含17个文件, 使用起来不是太难,可以看下官网上的介绍http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Advanced+Ogre+Framework

Ogre SKD中Sample_Character那个sinbad挺好玩的,花了点时间把它移植到到了Advanced Ogre Framework,可以很容易利用这开发一个小游戏或者虚拟人物漫游系统,至于场景的话可以在3dsmax中构建,然后利用Ogremax插件导出为场景文件,在createscene方法中加入下面三行代码即可导入场景

1
2
3
DotSceneLoader* pDotSceneLoader = new DotSceneLoader();
pDotSceneLoader->parseDotScene("你自己构建的场景.xml", "General", m_pSceneMgr, m_pSceneMgr->getRootSceneNode());
delete pDotSceneLoader;

我在Advanced Ogre Framework新增加的四个文件代码如下,加入的这四个文件实现了可操纵的sinbad:

SinbadCharacterController.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#ifndef __Sinbad_H__
#define __Sinbad_H__
 
#include "Ogre.h"
#include "OIS.h"
 
using namespace Ogre;
 
#define NUM_ANIMS 13           // number of animations the character has
#define CHAR_HEIGHT 5          // height of character's center of mass above ground
#define CAM_HEIGHT 2           // height of camera above character's center of mass
#define RUN_SPEED 17           // character running speed in units per second
#define TURN_SPEED 500.0f      // character turning in degrees per second
#define ANIM_FADE_SPEED 7.5f   // animation crossfade speed in % of full weight per second
#define JUMP_ACCEL 30.0f       // character jump acceleration in upward units per squared second
#define GRAVITY 90.0f          // gravity in downward units per squared second
 
class SinbadCharacterController
{
private:
 
// all the animations our character has, and a null ID
// some of these affect separate body parts and will be blended together
enum AnimID
{
ANIM_IDLE_BASE,
ANIM_IDLE_TOP,
ANIM_RUN_BASE,
ANIM_RUN_TOP,
ANIM_HANDS_CLOSED,
ANIM_HANDS_RELAXED,
ANIM_DRAW_SWORDS,
ANIM_SLICE_VERTICAL,
ANIM_SLICE_HORIZONTAL,
ANIM_DANCE,
ANIM_JUMP_START,
ANIM_JUMP_LOOP,
ANIM_JUMP_END,
ANIM_NONE
};
 
public:
SinbadCharacterController(Camera* cam);
 
void addTime(Real deltaTime);
 
void injectKeyDown(const OIS::KeyEvent& evt);
 
void injectKeyUp(const OIS::KeyEvent& evt);
void injectMouseMove(const OIS::MouseEvent& evt);
void injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
 
 
private:
 
void setupBody(SceneManager* sceneMgr);
void setupAnimations();
void setupCamera(Camera* cam);
 
void updateBody(Real deltaTime);
 
void updateAnimations(Real deltaTime);
 
void fadeAnimations(Real deltaTime);
 
void updateCamera(Real deltaTime);
 
void updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom);
 
void setBaseAnimation(AnimID id, bool reset = false);
 
void setTopAnimation(AnimID id, bool reset = false);
 
Camera* mCamera;
SceneNode* mBodyNode;
SceneNode* mCameraPivot;
SceneNode* mCameraGoal;
SceneNode* mCameraNode;
Real mPivotPitch;
Entity* mBodyEnt;
Entity* mSword1;
Entity* mSword2;
RibbonTrail* mSwordTrail;
AnimationState* mAnims[NUM_ANIMS];    // master animation list
AnimID mBaseAnimID;                   // current base (full- or lower-body) animation
AnimID mTopAnimID;                    // current top (upper-body) animation
bool mFadingIn[NUM_ANIMS];            // which animations are fading in
bool mFadingOut[NUM_ANIMS];           // which animations are fading out
bool mSwordsDrawn;
Vector3 mKeyDirection;      // player's local intended direction based on WASD keys
Vector3 mGoalDirection;     // actual intended direction in world-space
Real mVerticalVelocity;     // for jumping
Real mTimer;                // general timer to see how long animations have been playing
};
 
#endif

SinbadCharacterController.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
#include "SinbadCharacterController.hpp"
 
SinbadCharacterController::SinbadCharacterController(Camera* cam){
setupBody(cam->getSceneManager());
setupCamera(cam);
setupAnimations();
}
 
void SinbadCharacterController::addTime(Real deltaTime){
updateBody(deltaTime);
updateAnimations(deltaTime);
updateCamera(deltaTime);
}
 
void SinbadCharacterController::injectKeyDown(const OIS::KeyEvent& evt) {
if (evt.key == OIS::KC_Q && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// take swords out (or put them back, since it's the same animation but reversed)
setTopAnimation(ANIM_DRAW_SWORDS, true);
mTimer = 0;
}
else if (evt.key == OIS::KC_E && !mSwordsDrawn)
{
if (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP)
{
// start dancing
setBaseAnimation(ANIM_DANCE, true);
setTopAnimation(ANIM_NONE);
// disable hand animation because the dance controls hands
mAnims[ANIM_HANDS_RELAXED]->setEnabled(false);
}
else if (mBaseAnimID == ANIM_DANCE)
{
// stop dancing
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
// re-enable hand animation
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
}
}
 
// keep track of the player's intended direction
else 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;
 
else if (evt.key == OIS::KC_SPACE && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// jump if on ground
setBaseAnimation(ANIM_JUMP_START, true);
setTopAnimation(ANIM_NONE);
mTimer = 0;
}
 
if (!mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_IDLE_BASE)
{
// start running if not already moving and the player wants to move
setBaseAnimation(ANIM_RUN_BASE, true);
if (mTopAnimID == ANIM_IDLE_TOP) setTopAnimation(ANIM_RUN_TOP, true);
}
}
 
void SinbadCharacterController::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;
 
if (mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_RUN_BASE)
{
// stop running if already moving and the player doesn't want to move
setBaseAnimation(ANIM_IDLE_BASE);
if (mTopAnimID == ANIM_RUN_TOP) setTopAnimation(ANIM_IDLE_TOP);
}
}
 
void SinbadCharacterController::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 SinbadCharacterController::injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
if (mSwordsDrawn && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// if swords are out, and character's not doing something weird, then SLICE!
if (id == OIS::MB_Left) setTopAnimation(ANIM_SLICE_VERTICAL, true);
else if (id == OIS::MB_Right) setTopAnimation(ANIM_SLICE_HORIZONTAL, true);
mTimer = 0;
}
}
void SinbadCharacterController::setupBody(SceneManager* sceneMgr)
{
// create main model
mBodyNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3::UNIT_Y * CHAR_HEIGHT);
mBodyEnt = sceneMgr->createEntity("SinbadBody", "Sinbad.mesh");
mBodyNode->attachObject(mBodyEnt);
 
// create swords and attach to sheath
mSword1 = sceneMgr->createEntity("SinbadSword1", "Sword.mesh");
mSword2 = sceneMgr->createEntity("SinbadSword2", "Sword.mesh");
mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
mBodyEnt->attachObjectToBone("Sheath.R", mSword2);
 
// create a couple of ribbon trails for the swords, just for fun
NameValuePairList params;
params["numberOfChains"] = "2";
params["maxElements"] = "80";
mSwordTrail = (RibbonTrail*)sceneMgr->createMovableObject("RibbonTrail", &params);
mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
mSwordTrail->setTrailLength(20);
mSwordTrail->setVisible(false);
sceneMgr->getRootSceneNode()->attachObject(mSwordTrail);
 
 
for (int i = 0; i < 2; i++)
{
mSwordTrail->setInitialColour(i, 1, 0.8, 0);
mSwordTrail->setColourChange(i, 0.75, 1.25, 1.25, 1.25);
mSwordTrail->setWidthChange(i, 1);
mSwordTrail->setInitialWidth(i, 0.5);
}
 
mKeyDirection = Vector3::ZERO;
mVerticalVelocity = 0;
}
 
void SinbadCharacterController::setupAnimations()
{
// this is very important due to the nature of the exported animations
mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);
 
String animNames[] =
{"IdleBase", "IdleTop", "RunBase", "RunTop", "HandsClosed", "HandsRelaxed", "DrawSwords",
"SliceVertical", "SliceHorizontal", "Dance", "JumpStart", "JumpLoop", "JumpEnd"};
 
// populate our animation list
for (int i = 0; i < NUM_ANIMS; i++)
{
mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
mAnims[i]->setLoop(true);
mFadingIn[i] = false;
mFadingOut[i] = false;
}
 
// start off in the idle state (top and bottom together)
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
 
// relax the hands since we're not holding anything
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
 
mSwordsDrawn = false;
}
 
 
void SinbadCharacterController::setupCamera(Camera* cam)
{
// create a pivot at roughly the character's shoulder
mCameraPivot = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
// this is where the camera should be soon, and it spins around the pivot
mCameraGoal = mCameraPivot->createChildSceneNode(Vector3(0, 0, 15));
// this is where the camera actually is
mCameraNode = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition());
 
mCameraPivot->setFixedYawAxis(true);
mCameraGoal->setFixedYawAxis(true);
mCameraNode->setFixedYawAxis(true);
 
// our model is quite small, so reduce the clipping planes
cam->setNearClipDistance(0.1f);
cam->setFarClipDistance(100000);
mCameraNode->attachObject(cam);
 
mPivotPitch = 0;
}
void SinbadCharacterController::updateBody(Real deltaTime)
{
mGoalDirection = Vector3::ZERO;   // we will calculate this
 
if (mKeyDirection != Vector3::ZERO && mBaseAnimID != ANIM_DANCE)
{
// 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();
 
Quaternion toGoal = mBodyNode->getOrientation().zAxis().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;
 
// 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);
mBodyNode->yaw(Degree(yawToGoal));
 
// move in current body direction (not the goal direction)
mBodyNode->translate(0, 0, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),
Node::TS_LOCAL);
}
 
if (mBaseAnimID == ANIM_JUMP_LOOP)
{
// if we're jumping, add a vertical offset too, and apply gravity
mBodyNode->translate(0, mVerticalVelocity * deltaTime, 0, Node::TS_LOCAL);
mVerticalVelocity -= GRAVITY * deltaTime;
Vector3 pos = mBodyNode->getPosition();
if (pos.y <= CHAR_HEIGHT)
{
// if we've hit the ground, change to landing state
pos.y = CHAR_HEIGHT;
mBodyNode->setPosition(pos);
setBaseAnimation(ANIM_JUMP_END, true);
mTimer = 0;
}
}
}
 
void SinbadCharacterController::updateAnimations(Real deltaTime)
{
Real baseAnimSpeed = 1;
Real topAnimSpeed = 1;
 
mTimer += deltaTime;
 
if (mTopAnimID == ANIM_DRAW_SWORDS)
{
// flip the draw swords animation if we need to put it back
topAnimSpeed = mSwordsDrawn ? -1 : 1;
 
// half-way through the animation is when the hand grasps the handles...
if (mTimer >= mAnims[mTopAnimID]->getLength() / 2 &&
mTimer - deltaTime < mAnims[mTopAnimID]->getLength() / 2)
{
// so transfer the swords from the sheaths to the hands
mBodyEnt->detachAllObjectsFromBone();
mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.L" : "Handle.L", mSword1);
mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.R" : "Handle.R", mSword2);
// change the hand state to grab or let go
mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);
 
// toggle sword trails
if (mSwordsDrawn)
{
mSwordTrail->setVisible(false);
mSwordTrail->removeNode(mSword1->getParentNode());
mSwordTrail->removeNode(mSword2->getParentNode());
}
else
{
mSwordTrail->setVisible(true);
mSwordTrail->addNode(mSword1->getParentNode());
mSwordTrail->addNode(mSword2->getParentNode());
}
}
 
if (mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
mSwordsDrawn = !mSwordsDrawn;
}
}
else if (mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
{
if (mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
}
 
// don't sway hips from side to side when slicing. that's just embarrasing.
if (mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed = 0;
}
else if (mBaseAnimID == ANIM_JUMP_START)
{
if (mTimer >= mAnims[mBaseAnimID]->getLength())
{
// takeoff animation finished, so time to leave the ground!
setBaseAnimation(ANIM_JUMP_LOOP, true);
// apply a jump acceleration to the character
mVerticalVelocity = JUMP_ACCEL;
}
}
else if (mBaseAnimID == ANIM_JUMP_END)
{
if (mTimer >= mAnims[mBaseAnimID]->getLength())
{
// safely landed, so go back to running or idling
if (mKeyDirection == Vector3::ZERO)
{
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
}
else
{
setBaseAnimation(ANIM_RUN_BASE, true);
setTopAnimation(ANIM_RUN_TOP, true);
}
}
}
 
// increment the current base and top animation times
if (mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
if (mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);
 
// apply smooth transitioning between our animations
fadeAnimations(deltaTime);
}
 
void SinbadCharacterController::fadeAnimations(Real deltaTime)
{
for (int i = 0; i < NUM_ANIMS; i++)
{
if (mFadingIn[i])
{
// slowly fade this animation in until it has full weight
Real newWeight = mAnims[i]->getWeight() + deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
if (newWeight >= 1) mFadingIn[i] = false;
}
else if (mFadingOut[i])
{
// slowly fade this animation out until it has no weight, and then disable it
Real newWeight = mAnims[i]->getWeight() - deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
if (newWeight <= 0)
{
mAnims[i]->setEnabled(false);
mFadingOut[i] = false;
}
}
}
}
 
void SinbadCharacterController::updateCamera(Real deltaTime)
{
// place the camera pivot roughly at the character's shoulder
mCameraPivot->setPosition(mBodyNode->getPosition() + Vector3::UNIT_Y * CAM_HEIGHT);
// move the camera smoothly to the goal
Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();
mCameraNode->translate(goalOffset * deltaTime * 9.0f);
// always look at the pivot
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Node::TS_WORLD);
}
 
void SinbadCharacterController::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(0, 0, distChange, Node::TS_LOCAL);
}
}
 
void SinbadCharacterController::setBaseAnimation(AnimID id, bool reset)
{
if (mBaseAnimID >= 0 && mBaseAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mBaseAnimID] = false;
mFadingOut[mBaseAnimID] = true;
}
 
mBaseAnimID = id;
 
if (id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id] = false;
mFadingIn[id] = true;
if (reset) mAnims[id]->setTimePosition(0);
}
}
void SinbadCharacterController::setTopAnimation(AnimID id, bool reset)
{
if (mTopAnimID >= 0 && mTopAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mTopAnimID] = false;
mFadingOut[mTopAnimID] = true;
}
 
mTopAnimID = id;
 
if (id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id] = false;
mFadingIn[id] = true;
if (reset) mAnims[id]->setTimePosition(0);
}
}

上面两个文件主要负责sinbad这个角色的创建

SinbadState.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//|||||||||||||||||||||||||||||||||||||||||||||||
#ifndef SINBAD_STATE_HPP
#define SINBAD_STATE_HPP
//|||||||||||||||||||||||||||||||||||||||||||||||
#include "AppState.hpp"
#include "SinbadCharacterController.hpp"
#include "DotSceneLoader.hpp"
#include "SdkCameraMan.h"
#include <OgreSubEntity.h>
#include <OgreMaterialManager.h>
//|||||||||||||||||||||||||||||||||||||||||||||||
  
//|||||||||||||||||||||||||||||||||||||||||||||||
class SinbadState : public AppState
{
public:
SinbadState();
DECLARE_APPSTATE_CLASS(SinbadState)
void enter();
void createScene();
void exit();
bool pause();
void resume();
void buildGUI();
bool keyPressed(const OIS::KeyEvent &keyEventRef);
bool keyReleased(const OIS::KeyEvent &keyEventRef);
bool mouseMoved(const OIS::MouseEvent &arg);
bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
void itemSelected(OgreBites::SelectMenu* menu);
void update(double timeSinceLastFrame);
private:
OgreBites::ParamsPanel* m_pDetailsPanel;   // sample details panel
bool m_bQuit;
bool m_pCursorWasVisible; // was cursor visible before dialog appeared
bool m_pDragLook;              // click and drag to free-look
OgreBites::SdkCameraMan* m_pCameraMan;
SinbadCharacterController* m_pChara;
Ogre::NameValuePairList mInfo;    // custom sample info
};
//|||||||||||||||||||||||||||||||||||||||||||||||
#endif
//|||||||||||||||||||||||||||||||||||||||||||||||

SinbadState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//|||||||||||||||||||||||||||||||||||||||||||||||
#include "SinbadState.hpp"
//|||||||||||||||||||||||||||||||||||||||||||||||
using namespace Ogre;
//|||||||||||||||||||||||||||||||||||||||||||||||
SinbadState::SinbadState()
{
mInfo["Title"] = "Untitled";
mInfo["Description"] = "";
mInfo["Category"] = "Unsorted";
mInfo["Thumbnail"] = "";
mInfo["Help"] = "";
    m_bQuit             = false;
    m_pDetailsPanel = 0;
m_pCamera = 0;
m_pCameraMan = 0;
m_pChara = 0;
}
//|||||||||||||||||||||||||||||||||||||||||||||||
void SinbadState::enter()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering SinbadState...");
    m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "GameSceneMgr");
 
    m_pCamera = m_pSceneMgr->createCamera("MainCamera");
OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
m_pCamera->setAspectRatio((Ogre::Real)OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth() / (Ogre::Real)OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight());
m_pCamera->setNearClipDistance(5);
 
m_pCameraMan = new OgreBites::SdkCameraMan(m_pCamera);
 
    buildGUI();
    createScene();
}
 
void SinbadState::createScene()
{
// set background and some fog
//OgreFramework::getSingletonPtr()->m_pViewport->setBackgroundColour(ColourValue(1.0f, 1.0f, 0.8f));
//m_pSceneMgr->setFog(Ogre::FOG_LINEAR, ColourValue(1.0f, 1.0f, 0.8f), 0, 15, 100);
 
// set shadow properties
m_pSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
m_pSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
m_pSceneMgr->setShadowTextureSize(1024);
m_pSceneMgr->setShadowTextureCount(1);
 
// disable default camera control so the character can do its own
m_pCameraMan->setStyle(OgreBites::CS_MANUAL);
 
// use a small amount of ambient lighting
m_pSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6));
 
//set sky
m_pSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
 
// add a bright light above the scene
Light* light = m_pSceneMgr->createLight();
light->setType(Light::LT_POINT);
light->setPosition(-10, 40, 20);
light->setSpecularColour(ColourValue::White);
 
// create a floor mesh resource
MeshManager::getSingleton().createPlane("floor", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Plane(Vector3::UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Vector3::UNIT_Z);
 
// create a floor entity, give it a material, and place it at the origin
    Entity* floor = m_pSceneMgr->createEntity("Floor", "floor");
    floor->setMaterialName("Examples/Rockwall");
floor->setCastShadows(false);
    m_pSceneMgr->getRootSceneNode()->attachObject(floor);
 
//load scene
DotSceneLoader* pDotSceneLoader = new DotSceneLoader();
    pDotSceneLoader->parseDotScene("CubeScene.xml", "General", m_pSceneMgr, m_pSceneMgr->getRootSceneNode());
delete pDotSceneLoader;
 
m_pCamera->setNearClipDistance(0.1);
m_pCamera->setFarClipDistance(100000);//设置大些,否则看不到天空
// create our character controller
m_pChara = new SinbadCharacterController(m_pCamera);
 
OgreFramework::getSingletonPtr()->m_pTrayMgr->toggleAdvancedFrameStats();
 
StringVector items;
items.push_back("Help");
OgreBites::ParamsPanel* help = OgreFramework::getSingletonPtr()->m_pTrayMgr->createParamsPanel(OgreBites::TL_TOPLEFT, "HelpMessage", 100, items);
help->setParamValue("Help", "H / F1");
}
 
 
bool SinbadState::pause()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Pausing SinbadState...");
    return true;
}
//|||||||||||||||||||||||||||||||||||||||||||||||
void SinbadState::resume()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Resuming SinbadState...");
    buildGUI();
    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
    m_bQuit = false;
}
 
void SinbadState::exit()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving SinbadState...");
    m_pSceneMgr->destroyCamera(m_pCamera);
if (m_pCameraMan) delete m_pCameraMan;
    if(m_pSceneMgr)
        OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
}
 
 
bool SinbadState::keyPressed(const OIS::KeyEvent &evt)
{
if (!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible()) m_pChara->injectKeyDown(evt);
if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
    {
        pushAppState(findByName("PauseState"));
        return true;
    }
 
if (evt.key == OIS::KC_H || evt.key == OIS::KC_F1)   // toggle visibility of help dialog
{
if (!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible() && mInfo["Help"] != "") OgreFramework::getSingletonPtr()->m_pTrayMgr->showOkDialog("Help", mInfo["Help"]);
else OgreFramework::getSingletonPtr()->m_pTrayMgr->closeDialog();
}
 
if (OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible()) return true;   // don't process any more keys if dialog is up
 
if (evt.key == OIS::KC_F)   // toggle visibility of advanced frame stats
{
OgreFramework::getSingletonPtr()->m_pTrayMgr->toggleAdvancedFrameStats();
}
else if (evt.key == OIS::KC_G)   // toggle visibility of even rarer debugging details
{
if (m_pDetailsPanel->getTrayLocation() == OgreBites::TL_NONE)
{
OgreFramework::getSingletonPtr()->m_pTrayMgr->moveWidgetToTray(m_pDetailsPanel, OgreBites::TL_TOPRIGHT, 0);
m_pDetailsPanel->show();
}
else
{
OgreFramework::getSingletonPtr()->m_pTrayMgr->removeWidgetFromTray(m_pDetailsPanel);
m_pDetailsPanel->hide();
}
}
else if (evt.key == OIS::KC_T)   // cycle polygon rendering mode
{
Ogre::String newVal;
Ogre::TextureFilterOptions tfo;
unsigned int aniso;
 
switch (m_pDetailsPanel->getParamValue(9).asUTF8()[0])
{
case 'B':
newVal = "Trilinear";
tfo = Ogre::TFO_TRILINEAR;
aniso = 1;
break;
case 'T':
newVal = "Anisotropic";
tfo = Ogre::TFO_ANISOTROPIC;
aniso = 8;
break;
case 'A':
newVal = "None";
tfo = Ogre::TFO_NONE;
aniso = 1;
break;
default:
newVal = "Bilinear";
tfo = Ogre::TFO_BILINEAR;
aniso = 1;
}
 
Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(aniso);
m_pDetailsPanel->setParamValue(9, newVal);
}
else if (evt.key == OIS::KC_R)   // cycle polygon rendering mode
{
Ogre::String newVal;
Ogre::PolygonMode pm;
 
switch (m_pCamera->getPolygonMode())
{
case Ogre::PM_SOLID:
newVal = "Wireframe";
pm = Ogre::PM_WIREFRAME;
break;
case Ogre::PM_WIREFRAME:
newVal = "Points";
pm = Ogre::PM_POINTS;
break;
default:
newVal = "Solid";
pm = Ogre::PM_SOLID;
}
 
m_pCamera->setPolygonMode(pm);
m_pDetailsPanel->setParamValue(10, newVal);
}
else if(evt.key == OIS::KC_F5)   // refresh all textures
{
Ogre::TextureManager::getSingleton().reloadAll();
}
else if (evt.key == OIS::KC_SYSRQ)   // take a screenshot
{
OgreFramework::getSingletonPtr()->m_pRenderWnd->writeContentsToTimestampedFile("screenshot", ".png");
}
 
m_pCameraMan->injectKeyDown(evt);
return true;
}
//|||||||||||||||||||||||||||||||||||||||||||||||
bool SinbadState::keyReleased(const OIS::KeyEvent &keyEventRef)
{
m_pChara->injectKeyUp(keyEventRef);
m_pCameraMan->injectKeyUp(keyEventRef);
    OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
    return true;
}
 
bool SinbadState::mouseMoved(const OIS::MouseEvent &evt)
{
if (!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible()) m_pChara->injectMouseMove(evt);
if (OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseMove(evt)) return true;
m_pCameraMan->injectMouseMove(evt);
  
    return true;
}
//|||||||||||||||||||||||||||||||||||||||||||||||
bool SinbadState::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
// relay input events to character controller
if (!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible()) m_pChara->injectMouseDown(evt, id);
if (OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseDown(evt, id)) return true;
            
if (m_pDragLook && id == OIS::MB_Left)
{
m_pCameraMan->setStyle(OgreBites::CS_MANUAL);
OgreFramework::getSingletonPtr()->m_pTrayMgr->hideCursor();
}
 
m_pCameraMan->injectMouseDown(evt, id);
    return true;
}
//|||||||||||||||||||||||||||||||||||||||||||||||
bool SinbadState::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if (OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseUp(evt, id)) return true;
            
if (m_pDragLook && id == OIS::MB_Left)
{
m_pCameraMan->setStyle(OgreBites::CS_MANUAL);
OgreFramework::getSingletonPtr()->m_pTrayMgr->showCursor();
}
 
m_pCameraMan->injectMouseUp(evt, id);
 
return true;
}
 
 
void SinbadState::update(double timeSinceLastFrame)
{
    m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;
 
m_pChara->addTime(timeSinceLastFrame/1000);
 
    OgreFramework::getSingletonPtr()->m_pTrayMgr->frameRenderingQueued(m_FrameEvent);
 
    if(m_bQuit == true)
    {
        popAppState();
        return;
    }
if (!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible())
{
m_pCameraMan->frameRenderingQueued(m_FrameEvent);   // if dialog isn't up, then update the camera
 
if (m_pDetailsPanel->isVisible())   // if details panel is visible, then update its contents
{
m_pDetailsPanel->setParamValue(0, Ogre::StringConverter::toString(m_pCamera->getDerivedPosition().x));
m_pDetailsPanel->setParamValue(1, Ogre::StringConverter::toString(m_pCamera->getDerivedPosition().y));
m_pDetailsPanel->setParamValue(2, Ogre::StringConverter::toString(m_pCamera->getDerivedPosition().z));
m_pDetailsPanel->setParamValue(4, Ogre::StringConverter::toString(m_pCamera->getDerivedOrientation().w));
m_pDetailsPanel->setParamValue(5, Ogre::StringConverter::toString(m_pCamera->getDerivedOrientation().x));
m_pDetailsPanel->setParamValue(6, Ogre::StringConverter::toString(m_pCamera->getDerivedOrientation().y));
m_pDetailsPanel->setParamValue(7, Ogre::StringConverter::toString(m_pCamera->getDerivedOrientation().z));
}
}
 
    //getInput();
    //moveCamera();
}
 
void SinbadState::buildGUI()
{
// show stats and logo and hide the cursor
OgreFramework::getSingletonPtr()->m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
OgreFramework::getSingletonPtr()->m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
OgreFramework::getSingletonPtr()->m_pTrayMgr->createLabel(OgreBites::TL_TOP, "GameLbl", "Game mode", 250);
OgreFramework::getSingletonPtr()->m_pTrayMgr->hideCursor();
 
 
    // create a params panel for displaying sample details
Ogre::StringVector items;
items.push_back("cam.pX");
items.push_back("cam.pY");
items.push_back("cam.pZ");
items.push_back("");
items.push_back("cam.oW");
items.push_back("cam.oX");
items.push_back("cam.oY");
items.push_back("cam.oZ");
items.push_back("");
items.push_back("Filtering");
items.push_back("Poly Mode");
m_pDetailsPanel = OgreFramework::getSingletonPtr()->m_pTrayMgr->createParamsPanel(OgreBites::TL_NONE, "DetailsPanel", 200, items);
m_pDetailsPanel->hide();
 
m_pDetailsPanel->setParamValue(9, "Bilinear");
m_pDetailsPanel->setParamValue(10, "Solid");
 
}
 
void SinbadState::itemSelected(OgreBites::SelectMenu* menu)
{
    switch(menu->getSelectionIndex())
    {
    case 0:
        m_pCamera->setPolygonMode(Ogre::PM_SOLID);break;
    case 1:
        m_pCamera->setPolygonMode(Ogre::PM_WIREFRAME);break;
    case 2:
        m_pCamera->setPolygonMode(Ogre::PM_POINTS);break;
    }
}

上面两个文件创建了一个state,除了加入的这是个文件以外,还需要在MenuState.cpp,PauseState.cpp中各创建一个按钮,Demo.cpp中加入一个状态,具体的可以看下我分享的代码,代码下载地址:
[Downlink href="http://jchblog.u.qiniudn.com/201404/AdvancedOgreFramework-test.zip"]加入了可控制sinbad的Advanced Ogre Framework[/Downlink]

程序运行部分截图:
菜单界面
菜单界面

sinbadstate
Sinbadstate界面

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
标签: OGRE
最后更新:2022年3月27日

Jeff

管理员——代码为剑,如痴如醉

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • ohyes

    你的ogre SDK是什么版本。我用的1.9 可以生成exe执行文件,但是运行的时候报错Assertion failed!Program: ...REOgreSDK_vc11_v1-9-0bindebugOgreOverlay_d.dllFile: ..........ComponentsOverlaysrcOgre...Manager.cppLine: 52Expression: msSingletonFor information on how your program can cause an assertionfailure, see the Visual C++ documentation on asserts(Press Retry to debug the application - JIT must be enabled)线程 0x33f0 已退出,返回值为 3 (0x3)。我怀疑 是不是缺了个Overlay System的初始化。 怎么初始化Overlay System

    2015年1月5日
    回复
    • lily6

      @ohyes 我用网上下载的OgreSDK_vc10_v1-8-1的sdk文件配置后立刻运行成功了,ogre SDK1.9前几天试了一开始有些错误,目前运行还有些问题,可以加我qq交流:1665421845。

      2015年2月6日
      回复
    • Jianchihu

      @ohyes 很抱歉,好久没有登陆博客了,OGRE我已经好久没接触了,那时是毕业设计用到,我记得那时用的是SDK 1.8版本

      2015年3月3日
      回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    取消回复

    这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

    相关文章
    • Ogre中阴影设置问题
    • Ogre中的场景文件
    • Ogre中加入声音
    • Ogre中的粒子系统(Particle System)
    • Ogre中简单的AABB碰撞检测

    COPYRIGHT © 2025 jianchihu.net. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang