1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Camera.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31408 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/gfx/res/gfx_ResCamera.h>
21 #include <nw/gfx/gfx_Camera.h>
22 #include <nw/gfx/gfx_ISceneVisitor.h>
23 #include <nw/gfx/gfx_AimTargetViewUpdater.h>
24 #include <nw/gfx/gfx_AnimEvaluator.h>
25 #include <nw/gfx/gfx_LookAtTargetViewUpdater.h>
26 #include <nw/gfx/gfx_RotateViewUpdater.h>
27 #include <nw/gfx/gfx_PerspectiveProjectionUpdater.h>
28 #include <nw/gfx/gfx_OrthoProjectionUpdater.h>
29 #include <nw/gfx/gfx_FrustumProjectionUpdater.h>
30 
31 namespace nw
32 {
33 namespace gfx
34 {
35 
36 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Camera, TransformNode);
37 
38 //----------------------------------------
Camera(os::IAllocator * allocator,ResTransformNode resObj,const Camera::Description & description,GfxPtr<CameraViewUpdater> viewUpdater,GfxPtr<CameraProjectionUpdater> projectionUpdater,f32 wscale,bool isDynamic)39 Camera::Camera(
40     os::IAllocator* allocator,
41     ResTransformNode resObj,
42     const Camera::Description& description,
43     GfxPtr<CameraViewUpdater> viewUpdater,
44     GfxPtr<CameraProjectionUpdater> projectionUpdater,
45     f32 wscale,
46     bool isDynamic)
47 : TransformNode(
48     allocator,
49     resObj,
50     description),
51     m_ViewMatrix(math::MTX34::Identity()),
52     m_InverseViewMatrix(math::MTX34::Identity()),
53     m_ProjectionMatrix(math::MTX44::Identity()),
54     m_InverseProjectionMatrix(math::MTX44::Identity()),
55     m_TextureProjectionMatrix(math::MTX34::Identity()),
56     m_ViewUpdater(viewUpdater),
57     m_ProjectionUpdater(projectionUpdater),
58     m_AnimGroup(NULL),
59     m_OriginalValue(),
60     m_WScale(wscale),
61     m_IsDynamic(isDynamic)
62 {}
63 
64 //----------------------------------------
~Camera()65 Camera::~Camera()
66 {
67     ResCamera resCamera = ResDynamicCast<ResCamera>(this->GetResSceneNode());
68     if (this->m_IsDynamic && resCamera.IsValid())
69     {
70         this->GetAllocator().Free(resCamera.ptr());
71     }
72 
73     ResCameraDestroyer(&this->GetAllocator())(m_OriginalValue);
74     m_OriginalValue = ResCamera(NULL);
75 
76     ut::SafeDestroy(m_AnimGroup);
77 }
78 
79 //----------------------------------------
80 Result
CreateAnimGroup(os::IAllocator * allocator)81 Camera::CreateAnimGroup(os::IAllocator* allocator)
82 {
83     Result result = INITIALIZE_RESULT_OK;
84 
85     NW_ASSERT(m_OriginalValue.IsValid());
86 
87     if(!m_AnimBinding)
88     {
89         // DynamicBuilderを使用した場合は生成されない
90         return result;
91     }
92 
93     ResCamera resCamera = GetResCamera();
94     NW_ASSERT(resCamera.IsValid());
95 
96     NW_ASSERT(resCamera.GetAnimGroupsCount() == 1);
97     anim::ResAnimGroup resAnimGroup = resCamera.GetAnimGroups(0);
98 
99     NW_ASSERT(resAnimGroup.GetTargetType() == anim::ResGraphicsAnimGroup::TARGET_TYPE_CAMERA);
100 
101     AnimGroup* animGroup = AnimGroup::Builder()
102         .ResAnimGroup(resAnimGroup)
103         .SetSceneNode(this)
104         .UseOriginalValue(true) // TODO: 選択できる必要はある?
105         .Create(allocator);
106 
107     if (animGroup == NULL)
108     {
109         result |= Result::MASK_FAIL_BIT;
110     }
111 
112     NW_ENSURE_AND_RETURN(result);
113 
114     m_AnimGroup = animGroup;
115 
116     // 各メンバの参照解決
117     const int animMemberCount = m_AnimGroup->GetMemberCount();
118     for (int memberIdx = 0; memberIdx < animMemberCount; ++memberIdx)
119     {
120         anim::ResAnimGroupMember member = m_AnimGroup->GetResAnimGroupMember(memberIdx);
121 
122         void* object = GetAnimTargetObject(member);
123         m_AnimGroup->SetTargetObject(memberIdx, object);
124 
125         // TODO: アドレス算出もSetterに似た実装で行う?
126         if(member.GetObjectType() == anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM &&
127             member.GetMemberType() == anim::ResTransformMember::MEMBER_TYPE_TRANSFORM)
128         {
129             m_AnimGroup->SetTargetPtr(memberIdx, &this->Transform());
130         }
131         else
132         {
133             u8* target = static_cast<u8*>(object);
134             target += member.GetMemberOffset();
135             m_AnimGroup->SetTargetPtr(memberIdx, target);
136         }
137 
138         m_AnimGroup->SetTargetObjectIndex(memberIdx, 0); // TODO: 要検討
139 
140         // OriginalValueを登録する
141         void* originalValue = NULL;
142         switch (member.GetObjectType())
143         {
144         case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
145             {
146                 switch (member.GetMemberType())
147                 {
148                 case anim::ResTransformMember::MEMBER_TYPE_TRANSFORM:
149                     originalValue = &m_OriginalTransform;
150                     break;
151                 default:
152                     NW_ASSERT(false);
153                 }
154             }
155             break;
156         case anim::ResAnimGroupMember::OBJECT_TYPE_VIEW_UPDATER:
157             {
158                 originalValue =
159                     ut::AddOffsetToPtr(m_OriginalValue.GetViewUpdater().ptr(), member.GetMemberOffset());
160             }
161             break;
162         case anim::ResAnimGroupMember::OBJECT_TYPE_PROJECTION_UPDATER:
163             {
164                 originalValue =
165                     ut::AddOffsetToPtr(m_OriginalValue.GetProjectionUpdater().ptr(), member.GetMemberOffset());
166             }
167             break;
168         default:
169             NW_ASSERT(false);
170         }
171 
172         NW_NULL_ASSERT(originalValue);
173         m_AnimGroup->SetOriginalValue(memberIdx, originalValue);
174     }
175 
176     m_AnimBinding->SetAnimGroup(0, m_AnimGroup);
177 
178     return result;
179 }
180 
181 //----------------------------------------
182 Camera*
Create(os::IAllocator * allocator)183 Camera::DynamicBuilder::Create(
184     os::IAllocator* allocator
185 )
186 {
187     NW_NULL_ASSERT(allocator);
188 
189     if (!this->m_ViewUpdater)
190     {
191         this->m_ViewUpdater.Reset(LookAtTargetViewUpdater::Create(allocator));
192     }
193 
194     if (!this->m_ProjectionUpdater)
195     {
196         this->m_ProjectionUpdater.Reset(PerspectiveProjectionUpdater::Create(allocator));
197     }
198 
199     // カメラを生成します。
200 
201     ResCameraData* resCamera =
202         AllocateAndFillN<ResCameraData>(allocator, sizeof(ResCameraData), 0);
203 
204     // カメラのリソースに、各Updaterを結び付けます。
205     resCamera->toViewUpdater.set_ptr(this->m_ViewUpdater->GetResource().ptr());
206     resCamera->toProjectionUpdater.set_ptr(this->m_ProjectionUpdater->GetResource().ptr());
207 
208     switch (this->m_ViewUpdater->GetResource().GetTypeInfo())
209     {
210         case ResAimTargetViewUpdater::TYPE_INFO:
211             resCamera->m_ViewType = ResCamera::VIEWTYPE_AIM;
212             break;
213         case ResLookAtTargetViewUpdater::TYPE_INFO:
214             resCamera->m_ViewType = ResCamera::VIEWTYPE_LOOKAT;
215             break;
216         case ResRotateViewUpdater::TYPE_INFO:
217             resCamera->m_ViewType = ResCamera::VIEWTYPE_ROTATE;
218             break;
219         default:
220             NW_ASSERT(false);
221     }
222 
223     switch (this->m_ProjectionUpdater->GetResource().GetTypeInfo())
224     {
225         case ResPerspectiveProjectionUpdater::TYPE_INFO:
226             resCamera->m_ProjectionType = ResCamera::PROJTYPE_PERSPECTIVE;
227             break;
228         case ResFrustumProjectionUpdater::TYPE_INFO:
229             resCamera->m_ProjectionType = ResCamera::PROJTYPE_FRUSTUM;
230             break;
231         case ResOrthoProjectionUpdater::TYPE_INFO:
232             resCamera->m_ProjectionType = ResCamera::PROJTYPE_ORTHO;
233             break;
234         default:
235             NW_ASSERT(false);
236     }
237 
238     //--------------------------------
239     // ResSceneObjectData のメンバ初期化
240     resCamera->typeInfo = ResCamera::TYPE_INFO;
241     resCamera->m_Header.revision = ResCamera::BINARY_REVISION;
242     resCamera->m_Header.signature = ResCamera::SIGNATURE;
243 
244     resCamera->m_UserDataDicCount = 0;
245     resCamera->toUserDataDic.set_ptr( NULL );
246 
247     const char* name = NULL; // 名前をつけるようになったら、GetMemorySize() を修正する必要あり。
248     resCamera->toName.set_ptr(AllocateAndCopyString(name, allocator, MAX_NAME_LENGTH));
249 
250     //--------------------------------
251     // ResSceneNodeData のメンバ初期化
252     resCamera->m_ChildrenTableCount = 0;
253     resCamera->toChildrenTable.set_ptr( NULL );
254     resCamera->m_AnimGroupsDicCount = 0;
255     resCamera->toAnimGroupsDic.set_ptr( NULL );
256 
257     //--------------------------------
258     // ResTransformNode のメンバ初期化
259     const math::VEC3 scale(1.0f, 1.0f, 1.0f);
260     const math::VEC3 rotate(0.0f, 0.0f, 0.0f);
261     const math::VEC3 translate(0.0f, 0.0f, 0.0f);
262     resCamera->m_Transform = math::Transform3(scale, rotate, translate);
263     resCamera->m_WorldMatrix = math::MTX34::Identity();
264     ResTransformNode(resCamera).SetBranchVisible(true);
265 
266     void* memory = allocator->Alloc(sizeof(Camera));
267     NW_NULL_ASSERT(memory);
268 
269     Camera* camera = new(memory) Camera(
270         allocator,
271         ResCamera(resCamera),
272         m_Description,
273         m_ViewUpdater,
274         m_ProjectionUpdater,
275         0.0f,
276         true);
277 
278     camera->Initialize(allocator);
279 
280     return camera;
281 }
282 
283 //----------------------------------------------------------
284 size_t
GetMemorySize(size_t alignment) const285 Camera::DynamicBuilder::GetMemorySize(size_t alignment) const
286 {
287     NW_ASSERT(this->m_Description.isFixedSizeMemory);
288 
289     os::MemorySizeCalculator size(alignment);
290 
291     ResCamera::ViewType viewType;
292     ResCamera::ProjType projType;
293 
294     // DynamicBuilder::Create
295     if (!this->m_ViewUpdater)
296     {
297         LookAtTargetViewUpdater::GetMemorySizeInternal(&size, true);
298         viewType = ResCamera::VIEWTYPE_LOOKAT;
299     }
300     else
301     {
302         switch (this->m_ViewUpdater->GetResource().GetTypeInfo())
303         {
304         case ResAimTargetViewUpdater::TYPE_INFO:
305             viewType = ResCamera::VIEWTYPE_AIM;
306             break;
307         case ResLookAtTargetViewUpdater::TYPE_INFO:
308             viewType = ResCamera::VIEWTYPE_LOOKAT;
309             break;
310         case ResRotateViewUpdater::TYPE_INFO:
311             viewType = ResCamera::VIEWTYPE_ROTATE;
312             break;
313         default:
314             NW_ASSERT(false);
315         }
316     }
317     if (!this->m_ProjectionUpdater)
318     {
319         PerspectiveProjectionUpdater::GetMemorySizeInternal(&size, true);
320         projType = ResCamera::PROJTYPE_PERSPECTIVE;
321     }
322     else
323     {
324         switch (this->m_ProjectionUpdater->GetResource().GetTypeInfo())
325         {
326         case ResPerspectiveProjectionUpdater::TYPE_INFO:
327             projType = ResCamera::PROJTYPE_PERSPECTIVE;
328             break;
329         case ResFrustumProjectionUpdater::TYPE_INFO:
330             projType = ResCamera::PROJTYPE_FRUSTUM;
331             break;
332         case ResOrthoProjectionUpdater::TYPE_INFO:
333             projType = ResCamera::PROJTYPE_ORTHO;
334             break;
335         default:
336             NW_ASSERT(false);
337         }
338     }
339 
340     size += sizeof(ResCameraData);
341     size += sizeof(Camera);
342 
343     // Camera::Initialize
344     TransformNode::GetMemorySizeForInitialize(
345         &size,
346         res::ResTransformNode(),
347         m_Description);
348 
349     // Camera::StoreOriginal
350     size += sizeof(ResCameraData);
351 
352     switch (viewType)
353     {
354     case ResCamera::VIEWTYPE_AIM:
355         size += sizeof(ResAimTargetViewUpdaterData);
356         break;
357     case ResCamera::VIEWTYPE_LOOKAT:
358         size += sizeof(ResLookAtTargetViewUpdaterData);
359         break;
360     case ResCamera::VIEWTYPE_ROTATE:
361         size += sizeof(ResRotateViewUpdaterData);
362         break;
363     default:
364         NW_ASSERT(false);
365     }
366 
367     switch (projType)
368     {
369     case ResCamera::PROJTYPE_PERSPECTIVE:
370         size += sizeof(ResPerspectiveProjectionUpdaterData);
371         break;
372     case ResCamera::PROJTYPE_FRUSTUM:
373         size += sizeof(ResFrustumProjectionUpdaterData);
374         break;
375     case ResCamera::PROJTYPE_ORTHO:
376         size += sizeof(ResOrthoProjectionUpdaterData);
377         break;
378     default:
379         NW_ASSERT(false);
380     }
381 
382     // Camera::CreateAnimGroup
383     // DynamicBuilder 使用時には何も行なわれない。
384 
385     return size.GetSizeWithPadding(alignment);
386 }
387 
388 //----------------------------------------
389 Camera*
Create(SceneNode * parent,ResSceneObject resource,const Camera::Description & description,os::IAllocator * allocator)390 Camera::Create(
391     SceneNode* parent,
392     ResSceneObject resource,
393     const Camera::Description& description,
394     os::IAllocator* allocator
395 )
396 {
397     NW_NULL_ASSERT(allocator);
398 
399     ResCamera resCamera = ResDynamicCast<ResCamera>(resource);
400     NW_ASSERT(resCamera.IsValid());
401     NW_ASSERT( internal::ResCheckRevision( resCamera ) );
402 
403     void* memory = allocator->Alloc(sizeof(Camera));
404     NW_NULL_ASSERT(memory);
405 
406     // リソースからビューアップデータを作成します。
407     ResCamera::ViewType viewType = resCamera.GetViewType();
408     ResCameraViewUpdater resViewUpdater = resCamera.GetViewUpdater();
409     NW_ASSERT(resViewUpdater.IsValid());
410     NW_ASSERT(viewType < ResCamera::VIEWTYPE_COUNT);
411     CameraViewUpdater* cameraView = NULL;
412     if (viewType == ResCamera::VIEWTYPE_AIM)
413     {
414         ResAimTargetViewUpdater resAimView(resViewUpdater.ptr());
415         AimTargetViewUpdater* aimView = AimTargetViewUpdater::Create(allocator, resAimView);
416         cameraView = aimView;
417     }
418     else if (viewType == ResCamera::VIEWTYPE_LOOKAT)
419     {
420         ResLookAtTargetViewUpdater resLookAtView(resViewUpdater.ptr());
421         LookAtTargetViewUpdater* lookAtView
422             = LookAtTargetViewUpdater::Create(allocator, resLookAtView);
423 
424         cameraView = lookAtView;
425     }
426     else if (viewType == ResCamera::VIEWTYPE_ROTATE)
427     {
428         ResRotateViewUpdater resRotateView(resViewUpdater.ptr());
429         RotateViewUpdater* rotateView = RotateViewUpdater::Create(allocator, resRotateView);
430 
431         cameraView = rotateView;
432     }
433     GfxPtr<CameraViewUpdater> viewUpdater(cameraView);
434 
435     // リソースからプロジェクションアップデータを作成します。
436     ResCamera::ProjType projType = resCamera.GetProjectionType();
437     ResCameraProjectionUpdater resProjectionUpdater = resCamera.GetProjectionUpdater();
438     NW_ASSERT(resProjectionUpdater.IsValid());
439     NW_ASSERT(projType < ResCamera::PROJTYPE_COUNT);
440     CameraProjectionUpdater* cameraProjection = NULL;
441     if (projType == ResCamera::PROJTYPE_PERSPECTIVE)
442     {
443         ResPerspectiveProjectionUpdater resPersProjection(resProjectionUpdater.ptr());
444         PerspectiveProjectionUpdater* persProjection =
445             PerspectiveProjectionUpdater::Create(allocator, resPersProjection);
446 
447         cameraProjection = persProjection;
448     }
449     else if (projType == ResCamera::PROJTYPE_FRUSTUM)
450     {
451         ResFrustumProjectionUpdater resFrustumProjection(resProjectionUpdater.ptr());
452         FrustumProjectionUpdater* frustumProjection = FrustumProjectionUpdater::Create(allocator, resFrustumProjection);
453 
454         cameraProjection = frustumProjection;
455     }
456     else if (projType == ResCamera::PROJTYPE_ORTHO)
457     {
458         ResOrthoProjectionUpdater resOrthoProjection(resProjectionUpdater.ptr());
459         OrthoProjectionUpdater* orthoProjection = OrthoProjectionUpdater::Create(allocator, resOrthoProjection);
460 
461         cameraProjection = orthoProjection;
462     }
463     GfxPtr<CameraProjectionUpdater> projectionUpdater(cameraProjection);
464 
465     Camera* camera = new(memory) Camera(
466         allocator,
467         resCamera,
468         description,
469         viewUpdater,
470         projectionUpdater,
471         resCamera.GetWScale(),
472         false);
473 
474     camera->Initialize(allocator);
475 
476     if (parent)
477     {
478         bool result = parent->AttachChild(camera);
479         NW_ASSERT(result);
480     }
481 
482     return camera;
483 }
484 
485 //----------------------------------------------------------
486 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResCamera resCamera,Description description)487 Camera::GetMemorySizeInternal(
488     os::MemorySizeCalculator* pSize,
489     ResCamera resCamera,
490     Description description
491 )
492 {
493     NW_ASSERT(description.isFixedSizeMemory);
494 
495     os::MemorySizeCalculator& size = *pSize;
496 
497     // Camera::Create
498     size += sizeof(Camera);
499 
500     ResCamera::ViewType viewType = resCamera.GetViewType();
501     NW_ASSERT(viewType < ResCamera::VIEWTYPE_COUNT);
502     if (viewType == ResCamera::VIEWTYPE_AIM)
503     {
504         AimTargetViewUpdater::GetMemorySizeInternal(&size, false);
505     }
506     else if (viewType == ResCamera::VIEWTYPE_LOOKAT)
507     {
508         LookAtTargetViewUpdater::GetMemorySizeInternal(&size, false);
509     }
510     else if (viewType == ResCamera::VIEWTYPE_ROTATE)
511     {
512         RotateViewUpdater::GetMemorySizeInternal(&size, false);
513     }
514 
515     ResCamera::ProjType projType = resCamera.GetProjectionType();
516     NW_ASSERT(projType < ResCamera::PROJTYPE_COUNT);
517     if (projType == ResCamera::PROJTYPE_PERSPECTIVE)
518     {
519         PerspectiveProjectionUpdater::GetMemorySizeInternal(&size, false);
520     }
521     else if (projType == ResCamera::PROJTYPE_FRUSTUM)
522     {
523         FrustumProjectionUpdater::GetMemorySizeInternal(&size, false);
524     }
525     else if (projType == ResCamera::PROJTYPE_ORTHO)
526     {
527         OrthoProjectionUpdater::GetMemorySizeInternal(&size, false);
528     }
529 
530     // Camera::Initialize
531     TransformNode::GetMemorySizeForInitialize(&size, resCamera, description);
532 
533     // Camera::StoreOriginal
534     size += sizeof(ResCameraData);
535 
536     switch (viewType)
537     {
538     case ResCamera::VIEWTYPE_AIM:
539         size += sizeof(ResAimTargetViewUpdaterData);
540         break;
541     case ResCamera::VIEWTYPE_LOOKAT:
542         size += sizeof(ResLookAtTargetViewUpdaterData);
543         break;
544     case ResCamera::VIEWTYPE_ROTATE:
545         size += sizeof(ResRotateViewUpdaterData);
546         break;
547     default:
548         NW_ASSERT(false);
549     }
550 
551     switch (projType)
552     {
553     case ResCamera::PROJTYPE_PERSPECTIVE:
554         size += sizeof(ResPerspectiveProjectionUpdaterData);
555         break;
556     case ResCamera::PROJTYPE_FRUSTUM:
557         size += sizeof(ResFrustumProjectionUpdaterData);
558         break;
559     case ResCamera::PROJTYPE_ORTHO:
560         size += sizeof(ResOrthoProjectionUpdaterData);
561         break;
562     default:
563         NW_ASSERT(false);
564     }
565 
566     // Camera::CreateAnimGroup
567     if (description.isAnimationEnabled &&
568         resCamera.GetAnimGroupsCount() > 0)
569     {
570         AnimGroup::Builder()
571             .ResAnimGroup(resCamera.GetAnimGroups(0))
572             .UseOriginalValue(true)
573             .GetMemorySizeInternal(&size);
574     }
575 }
576 
577 //----------------------------------------
578 void
Accept(ISceneVisitor * visitor)579 Camera::Accept(
580     ISceneVisitor* visitor
581 )
582 {
583     visitor->VisitCamera(this);
584     AcceptChildren(visitor);
585 }
586 
587 //----------------------------------------
588 void
UpdateCameraMatrix()589 Camera::UpdateCameraMatrix()
590 {
591     NW_NULL_ASSERT(this->m_ViewUpdater);
592     NW_NULL_ASSERT(this->m_ProjectionUpdater);
593 
594     SceneNode* parentNode = this->GetParent();
595 
596     math::VEC3 cameraPosition(this->WorldMatrix().GetColumn(3));
597 
598     if (parentNode != NULL)
599     {
600         this->m_ViewUpdater->Update(&this->m_ViewMatrix, parentNode->TrackbackWorldMatrix(), cameraPosition);
601     }
602     else
603     {
604         this->m_ViewUpdater->Update(&this->m_ViewMatrix, math::MTX34::Identity(), cameraPosition);
605     }
606 
607     NW_FAILSAFE_IF(math::MTX34Inverse(&this->m_InverseViewMatrix, &this->m_ViewMatrix) == 0)
608     {
609         this->m_InverseViewMatrix = math::MTX34::Identity();
610     }
611 
612     this->m_ProjectionUpdater->Update(&this->m_ProjectionMatrix, &this->m_TextureProjectionMatrix);
613 
614     NW_FAILSAFE_IF(math::MTX44Inverse(&this->m_InverseProjectionMatrix, &this->m_ProjectionMatrix) == 0)
615     {
616         this->m_InverseProjectionMatrix = math::MTX44::Identity();
617     }
618 }
619 
620 
621 
622 //----------------------------------------
623 const nw::math::VEC3&
GetTargetPosition() const624 Camera::GetTargetPosition() const
625 {
626     const ResAimTargetViewUpdater resAim =
627         ResDynamicCast<const ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
628     const ResLookAtTargetViewUpdater resLookAt =
629         ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
630 
631     if (resAim.IsValid())
632     {
633         return resAim.GetTargetPosition();
634     }
635     else if (resLookAt.IsValid())
636     {
637         return resLookAt.GetTargetPosition();
638     }
639     else
640     {
641         NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
642         return resAim.GetTargetPosition();
643     }
644 }
645 
646 //----------------------------------------
647 void
SetTargetPosition(const nw::math::VEC3 & targetPosition)648 Camera::SetTargetPosition(const nw::math::VEC3& targetPosition)
649 {
650     ResAimTargetViewUpdater resAim =
651         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
652     ResLookAtTargetViewUpdater resLookAt =
653         ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
654 
655     if (resAim.IsValid())
656     {
657         resAim.SetTargetPosition(targetPosition);
658     }
659     else if (resLookAt.IsValid())
660     {
661         resLookAt.SetTargetPosition(targetPosition);
662     }
663     else
664     {
665         NW_ASSERTMSG(false, "View updater isn't \"Aim\" nor \"LookAt\"");
666     }
667 }
668 
669 //----------------------------------------
670 const nw::math::VEC3&
GetUpwardVector() const671 Camera::GetUpwardVector() const
672 {
673     const ResLookAtTargetViewUpdater resLookAt =
674         ResDynamicCast<const ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
675 
676     NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
677 
678     return resLookAt.GetUpwardVector();
679 }
680 
681 //----------------------------------------
682 void
SetUpwardVector(const nw::math::VEC3 & upwardVector)683 Camera::SetUpwardVector(const nw::math::VEC3& upwardVector)
684 {
685     ResLookAtTargetViewUpdater resLookAt =
686         ResDynamicCast<ResLookAtTargetViewUpdater>( GetViewUpdater()->GetResource() );
687 
688     NW_ASSERTMSG(resLookAt.IsValid(), "View updater isn't \"LookAt\"");
689 
690     resLookAt.SetUpwardVector(upwardVector);
691 }
692 
693 //----------------------------------------
694 f32
GetTwist() const695 Camera::GetTwist() const
696 {
697     ResAimTargetViewUpdater resAim =
698         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
699 
700     NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
701 
702     return resAim.GetTwist();
703 }
704 
705 //----------------------------------------
706 void
SetTwist(f32 twist)707 Camera::SetTwist(f32 twist)
708 {
709     ResAimTargetViewUpdater resAim =
710         ResDynamicCast<ResAimTargetViewUpdater>( GetViewUpdater()->GetResource() );
711 
712     NW_ASSERTMSG(resAim.IsValid(), "View updater isn't \"LookAt\"");
713 
714     resAim.SetTwist(twist);
715 }
716 
717 //----------------------------------------
718 const nw::math::VEC3&
GetViewRotate() const719 Camera::GetViewRotate() const
720 {
721     const ResRotateViewUpdater resRotate =
722         ResDynamicCast<const ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
723 
724     NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
725 
726     return resRotate.GetViewRotate();
727 }
728 
729 //----------------------------------------
730 void
SetViewRotate(const nw::math::VEC3 & viewRotate)731 Camera::SetViewRotate(const nw::math::VEC3& viewRotate)
732 {
733     ResRotateViewUpdater resRotate =
734         ResDynamicCast<ResRotateViewUpdater>( GetViewUpdater()->GetResource() );
735 
736     NW_ASSERTMSG(resRotate.IsValid(), "View updater isn't \"Rotate\"");
737 
738     resRotate.SetViewRotate(viewRotate);
739 }
740 
741 
742 
743 
744 //----------------------------------------
745 void
GetPerspective(f32 * fovy,f32 * aspectRatio,f32 * nearClip,f32 * farClip) const746 Camera::GetPerspective(
747     f32* fovy,
748     f32* aspectRatio,
749     f32* nearClip,
750     f32* farClip
751 ) const
752 {
753     const ResPerspectiveProjectionUpdater resource =
754         ResDynamicCast<const ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
755 
756     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
757 
758     if (fovy)
759     {
760         *fovy = resource.GetFovy();
761     }
762     if (aspectRatio)
763     {
764         *aspectRatio = resource.GetAspectRatio();
765     }
766     if (nearClip)
767     {
768         *nearClip = resource.GetNear();
769     }
770     if (farClip)
771     {
772         *farClip = resource.GetFar();
773     }
774 }
775 
776 //----------------------------------------
777 void
SetPerspective(f32 fovy,f32 aspectRatio,f32 nearClip,f32 farClip)778 Camera::SetPerspective(
779     f32 fovy,
780     f32 aspectRatio,
781     f32 nearClip,
782     f32 farClip
783 )
784 {
785     ResPerspectiveProjectionUpdater resource =
786         ResDynamicCast<ResPerspectiveProjectionUpdater>( GetProjectionUpdater()->GetResource() );
787 
788     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't perspective");
789 
790     resource.SetFovy(fovy);
791     resource.SetAspectRatio(aspectRatio);
792     resource.SetNear(nearClip);
793     resource.SetFar(farClip);
794 }
795 
796 //----------------------------------------
797 void
GetFrustum(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const798 Camera::GetFrustum(
799     f32* left,
800     f32* right,
801     f32* bottom,
802     f32* top,
803     f32* nearClip,
804     f32* farClip
805 ) const
806 {
807     const ResFrustumProjectionUpdater resource =
808         ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
809 
810     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
811 
812     if (left && right && bottom && top)
813     {
814         const ut::Rect rect = resource.GetRect();
815         if (left)
816         {
817             *left = rect.left;
818         }
819         if (right)
820         {
821             *right = rect.right;
822         }
823         if (bottom)
824         {
825             *bottom = rect.bottom;
826         }
827         if (top)
828         {
829             *top = rect.top;
830         }
831     }
832     if (nearClip)
833     {
834         *nearClip = resource.GetNear();
835     }
836     if (farClip)
837     {
838         *farClip = resource.GetFar();
839     }
840 }
841 
842 //----------------------------------------
843 void
SetFrustum(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)844 Camera::SetFrustum(
845     f32 left,
846     f32 right,
847     f32 bottom,
848     f32 top,
849     f32 nearClip,
850     f32 farClip
851 )
852 {
853     ResFrustumProjectionUpdater resource =
854         ResDynamicCast<ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
855 
856     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
857 
858     resource.SetRectWithoutFlip(left, right, bottom, top);
859     resource.SetNear(nearClip);
860     resource.SetFar(farClip);
861 }
862 
863 //----------------------------------------
864 void
GetOrtho(f32 * left,f32 * right,f32 * bottom,f32 * top,f32 * nearClip,f32 * farClip) const865 Camera::GetOrtho(
866     f32* left,
867     f32* right,
868     f32* bottom,
869     f32* top,
870     f32* nearClip,
871     f32* farClip
872 ) const
873 {
874     const ResOrthoProjectionUpdater resource =
875         ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
876 
877     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
878 
879     if (left && right && bottom && top)
880     {
881         const ut::Rect rect = resource.GetRect();
882         if (left)
883         {
884             *left = rect.left;
885         }
886         if (right)
887         {
888             *right = rect.right;
889         }
890         if (bottom)
891         {
892             *bottom = rect.bottom;
893         }
894         if (top)
895         {
896             *top = rect.top;
897         }
898     }
899     if (nearClip)
900     {
901         *nearClip = resource.GetNear();
902     }
903     if (farClip)
904     {
905         *farClip = resource.GetFar();
906     }
907 }
908 
909 //----------------------------------------
910 void
SetOrtho(f32 left,f32 right,f32 bottom,f32 top,f32 nearClip,f32 farClip)911 Camera::SetOrtho(
912     f32 left,
913     f32 right,
914     f32 bottom,
915     f32 top,
916     f32 nearClip,
917     f32 farClip
918 )
919 {
920     ResOrthoProjectionUpdater resource =
921         ResDynamicCast<ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
922 
923     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
924 
925     resource.SetRectWithoutFlip(left, right, bottom, top);
926     resource.SetNear(nearClip);
927     resource.SetFar(farClip);
928 }
929 
930 //----------------------------------------
931 void
GetFrustum(ut::Rect * rect,f32 * nearClip,f32 * farClip) const932 Camera::GetFrustum(
933     ut::Rect* rect,
934     f32* nearClip,
935     f32* farClip
936 ) const
937 {
938     const ResFrustumProjectionUpdater resource =
939         ResDynamicCast<const ResFrustumProjectionUpdater>( GetProjectionUpdater()->GetResource() );
940 
941     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't frustum");
942 
943     if (rect)
944     {
945         *rect = resource.GetRect();
946     }
947     if (nearClip)
948     {
949         *nearClip = resource.GetNear();
950     }
951     if (farClip)
952     {
953         *farClip = resource.GetFar();
954     }
955 }
956 
957 //----------------------------------------
958 void
SetFrustum(const ut::Rect & rect,f32 nearClip,f32 farClip)959 Camera::SetFrustum(
960     const ut::Rect& rect,
961     f32 nearClip,
962     f32 farClip
963 )
964 {
965     SetFrustum(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
966 }
967 
968 //----------------------------------------
969 void
GetOrtho(ut::Rect * rect,f32 * nearClip,f32 * farClip) const970 Camera::GetOrtho(
971     ut::Rect* rect,
972     f32* nearClip,
973     f32* farClip
974 ) const
975 {
976     const ResOrthoProjectionUpdater resource =
977         ResDynamicCast<const ResOrthoProjectionUpdater>( GetProjectionUpdater()->GetResource() );
978 
979     NW_ASSERTMSG(resource.IsValid(), "Projection updater isn't ortho");
980 
981     if (rect)
982     {
983         *rect = resource.GetRect();
984     }
985     if (nearClip)
986     {
987         *nearClip = resource.GetNear();
988     }
989     if (farClip)
990     {
991         *farClip = resource.GetFar();
992     }
993 }
994 
995 //----------------------------------------
996 void
SetOrtho(const ut::Rect & rect,f32 nearClip,f32 farClip)997 Camera::SetOrtho(
998     const ut::Rect& rect,
999     f32 nearClip,
1000     f32 farClip
1001 )
1002 {
1003     SetOrtho(rect.left, rect.right, rect.bottom, rect.top, nearClip, farClip);
1004 }
1005 
1006 //----------------------------------------
1007 void
SetFrustum(const Viewport & viewport)1008 Camera::SetFrustum(
1009     const Viewport& viewport
1010 )
1011 {
1012     SetFrustum(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
1013 }
1014 
1015 //----------------------------------------
1016 void
SetOrtho(const Viewport & viewport)1017 Camera::SetOrtho(
1018     const Viewport& viewport
1019 )
1020 {
1021     SetOrtho(viewport.GetBound(), viewport.GetDepthNear(), viewport.GetDepthFar());
1022 }
1023 
1024 //-----------------------------------------
1025 f32
GetNear() const1026 Camera::GetNear() const
1027 {
1028     const ResCameraProjectionUpdater resource =
1029         ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1030 
1031     NW_ASSERT(resource.IsValid());
1032 
1033     return resource.GetNear();
1034 }
1035 
1036 //-----------------------------------------
1037 void
SetNear(f32 near)1038 Camera::SetNear(f32 near)
1039 {
1040     ResCameraProjectionUpdater resource =
1041         ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1042 
1043     NW_ASSERT(resource.IsValid());
1044 
1045     resource.SetNear(near);
1046 }
1047 
1048 //-----------------------------------------
1049 f32
GetFar() const1050 Camera::GetFar() const
1051 {
1052     const ResCameraProjectionUpdater resource =
1053         ResDynamicCast<const ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1054 
1055     NW_ASSERT(resource.IsValid());
1056 
1057     return resource.GetFar();
1058 }
1059 
1060 //-----------------------------------------
1061 void
SetFar(f32 far)1062 Camera::SetFar(f32 far)
1063 {
1064     ResCameraProjectionUpdater resource =
1065         ResDynamicCast<ResCameraProjectionUpdater>( GetProjectionUpdater()->GetResource() );
1066 
1067     NW_ASSERT(resource.IsValid());
1068 
1069     resource.SetFar(far);
1070 }
1071 
1072 //----------------------------------------
1073 Result
StoreOriginal(os::IAllocator * allocator)1074 Camera::StoreOriginal(os::IAllocator* allocator)
1075 {
1076     Result result = INITIALIZE_RESULT_OK;
1077 
1078     ResCamera original = this->GetResCamera();
1079     NW_NULL_ASSERT(original.GetViewUpdater().ptr());
1080     NW_NULL_ASSERT(original.GetProjectionUpdater().ptr());
1081 
1082     void* cameraMemory = allocator->Alloc(sizeof(ResCameraData));
1083     NW_NULL_ASSERT(cameraMemory);
1084 
1085     ResCameraData* cameraData =
1086         new(cameraMemory) ResCameraData(original.ref());
1087 
1088     cameraData->toViewUpdater = NULL;
1089     cameraData->toProjectionUpdater = NULL;
1090 
1091     // viewUpdaterのコピー
1092     void* viewUpdaterMemory = NULL;
1093     ResCameraViewUpdaterData* viewUpdaterData = NULL;
1094     switch (original.GetViewType())
1095     {
1096     case ResCamera::VIEWTYPE_AIM:
1097         viewUpdaterMemory = allocator->Alloc(sizeof(ResAimTargetViewUpdaterData));
1098         NW_NULL_ASSERT(viewUpdaterMemory);
1099         viewUpdaterData =
1100             new(viewUpdaterMemory) ResAimTargetViewUpdaterData(
1101                 *reinterpret_cast<ResAimTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
1102         break;
1103 
1104     case ResCamera::VIEWTYPE_LOOKAT:
1105         viewUpdaterMemory = allocator->Alloc(sizeof(ResLookAtTargetViewUpdaterData));
1106         NW_NULL_ASSERT(viewUpdaterMemory);
1107         viewUpdaterData =
1108             new(viewUpdaterMemory) ResLookAtTargetViewUpdaterData(
1109                 *reinterpret_cast<ResLookAtTargetViewUpdaterData*>(original.GetViewUpdater().ptr()));
1110         break;
1111 
1112     case ResCamera::VIEWTYPE_ROTATE:
1113         viewUpdaterMemory = allocator->Alloc(sizeof(ResRotateViewUpdaterData));
1114         NW_NULL_ASSERT(viewUpdaterMemory);
1115         viewUpdaterData =
1116             new(viewUpdaterMemory) ResRotateViewUpdaterData(
1117                 *reinterpret_cast<ResRotateViewUpdaterData*>(original.GetViewUpdater().ptr()));
1118         break;
1119 
1120     default:
1121         NW_ASSERT(false);
1122     }
1123 
1124     cameraData->toViewUpdater.set_ptr(viewUpdaterData);
1125 
1126     // ProjectionUpdaterのコピー
1127     void* projectionUpdaterMemory = NULL;
1128     ResCameraProjectionUpdaterData* projectionUpdaterData = NULL;
1129 
1130     switch (original.GetProjectionType())
1131     {
1132     case ResCamera::PROJTYPE_PERSPECTIVE:
1133         projectionUpdaterMemory = allocator->Alloc(sizeof(ResPerspectiveProjectionUpdaterData));
1134         NW_NULL_ASSERT(projectionUpdaterMemory);
1135         projectionUpdaterData =
1136             new(projectionUpdaterMemory) ResPerspectiveProjectionUpdaterData(
1137                 *reinterpret_cast<ResPerspectiveProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1138         break;
1139 
1140     case ResCamera::PROJTYPE_FRUSTUM:
1141         projectionUpdaterMemory = allocator->Alloc(sizeof(ResFrustumProjectionUpdaterData));
1142         NW_NULL_ASSERT(projectionUpdaterMemory);
1143         projectionUpdaterData =
1144             new(projectionUpdaterMemory) ResFrustumProjectionUpdaterData(
1145                 *reinterpret_cast<ResFrustumProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1146         break;
1147 
1148     case ResCamera::PROJTYPE_ORTHO:
1149         projectionUpdaterMemory = allocator->Alloc(sizeof(ResOrthoProjectionUpdaterData));
1150         NW_NULL_ASSERT(projectionUpdaterMemory);
1151         projectionUpdaterData =
1152             new(projectionUpdaterMemory) ResOrthoProjectionUpdaterData(
1153                 *reinterpret_cast<ResOrthoProjectionUpdaterData*>(original.GetProjectionUpdater().ptr()));
1154         break;
1155 
1156     default:
1157         NW_ASSERT(false);
1158     }
1159 
1160     cameraData->toProjectionUpdater.set_ptr(projectionUpdaterData);
1161 
1162     // メンバに保存
1163     m_OriginalValue = ResCamera(cameraData);
1164 
1165     // CalculatedTransformを保存
1166     m_OriginalTransform = this->GetResTransformNode().GetTransform();
1167 
1168     return result;
1169 }
1170 
1171 //-----------------------------------------
1172 void
DestroyResCamera(os::IAllocator * allocator,ResCamera resCamera)1173 Camera::DestroyResCamera(os::IAllocator* allocator, ResCamera resCamera)
1174 {
1175     NW_NULL_ASSERT( allocator );
1176     if (resCamera.IsValid())
1177     {
1178         if (resCamera.GetProjectionUpdater().IsValid())
1179         {
1180             allocator->Free(resCamera.GetProjectionUpdater().ptr());
1181             resCamera.ref().toProjectionUpdater.set_ptr(NULL);
1182         }
1183         if (resCamera.GetViewUpdater().IsValid())
1184         {
1185             allocator->Free(resCamera.GetViewUpdater().ptr());
1186             resCamera.ref().toViewUpdater.set_ptr(NULL);
1187         }
1188 
1189         allocator->Free(resCamera.ptr());
1190     }
1191 }
1192 
1193 //-----------------------------------------
1194 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim)1195 Camera::GetAnimTargetObject(const anim::ResAnimGroupMember& anim)
1196 {
1197     switch(anim.GetObjectType())
1198     {
1199     case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
1200         {
1201             return static_cast<gfx::TransformNode*>(this);
1202         }
1203 
1204     case anim::ResAnimGroupMember::OBJECT_TYPE_VIEW_UPDATER:
1205         {
1206             ResCameraViewUpdaterData* ptr = GetViewUpdater()->GetResource().ptr();
1207             return ptr;
1208         }
1209 
1210     case anim::ResAnimGroupMember::OBJECT_TYPE_PROJECTION_UPDATER:
1211         {
1212             ResCameraProjectionUpdaterData* ptr = GetProjectionUpdater()->GetResource().ptr();
1213             return ptr;
1214         }
1215 
1216     default:
1217         NW_ASSERT(false);
1218         return NULL;
1219     }
1220 }
1221 
1222 //----------------------------------------
1223 Result
Initialize(os::IAllocator * allocator)1224 Camera::Initialize(os::IAllocator* allocator)
1225 {
1226     Result result = INITIALIZE_RESULT_OK;
1227 
1228     result |= TransformNode::Initialize(allocator);
1229     NW_ENSURE_AND_RETURN(result);
1230 
1231     result |= StoreOriginal(allocator);
1232     result |= CreateAnimGroup(allocator);
1233 
1234     return result;
1235 }
1236 
1237 //----------------------------------------
1238 bool
ValidateCameraAnimType(AnimObject * animObject)1239 Camera::ValidateCameraAnimType(AnimObject* animObject)
1240 {
1241     if (animObject == NULL)
1242     {
1243         // NULLの時はアニメを取り外そうとしているので、型チェックは通る
1244         return true;
1245     }
1246 
1247     // blenderならば、再帰的に調べないといけない
1248     AnimBlender* blender = ut::DynamicCast<AnimBlender*>(animObject);
1249 
1250     if (blender != NULL)
1251     {
1252         const int animObjCount = blender->GetAnimObjectCount();
1253         for (int i = 0; i < animObjCount; ++i)
1254         {
1255             AnimObject* animObj = blender->GetAnimObject(i);
1256 
1257             // ひとつでもvalidateに失敗したらfalseを返す
1258             if (!ValidateCameraAnimType(animObj))
1259             {
1260                 return false;
1261             }
1262         }
1263 
1264         // 全てのAnimObjectのチェックを通過すれば成功
1265         return true;
1266     }
1267     else
1268     {
1269         // blenderではなかったので、AnimEvaluatorのはず
1270         AnimEvaluator* evaluator = ut::DynamicCast<AnimEvaluator*>(animObject);
1271         NW_NULL_ASSERT(evaluator);
1272 
1273         anim::ResCameraAnim cameraAnim(evaluator->GetAnimData().ptr());
1274 
1275         return (
1276             (cameraAnim.GetProjectionUpdaterKind() == m_ProjectionUpdater->Kind()) &&
1277             (cameraAnim.GetViewUpdaterKind() == m_ViewUpdater->Kind()));
1278     }
1279 }
1280 
1281 } // namespace gfx
1282 } // namespace nw
1283