1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_Camera.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 25881 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/res/gfx_ResCamera.h>
19 #include <nw/gfx/gfx_Camera.h>
20 #include <nw/gfx/gfx_ISceneVisitor.h>
21 #include <nw/gfx/gfx_AimTargetViewUpdater.h>
22 #include <nw/gfx/gfx_LookAtTargetViewUpdater.h>
23 #include <nw/gfx/gfx_RotateViewUpdater.h>
24 #include <nw/gfx/gfx_PerspectiveProjectionUpdater.h>
25 #include <nw/gfx/gfx_OrthoProjectionUpdater.h>
26 #include <nw/gfx/gfx_FrustumProjectionUpdater.h>
27
28 namespace nw
29 {
30 namespace gfx
31 {
32
33 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Camera, TransformNode);
34
35 //----------------------------------------
Camera(os::IAllocator * allocator,ResTransformNode resObj,const Camera::Description & description,GfxPtr<CameraViewUpdater> viewUpdater,GfxPtr<CameraProjectionUpdater> projectionUpdater,f32 wscale,bool isDynamic)36 Camera::Camera(
37 os::IAllocator* allocator,
38 ResTransformNode resObj,
39 const Camera::Description& description,
40 GfxPtr<CameraViewUpdater> viewUpdater,
41 GfxPtr<CameraProjectionUpdater> projectionUpdater,
42 f32 wscale,
43 bool isDynamic)
44 : TransformNode(
45 allocator,
46 resObj,
47 description),
48 m_ViewMatrix(math::MTX34::Identity()),
49 m_InverseViewMatrix(math::MTX34::Identity()),
50 m_ProjectionMatrix(math::MTX44::Identity()),
51 m_InverseProjectionMatrix(math::MTX44::Identity()),
52 m_TextureProjectionMatrix(math::MTX34::Identity()),
53 m_ViewUpdater(viewUpdater),
54 m_ProjectionUpdater(projectionUpdater),
55 m_AnimGroup(NULL),
56 m_OriginalValue(),
57 m_WScale(wscale),
58 m_IsDynamic(isDynamic)
59 {}
60
61 //----------------------------------------
~Camera()62 Camera::~Camera()
63 {
64 ResCamera resCamera = ResDynamicCast<ResCamera>(this->GetResSceneNode());
65 if (this->m_IsDynamic && resCamera.IsValid())
66 {
67 this->GetAllocator().Free(resCamera.ptr());
68 }
69
70 ResCameraDestroyer(&this->GetAllocator())(m_OriginalValue);
71 m_OriginalValue = ResCamera(NULL);
72
73 ut::SafeDestroy(m_AnimGroup);
74 }
75
76 //----------------------------------------
77 Result
CreateAnimGroup(os::IAllocator * allocator)78 Camera::CreateAnimGroup(os::IAllocator* allocator)
79 {
80 Result result = INITIALIZE_RESULT_OK;
81
82 NW_ASSERT(m_OriginalValue.IsValid());
83
84 if(!m_AnimBinding)
85 {
86 // DynamicBuilderを使用した場合は生成されない
87 return result;
88 }
89
90 ResCamera resCamera = GetResCamera();
91 NW_ASSERT(resCamera.IsValid());
92
93 NW_ASSERT(resCamera.GetAnimGroupsCount() == 1);
94 anim::ResAnimGroup resAnimGroup = resCamera.GetAnimGroups(0);
95
96 NW_ASSERT(resAnimGroup.GetTargetType() == anim::ResGraphicsAnimGroup::TARGET_TYPE_CAMERA);
97
98 AnimGroup* animGroup = AnimGroup::Builder()
99 .ResAnimGroup(resAnimGroup)
100 .SetSceneNode(this)
101 .UseOriginalValue(true) // TODO: 選択できる必要はある?
102 .Create(allocator);
103
104 if (animGroup == NULL)
105 {
106 result |= Result::MASK_FAIL_BIT;
107 }
108
109 NW_ENSURE_AND_RETURN(result);
110
111 m_AnimGroup = animGroup;
112
113 // 各メンバの参照解決
114 const int animMemberCount = m_AnimGroup->GetMemberCount();
115 for (int memberIdx = 0; memberIdx < animMemberCount; ++memberIdx)
116 {
117 anim::ResAnimGroupMember member = m_AnimGroup->GetResAnimGroupMember(memberIdx);
118
119 void* object = GetAnimTargetObject(member);
120 m_AnimGroup->SetTargetObject(memberIdx, object);
121
122 // TODO: アドレス算出もSetterに似た実装で行う?
123 if(member.GetObjectType() == anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM &&
124 member.GetMemberType() == anim::ResTransformMember::MEMBER_TYPE_TRANSFORM)
125 {
126 m_AnimGroup->SetTargetPtr(memberIdx, &this->Transform());
127 }
128 else
129 {
130 u8* target = static_cast<u8*>(object);
131 target += member.GetMemberOffset();
132 m_AnimGroup->SetTargetPtr(memberIdx, target);
133 }
134
135 m_AnimGroup->SetTargetObjectIndex(memberIdx, 0); // TODO: 要検討
136
137 // OriginalValueを登録する
138 void* originalValue = NULL;
139 switch (member.GetObjectType())
140 {
141 case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
142 {
143 switch (member.GetMemberType())
144 {
145 case anim::ResTransformMember::MEMBER_TYPE_TRANSFORM:
146 originalValue = &m_OriginalTransform;
147 break;
148 default:
149 NW_ASSERT(false);
150 }
151 }
152 break;
153 case anim::ResAnimGroupMember::OBJECT_TYPE_VIEW_UPDATER:
154 {
155 originalValue =
156 ut::AddOffsetToPtr(m_OriginalValue.GetViewUpdater().ptr(), member.GetMemberOffset());
157 }
158 break;
159 case anim::ResAnimGroupMember::OBJECT_TYPE_PROJECTION_UPDATER:
160 {
161 originalValue =
162 ut::AddOffsetToPtr(m_OriginalValue.GetProjectionUpdater().ptr(), member.GetMemberOffset());
163 }
164 break;
165 default:
166 NW_ASSERT(false);
167 }
168
169 NW_NULL_ASSERT(originalValue);
170 m_AnimGroup->SetOriginalValue(memberIdx, originalValue);
171 }
172
173 m_AnimBinding->SetAnimGroup(0, m_AnimGroup);
174
175 return result;
176 }
177
178 //----------------------------------------
179 Camera*
Create(os::IAllocator * allocator)180 Camera::DynamicBuilder::Create(
181 os::IAllocator* allocator
182 )
183 {
184 NW_NULL_ASSERT(allocator);
185
186 if (!this->m_ViewUpdater)
187 {
188 this->m_ViewUpdater.Reset(LookAtTargetViewUpdater::Create(allocator));
189 }
190
191 if (!this->m_ProjectionUpdater)
192 {
193 this->m_ProjectionUpdater.Reset(PerspectiveProjectionUpdater::Create(allocator));
194 }
195
196 // カメラを生成します。
197
198 ResCameraData* resCamera =
199 AllocateAndFillN<ResCameraData>(allocator, sizeof(ResCameraData), 0);
200
201 // カメラのリソースに、各Updaterを結び付けます。
202 resCamera->toViewUpdater.set_ptr(this->m_ViewUpdater->GetResource().ptr());
203 resCamera->toProjectionUpdater.set_ptr(this->m_ProjectionUpdater->GetResource().ptr());
204
205 switch (this->m_ViewUpdater->GetResource().GetTypeInfo())
206 {
207 case ResAimTargetViewUpdater::TYPE_INFO:
208 resCamera->m_ViewType = ResCamera::VIEWTYPE_AIM;
209 break;
210 case ResLookAtTargetViewUpdater::TYPE_INFO:
211 resCamera->m_ViewType = ResCamera::VIEWTYPE_LOOKAT;
212 break;
213 case ResRotateViewUpdater::TYPE_INFO:
214 resCamera->m_ViewType = ResCamera::VIEWTYPE_ROTATE;
215 break;
216 default:
217 NW_ASSERT(false);
218 }
219
220 switch (this->m_ProjectionUpdater->GetResource().GetTypeInfo())
221 {
222 case ResPerspectiveProjectionUpdater::TYPE_INFO:
223 resCamera->m_ProjectionType = ResCamera::PROJTYPE_PERSPECTIVE;
224 break;
225 case ResFrustumProjectionUpdater::TYPE_INFO:
226 resCamera->m_ProjectionType = ResCamera::PROJTYPE_FRUSTUM;
227 break;
228 case ResOrthoProjectionUpdater::TYPE_INFO:
229 resCamera->m_ProjectionType = ResCamera::PROJTYPE_ORTHO;
230 break;
231 default:
232 NW_ASSERT(false);
233 }
234
235 //--------------------------------
236 // ResSceneObjectData のメンバ初期化
237 resCamera->typeInfo = ResCamera::TYPE_INFO;
238 resCamera->m_Header.revision = ResCamera::BINARY_REVISION;
239 resCamera->m_Header.signature = ResCamera::SIGNATURE;
240
241 resCamera->m_UserDataDicCount = 0;
242 resCamera->toUserDataDic.set_ptr( NULL );
243
244 const char* name = NULL;
245 resCamera->toName.set_ptr(AllocateAndCopyString(name, allocator, MAX_NAME_LENGTH));
246
247 //--------------------------------
248 // ResSceneNodeData のメンバ初期化
249 resCamera->m_ChildrenTableCount = 0;
250 resCamera->toChildrenTable.set_ptr( NULL );
251 resCamera->m_AnimGroupsDicCount = NULL;
252 resCamera->toAnimGroupsDic.set_ptr( NULL );
253
254 //--------------------------------
255 // ResTransformNode のメンバ初期化
256 const math::VEC3 scale(1.0f, 1.0f, 1.0f);
257 const math::VEC3 rotate(0.0f, 0.0f, 0.0f);
258 const math::VEC3 translate(0.0f, 0.0, 0.0f);
259 resCamera->m_Transform = math::Transform3(scale, rotate, translate);
260 resCamera->m_WorldMatrix = math::MTX34::Identity();
261
262 void* memory = allocator->Alloc(sizeof(Camera));
263 NW_NULL_ASSERT(memory);
264
265 Camera* camera = new(memory) Camera(
266 allocator,
267 ResCamera(resCamera),
268 m_Description,
269 m_ViewUpdater,
270 m_ProjectionUpdater,
271 0.0f,
272 true);
273
274 camera->Initialize(allocator);
275
276 return camera;
277 }
278
279 //----------------------------------------
280 Camera*
Create(SceneNode * parent,ResSceneObject resource,const Camera::Description & description,os::IAllocator * allocator)281 Camera::Create(
282 SceneNode* parent,
283 ResSceneObject resource,
284 const Camera::Description& description,
285 os::IAllocator* allocator
286 )
287 {
288 NW_NULL_ASSERT(allocator);
289
290 ResCamera resCamera = ResDynamicCast<ResCamera>(resource);
291 NW_ASSERT(resCamera.IsValid());
292 NW_ASSERT( internal::ResCheckRevision( resCamera ) );
293
294 void* memory = allocator->Alloc(sizeof(Camera));
295 NW_NULL_ASSERT(memory);
296
297 // リソースからビューアップデータを作成します。
298 ResCamera::ViewType viewType = resCamera.GetViewType();
299 ResCameraViewUpdater resViewUpdater = resCamera.GetViewUpdater();
300 NW_ASSERT(resViewUpdater.IsValid());
301 NW_ASSERT(viewType < ResCamera::VIEWTYPE_COUNT);
302 CameraViewUpdater* cameraView = NULL;
303 if (viewType == ResCamera::VIEWTYPE_AIM)
304 {
305 ResAimTargetViewUpdater resAimView(resViewUpdater.ptr());
306 AimTargetViewUpdater* aimView = AimTargetViewUpdater::Create(allocator, resAimView);
307 cameraView = aimView;
308 }
309 else if (viewType == ResCamera::VIEWTYPE_LOOKAT)
310 {
311 ResLookAtTargetViewUpdater resLookAtView(resViewUpdater.ptr());
312 LookAtTargetViewUpdater* lookAtView
313 = LookAtTargetViewUpdater::Create(allocator, resLookAtView);
314
315 cameraView = lookAtView;
316 }
317 else if (viewType == ResCamera::VIEWTYPE_ROTATE)
318 {
319 ResRotateViewUpdater resRotateView(resViewUpdater.ptr());
320 RotateViewUpdater* rotateView = RotateViewUpdater::Create(allocator, resRotateView);
321
322 cameraView = rotateView;
323 }
324 GfxPtr<CameraViewUpdater> viewUpdater(cameraView);
325
326 // リソースからプロジェクションアップデータを作成します。
327 ResCamera::ProjType projType = resCamera.GetProjectionType();
328 ResCameraProjectionUpdater resProjectionUpdater = resCamera.GetProjectionUpdater();
329 NW_ASSERT(resProjectionUpdater.IsValid());
330 NW_ASSERT(projType < ResCamera::PROJTYPE_COUNT);
331 CameraProjectionUpdater* cameraProjection = NULL;
332 if (projType == ResCamera::PROJTYPE_PERSPECTIVE)
333 {
334 ResPerspectiveProjectionUpdater resPersProjection(resProjectionUpdater.ptr());
335 PerspectiveProjectionUpdater* persProjection =
336 PerspectiveProjectionUpdater::Create(allocator, resPersProjection);
337
338 cameraProjection = persProjection;
339 }
340 else if (projType == ResCamera::PROJTYPE_FRUSTUM)
341 {
342 ResFrustumProjectionUpdater resFrustumProjection(resProjectionUpdater.ptr());
343 FrustumProjectionUpdater* frustumProjection = FrustumProjectionUpdater::Create(allocator, resFrustumProjection);
344
345 cameraProjection = frustumProjection;
346 }
347 else if (projType == ResCamera::PROJTYPE_ORTHO)
348 {
349 ResOrthoProjectionUpdater resOrthoProjection(resProjectionUpdater.ptr());
350 OrthoProjectionUpdater* orthoProjection = OrthoProjectionUpdater::Create(allocator, resOrthoProjection);
351
352 cameraProjection = orthoProjection;
353 }
354 GfxPtr<CameraProjectionUpdater> projectionUpdater(cameraProjection);
355
356 Camera* camera = new(memory) Camera(
357 allocator,
358 resCamera,
359 description,
360 viewUpdater,
361 projectionUpdater,
362 resCamera.GetWScale(),
363 false);
364
365 camera->Initialize(allocator);
366
367 if (parent)
368 {
369 bool result = parent->AttachChild(camera);
370 NW_ASSERT(result);
371 }
372
373 return camera;
374 }
375
376 //----------------------------------------
377 void
Accept(ISceneVisitor * visitor)378 Camera::Accept(
379 ISceneVisitor* visitor
380 )
381 {
382 visitor->VisitCamera(this);
383 AcceptChildren(visitor);
384 }
385
386 //----------------------------------------
387 void
UpdateCameraMatrix()388 Camera::UpdateCameraMatrix()
389 {
390 NW_NULL_ASSERT(this->m_ViewUpdater);
391 NW_NULL_ASSERT(this->m_ProjectionUpdater);
392
393 SceneNode* parentNode = this->GetParent();
394
395 math::VEC3 cameraPosition(this->WorldMatrix().GetColumn(3));
396
397 if (parentNode != NULL)
398 {
399 this->m_ViewUpdater->Update(&this->m_ViewMatrix, parentNode->TrackbackWorldMatrix(), cameraPosition);
400 }
401 else
402 {
403 this->m_ViewUpdater->Update(&this->m_ViewMatrix, math::MTX34::Identity(), cameraPosition);
404 }
405
406 NW_FAILSAFE_IF(math::MTX34Inverse(&this->m_InverseViewMatrix, &this->m_ViewMatrix) == 0)
407 {
408 this->m_InverseViewMatrix = math::MTX34::Identity();
409 }
410
411 this->m_ProjectionUpdater->Update(&this->m_ProjectionMatrix, &this->m_TextureProjectionMatrix);
412
413 NW_FAILSAFE_IF(math::MTX44Inverse(&this->m_InverseProjectionMatrix, &this->m_ProjectionMatrix) == 0)
414 {
415 this->m_InverseProjectionMatrix = math::MTX34::Identity();
416 }
417 }
418
419
420
421 //----------------------------------------
422 const nw::math::VEC3&
GetTargetPosition() const423 Camera::GetTargetPosition() const
424 {
425 const ResAimTargetViewUpdater resAim =
426 ResDynamicCast<const ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
427 const ResLookAtTargetViewUpdater resLookAt =
428 ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
429
430 if (resAim.IsValid())
431 {
432 return resAim.GetTargetPosition();
433 }
434 else if (resLookAt.IsValid())
435 {
436 return resLookAt.GetTargetPosition();
437 }
438 else
439 {
440 NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
441 return resAim.GetTargetPosition();
442 }
443 }
444
445 //----------------------------------------
446 void
SetTargetPosition(const nw::math::VEC3 & targetPosition)447 Camera::SetTargetPosition(const nw::math::VEC3& targetPosition)
448 {
449 ResAimTargetViewUpdater resAim =
450 ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
451 ResLookAtTargetViewUpdater resLookAt =
452 ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
453
454 if (resAim.IsValid())
455 {
456 resAim.SetTargetPosition(targetPosition);
457 }
458 else if (resLookAt.IsValid())
459 {
460 resLookAt.SetTargetPosition(targetPosition);
461 }
462 else
463 {
464 NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
465 }
466 }
467
468 //----------------------------------------
469 const nw::math::VEC3&
GetUpwardVector() const470 Camera::GetUpwardVector() const
471 {
472 const ResLookAtTargetViewUpdater resLookAt =
473 ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
474
475 NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
476
477 return resLookAt.GetUpwardVector();
478 }
479
480 //----------------------------------------
481 void
SetUpwardVector(const nw::math::VEC3 & upwardVector)482 Camera::SetUpwardVector(const nw::math::VEC3& upwardVector)
483 {
484 ResLookAtTargetViewUpdater resLookAt =
485 ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
486
487 NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
488
489 resLookAt.SetUpwardVector(upwardVector);
490 }
491
492 //----------------------------------------
493 f32
GetTwist() const494 Camera::GetTwist() const
495 {
496 ResAimTargetViewUpdater resAim =
497 ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
498
499 NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
500
501 return resAim.GetTwist();
502 }
503
504 //----------------------------------------
505 void
SetTwist(f32 twist)506 Camera::SetTwist(f32 twist)
507 {
508 ResAimTargetViewUpdater resAim =
509 ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
510
511 NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
512
513 resAim.SetTwist(twist);
514 }
515
516 //----------------------------------------
517 const nw::math::VEC3&
GetViewRotate() const518 Camera::GetViewRotate() const
519 {
520 const ResRotateViewUpdater resRotate =
521 ResDynamicCast<const ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
522
523 NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
524
525 return resRotate.GetViewRotate();
526 }
527
528 //----------------------------------------
529 void
SetViewRotate(const nw::math::VEC3 & viewRotate)530 Camera::SetViewRotate(const nw::math::VEC3& viewRotate)
531 {
532 ResRotateViewUpdater resRotate =
533 ResDynamicCast<ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
534
535 NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
536
537 resRotate.SetViewRotate(viewRotate);
538 }
539
540
541
542
543 //----------------------------------------
544 void
GetPerspective(f32 * fovy,f32 * aspectRatio,f32 * nearClip,f32 * farClip) const545 Camera::GetPerspective(
546 f32* fovy,
547 f32* aspectRatio,
548 f32* nearClip,
549 f32* farClip
550 ) const
551 {
552 const ResPerspectiveProjectionUpdater resource =
553 ResDynamicCast<const ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
554
555 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
556
557 if (fovy)
558 {
559 *fovy = resource.GetFovy();
560 }
561 if (aspectRatio)
562 {
563 *aspectRatio = resource.GetAspectRatio();
564 }
565 if (nearClip)
566 {
567 *nearClip = resource.GetNear();
568 }
569 if (farClip)
570 {
571 *farClip = resource.GetFar();
572 }
573 }
574
575 //----------------------------------------
576 void
SetPerspective(f32 fovy,f32 aspectRatio,f32 nearClip,f32 farClip)577 Camera::SetPerspective(
578 f32 fovy,
579 f32 aspectRatio,
580 f32 nearClip,
581 f32 farClip
582 )
583 {
584 ResPerspectiveProjectionUpdater resource =
585 ResDynamicCast<ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
586
587 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
588
589 resource.SetFovy(fovy);
590 resource.SetAspectRatio(aspectRatio);
591 resource.SetNear(nearClip);
592 resource.SetFar(farClip);
593 }
594
595 //----------------------------------------
596 void
GetFrustum(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const597 Camera::GetFrustum(
598 f32* left,
599 f32* right,
600 f32* bottom,
601 f32* top,
602 f32* nearClip,
603 f32* farClip
604 ) const
605 {
606 const ResFrustumProjectionUpdater resource =
607 ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
608
609 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
610
611 if (left && right && bottom && top)
612 {
613 const ut::Rect rect = resource.GetRect();
614 if (left)
615 {
616 *left = rect.left;
617 }
618 if (right)
619 {
620 *right = rect.right;
621 }
622 if (bottom)
623 {
624 *bottom = rect.bottom;
625 }
626 if (top)
627 {
628 *top = rect.top;
629 }
630 }
631 if (nearClip)
632 {
633 *nearClip = resource.GetNear();
634 }
635 if (farClip)
636 {
637 *farClip = resource.GetFar();
638 }
639 }
640
641 //----------------------------------------
642 void
SetFrustum(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)643 Camera::SetFrustum(
644 f32 left,
645 f32 right,
646 f32 bottom,
647 f32 top,
648 f32 nearClip,
649 f32 farClip
650 )
651 {
652 ResFrustumProjectionUpdater resource =
653 ResDynamicCast<ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
654
655 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
656
657 resource.SetRect(left, right, bottom, top);
658 resource.SetNear(nearClip);
659 resource.SetFar(farClip);
660 }
661
662 //----------------------------------------
663 void
GetOrtho(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const664 Camera::GetOrtho(
665 f32* left,
666 f32* right,
667 f32* bottom,
668 f32* top,
669 f32* nearClip,
670 f32* farClip
671 ) const
672 {
673 const ResOrthoProjectionUpdater resource =
674 ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
675
676 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
677
678 if (left && right && bottom && top)
679 {
680 const ut::Rect rect = resource.GetRect();
681 if (left)
682 {
683 *left = rect.left;
684 }
685 if (right)
686 {
687 *right = rect.right;
688 }
689 if (bottom)
690 {
691 *bottom = rect.bottom;
692 }
693 if (top)
694 {
695 *top = rect.top;
696 }
697 }
698 if (nearClip)
699 {
700 *nearClip = resource.GetNear();
701 }
702 if (farClip)
703 {
704 *farClip = resource.GetFar();
705 }
706 }
707
708 //----------------------------------------
709 void
SetOrtho(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)710 Camera::SetOrtho(
711 f32 left,
712 f32 right,
713 f32 bottom,
714 f32 top,
715 f32 nearClip,
716 f32 farClip
717 )
718 {
719 ResOrthoProjectionUpdater resource =
720 ResDynamicCast<ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
721
722 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
723
724 resource.SetRect(left, right, bottom, top);
725 resource.SetNear(nearClip);
726 resource.SetFar(farClip);
727 }
728
729 //----------------------------------------
730 void
GetFrustum(ut::Rect * rect,f32 * nearClip,f32 * farClip) const731 Camera::GetFrustum(
732 ut::Rect* rect,
733 f32* nearClip,
734 f32* farClip
735 ) const
736 {
737 const ResFrustumProjectionUpdater resource =
738 ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
739
740 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
741
742 if (rect)
743 {
744 *rect = resource.GetRect();
745 }
746 if (nearClip)
747 {
748 *nearClip = resource.GetNear();
749 }
750 if (farClip)
751 {
752 *farClip = resource.GetFar();
753 }
754 }
755
756 //----------------------------------------
757 void
SetFrustum(const ut::Rect & rect,f32 nearClip,f32 farClip)758 Camera::SetFrustum(
759 const ut::Rect& rect,
760 f32 nearClip,
761 f32 farClip
762 )
763 {
764 SetFrustum(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
765 }
766
767 //----------------------------------------
768 void
GetOrtho(ut::Rect * rect,f32 * nearClip,f32 * farClip) const769 Camera::GetOrtho(
770 ut::Rect* rect,
771 f32* nearClip,
772 f32* farClip
773 ) const
774 {
775 const ResOrthoProjectionUpdater resource =
776 ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
777
778 NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
779
780 if (rect)
781 {
782 *rect = resource.GetRect();
783 }
784 if (nearClip)
785 {
786 *nearClip = resource.GetNear();
787 }
788 if (farClip)
789 {
790 *farClip = resource.GetFar();
791 }
792 }
793
794 //----------------------------------------
795 void
SetOrtho(const ut::Rect & rect,f32 nearClip,f32 farClip)796 Camera::SetOrtho(
797 const ut::Rect& rect,
798 f32 nearClip,
799 f32 farClip
800 )
801 {
802 SetOrtho(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
803 }
804
805 //----------------------------------------
806 void
SetFrustum(const Viewport & viewport)807 Camera::SetFrustum(
808 const Viewport& viewport
809 )
810 {
811 SetFrustum(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
812 }
813
814 //----------------------------------------
815 void
SetOrtho(const Viewport & viewport)816 Camera::SetOrtho(
817 const Viewport& viewport
818 )
819 {
820 SetOrtho(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
821 }
822
823 //-----------------------------------------
824 f32
GetNear() const825 Camera::GetNear() const
826 {
827 const ResCameraProjectionUpdater resource =
828 ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
829
830 NW_ASSERT(resource.IsValid());
831
832 return resource.GetNear();
833 }
834
835 //-----------------------------------------
836 void
SetNear(f32 near)837 Camera::SetNear(f32 near)
838 {
839 ResCameraProjectionUpdater resource =
840 ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
841
842 NW_ASSERT(resource.IsValid());
843
844 resource.SetNear(near);
845 }
846
847 //-----------------------------------------
848 f32
GetFar() const849 Camera::GetFar() const
850 {
851 const ResCameraProjectionUpdater resource =
852 ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
853
854 NW_ASSERT(resource.IsValid());
855
856 return resource.GetFar();
857 }
858
859 //-----------------------------------------
860 void
SetFar(f32 far)861 Camera::SetFar(f32 far)
862 {
863 ResCameraProjectionUpdater resource =
864 ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
865
866 NW_ASSERT(resource.IsValid());
867
868 resource.SetFar(far);
869 }
870
871 //----------------------------------------
872 Result
StoreOriginal(os::IAllocator * allocator)873 Camera::StoreOriginal(os::IAllocator* allocator)
874 {
875 Result result = INITIALIZE_RESULT_OK;
876
877 ResCamera original = this->GetResCamera();
878 NW_NULL_ASSERT(original.GetViewUpdater().ptr());
879 NW_NULL_ASSERT(original.GetProjectionUpdater().ptr());
880
881 void* cameraMemory = allocator->Alloc(sizeof(ResCameraData));
882 NW_NULL_ASSERT(cameraMemory);
883
884 ResCameraData* cameraData =
885 new(cameraMemory) ResCameraData(original.ref());
886
887 cameraData->toViewUpdater = NULL;
888 cameraData->toProjectionUpdater = NULL;
889
890 // viewUpdaterのコピー
891 void* viewUpdaterMemory = NULL;
892 ResCameraViewUpdaterData* viewUpdaterData = NULL;
893 switch (original.GetViewType())
894 {
895 case ResCamera::VIEWTYPE_AIM:
896 viewUpdaterMemory = allocator->Alloc(sizeof(ResAimTargetViewUpdaterData));
897 NW_NULL_ASSERT(viewUpdaterMemory);
898 viewUpdaterData =
899 new(viewUpdaterMemory) ResAimTargetViewUpdaterData(
900 *reinterpret_cast<ResAimTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
901 break;
902
903 case ResCamera::VIEWTYPE_LOOKAT:
904 viewUpdaterMemory = allocator->Alloc(sizeof(ResLookAtTargetViewUpdaterData));
905 NW_NULL_ASSERT(viewUpdaterMemory);
906 viewUpdaterData =
907 new(viewUpdaterMemory) ResLookAtTargetViewUpdaterData(
908 *reinterpret_cast<ResLookAtTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
909 break;
910
911 case ResCamera::VIEWTYPE_ROTATE:
912 viewUpdaterMemory = allocator->Alloc(sizeof(ResRotateViewUpdaterData));
913 NW_NULL_ASSERT(viewUpdaterMemory);
914 viewUpdaterData =
915 new(viewUpdaterMemory) ResRotateViewUpdaterData(
916 *reinterpret_cast<ResRotateViewUpdaterData*>(original.GetViewUpdater().ptr()));
917 break;
918
919 default:
920 NW_ASSERT(false);
921 }
922
923 cameraData->toViewUpdater.set_ptr(viewUpdaterData);
924
925 // ProjectionUpdaterのコピー
926 void* projectionUpdaterMemory = NULL;
927 ResCameraProjectionUpdaterData* projectionUpdaterData = NULL;
928
929 switch (original.GetProjectionType())
930 {
931 case ResCamera::PROJTYPE_PERSPECTIVE:
932 projectionUpdaterMemory = allocator->Alloc(sizeof(ResPerspectiveProjectionUpdaterData));
933 NW_NULL_ASSERT(projectionUpdaterMemory);
934 projectionUpdaterData =
935 new(projectionUpdaterMemory) ResPerspectiveProjectionUpdaterData(
936 *reinterpret_cast<ResPerspectiveProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
937 break;
938
939 case ResCamera::PROJTYPE_FRUSTUM:
940 projectionUpdaterMemory = allocator->Alloc(sizeof(ResFrustumProjectionUpdaterData));
941 NW_NULL_ASSERT(projectionUpdaterMemory);
942 projectionUpdaterData =
943 new(projectionUpdaterMemory) ResFrustumProjectionUpdaterData(
944 *reinterpret_cast<ResFrustumProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
945 break;
946
947 case ResCamera::PROJTYPE_ORTHO:
948 projectionUpdaterMemory = allocator->Alloc(sizeof(ResOrthoProjectionUpdaterData));
949 NW_NULL_ASSERT(projectionUpdaterMemory);
950 projectionUpdaterData =
951 new(projectionUpdaterMemory) ResOrthoProjectionUpdaterData(
952 *reinterpret_cast<ResOrthoProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
953 break;
954
955 default:
956 NW_ASSERT(false);
957 }
958
959 cameraData->toProjectionUpdater.set_ptr(projectionUpdaterData);
960
961 // メンバに保存
962 m_OriginalValue = ResCamera(cameraData);
963
964 // CalculatedTransformを保存
965 m_OriginalTransform = this->GetResTransformNode().GetTransform();
966
967 return result;
968 }
969
970 //-----------------------------------------
971 void
DestroyResCamera(os::IAllocator * allocator,ResCamera resCamera)972 Camera::DestroyResCamera(os::IAllocator* allocator, ResCamera resCamera)
973 {
974 NW_NULL_ASSERT( allocator );
975 if (resCamera.IsValid())
976 {
977 if (resCamera.GetProjectionUpdater().IsValid())
978 {
979 allocator->Free(resCamera.GetProjectionUpdater().ptr());
980 resCamera.ref().toProjectionUpdater.set_ptr(NULL);
981 }
982 if (resCamera.GetViewUpdater().IsValid())
983 {
984 allocator->Free(resCamera.GetViewUpdater().ptr());
985 resCamera.ref().toViewUpdater.set_ptr(NULL);
986 }
987
988 allocator->Free(resCamera.ptr());
989 }
990 }
991
992 //-----------------------------------------
993 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim)994 Camera::GetAnimTargetObject(const anim::ResAnimGroupMember& anim)
995 {
996 switch(anim.GetObjectType())
997 {
998 case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
999 {
1000 return static_cast<gfx::TransformNode*>(this);
1001 }
1002
1003 case anim::ResAnimGroupMember::OBJECT_TYPE_VIEW_UPDATER:
1004 {
1005 ResCameraViewUpdaterData* ptr = GetViewUpdater()->GetResource().ptr();
1006 return ptr;
1007 }
1008
1009 case anim::ResAnimGroupMember::OBJECT_TYPE_PROJECTION_UPDATER:
1010 {
1011 ResCameraProjectionUpdaterData* ptr = GetProjectionUpdater()->GetResource().ptr();
1012 return ptr;
1013 }
1014
1015 default:
1016 NW_ASSERT(false);
1017 return NULL;
1018 }
1019 }
1020
1021 //----------------------------------------
1022 Result
Initialize(os::IAllocator * allocator)1023 Camera::Initialize(os::IAllocator* allocator)
1024 {
1025 Result result = INITIALIZE_RESULT_OK;
1026
1027 result |= TransformNode::Initialize(allocator);
1028 NW_ENSURE_AND_RETURN(result);
1029
1030 result |= StoreOriginal(allocator);
1031 result |= CreateAnimGroup(allocator);
1032
1033 return result;
1034 }
1035
1036 } // namespace gfx
1037 } // namespace nw
1038