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