aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/extantz/extantzCamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/extantz/extantzCamera.cpp')
-rw-r--r--src/extantz/extantzCamera.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/src/extantz/extantzCamera.cpp b/src/extantz/extantzCamera.cpp
new file mode 100644
index 0000000..6a7d36a
--- /dev/null
+++ b/src/extantz/extantzCamera.cpp
@@ -0,0 +1,282 @@
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// Initally I'll make it SecondLife like, coz that's what my muscle memory is used to.
13// It will get extended and made generic though.
14
15#include "extantzCamera.h"
16#include "IVideoDriver.h"
17#include "ISceneManager.h"
18#include "Keycodes.h"
19#include "ICursorControl.h"
20#include "ICameraSceneNode.h"
21#include "ISceneNodeAnimatorCollisionResponse.h"
22
23namespace irr
24{
25namespace scene
26{
27
28// 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.
29// TODO - 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. But only for mouselook mode.
30ICameraSceneNode *addExtantzCamera(ISceneManager* sm, ISceneNode* parent, s32 id)
31{
32 ICameraSceneNode* node = sm->addCameraSceneNode(parent, core::vector3df(), core::vector3df(0, 0, 100), id, true);
33 if (node)
34 {
35// ISceneNodeAnimator* anm = new extantzCamera(CursorControl);
36 ISceneNodeAnimator* anm = new extantzCamera();
37
38 // Bind the node's rotation to its target. This is consistent with 1.4.2 and below.
39 node->bindTargetAndRotation(true);
40 node->addAnimator(anm);
41 anm->drop();
42 }
43
44 return node;
45}
46
47
48//! constructor
49//extantzCamera::extantzCamera(gui::ICursorControl* cursorControl)
50// : CursorControl(cursorControl), MaxVerticalAngle(88.0f), MoveSpeed(0.4f), RotateSpeed(100.0f), JumpSpeed(3.0f),
51extantzCamera::extantzCamera()
52 : MaxVerticalAngle(88.0f), MouseYDirection(1.0f), LastAnimationTime(0), NoVerticalMovement(false)
53{
54 #ifdef _DEBUG
55 setDebugName("extantzCamera");
56 #endif
57
58 move.jump = 0.0; // Coz otherwise we start in jumping mode.
59 move.MoveSpeed = 0.1f;
60 move.RotateSpeed = 1.0f;
61 move.JumpSpeed = 3.0f;
62
63// if (CursorControl)
64// CursorControl->grab();
65}
66
67
68//! destructor
69extantzCamera::~extantzCamera()
70{
71// if (CursorControl)
72// CursorControl->drop();
73}
74
75
76void extantzCamera::animateNode(ISceneNode* node, u32 timeMs)
77{
78 if (!node || node->getType() != ESNT_CAMERA)
79 return;
80
81 ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
82
83 if (0 == LastAnimationTime)
84 {
85 camera->updateAbsolutePosition();
86// if (CursorControl )
87// {
88// CursorControl->setPosition(0.5f, 0.5f);
89// CursorPos = CenterCursor = CursorControl->getRelativePosition();
90// }
91
92 LastAnimationTime = timeMs;
93 }
94
95 // If the camera isn't the active camera, and receiving input, then don't process it.
96 // TODO - it never is, coz we are bypassing that, but can we replace this with something else?
97 if(!camera->isInputReceiverEnabled())
98 {
99// return;
100 }
101
102 scene::ISceneManager * smgr = camera->getSceneManager();
103 if(smgr && smgr->getActiveCamera() != camera)
104 return;
105
106 // get time
107 f32 timeDiff = (f32) (timeMs - LastAnimationTime);
108 LastAnimationTime = timeMs;
109
110 // update position
111 core::vector3df pos = camera->getPosition();
112
113 // Update rotation
114 core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition());
115 core::vector3df relativeRotation = target.getHorizontalAngle();
116
117#if 0
118 if (CursorControl)
119 {
120 if (CursorPos != CenterCursor)
121 {
122 relativeRotation.Y -= (0.5f - CursorPos.X) * move.RotateSpeed;
123 relativeRotation.X -= (0.5f - CursorPos.Y) * move.RotateSpeed * MouseYDirection;
124
125 // X < MaxVerticalAngle or X > 360-MaxVerticalAngle
126
127 if (relativeRotation.X > MaxVerticalAngle*2 &&
128 relativeRotation.X < 360.0f-MaxVerticalAngle)
129 {
130 relativeRotation.X = 360.0f-MaxVerticalAngle;
131 }
132 else
133 if (relativeRotation.X > MaxVerticalAngle &&
134 relativeRotation.X < 360.0f-MaxVerticalAngle)
135 {
136 relativeRotation.X = MaxVerticalAngle;
137 }
138
139 // Do the fix as normal, special case below
140 // reset cursor position to the centre of the window.
141 CursorControl->setPosition(0.5f, 0.5f);
142 CenterCursor = CursorControl->getRelativePosition();
143
144 // needed to avoid problems when the event receiver is disabled
145 CursorPos = CenterCursor;
146 }
147
148 // Special case, mouse is whipped outside of window before it can update.
149 video::IVideoDriver* driver = smgr->getVideoDriver();
150 core::vector2d<u32> mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y));
151 core::rect<u32> screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height);
152
153 // Only if we are moving outside quickly.
154 bool reset = !screenRect.isPointInside(mousepos);
155
156 if(reset)
157 {
158 // Force a reset.
159 CursorControl->setPosition(0.5f, 0.5f);
160 CenterCursor = CursorControl->getRelativePosition();
161 CursorPos = CenterCursor;
162 }
163 }
164#else
165 relativeRotation.Y -= move.r * move.RotateSpeed;
166 relativeRotation.X -= move.s * move.RotateSpeed * MouseYDirection;
167
168 // X < MaxVerticalAngle or X > 360-MaxVerticalAngle
169
170 if ((relativeRotation.X > (MaxVerticalAngle * 2)) && (relativeRotation.X < (360.0f - MaxVerticalAngle)))
171 relativeRotation.X = 360.0f - MaxVerticalAngle;
172 else if ((relativeRotation.X > MaxVerticalAngle) && (relativeRotation.X < (360.0f - MaxVerticalAngle)))
173 relativeRotation.X = MaxVerticalAngle;
174#endif
175
176 // set target
177
178 target.set(0,0, core::max_(1.f, pos.getLength()));
179 core::vector3df movedir = target;
180
181 core::matrix4 mat;
182 mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0));
183 mat.transformVect(target);
184
185 if (NoVerticalMovement)
186 {
187 mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0));
188 mat.transformVect(movedir);
189 }
190 else
191 {
192 movedir = target;
193 }
194
195 movedir.normalize();
196
197 pos += movedir * timeDiff * move.MoveSpeed * move.x;
198
199 // strafing
200 core::vector3df strafevect = target;
201 strafevect = strafevect.crossProduct(camera->getUpVector());
202
203 if (NoVerticalMovement)
204 strafevect.Y = 0.0f;
205
206 strafevect.normalize();
207
208 pos += strafevect * timeDiff * move.MoveSpeed * move.y;
209
210 // For jumping, we find the collision response animator attached to our camera
211 // and if it's not falling, we tell it to jump.
212 if (0.0 < move.jump)
213 {
214 const ISceneNodeAnimatorList& animators = camera->getAnimators();
215 ISceneNodeAnimatorList::ConstIterator it = animators.begin();
216 while(it != animators.end())
217 {
218 if(ESNAT_COLLISION_RESPONSE == (*it)->getType())
219 {
220 ISceneNodeAnimatorCollisionResponse * collisionResponse =
221 static_cast<ISceneNodeAnimatorCollisionResponse *>(*it);
222
223 if(!collisionResponse->isFalling())
224 collisionResponse->jump(move.JumpSpeed);
225 }
226
227 it++;
228 }
229 }
230
231 // write translation
232 camera->setPosition(pos);
233
234 // write right target
235 target += pos;
236 camera->setTarget(target);
237}
238
239
240ISceneNodeAnimator* extantzCamera::createClone(ISceneNode* node, ISceneManager* newManager)
241{
242// extantzCamera *newAnimator = new extantzCamera(CursorControl);
243 extantzCamera *newAnimator = new extantzCamera();
244 return newAnimator;
245}
246
247#ifdef __cplusplus
248extern "C" {
249#endif
250
251cameraMove *getCameraMove(ICameraSceneNode *camera)
252{
253 cameraMove *cm = NULL;
254
255 if (camera)
256 {
257 const ISceneNodeAnimatorList &animators = camera->getAnimators();
258 ISceneNodeAnimatorList::ConstIterator it = animators.begin();
259 while(it != animators.end())
260 {
261 // TODO - We assume FPS == extantzCamera, coz Irrlicht hard codes the camera types in an enum, which is a pain to add to from outside.
262 if(ESNAT_CAMERA_FPS == (*it)->getType())
263 {
264 extantzCamera *ec = static_cast<extantzCamera *>(*it);
265
266 cm = &(ec->move);
267 }
268
269 it++;
270 }
271 }
272 return cm;
273}
274
275#ifdef __cplusplus
276}
277#endif
278
279
280} // namespace scene
281} // namespace irr
282