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