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