diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CCameraSceneNode.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CCameraSceneNode.cpp | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CCameraSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CCameraSceneNode.cpp new file mode 100644 index 0000000..370b893 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CCameraSceneNode.cpp | |||
@@ -0,0 +1,385 @@ | |||
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 | #include "CCameraSceneNode.h" | ||
6 | #include "ISceneManager.h" | ||
7 | #include "IVideoDriver.h" | ||
8 | #include "os.h" | ||
9 | |||
10 | namespace irr | ||
11 | { | ||
12 | namespace scene | ||
13 | { | ||
14 | |||
15 | |||
16 | //! constructor | ||
17 | CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, | ||
18 | const core::vector3df& position, const core::vector3df& lookat) | ||
19 | : ICameraSceneNode(parent, mgr, id, position), | ||
20 | Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f), | ||
21 | InputReceiverEnabled(true), TargetAndRotationAreBound(false) | ||
22 | { | ||
23 | #ifdef _DEBUG | ||
24 | setDebugName("CCameraSceneNode"); | ||
25 | #endif | ||
26 | |||
27 | // set default projection | ||
28 | Fovy = core::PI / 2.5f; // Field of view, in radians. | ||
29 | |||
30 | const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0; | ||
31 | if (d) | ||
32 | Aspect = (f32)d->getCurrentRenderTargetSize().Width / | ||
33 | (f32)d->getCurrentRenderTargetSize().Height; | ||
34 | else | ||
35 | Aspect = 4.0f / 3.0f; // Aspect ratio. | ||
36 | |||
37 | recalculateProjectionMatrix(); | ||
38 | recalculateViewArea(); | ||
39 | } | ||
40 | |||
41 | |||
42 | //! Disables or enables the camera to get key or mouse inputs. | ||
43 | void CCameraSceneNode::setInputReceiverEnabled(bool enabled) | ||
44 | { | ||
45 | InputReceiverEnabled = enabled; | ||
46 | } | ||
47 | |||
48 | |||
49 | //! Returns if the input receiver of the camera is currently enabled. | ||
50 | bool CCameraSceneNode::isInputReceiverEnabled() const | ||
51 | { | ||
52 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
53 | return InputReceiverEnabled; | ||
54 | } | ||
55 | |||
56 | |||
57 | //! Sets the projection matrix of the camera. | ||
58 | /** The core::matrix4 class has some methods | ||
59 | to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH | ||
60 | \param projection: The new projection matrix of the camera. */ | ||
61 | void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal) | ||
62 | { | ||
63 | IsOrthogonal = isOrthogonal; | ||
64 | ViewArea.getTransform ( video::ETS_PROJECTION ) = projection; | ||
65 | } | ||
66 | |||
67 | |||
68 | //! Gets the current projection matrix of the camera | ||
69 | //! \return Returns the current projection matrix of the camera. | ||
70 | const core::matrix4& CCameraSceneNode::getProjectionMatrix() const | ||
71 | { | ||
72 | return ViewArea.getTransform ( video::ETS_PROJECTION ); | ||
73 | } | ||
74 | |||
75 | |||
76 | //! Gets the current view matrix of the camera | ||
77 | //! \return Returns the current view matrix of the camera. | ||
78 | const core::matrix4& CCameraSceneNode::getViewMatrix() const | ||
79 | { | ||
80 | return ViewArea.getTransform ( video::ETS_VIEW ); | ||
81 | } | ||
82 | |||
83 | |||
84 | //! Sets a custom view matrix affector. The matrix passed here, will be | ||
85 | //! multiplied with the view matrix when it gets updated. | ||
86 | //! This allows for custom camera setups like, for example, a reflection camera. | ||
87 | /** \param affector: The affector matrix. */ | ||
88 | void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector) | ||
89 | { | ||
90 | Affector = affector; | ||
91 | } | ||
92 | |||
93 | |||
94 | //! Gets the custom view matrix affector. | ||
95 | const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const | ||
96 | { | ||
97 | return Affector; | ||
98 | } | ||
99 | |||
100 | |||
101 | //! It is possible to send mouse and key events to the camera. Most cameras | ||
102 | //! may ignore this input, but camera scene nodes which are created for | ||
103 | //! example with scene::ISceneManager::addMayaCameraSceneNode or | ||
104 | //! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input | ||
105 | //! for changing their position, look at target or whatever. | ||
106 | bool CCameraSceneNode::OnEvent(const SEvent& event) | ||
107 | { | ||
108 | if (!InputReceiverEnabled) | ||
109 | return false; | ||
110 | |||
111 | // send events to event receiving animators | ||
112 | |||
113 | ISceneNodeAnimatorList::Iterator ait = Animators.begin(); | ||
114 | |||
115 | for (; ait != Animators.end(); ++ait) | ||
116 | if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event)) | ||
117 | return true; | ||
118 | |||
119 | // if nobody processed the event, return false | ||
120 | return false; | ||
121 | } | ||
122 | |||
123 | |||
124 | //! sets the look at target of the camera | ||
125 | //! \param pos: Look at target of the camera. | ||
126 | void CCameraSceneNode::setTarget(const core::vector3df& pos) | ||
127 | { | ||
128 | Target = pos; | ||
129 | |||
130 | if(TargetAndRotationAreBound) | ||
131 | { | ||
132 | const core::vector3df toTarget = Target - getAbsolutePosition(); | ||
133 | ISceneNode::setRotation(toTarget.getHorizontalAngle()); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | |||
138 | //! Sets the rotation of the node. | ||
139 | /** This only modifies the relative rotation of the node. | ||
140 | If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) | ||
141 | then calling this will also change the camera's target to match the rotation. | ||
142 | \param rotation New rotation of the node in degrees. */ | ||
143 | void CCameraSceneNode::setRotation(const core::vector3df& rotation) | ||
144 | { | ||
145 | if(TargetAndRotationAreBound) | ||
146 | Target = getAbsolutePosition() + rotation.rotationToDirection(); | ||
147 | |||
148 | ISceneNode::setRotation(rotation); | ||
149 | } | ||
150 | |||
151 | |||
152 | //! Gets the current look at target of the camera | ||
153 | //! \return Returns the current look at target of the camera | ||
154 | const core::vector3df& CCameraSceneNode::getTarget() const | ||
155 | { | ||
156 | return Target; | ||
157 | } | ||
158 | |||
159 | |||
160 | //! sets the up vector of the camera | ||
161 | //! \param pos: New upvector of the camera. | ||
162 | void CCameraSceneNode::setUpVector(const core::vector3df& pos) | ||
163 | { | ||
164 | UpVector = pos; | ||
165 | } | ||
166 | |||
167 | |||
168 | //! Gets the up vector of the camera. | ||
169 | //! \return Returns the up vector of the camera. | ||
170 | const core::vector3df& CCameraSceneNode::getUpVector() const | ||
171 | { | ||
172 | return UpVector; | ||
173 | } | ||
174 | |||
175 | |||
176 | f32 CCameraSceneNode::getNearValue() const | ||
177 | { | ||
178 | return ZNear; | ||
179 | } | ||
180 | |||
181 | |||
182 | f32 CCameraSceneNode::getFarValue() const | ||
183 | { | ||
184 | return ZFar; | ||
185 | } | ||
186 | |||
187 | |||
188 | f32 CCameraSceneNode::getAspectRatio() const | ||
189 | { | ||
190 | return Aspect; | ||
191 | } | ||
192 | |||
193 | |||
194 | f32 CCameraSceneNode::getFOV() const | ||
195 | { | ||
196 | return Fovy; | ||
197 | } | ||
198 | |||
199 | |||
200 | void CCameraSceneNode::setNearValue(f32 f) | ||
201 | { | ||
202 | ZNear = f; | ||
203 | recalculateProjectionMatrix(); | ||
204 | } | ||
205 | |||
206 | |||
207 | void CCameraSceneNode::setFarValue(f32 f) | ||
208 | { | ||
209 | ZFar = f; | ||
210 | recalculateProjectionMatrix(); | ||
211 | } | ||
212 | |||
213 | |||
214 | void CCameraSceneNode::setAspectRatio(f32 f) | ||
215 | { | ||
216 | Aspect = f; | ||
217 | recalculateProjectionMatrix(); | ||
218 | } | ||
219 | |||
220 | |||
221 | void CCameraSceneNode::setFOV(f32 f) | ||
222 | { | ||
223 | Fovy = f; | ||
224 | recalculateProjectionMatrix(); | ||
225 | } | ||
226 | |||
227 | |||
228 | void CCameraSceneNode::recalculateProjectionMatrix() | ||
229 | { | ||
230 | ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); | ||
231 | } | ||
232 | |||
233 | |||
234 | //! prerender | ||
235 | void CCameraSceneNode::OnRegisterSceneNode() | ||
236 | { | ||
237 | if ( SceneManager->getActiveCamera () == this ) | ||
238 | SceneManager->registerNodeForRendering(this, ESNRP_CAMERA); | ||
239 | |||
240 | ISceneNode::OnRegisterSceneNode(); | ||
241 | } | ||
242 | |||
243 | |||
244 | //! render | ||
245 | void CCameraSceneNode::render() | ||
246 | { | ||
247 | core::vector3df pos = getAbsolutePosition(); | ||
248 | core::vector3df tgtv = Target - pos; | ||
249 | tgtv.normalize(); | ||
250 | |||
251 | // if upvector and vector to the target are the same, we have a | ||
252 | // problem. so solve this problem: | ||
253 | core::vector3df up = UpVector; | ||
254 | up.normalize(); | ||
255 | |||
256 | f32 dp = tgtv.dotProduct(up); | ||
257 | |||
258 | if ( core::equals(core::abs_<f32>(dp), 1.f) ) | ||
259 | { | ||
260 | up.X += 0.5f; | ||
261 | } | ||
262 | |||
263 | ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up); | ||
264 | ViewArea.getTransform(video::ETS_VIEW) *= Affector; | ||
265 | recalculateViewArea(); | ||
266 | |||
267 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | ||
268 | if ( driver) | ||
269 | { | ||
270 | driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) ); | ||
271 | driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) ); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | |||
276 | //! returns the axis aligned bounding box of this node | ||
277 | const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const | ||
278 | { | ||
279 | return ViewArea.getBoundingBox(); | ||
280 | } | ||
281 | |||
282 | |||
283 | //! returns the view frustum. needed sometimes by bsp or lod render nodes. | ||
284 | const SViewFrustum* CCameraSceneNode::getViewFrustum() const | ||
285 | { | ||
286 | return &ViewArea; | ||
287 | } | ||
288 | |||
289 | |||
290 | void CCameraSceneNode::recalculateViewArea() | ||
291 | { | ||
292 | ViewArea.cameraPosition = getAbsolutePosition(); | ||
293 | |||
294 | core::matrix4 m(core::matrix4::EM4CONST_NOTHING); | ||
295 | m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION), | ||
296 | ViewArea.getTransform(video::ETS_VIEW)); | ||
297 | ViewArea.setFrom(m); | ||
298 | } | ||
299 | |||
300 | |||
301 | //! Writes attributes of the scene node. | ||
302 | void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const | ||
303 | { | ||
304 | ICameraSceneNode::serializeAttributes(out, options); | ||
305 | |||
306 | out->addVector3d("Target", Target); | ||
307 | out->addVector3d("UpVector", UpVector); | ||
308 | out->addFloat("Fovy", Fovy); | ||
309 | out->addFloat("Aspect", Aspect); | ||
310 | out->addFloat("ZNear", ZNear); | ||
311 | out->addFloat("ZFar", ZFar); | ||
312 | out->addBool("Binding", TargetAndRotationAreBound); | ||
313 | out->addBool("ReceiveInput", InputReceiverEnabled); | ||
314 | } | ||
315 | |||
316 | //! Reads attributes of the scene node. | ||
317 | void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) | ||
318 | { | ||
319 | ICameraSceneNode::deserializeAttributes(in, options); | ||
320 | |||
321 | Target = in->getAttributeAsVector3d("Target"); | ||
322 | UpVector = in->getAttributeAsVector3d("UpVector"); | ||
323 | Fovy = in->getAttributeAsFloat("Fovy"); | ||
324 | Aspect = in->getAttributeAsFloat("Aspect"); | ||
325 | ZNear = in->getAttributeAsFloat("ZNear"); | ||
326 | ZFar = in->getAttributeAsFloat("ZFar"); | ||
327 | TargetAndRotationAreBound = in->getAttributeAsBool("Binding"); | ||
328 | if ( in->findAttribute("ReceiveInput") ) | ||
329 | InputReceiverEnabled = in->getAttributeAsBool("InputReceiverEnabled"); | ||
330 | |||
331 | recalculateProjectionMatrix(); | ||
332 | recalculateViewArea(); | ||
333 | } | ||
334 | |||
335 | |||
336 | //! Set the binding between the camera's rotation adn target. | ||
337 | void CCameraSceneNode::bindTargetAndRotation(bool bound) | ||
338 | { | ||
339 | TargetAndRotationAreBound = bound; | ||
340 | } | ||
341 | |||
342 | |||
343 | //! Gets the binding between the camera's rotation and target. | ||
344 | bool CCameraSceneNode::getTargetAndRotationBinding(void) const | ||
345 | { | ||
346 | return TargetAndRotationAreBound; | ||
347 | } | ||
348 | |||
349 | |||
350 | //! Creates a clone of this scene node and its children. | ||
351 | ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) | ||
352 | { | ||
353 | ICameraSceneNode::clone(newParent, newManager); | ||
354 | |||
355 | if (!newParent) | ||
356 | newParent = Parent; | ||
357 | if (!newManager) | ||
358 | newManager = SceneManager; | ||
359 | |||
360 | CCameraSceneNode* nb = new CCameraSceneNode(newParent, | ||
361 | newManager, ID, RelativeTranslation, Target); | ||
362 | |||
363 | nb->ISceneNode::cloneMembers(this, newManager); | ||
364 | nb->ICameraSceneNode::cloneMembers(this); | ||
365 | |||
366 | nb->Target = Target; | ||
367 | nb->UpVector = UpVector; | ||
368 | nb->Fovy = Fovy; | ||
369 | nb->Aspect = Aspect; | ||
370 | nb->ZNear = ZNear; | ||
371 | nb->ZFar = ZFar; | ||
372 | nb->ViewArea = ViewArea; | ||
373 | nb->Affector = Affector; | ||
374 | nb->InputReceiverEnabled = InputReceiverEnabled; | ||
375 | nb->TargetAndRotationAreBound = TargetAndRotationAreBound; | ||
376 | |||
377 | if ( newParent ) | ||
378 | nb->drop(); | ||
379 | return nb; | ||
380 | } | ||
381 | |||
382 | |||
383 | } // end namespace | ||
384 | } // end namespace | ||
385 | |||