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: 29649 $
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; // 名前をつけるようになったら、GetMemorySize() を修正する必要あり。
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 = 0;
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.0f, 0.0f);
259     resCamera->m_Transform = math::Transform3(scale, rotate, translate);
260     resCamera->m_WorldMatrix = math::MTX34::Identity();
261     ResTransformNode(resCamera).SetBranchVisible(true);
262 
263     void* memory = allocator->Alloc(sizeof(Camera));
264     NW_NULL_ASSERT(memory);
265 
266     Camera* camera = new(memory) Camera(
267         allocator,
268         ResCamera(resCamera),
269         m_Description,
270         m_ViewUpdater,
271         m_ProjectionUpdater,
272         0.0f,
273         true);
274 
275     camera->Initialize(allocator);
276 
277     return camera;
278 }
279 
280 //----------------------------------------------------------
281 size_t
GetMemorySize(size_t alignment) const282 Camera::DynamicBuilder::GetMemorySize(size_t alignment) const
283 {
284     NW_ASSERT(this->m_Description.isFixedSizeMemory);
285 
286     os::MemorySizeCalculator size(alignment);
287 
288     ResCamera::ViewType viewType;
289     ResCamera::ProjType projType;
290 
291     // DynamicBuilder::Create
292     if (!this->m_ViewUpdater)
293     {
294         LookAtTargetViewUpdater::GetMemorySizeInternal(&size, true);
295         viewType = ResCamera::VIEWTYPE_LOOKAT;
296     }
297     else
298     {
299         switch (this->m_ViewUpdater->GetResource().GetTypeInfo())
300         {
301         case ResAimTargetViewUpdater::TYPE_INFO:
302             viewType = ResCamera::VIEWTYPE_AIM;
303             break;
304         case ResLookAtTargetViewUpdater::TYPE_INFO:
305             viewType = ResCamera::VIEWTYPE_LOOKAT;
306             break;
307         case ResRotateViewUpdater::TYPE_INFO:
308             viewType = ResCamera::VIEWTYPE_ROTATE;
309             break;
310         default:
311             NW_ASSERT(false);
312         }
313     }
314     if (!this->m_ProjectionUpdater)
315     {
316         PerspectiveProjectionUpdater::GetMemorySizeInternal(&size, true);
317         projType = ResCamera::PROJTYPE_PERSPECTIVE;
318     }
319     else
320     {
321         switch (this->m_ProjectionUpdater->GetResource().GetTypeInfo())
322         {
323         case ResPerspectiveProjectionUpdater::TYPE_INFO:
324             projType = ResCamera::PROJTYPE_PERSPECTIVE;
325             break;
326         case ResFrustumProjectionUpdater::TYPE_INFO:
327             projType = ResCamera::PROJTYPE_FRUSTUM;
328             break;
329         case ResOrthoProjectionUpdater::TYPE_INFO:
330             projType = ResCamera::PROJTYPE_ORTHO;
331             break;
332         default:
333             NW_ASSERT(false);
334         }
335     }
336 
337     size += sizeof(ResCameraData);
338     size += sizeof(Camera);
339 
340     // Camera::Initialize
341     TransformNode::GetMemorySizeForInitialize(
342         &size,
343         res::ResTransformNode(),
344         m_Description);
345 
346     // Camera::StoreOriginal
347     size += sizeof(ResCameraData);
348 
349     switch (viewType)
350     {
351     case ResCamera::VIEWTYPE_AIM:
352         size += sizeof(ResAimTargetViewUpdaterData);
353         break;
354     case ResCamera::VIEWTYPE_LOOKAT:
355         size += sizeof(ResLookAtTargetViewUpdaterData);
356         break;
357     case ResCamera::VIEWTYPE_ROTATE:
358         size += sizeof(ResRotateViewUpdaterData);
359         break;
360     default:
361         NW_ASSERT(false);
362     }
363 
364     switch (projType)
365     {
366     case ResCamera::PROJTYPE_PERSPECTIVE:
367         size += sizeof(ResPerspectiveProjectionUpdaterData);
368         break;
369     case ResCamera::PROJTYPE_FRUSTUM:
370         size += sizeof(ResFrustumProjectionUpdaterData);
371         break;
372     case ResCamera::PROJTYPE_ORTHO:
373         size += sizeof(ResOrthoProjectionUpdaterData);
374         break;
375     default:
376         NW_ASSERT(false);
377     }
378 
379     // Camera::CreateAnimGroup
380     // DynamicBuilder 使用時には何も行なわれない。
381 
382     return size.GetSizeWithPadding(alignment);
383 }
384 
385 //----------------------------------------
386 Camera*
Create(SceneNode * parent,ResSceneObject resource,const Camera::Description & description,os::IAllocator * allocator)387 Camera::Create(
388     SceneNode* parent,
389     ResSceneObject resource,
390     const Camera::Description& description,
391     os::IAllocator* allocator
392 )
393 {
394     NW_NULL_ASSERT(allocator);
395 
396     ResCamera resCamera = ResDynamicCast<ResCamera>(resource);
397     NW_ASSERT(resCamera.IsValid());
398     NW_ASSERT( internal::ResCheckRevision( resCamera ) );
399 
400     void* memory = allocator->Alloc(sizeof(Camera));
401     NW_NULL_ASSERT(memory);
402 
403     // リソースからビューアップデータを作成します。
404     ResCamera::ViewType viewType = resCamera.GetViewType();
405     ResCameraViewUpdater resViewUpdater = resCamera.GetViewUpdater();
406     NW_ASSERT(resViewUpdater.IsValid());
407     NW_ASSERT(viewType < ResCamera::VIEWTYPE_COUNT);
408     CameraViewUpdater* cameraView = NULL;
409     if (viewType == ResCamera::VIEWTYPE_AIM)
410     {
411         ResAimTargetViewUpdater resAimView(resViewUpdater.ptr());
412         AimTargetViewUpdater* aimView = AimTargetViewUpdater::Create(allocator, resAimView);
413         cameraView = aimView;
414     }
415     else if (viewType == ResCamera::VIEWTYPE_LOOKAT)
416     {
417         ResLookAtTargetViewUpdater resLookAtView(resViewUpdater.ptr());
418         LookAtTargetViewUpdater* lookAtView
419             = LookAtTargetViewUpdater::Create(allocator, resLookAtView);
420 
421         cameraView = lookAtView;
422     }
423     else if (viewType == ResCamera::VIEWTYPE_ROTATE)
424     {
425         ResRotateViewUpdater resRotateView(resViewUpdater.ptr());
426         RotateViewUpdater* rotateView = RotateViewUpdater::Create(allocator, resRotateView);
427 
428         cameraView = rotateView;
429     }
430     GfxPtr<CameraViewUpdater> viewUpdater(cameraView);
431 
432     // リソースからプロジェクションアップデータを作成します。
433     ResCamera::ProjType projType = resCamera.GetProjectionType();
434     ResCameraProjectionUpdater resProjectionUpdater = resCamera.GetProjectionUpdater();
435     NW_ASSERT(resProjectionUpdater.IsValid());
436     NW_ASSERT(projType < ResCamera::PROJTYPE_COUNT);
437     CameraProjectionUpdater* cameraProjection = NULL;
438     if (projType == ResCamera::PROJTYPE_PERSPECTIVE)
439     {
440         ResPerspectiveProjectionUpdater resPersProjection(resProjectionUpdater.ptr());
441         PerspectiveProjectionUpdater* persProjection =
442             PerspectiveProjectionUpdater::Create(allocator, resPersProjection);
443 
444         cameraProjection = persProjection;
445     }
446     else if (projType == ResCamera::PROJTYPE_FRUSTUM)
447     {
448         ResFrustumProjectionUpdater resFrustumProjection(resProjectionUpdater.ptr());
449         FrustumProjectionUpdater* frustumProjection = FrustumProjectionUpdater::Create(allocator, resFrustumProjection);
450 
451         cameraProjection = frustumProjection;
452     }
453     else if (projType == ResCamera::PROJTYPE_ORTHO)
454     {
455         ResOrthoProjectionUpdater resOrthoProjection(resProjectionUpdater.ptr());
456         OrthoProjectionUpdater* orthoProjection = OrthoProjectionUpdater::Create(allocator, resOrthoProjection);
457 
458         cameraProjection = orthoProjection;
459     }
460     GfxPtr<CameraProjectionUpdater> projectionUpdater(cameraProjection);
461 
462     Camera* camera = new(memory) Camera(
463         allocator,
464         resCamera,
465         description,
466         viewUpdater,
467         projectionUpdater,
468         resCamera.GetWScale(),
469         false);
470 
471     camera->Initialize(allocator);
472 
473     if (parent)
474     {
475         bool result = parent->AttachChild(camera);
476         NW_ASSERT(result);
477     }
478 
479     return camera;
480 }
481 
482 //----------------------------------------------------------
483 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResCamera resCamera,Description description)484 Camera::GetMemorySizeInternal(
485     os::MemorySizeCalculator* pSize,
486     ResCamera resCamera,
487     Description description
488 )
489 {
490     NW_ASSERT(description.isFixedSizeMemory);
491 
492     os::MemorySizeCalculator& size = *pSize;
493 
494     // Camera::Create
495     size += sizeof(Camera);
496 
497     ResCamera::ViewType viewType = resCamera.GetViewType();
498     NW_ASSERT(viewType < ResCamera::VIEWTYPE_COUNT);
499     if (viewType == ResCamera::VIEWTYPE_AIM)
500     {
501         AimTargetViewUpdater::GetMemorySizeInternal(&size, false);
502     }
503     else if (viewType == ResCamera::VIEWTYPE_LOOKAT)
504     {
505         LookAtTargetViewUpdater::GetMemorySizeInternal(&size, false);
506     }
507     else if (viewType == ResCamera::VIEWTYPE_ROTATE)
508     {
509         RotateViewUpdater::GetMemorySizeInternal(&size, false);
510     }
511 
512     ResCamera::ProjType projType = resCamera.GetProjectionType();
513     NW_ASSERT(projType < ResCamera::PROJTYPE_COUNT);
514     if (projType == ResCamera::PROJTYPE_PERSPECTIVE)
515     {
516         PerspectiveProjectionUpdater::GetMemorySizeInternal(&size, false);
517     }
518     else if (projType == ResCamera::PROJTYPE_FRUSTUM)
519     {
520         FrustumProjectionUpdater::GetMemorySizeInternal(&size, false);
521     }
522     else if (projType == ResCamera::PROJTYPE_ORTHO)
523     {
524         OrthoProjectionUpdater::GetMemorySizeInternal(&size, false);
525     }
526 
527     // Camera::Initialize
528     TransformNode::GetMemorySizeForInitialize(&size, resCamera, description);
529 
530     // Camera::StoreOriginal
531     size += sizeof(ResCameraData);
532 
533     switch (viewType)
534     {
535     case ResCamera::VIEWTYPE_AIM:
536         size += sizeof(ResAimTargetViewUpdaterData);
537         break;
538     case ResCamera::VIEWTYPE_LOOKAT:
539         size += sizeof(ResLookAtTargetViewUpdaterData);
540         break;
541     case ResCamera::VIEWTYPE_ROTATE:
542         size += sizeof(ResRotateViewUpdaterData);
543         break;
544     default:
545         NW_ASSERT(false);
546     }
547 
548     switch (projType)
549     {
550     case ResCamera::PROJTYPE_PERSPECTIVE:
551         size += sizeof(ResPerspectiveProjectionUpdaterData);
552         break;
553     case ResCamera::PROJTYPE_FRUSTUM:
554         size += sizeof(ResFrustumProjectionUpdaterData);
555         break;
556     case ResCamera::PROJTYPE_ORTHO:
557         size += sizeof(ResOrthoProjectionUpdaterData);
558         break;
559     default:
560         NW_ASSERT(false);
561     }
562 
563     // Camera::CreateAnimGroup
564     if (description.isAnimationEnabled &&
565         resCamera.GetAnimGroupsCount() > 0)
566     {
567         AnimGroup::Builder()
568             .ResAnimGroup(resCamera.GetAnimGroups(0))
569             .UseOriginalValue(true)
570             .GetMemorySizeInternal(&size);
571     }
572 }
573 
574 //----------------------------------------
575 void
Accept(ISceneVisitor * visitor)576 Camera::Accept(
577     ISceneVisitor* visitor
578 )
579 {
580     visitor->VisitCamera(this);
581     AcceptChildren(visitor);
582 }
583 
584 //----------------------------------------
585 void
UpdateCameraMatrix()586 Camera::UpdateCameraMatrix()
587 {
588     NW_NULL_ASSERT(this->m_ViewUpdater);
589     NW_NULL_ASSERT(this->m_ProjectionUpdater);
590 
591     SceneNode* parentNode = this->GetParent();
592 
593     math::VEC3 cameraPosition(this->WorldMatrix().GetColumn(3));
594 
595     if (parentNode != NULL)
596     {
597         this->m_ViewUpdater->Update(&this->m_ViewMatrix, parentNode->TrackbackWorldMatrix(), cameraPosition);
598     }
599     else
600     {
601         this->m_ViewUpdater->Update(&this->m_ViewMatrix, math::MTX34::Identity(), cameraPosition);
602     }
603 
604     NW_FAILSAFE_IF(math::MTX34Inverse(&this->m_InverseViewMatrix, &this->m_ViewMatrix) == 0)
605     {
606         this->m_InverseViewMatrix = math::MTX34::Identity();
607     }
608 
609     this->m_ProjectionUpdater->Update(&this->m_ProjectionMatrix, &this->m_TextureProjectionMatrix);
610 
611     NW_FAILSAFE_IF(math::MTX44Inverse(&this->m_InverseProjectionMatrix, &this->m_ProjectionMatrix) == 0)
612     {
613         this->m_InverseProjectionMatrix = math::MTX34::Identity();
614     }
615 }
616 
617 
618 
619 //----------------------------------------
620 const nw::math::VEC3&
GetTargetPosition() const621 Camera::GetTargetPosition() const
622 {
623     const ResAimTargetViewUpdater resAim =
624         ResDynamicCast<const ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
625     const ResLookAtTargetViewUpdater resLookAt =
626         ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
627 
628     if (resAim.IsValid())
629     {
630         return resAim.GetTargetPosition();
631     }
632     else if (resLookAt.IsValid())
633     {
634         return resLookAt.GetTargetPosition();
635     }
636     else
637     {
638         NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
639         return resAim.GetTargetPosition();
640     }
641 }
642 
643 //----------------------------------------
644 void
SetTargetPosition(const nw::math::VEC3 & targetPosition)645 Camera::SetTargetPosition(const nw::math::VEC3& targetPosition)
646 {
647     ResAimTargetViewUpdater resAim =
648         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
649     ResLookAtTargetViewUpdater resLookAt =
650         ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
651 
652     if (resAim.IsValid())
653     {
654         resAim.SetTargetPosition(targetPosition);
655     }
656     else if (resLookAt.IsValid())
657     {
658         resLookAt.SetTargetPosition(targetPosition);
659     }
660     else
661     {
662         NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
663     }
664 }
665 
666 //----------------------------------------
667 const nw::math::VEC3&
GetUpwardVector() const668 Camera::GetUpwardVector() const
669 {
670     const ResLookAtTargetViewUpdater resLookAt =
671         ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
672 
673     NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
674 
675     return resLookAt.GetUpwardVector();
676 }
677 
678 //----------------------------------------
679 void
SetUpwardVector(const nw::math::VEC3 & upwardVector)680 Camera::SetUpwardVector(const nw::math::VEC3& upwardVector)
681 {
682     ResLookAtTargetViewUpdater resLookAt =
683         ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
684 
685     NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
686 
687     resLookAt.SetUpwardVector(upwardVector);
688 }
689 
690 //----------------------------------------
691 f32
GetTwist() const692 Camera::GetTwist() const
693 {
694     ResAimTargetViewUpdater resAim =
695         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
696 
697     NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
698 
699     return resAim.GetTwist();
700 }
701 
702 //----------------------------------------
703 void
SetTwist(f32 twist)704 Camera::SetTwist(f32 twist)
705 {
706     ResAimTargetViewUpdater resAim =
707         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
708 
709     NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
710 
711     resAim.SetTwist(twist);
712 }
713 
714 //----------------------------------------
715 const nw::math::VEC3&
GetViewRotate() const716 Camera::GetViewRotate() const
717 {
718     const ResRotateViewUpdater resRotate =
719         ResDynamicCast<const ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
720 
721     NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
722 
723     return resRotate.GetViewRotate();
724 }
725 
726 //----------------------------------------
727 void
SetViewRotate(const nw::math::VEC3 & viewRotate)728 Camera::SetViewRotate(const nw::math::VEC3& viewRotate)
729 {
730     ResRotateViewUpdater resRotate =
731         ResDynamicCast<ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
732 
733     NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
734 
735     resRotate.SetViewRotate(viewRotate);
736 }
737 
738 
739 
740 
741 //----------------------------------------
742 void
GetPerspective(f32 * fovy,f32 * aspectRatio,f32 * nearClip,f32 * farClip) const743 Camera::GetPerspective(
744     f32* fovy,
745     f32* aspectRatio,
746     f32* nearClip,
747     f32* farClip
748 ) const
749 {
750     const ResPerspectiveProjectionUpdater resource =
751         ResDynamicCast<const ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
752 
753     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
754 
755     if (fovy)
756     {
757         *fovy = resource.GetFovy();
758     }
759     if (aspectRatio)
760     {
761         *aspectRatio = resource.GetAspectRatio();
762     }
763     if (nearClip)
764     {
765         *nearClip = resource.GetNear();
766     }
767     if (farClip)
768     {
769         *farClip = resource.GetFar();
770     }
771 }
772 
773 //----------------------------------------
774 void
SetPerspective(f32 fovy,f32 aspectRatio,f32 nearClip,f32 farClip)775 Camera::SetPerspective(
776     f32 fovy,
777     f32 aspectRatio,
778     f32 nearClip,
779     f32 farClip
780 )
781 {
782     ResPerspectiveProjectionUpdater resource =
783         ResDynamicCast<ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
784 
785     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
786 
787     resource.SetFovy(fovy);
788     resource.SetAspectRatio(aspectRatio);
789     resource.SetNear(nearClip);
790     resource.SetFar(farClip);
791 }
792 
793 //----------------------------------------
794 void
GetFrustum(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const795 Camera::GetFrustum(
796     f32* left,
797     f32* right,
798     f32* bottom,
799     f32* top,
800     f32* nearClip,
801     f32* farClip
802 ) const
803 {
804     const ResFrustumProjectionUpdater resource =
805         ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
806 
807     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
808 
809     if (left && right && bottom && top)
810     {
811         const ut::Rect rect = resource.GetRect();
812         if (left)
813         {
814             *left = rect.left;
815         }
816         if (right)
817         {
818             *right = rect.right;
819         }
820         if (bottom)
821         {
822             *bottom = rect.bottom;
823         }
824         if (top)
825         {
826             *top = rect.top;
827         }
828     }
829     if (nearClip)
830     {
831         *nearClip = resource.GetNear();
832     }
833     if (farClip)
834     {
835         *farClip = resource.GetFar();
836     }
837 }
838 
839 //----------------------------------------
840 void
SetFrustum(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)841 Camera::SetFrustum(
842     f32 left,
843     f32 right,
844     f32 bottom,
845     f32 top,
846     f32 nearClip,
847     f32 farClip
848 )
849 {
850     ResFrustumProjectionUpdater resource =
851         ResDynamicCast<ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
852 
853     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
854 
855     resource.SetRectWithoutFlip(left, right, bottom, top);
856     resource.SetNear(nearClip);
857     resource.SetFar(farClip);
858 }
859 
860 //----------------------------------------
861 void
GetOrtho(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const862 Camera::GetOrtho(
863     f32* left,
864     f32* right,
865     f32* bottom,
866     f32* top,
867     f32* nearClip,
868     f32* farClip
869 ) const
870 {
871     const ResOrthoProjectionUpdater resource =
872         ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
873 
874     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
875 
876     if (left && right && bottom && top)
877     {
878         const ut::Rect rect = resource.GetRect();
879         if (left)
880         {
881             *left = rect.left;
882         }
883         if (right)
884         {
885             *right = rect.right;
886         }
887         if (bottom)
888         {
889             *bottom = rect.bottom;
890         }
891         if (top)
892         {
893             *top = rect.top;
894         }
895     }
896     if (nearClip)
897     {
898         *nearClip = resource.GetNear();
899     }
900     if (farClip)
901     {
902         *farClip = resource.GetFar();
903     }
904 }
905 
906 //----------------------------------------
907 void
SetOrtho(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)908 Camera::SetOrtho(
909     f32 left,
910     f32 right,
911     f32 bottom,
912     f32 top,
913     f32 nearClip,
914     f32 farClip
915 )
916 {
917     ResOrthoProjectionUpdater resource =
918         ResDynamicCast<ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
919 
920     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
921 
922     resource.SetRectWithoutFlip(left, right, bottom, top);
923     resource.SetNear(nearClip);
924     resource.SetFar(farClip);
925 }
926 
927 //----------------------------------------
928 void
GetFrustum(ut::Rect * rect,f32 * nearClip,f32 * farClip) const929 Camera::GetFrustum(
930     ut::Rect* rect,
931     f32* nearClip,
932     f32* farClip
933 ) const
934 {
935     const ResFrustumProjectionUpdater resource =
936         ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
937 
938     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
939 
940     if (rect)
941     {
942         *rect = resource.GetRect();
943     }
944     if (nearClip)
945     {
946         *nearClip = resource.GetNear();
947     }
948     if (farClip)
949     {
950         *farClip = resource.GetFar();
951     }
952 }
953 
954 //----------------------------------------
955 void
SetFrustum(const ut::Rect & rect,f32 nearClip,f32 farClip)956 Camera::SetFrustum(
957     const ut::Rect& rect,
958     f32 nearClip,
959     f32 farClip
960 )
961 {
962     SetFrustum(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
963 }
964 
965 //----------------------------------------
966 void
GetOrtho(ut::Rect * rect,f32 * nearClip,f32 * farClip) const967 Camera::GetOrtho(
968     ut::Rect* rect,
969     f32* nearClip,
970     f32* farClip
971 ) const
972 {
973     const ResOrthoProjectionUpdater resource =
974         ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
975 
976     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
977 
978     if (rect)
979     {
980         *rect = resource.GetRect();
981     }
982     if (nearClip)
983     {
984         *nearClip = resource.GetNear();
985     }
986     if (farClip)
987     {
988         *farClip = resource.GetFar();
989     }
990 }
991 
992 //----------------------------------------
993 void
SetOrtho(const ut::Rect & rect,f32 nearClip,f32 farClip)994 Camera::SetOrtho(
995     const ut::Rect& rect,
996     f32 nearClip,
997     f32 farClip
998 )
999 {
1000     SetOrtho(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
1001 }
1002 
1003 //----------------------------------------
1004 void
SetFrustum(const Viewport & viewport)1005 Camera::SetFrustum(
1006     const Viewport& viewport
1007 )
1008 {
1009     SetFrustum(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
1010 }
1011 
1012 //----------------------------------------
1013 void
SetOrtho(const Viewport & viewport)1014 Camera::SetOrtho(
1015     const Viewport& viewport
1016 )
1017 {
1018     SetOrtho(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
1019 }
1020 
1021 //-----------------------------------------
1022 f32
GetNear() const1023 Camera::GetNear() const
1024 {
1025     const ResCameraProjectionUpdater resource =
1026         ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1027 
1028     NW_ASSERT(resource.IsValid());
1029 
1030     return resource.GetNear();
1031 }
1032 
1033 //-----------------------------------------
1034 void
SetNear(f32 near)1035 Camera::SetNear(f32 near)
1036 {
1037     ResCameraProjectionUpdater resource =
1038         ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1039 
1040     NW_ASSERT(resource.IsValid());
1041 
1042     resource.SetNear(near);
1043 }
1044 
1045 //-----------------------------------------
1046 f32
GetFar() const1047 Camera::GetFar() const
1048 {
1049     const ResCameraProjectionUpdater resource =
1050         ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1051 
1052     NW_ASSERT(resource.IsValid());
1053 
1054     return resource.GetFar();
1055 }
1056 
1057 //-----------------------------------------
1058 void
SetFar(f32 far)1059 Camera::SetFar(f32 far)
1060 {
1061     ResCameraProjectionUpdater resource =
1062         ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1063 
1064     NW_ASSERT(resource.IsValid());
1065 
1066     resource.SetFar(far);
1067 }
1068 
1069 //----------------------------------------
1070 Result
StoreOriginal(os::IAllocator * allocator)1071 Camera::StoreOriginal(os::IAllocator* allocator)
1072 {
1073     Result result = INITIALIZE_RESULT_OK;
1074 
1075     ResCamera original = this->GetResCamera();
1076     NW_NULL_ASSERT(original.GetViewUpdater().ptr());
1077     NW_NULL_ASSERT(original.GetProjectionUpdater().ptr());
1078 
1079     void* cameraMemory = allocator->Alloc(sizeof(ResCameraData));
1080     NW_NULL_ASSERT(cameraMemory);
1081 
1082     ResCameraData* cameraData =
1083         new(cameraMemory) ResCameraData(original.ref());
1084 
1085     cameraData->toViewUpdater = NULL;
1086     cameraData->toProjectionUpdater = NULL;
1087 
1088     // viewUpdaterのコピー
1089     void* viewUpdaterMemory = NULL;
1090     ResCameraViewUpdaterData* viewUpdaterData = NULL;
1091     switch (original.GetViewType())
1092     {
1093     case ResCamera::VIEWTYPE_AIM:
1094         viewUpdaterMemory = allocator->Alloc(sizeof(ResAimTargetViewUpdaterData));
1095         NW_NULL_ASSERT(viewUpdaterMemory);
1096         viewUpdaterData =
1097             new(viewUpdaterMemory) ResAimTargetViewUpdaterData(
1098                 *reinterpret_cast<ResAimTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
1099         break;
1100 
1101     case ResCamera::VIEWTYPE_LOOKAT:
1102         viewUpdaterMemory = allocator->Alloc(sizeof(ResLookAtTargetViewUpdaterData));
1103         NW_NULL_ASSERT(viewUpdaterMemory);
1104         viewUpdaterData =
1105             new(viewUpdaterMemory) ResLookAtTargetViewUpdaterData(
1106                 *reinterpret_cast<ResLookAtTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
1107         break;
1108 
1109     case ResCamera::VIEWTYPE_ROTATE:
1110         viewUpdaterMemory = allocator->Alloc(sizeof(ResRotateViewUpdaterData));
1111         NW_NULL_ASSERT(viewUpdaterMemory);
1112         viewUpdaterData =
1113             new(viewUpdaterMemory) ResRotateViewUpdaterData(
1114                 *reinterpret_cast<ResRotateViewUpdaterData*>(original.GetViewUpdater().ptr()));
1115         break;
1116 
1117     default:
1118         NW_ASSERT(false);
1119     }
1120 
1121     cameraData->toViewUpdater.set_ptr(viewUpdaterData);
1122 
1123     // ProjectionUpdaterのコピー
1124     void* projectionUpdaterMemory = NULL;
1125     ResCameraProjectionUpdaterData* projectionUpdaterData = NULL;
1126 
1127     switch (original.GetProjectionType())
1128     {
1129     case ResCamera::PROJTYPE_PERSPECTIVE:
1130         projectionUpdaterMemory = allocator->Alloc(sizeof(ResPerspectiveProjectionUpdaterData));
1131         NW_NULL_ASSERT(projectionUpdaterMemory);
1132         projectionUpdaterData =
1133             new(projectionUpdaterMemory) ResPerspectiveProjectionUpdaterData(
1134                 *reinterpret_cast<ResPerspectiveProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1135         break;
1136 
1137     case ResCamera::PROJTYPE_FRUSTUM:
1138         projectionUpdaterMemory = allocator->Alloc(sizeof(ResFrustumProjectionUpdaterData));
1139         NW_NULL_ASSERT(projectionUpdaterMemory);
1140         projectionUpdaterData =
1141             new(projectionUpdaterMemory) ResFrustumProjectionUpdaterData(
1142                 *reinterpret_cast<ResFrustumProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1143         break;
1144 
1145     case ResCamera::PROJTYPE_ORTHO:
1146         projectionUpdaterMemory = allocator->Alloc(sizeof(ResOrthoProjectionUpdaterData));
1147         NW_NULL_ASSERT(projectionUpdaterMemory);
1148         projectionUpdaterData =
1149             new(projectionUpdaterMemory) ResOrthoProjectionUpdaterData(
1150                 *reinterpret_cast<ResOrthoProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1151         break;
1152 
1153     default:
1154         NW_ASSERT(false);
1155     }
1156 
1157     cameraData->toProjectionUpdater.set_ptr(projectionUpdaterData);
1158 
1159     // メンバに保存
1160     m_OriginalValue = ResCamera(cameraData);
1161 
1162     // CalculatedTransformを保存
1163     m_OriginalTransform = this->GetResTransformNode().GetTransform();
1164 
1165     return result;
1166 }
1167 
1168 //-----------------------------------------
1169 void
DestroyResCamera(os::IAllocator * allocator,ResCamera resCamera)1170 Camera::DestroyResCamera(os::IAllocator* allocator, ResCamera resCamera)
1171 {
1172     NW_NULL_ASSERT( allocator );
1173     if (resCamera.IsValid())
1174     {
1175         if (resCamera.GetProjectionUpdater().IsValid())
1176         {
1177             allocator->Free(resCamera.GetProjectionUpdater().ptr());
1178             resCamera.ref().toProjectionUpdater.set_ptr(NULL);
1179         }
1180         if (resCamera.GetViewUpdater().IsValid())
1181         {
1182             allocator->Free(resCamera.GetViewUpdater().ptr());
1183             resCamera.ref().toViewUpdater.set_ptr(NULL);
1184         }
1185 
1186         allocator->Free(resCamera.ptr());
1187     }
1188 }
1189 
1190 //-----------------------------------------
1191 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim)1192 Camera::GetAnimTargetObject(const anim::ResAnimGroupMember& anim)
1193 {
1194     switch(anim.GetObjectType())
1195     {
1196     case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
1197         {
1198             return static_cast<gfx::TransformNode*>(this);
1199         }
1200 
1201     case anim::ResAnimGroupMember::OBJECT_TYPE_VIEW_UPDATER:
1202         {
1203             ResCameraViewUpdaterData* ptr = GetViewUpdater()->GetResource().ptr();
1204             return ptr;
1205         }
1206 
1207     case anim::ResAnimGroupMember::OBJECT_TYPE_PROJECTION_UPDATER:
1208         {
1209             ResCameraProjectionUpdaterData* ptr = GetProjectionUpdater()->GetResource().ptr();
1210             return ptr;
1211         }
1212 
1213     default:
1214         NW_ASSERT(false);
1215         return NULL;
1216     }
1217 }
1218 
1219 //----------------------------------------
1220 Result
Initialize(os::IAllocator * allocator)1221 Camera::Initialize(os::IAllocator* allocator)
1222 {
1223     Result result = INITIALIZE_RESULT_OK;
1224 
1225     result |= TransformNode::Initialize(allocator);
1226     NW_ENSURE_AND_RETURN(result);
1227 
1228     result |= StoreOriginal(allocator);
1229     result |= CreateAnimGroup(allocator);
1230 
1231     return result;
1232 }
1233 
1234 //----------------------------------------
1235 bool
ValidateCameraAnimType(AnimObject * animObject)1236 Camera::ValidateCameraAnimType(AnimObject* animObject)
1237 {
1238     if (animObject == NULL)
1239     {
1240         // NULLの時はアニメを取り外そうとしているので、型チェックは通る
1241         return true;
1242     }
1243 
1244     // blenderならば、再帰的に調べないといけない
1245     AnimBlender* blender = ut::DynamicCast<AnimBlender*>(animObject);
1246 
1247     if (blender != NULL)
1248     {
1249         const int animObjCount = blender->GetAnimObjectCount();
1250         for (int i = 0; i < animObjCount; ++i)
1251         {
1252             AnimObject* animObj = blender->GetAnimObject(i);
1253 
1254             // ひとつでもvalidateに失敗したらfalseを返す
1255             if (!ValidateCameraAnimType(animObj))
1256             {
1257                 return false;
1258             }
1259         }
1260 
1261         // 全てのAnimObjectのチェックを通過すれば成功
1262         return true;
1263     }
1264     else
1265     {
1266         // blenderではなかったので、AnimEvaluatorのはず
1267         AnimEvaluator* evaluator = ut::DynamicCast<AnimEvaluator*>(animObject);
1268         NW_NULL_ASSERT(evaluator);
1269 
1270         anim::ResCameraAnim cameraAnim(evaluator->GetAnimData().ptr());
1271 
1272         return (
1273             (cameraAnim.GetProjectionUpdaterKind() == m_ProjectionUpdater->Kind()) &&
1274             (cameraAnim.GetViewUpdaterKind() == m_ViewUpdater->Kind()));
1275     }
1276 }
1277 
1278 } // namespace gfx
1279 } // namespace nw
1280