1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_Light.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: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 #include "precompiled.h"
19
20 #include <nw/gfx/gfx_AnimEvaluator.h>
21 #include <nw/gfx/gfx_Light.h>
22 #include <nw/gfx/gfx_ISceneVisitor.h>
23
24 namespace nw
25 {
26 namespace gfx
27 {
28
29 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Light, TransformNode);
30
31 //----------------------------------------
32 void
Accept(ISceneVisitor * visitor)33 Light::Accept(
34 ISceneVisitor* visitor
35 )
36 {
37 visitor->VisitLight(this);
38 AcceptChildren(visitor);
39 }
40
41 //----------------------------------------
42 Result
CreateAnimGroup(os::IAllocator * allocator)43 Light::CreateAnimGroup(os::IAllocator* allocator)
44 {
45 Result result = INITIALIZE_RESULT_OK;
46
47 NW_ASSERT(m_OriginalValue.IsValid());
48
49 if (!m_AnimBinding)
50 {
51 // DynamicBuilderを使用した場合は生成されない
52 return result;
53 }
54
55 ResSceneNode resSceneNode = GetResSceneNode();
56 NW_ASSERT(resSceneNode.IsValid());
57
58 NW_ASSERT(resSceneNode.GetAnimGroupsCount() == 1);
59 anim::ResAnimGroup resAnimGroup = resSceneNode.GetAnimGroups(0);
60
61 NW_ASSERT(resAnimGroup.GetTargetType() == anim::ResGraphicsAnimGroup::TARGET_TYPE_LIGHT);
62
63 AnimGroup* animGroup = AnimGroup::Builder()
64 .ResAnimGroup(resAnimGroup)
65 .SetSceneNode(this)
66 .UseOriginalValue(true) // TODO: 選択できる必要はある?
67 .Create(allocator);
68
69 if (animGroup == NULL)
70 {
71 result |= Result::MASK_FAIL_BIT;
72 }
73
74 NW_ENSURE_AND_RETURN(result);
75
76 m_AnimGroup = animGroup;
77
78 // 各メンバの参照解決
79 const int animMemberCount = m_AnimGroup->GetMemberCount();
80 for (int memberIdx = 0; memberIdx < animMemberCount; ++memberIdx)
81 {
82 anim::ResAnimGroupMember member = m_AnimGroup->GetResAnimGroupMember(memberIdx);
83
84 void* object = GetAnimTargetObject(member);
85 m_AnimGroup->SetTargetObject(memberIdx, object);
86
87 // TODO: アドレス算出もSetterに似た実装で行う?
88 if (member.GetObjectType() == anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM &&
89 member.GetMemberType() == anim::ResTransformMember::MEMBER_TYPE_TRANSFORM)
90 {
91 m_AnimGroup->SetTargetPtr(memberIdx, &this->Transform());
92 }
93 else
94 {
95 u8* target = static_cast<u8*>(object);
96 target += member.GetMemberOffset();
97 m_AnimGroup->SetTargetPtr(memberIdx, target);
98 }
99
100 m_AnimGroup->SetTargetObjectIndex(memberIdx, 0); // TODO: 要検討
101
102 if (member.GetObjectType() == nw::anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM)
103 {
104 m_AnimGroup->SetOriginalValue(memberIdx, &m_OriginalTransform);
105 }
106 else
107 {
108 u8* originalValue = reinterpret_cast<u8*>(m_OriginalValue.ptr());
109 originalValue += member.GetMemberOffset();
110 m_AnimGroup->SetOriginalValue(memberIdx, originalValue);
111 }
112 }
113
114 m_AnimBinding->SetAnimGroup(0, m_AnimGroup);
115
116 return result;
117 }
118
119 //----------------------------------------
120 void
DestroyOriginalValue()121 Light::DestroyOriginalValue()
122 {
123 NW_ASSERT(m_OriginalValue.IsValid());
124
125 GetAllocator().Free(m_OriginalValue.ptr());
126 m_OriginalValue = ResLight(NULL);
127 }
128
129 //----------------------------------------
130 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim)131 Light::GetAnimTargetObject(const anim::ResAnimGroupMember& anim)
132 {
133 switch (anim.GetObjectType())
134 {
135 case anim::ResAnimGroupMember::OBJECT_TYPE_TRANSFORM:
136 {
137 return static_cast<gfx::TransformNode*>(this);
138 }
139
140 case anim::ResAnimGroupMember::OBJECT_TYPE_LIGHT:
141 {
142 ResLight resLight = ResDynamicCast<ResLight>(this->GetResSceneObject());
143 NW_ASSERT(resLight.IsValid());
144
145 ResLightData* ptr = resLight.ptr();
146 return ptr;
147 }
148
149 case anim::ResAnimGroupMember::OBJECT_TYPE_FRAGMENT_LIGHT:
150 {
151 NW_ASSERT(ut::IsTypeOf<gfx::FragmentLight>(this));
152 ResFragmentLightData* ptr = static_cast<gfx::FragmentLight&>(*this).GetResFragmentLight().ptr();
153 return ptr;
154 }
155
156 case anim::ResAnimGroupMember::OBJECT_TYPE_AMBIENT_LIGHT:
157 {
158 NW_ASSERT(ut::IsTypeOf<gfx::AmbientLight>(this));
159 ResAmbientLightData* ptr = static_cast<gfx::AmbientLight&>(*this).GetResAmbientLight().ptr();
160 return ptr;
161 }
162
163 #if defined(NW_GFX_VERTEX_LIGHT_ENABLED)
164 case anim::ResAnimGroupMember::OBJECT_TYPE_VERTEX_LIGHT:
165 {
166 NW_ASSERT(ut::IsTypeOf<gfx::VertexLight>(this));
167 ResVertexLightData* ptr = static_cast<gfx::VertexLight&>(*this).GetResVertexLight().ptr();
168 return ptr;
169 }
170 #endif
171 case anim::ResAnimGroupMember::OBJECT_TYPE_HEMISPHERE_LIGHT:
172 {
173 NW_ASSERT(ut::IsTypeOf<gfx::HemiSphereLight>(this));
174 ResHemiSphereLightData* ptr = static_cast<gfx::HemiSphereLight&>(*this).GetResHemiSphereLight().ptr();
175 return ptr;
176 }
177
178 default:
179 NW_ASSERT(false);
180 return NULL;
181 }
182 }
183
184 //----------------------------------------
185 bool
ValidateLightAnimType(AnimObject * animObject)186 Light::ValidateLightAnimType(AnimObject* animObject)
187 {
188 if (animObject == NULL)
189 {
190 // NULLの時はアニメを取り外そうとしているので、型チェックは通る
191 return true;
192 }
193
194 // blenderならば、再帰的に調べないといけない
195 AnimBlender* blender = ut::DynamicCast<AnimBlender*>(animObject);
196
197 if (blender != NULL)
198 {
199 const int animObjCount = blender->GetAnimObjectCount();
200 for (int i = 0; i < animObjCount; ++i)
201 {
202 AnimObject* animObj = blender->GetAnimObject(i);
203
204 // ひとつでもvalidateに失敗したらfalseを返す
205 if (!ValidateLightAnimType(animObj))
206 {
207 return false;
208 }
209 }
210
211 // 全てのAnimObjectのチェックを通過すれば成功
212 return true;
213 }
214 else
215 {
216 // blenderではなかったので、AnimEvaluatorのはず
217 AnimEvaluator* evaluator = ut::DynamicCast<AnimEvaluator*>(animObject);
218 NW_NULL_ASSERT(evaluator);
219
220 anim::ResLightAnim lightAnim(evaluator->GetAnimData().ptr());
221
222 return (
223 (lightAnim.GetLightType() == GetLightType()) &&
224 (lightAnim.GetLightKind() == GetLightKind()));
225 }
226 }
227
228 } // namespace gfx
229 } // namespace nw
230