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