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