aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ClientHamr/extantz/extantzCamera.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-23 04:39:12 +1000
committerDavid Walter Seikel2013-01-23 04:39:12 +1000
commite21ef5cff24774ca85f4ab3adc27131e569be74e (patch)
tree35d6670f4c0b90dbe21dafeaed2d04827a1c97e6 /ClientHamr/extantz/extantzCamera.cpp
parentStabilise the GL image with respect to window resizes. Still needs some clea... (diff)
downloadSledjHamr-e21ef5cff24774ca85f4ab3adc27131e569be74e.zip
SledjHamr-e21ef5cff24774ca85f4ab3adc27131e569be74e.tar.gz
SledjHamr-e21ef5cff24774ca85f4ab3adc27131e569be74e.tar.bz2
SledjHamr-e21ef5cff24774ca85f4ab3adc27131e569be74e.tar.xz
Clone CSceneNodeAnimatorCameraFPS so I can start to morph it into a real camera.
Diffstat (limited to '')
-rw-r--r--ClientHamr/extantz/extantzCamera.cpp378
1 files changed, 378 insertions, 0 deletions
diff --git a/ClientHamr/extantz/extantzCamera.cpp b/ClientHamr/extantz/extantzCamera.cpp
new file mode 100644
index 0000000..3c0ff7a
--- /dev/null
+++ b/ClientHamr/extantz/extantzCamera.cpp
@@ -0,0 +1,378 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5// The above is the copyright notice for CSceneNodeAnimatorCameraFPS.cpp,
6// According to the Irrlicht docs, that's just a demo and you are supposed to use it as an example for writing your own FPS style camera.
7// I'll be writing my own camera code, that includes first person, third person, and free camera styles.
8// I'll start with CSceneNodeAnimatorCameraFPS.cpp and morph it until it suits me.
9// As such, I expect lots of Nikolaus Gebhardt's code to go away.
10// To be replaced by my code, which will be copyright and licensed under the same license as the rest of extantz.
11
12#include "extantzCamera.h"
13#include "IVideoDriver.h"
14#include "ISceneManager.h"
15#include "Keycodes.h"
16#include "ICursorControl.h"
17#include "ICameraSceneNode.h"
18#include "ISceneNodeAnimatorCollisionResponse.h"
19
20namespace irr
21{
22namespace scene
23{
24
25// Irrlicht hard codes a reference to the original FPS camera code inside it's scene manager. This is that code extracted so we can be more flexible.
26// Hmmm, Where's CursorControl come from? Ah, passed to the scene manager constructor, it's a GUI thing that we need to replace with an EFL thing.
27ICameraSceneNode *addExtantzCamera(ISceneManager* sm, ISceneNode* parent, f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, bool invertMouseY, bool makeActive)
28{
29 ICameraSceneNode* node = sm->addCameraSceneNode(parent, core::vector3df(), core::vector3df(0, 0, 100), id, makeActive);
30 if (node)
31 {
32// ISceneNodeAnimator* anm = new extantzCamera(CursorControl, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement, invertMouseY);
33 ISceneNodeAnimator* anm = new extantzCamera(NULL, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement, invertMouseY);
34
35 // Bind the node's rotation to its target. This is consistent with 1.4.2 and below.
36 node->bindTargetAndRotation(true);
37 node->addAnimator(anm);
38 anm->drop();
39 }
40
41 return node;
42}
43
44
45//! constructor
46extantzCamera::extantzCamera(gui::ICursorControl* cursorControl, f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY)
47 : CursorControl(cursorControl), MaxVerticalAngle(88.0f), MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed),
48 MouseYDirection(invertY ? -1.0f : 1.0f), LastAnimationTime(0), firstUpdate(true), firstInput(true), NoVerticalMovement(noVerticalMovement)
49{
50 #ifdef _DEBUG
51 setDebugName("extantzCamera");
52 #endif
53
54// if (CursorControl)
55// CursorControl->grab();
56
57 allKeysUp();
58
59 // create key map
60 if (!keyMapArray || !keyMapSize)
61 {
62 // create default key map
63 KeyMap.push_back(SKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP));
64 KeyMap.push_back(SKeyMap(EKA_MOVE_BACKWARD, irr::KEY_DOWN));
65 KeyMap.push_back(SKeyMap(EKA_STRAFE_LEFT, irr::KEY_LEFT));
66 KeyMap.push_back(SKeyMap(EKA_STRAFE_RIGHT, irr::KEY_RIGHT));
67 KeyMap.push_back(SKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J));
68 }
69 else
70 {
71 // create custom key map
72 setKeyMap(keyMapArray, keyMapSize);
73 }
74}
75
76
77//! destructor
78extantzCamera::~extantzCamera()
79{
80// if (CursorControl)
81// CursorControl->drop();
82}
83
84
85//! It is possible to send mouse and key events to the camera. Most cameras
86//! may ignore this input, but camera scene nodes which are created for
87//! example with scene::ISceneManager::addMayaCameraSceneNode or
88//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
89//! for changing their position, look at target or whatever.
90bool extantzCamera::OnEvent(const SEvent& evt)
91{
92 switch(evt.EventType)
93 {
94 case EET_KEY_INPUT_EVENT:
95 for (u32 i=0; i<KeyMap.size(); ++i)
96 {
97 if (KeyMap[i].KeyCode == evt.KeyInput.Key)
98 {
99 CursorKeys[KeyMap[i].Action] = evt.KeyInput.PressedDown;
100 return true;
101 }
102 }
103 break;
104
105 case EET_MOUSE_INPUT_EVENT:
106 if (evt.MouseInput.Event == EMIE_MOUSE_MOVED)
107 {
108// CursorPos = CursorControl->getRelativePosition();
109 return true;
110 }
111 break;
112
113 default:
114 break;
115 }
116
117 return false;
118}
119
120
121void extantzCamera::animateNode(ISceneNode* node, u32 timeMs)
122{
123 if (!node || node->getType() != ESNT_CAMERA)
124 return;
125
126 ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
127
128 if (firstUpdate)
129 {
130 camera->updateAbsolutePosition();
131// if (CursorControl )
132// {
133// CursorControl->setPosition(0.5f, 0.5f);
134// CursorPos = CenterCursor = CursorControl->getRelativePosition();
135// }
136
137 LastAnimationTime = timeMs;
138
139 firstUpdate = false;
140 }
141
142 // If the camera isn't the active camera, and receiving input, then don't process it.
143 if(!camera->isInputReceiverEnabled())
144 {
145 firstInput = true;
146 return;
147 }
148
149 if ( firstInput )
150 {
151 allKeysUp();
152 firstInput = false;
153 }
154
155 scene::ISceneManager * smgr = camera->getSceneManager();
156 if(smgr && smgr->getActiveCamera() != camera)
157 return;
158
159 // get time
160 f32 timeDiff = (f32) ( timeMs - LastAnimationTime );
161 LastAnimationTime = timeMs;
162
163 // update position
164 core::vector3df pos = camera->getPosition();
165
166 // Update rotation
167 core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition());
168 core::vector3df relativeRotation = target.getHorizontalAngle();
169
170#if 0
171 if (CursorControl)
172 {
173 if (CursorPos != CenterCursor)
174 {
175 relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed;
176 relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed * MouseYDirection;
177
178 // X < MaxVerticalAngle or X > 360-MaxVerticalAngle
179
180 if (relativeRotation.X > MaxVerticalAngle*2 &&
181 relativeRotation.X < 360.0f-MaxVerticalAngle)
182 {
183 relativeRotation.X = 360.0f-MaxVerticalAngle;
184 }
185 else
186 if (relativeRotation.X > MaxVerticalAngle &&
187 relativeRotation.X < 360.0f-MaxVerticalAngle)
188 {
189 relativeRotation.X = MaxVerticalAngle;
190 }
191
192 // Do the fix as normal, special case below
193 // reset cursor position to the centre of the window.
194 CursorControl->setPosition(0.5f, 0.5f);
195 CenterCursor = CursorControl->getRelativePosition();
196
197 // needed to avoid problems when the event receiver is disabled
198 CursorPos = CenterCursor;
199 }
200
201 // Special case, mouse is whipped outside of window before it can update.
202 video::IVideoDriver* driver = smgr->getVideoDriver();
203 core::vector2d<u32> mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y));
204 core::rect<u32> screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height);
205
206 // Only if we are moving outside quickly.
207 bool reset = !screenRect.isPointInside(mousepos);
208
209 if(reset)
210 {
211 // Force a reset.
212 CursorControl->setPosition(0.5f, 0.5f);
213 CenterCursor = CursorControl->getRelativePosition();
214 CursorPos = CenterCursor;
215 }
216 }
217#endif
218
219 // set target
220
221 target.set(0,0, core::max_(1.f, pos.getLength()));
222 core::vector3df movedir = target;
223
224 core::matrix4 mat;
225 mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0));
226 mat.transformVect(target);
227
228 if (NoVerticalMovement)
229 {
230 mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0));
231 mat.transformVect(movedir);
232 }
233 else
234 {
235 movedir = target;
236 }
237
238 movedir.normalize();
239
240 if (CursorKeys[EKA_MOVE_FORWARD])
241 pos += movedir * timeDiff * MoveSpeed;
242
243 if (CursorKeys[EKA_MOVE_BACKWARD])
244 pos -= movedir * timeDiff * MoveSpeed;
245
246 // strafing
247
248 core::vector3df strafevect = target;
249 strafevect = strafevect.crossProduct(camera->getUpVector());
250
251 if (NoVerticalMovement)
252 strafevect.Y = 0.0f;
253
254 strafevect.normalize();
255
256 if (CursorKeys[EKA_STRAFE_LEFT])
257 pos += strafevect * timeDiff * MoveSpeed;
258
259 if (CursorKeys[EKA_STRAFE_RIGHT])
260 pos -= strafevect * timeDiff * MoveSpeed;
261
262 // For jumping, we find the collision response animator attached to our camera
263 // and if it's not falling, we tell it to jump.
264 if (CursorKeys[EKA_JUMP_UP])
265 {
266 const ISceneNodeAnimatorList& animators = camera->getAnimators();
267 ISceneNodeAnimatorList::ConstIterator it = animators.begin();
268 while(it != animators.end())
269 {
270 if(ESNAT_COLLISION_RESPONSE == (*it)->getType())
271 {
272 ISceneNodeAnimatorCollisionResponse * collisionResponse =
273 static_cast<ISceneNodeAnimatorCollisionResponse *>(*it);
274
275 if(!collisionResponse->isFalling())
276 collisionResponse->jump(JumpSpeed);
277 }
278
279 it++;
280 }
281 }
282
283 // write translation
284 camera->setPosition(pos);
285
286 // write right target
287 target += pos;
288 camera->setTarget(target);
289}
290
291
292void extantzCamera::allKeysUp()
293{
294 for (u32 i=0; i<EKA_COUNT; ++i)
295 CursorKeys[i] = false;
296}
297
298
299//! Sets the rotation speed
300void extantzCamera::setRotateSpeed(f32 speed)
301{
302 RotateSpeed = speed;
303}
304
305
306//! Sets the movement speed
307void extantzCamera::setMoveSpeed(f32 speed)
308{
309 MoveSpeed = speed;
310}
311
312
313//! Gets the rotation speed
314f32 extantzCamera::getRotateSpeed() const
315{
316 return RotateSpeed;
317}
318
319
320// Gets the movement speed
321f32 extantzCamera::getMoveSpeed() const
322{
323 return MoveSpeed;
324}
325
326
327//! Sets the keyboard mapping for this animator
328void extantzCamera::setKeyMap(SKeyMap *map, u32 count)
329{
330 // clear the keymap
331 KeyMap.clear();
332
333 // add actions
334 for (u32 i=0; i<count; ++i)
335 {
336 KeyMap.push_back(map[i]);
337 }
338}
339
340void extantzCamera::setKeyMap(const core::array<SKeyMap>& keymap)
341{
342 KeyMap=keymap;
343}
344
345const core::array<SKeyMap>& extantzCamera::getKeyMap() const
346{
347 return KeyMap;
348}
349
350
351//! Sets whether vertical movement should be allowed.
352void extantzCamera::setVerticalMovement(bool allow)
353{
354 NoVerticalMovement = !allow;
355}
356
357
358//! Sets whether the Y axis of the mouse should be inverted.
359void extantzCamera::setInvertMouse(bool invert)
360{
361 if (invert)
362 MouseYDirection = -1.0f;
363 else
364 MouseYDirection = 1.0f;
365}
366
367
368ISceneNodeAnimator* extantzCamera::createClone(ISceneNode* node, ISceneManager* newManager)
369{
370 extantzCamera *newAnimator = new extantzCamera(CursorControl, RotateSpeed, MoveSpeed, JumpSpeed, 0, 0, NoVerticalMovement);
371 newAnimator->setKeyMap(KeyMap);
372 return newAnimator;
373}
374
375
376} // namespace scene
377} // namespace irr
378