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