1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_FragmentLight.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/os/os_Memory.h>
19 
20 #include <nw/gfx/gfx_FragmentLight.h>
21 #include <nw/gfx/gfx_ISceneVisitor.h>
22 
23 #include <cstring>
24 
25 namespace nw
26 {
27 namespace gfx
28 {
29 
30 NW_UT_RUNTIME_TYPEINFO_DEFINITION(FragmentLight, Light);
31 
32 //----------------------------------------
33 FragmentLight*
Create(os::IAllocator * allocator)34 FragmentLight::DynamicBuilder::Create(
35     os::IAllocator* allocator
36 )
37 {
38     NW_NULL_ASSERT(allocator);
39 
40     // CreateResFragmentLight で名前を指定するようにしたら
41     // GetMemorySize も修正する必要がある。
42 
43     ResPtr resource(
44         CreateResFragmentLight(allocator),
45         ResFragmentLightDataDestroyer(allocator));
46 
47     void* memory = allocator->Alloc(sizeof(FragmentLight));
48     NW_NULL_ASSERT(memory);
49     FragmentLight* light = new(memory) FragmentLight(
50         allocator,
51         resource,
52         m_Description);
53 
54     Result result = light->Initialize(allocator);
55     NW_ASSERT(result.IsSuccess());
56 
57     return light;
58 }
59 
60 //----------------------------------------------------------
61 size_t
GetMemorySize(size_t alignment) const62 FragmentLight::DynamicBuilder::GetMemorySize( size_t alignment ) const
63 {
64     NW_ASSERT(this->m_Description.isFixedSizeMemory);
65 
66     os::MemorySizeCalculator size(alignment);
67 
68     // FragmentLight::CreateResFragmentLight
69     size += sizeof(ResFragmentLightData);
70     size += sizeof(ResReferenceLookupTable);
71     size += sizeof(ResLightingLookupTable);
72     size += sizeof(ResReferenceLookupTable);
73 
74     size += sizeof(FragmentLight);
75 
76     // FragmentLight::Initialize
77     TransformNode::GetMemorySizeForInitialize(
78         &size,
79         ResTransformNode(),
80         m_Description);
81 
82     // FragmentLight::CreateOriginalValue
83     size += sizeof(ResFragmentLightData);
84 
85     // Light::CreateAnimGroup
86     // DynamicBuilder 使用時には何も行なわれない。
87 
88     return size.GetSizeWithPadding(alignment);
89 }
90 
91 //----------------------------------------
92 FragmentLight*
Create(SceneNode * parent,ResSceneObject resource,const FragmentLight::Description & description,os::IAllocator * allocator)93 FragmentLight::Create(
94     SceneNode* parent,
95     ResSceneObject resource,
96     const FragmentLight::Description& description,
97     os::IAllocator* allocator
98 )
99 {
100     NW_NULL_ASSERT(allocator);
101 
102     ResFragmentLight resNode = ResDynamicCast<ResFragmentLight>(resource);
103     NW_ASSERT(resNode.IsValid());
104     NW_ASSERT( internal::ResCheckRevision( resNode ) );
105 
106     void* memory = allocator->Alloc(sizeof(FragmentLight));
107     NW_NULL_ASSERT(memory);
108 
109     FragmentLight* light = new(memory) FragmentLight(
110         allocator,
111         resNode,
112         description);
113 
114     Result result = light->Initialize(allocator);
115     NW_ASSERT(result.IsSuccess());
116 
117     if (parent)
118     {
119         bool isAttached = parent->AttachChild(light);
120         NW_ASSERT(isAttached);
121     }
122 
123     return light;
124 }
125 
126 //----------------------------------------
127 void
UpdateDirection()128 FragmentLight::UpdateDirection()
129 {
130     ResFragmentLight resLight = this->GetResFragmentLight();
131 
132     if (ut::CheckFlag(resLight.GetFlags(), ResFragmentLightData::FLAG_IS_INHERITING_DIRECTION_ROTATE))
133     {
134         this->CalcInheritingDiretion(this->Direction(), resLight.GetDirection());
135     }
136     else
137     {
138         this->Direction() = resLight.GetDirection();
139     }
140 }
141 
142 
143 //----------------------------------------
144 void
Accept(ISceneVisitor * visitor)145 FragmentLight::Accept(
146     ISceneVisitor* visitor
147 )
148 {
149     visitor->VisitFragmentLight(this);
150     AcceptChildren(visitor);
151 }
152 
153 
154 //-----------------------------------------
155 /* static*/ ResFragmentLightData*
CreateResFragmentLight(os::IAllocator * allocator,const char * name)156 FragmentLight::CreateResFragmentLight(os::IAllocator* allocator, const char* name /* = NULL */)
157 {
158     // TODO: 細かくアロケートする実装になっているが、まとめて確保できる仕組みも追加予定。
159 
160     ResFragmentLightData* resFragmentLight =
161         AllocateAndFillN<ResFragmentLightData>(allocator, sizeof(ResFragmentLightData), 0);
162 
163     //--------------------------------
164     // ResSceneObjectData のメンバ初期化
165     resFragmentLight->typeInfo = ResFragmentLight::TYPE_INFO;
166     resFragmentLight->m_Header.revision = ResLight::BINARY_REVISION;
167     resFragmentLight->m_Header.signature = ResLight::SIGNATURE;
168 
169     resFragmentLight->m_UserDataDicCount = 0;
170     resFragmentLight->toUserDataDic.set_ptr( NULL );
171 
172     resFragmentLight->toName.set_ptr(AllocateAndCopyString(name, allocator, MAX_NAME_LENGTH));
173 
174     //--------------------------------
175     // ResSceneNodeData のメンバ初期化
176     resFragmentLight->m_ChildrenTableCount = 0;
177     resFragmentLight->toChildrenTable.set_ptr( NULL );
178     resFragmentLight->m_AnimGroupsDicCount = 0;
179     resFragmentLight->toAnimGroupsDic.set_ptr( NULL );
180 
181     //--------------------------------
182     // ResTransformNode のメンバ初期化
183     const math::VEC3 scale(1.0f, 1.0f, 1.0f);
184     const math::VEC3 rotate(0.0f, 0.0f, 0.0f);
185     const math::VEC3 translate(0.0f, 0.0f, 0.0f);
186     resFragmentLight->m_Transform = math::Transform3(scale, rotate, translate);
187     resFragmentLight->m_WorldMatrix = math::MTX34::Identity();
188     ResTransformNode(resFragmentLight).SetBranchVisible(true);
189 
190     //--------------------------------
191     // ResFragmentLightData のメンバ初期化
192     ResReferenceLookupTableData* distanceSampler =
193         AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
194 
195     distanceSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
196     distanceSampler->toTargetLut.set_ptr(NULL);
197     distanceSampler->toPath.set_ptr(NULL);
198 
199     ResLightingLookupTableData* angleSampler =
200         AllocateAndFill<ResLightingLookupTableData>(allocator, 0);
201 
202     ResReferenceLookupTableData* referenceAngleSampler =
203         AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
204 
205     referenceAngleSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
206     referenceAngleSampler->toPath.set_ptr(NULL);
207     referenceAngleSampler->toTargetLut.set_ptr(NULL);
208 
209     angleSampler->toSampler.set_ptr(referenceAngleSampler);
210     angleSampler->m_Input = ResLightingLookupTable::INPUT_NH;
211     angleSampler->m_Scale = ResLightingLookupTable::SCALE_1;
212 
213     resFragmentLight->toDistanceSampler.set_ptr( distanceSampler );
214     resFragmentLight->toAngleSampler.set_ptr( angleSampler );
215 
216     return resFragmentLight;
217 }
218 
219 
220 //-----------------------------------------
221 /* static */ void
DestroyResFragmentLight(os::IAllocator * allocator,ResFragmentLightData * resFragmentLight)222 FragmentLight::DestroyResFragmentLight(os::IAllocator* allocator, ResFragmentLightData* resFragmentLight)
223 {
224     NW_NULL_ASSERT( allocator );
225     NW_NULL_ASSERT( resFragmentLight );
226 
227     allocator->Free( resFragmentLight->toDistanceSampler.to_ptr() );
228 
229     ResLightingLookupTableData* angleSampler =
230         reinterpret_cast<ResLightingLookupTableData*>(resFragmentLight->toAngleSampler.to_ptr());
231     allocator->Free( angleSampler->toSampler.to_ptr() );
232     allocator->Free( resFragmentLight->toAngleSampler.to_ptr() );
233     if ( resFragmentLight->toName.to_ptr() != NULL )
234     {
235         allocator->Free( const_cast<char*>( resFragmentLight->toName.to_ptr() ) );
236     }
237     allocator->Free( resFragmentLight );
238 }
239 
240 
241 //-----------------------------------------
242 Result
CreateOriginalValue(os::IAllocator * allocator)243 FragmentLight::CreateOriginalValue(os::IAllocator* allocator)
244 {
245     Result result = INITIALIZE_RESULT_OK;
246 
247     void* buffer = allocator->Alloc(sizeof(ResFragmentLightData));
248     NW_NULL_ASSERT(buffer);
249 
250     // リソースをコピー
251     ResFragmentLightData* originalValue = new(buffer) ResFragmentLightData(GetResFragmentLight().ref());
252     m_OriginalValue = ResFragmentLight(originalValue);
253 
254     m_OriginalTransform = this->GetResTransformNode().GetTransform();
255 
256     return result;
257 }
258 
259 //----------------------------------------
260 Result
Initialize(os::IAllocator * allocator)261 FragmentLight::Initialize(os::IAllocator* allocator)
262 {
263     Result result = INITIALIZE_RESULT_OK;
264 
265     result |= TransformNode::Initialize(allocator);
266     NW_ENSURE_AND_RETURN(result);
267 
268     result |= CreateOriginalValue(allocator);
269     NW_ENSURE_AND_RETURN(result);
270 
271     result |= CreateAnimGroup(allocator);
272     NW_ENSURE_AND_RETURN(result);
273 
274     return result;
275 }
276 
277 //----------------------------------------------------------
278 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResFragmentLight resFragmentLight,Description description)279 FragmentLight::GetMemorySizeInternal(
280     os::MemorySizeCalculator* pSize,
281     ResFragmentLight resFragmentLight,
282     Description description
283     )
284 {
285     NW_ASSERT(description.isFixedSizeMemory);
286 
287     os::MemorySizeCalculator& size = *pSize;
288 
289     size += sizeof(FragmentLight);
290 
291     // FragmentLight::Initialize
292     TransformNode::GetMemorySizeForInitialize(
293         &size,
294         resFragmentLight,
295         description);
296 
297     size += sizeof(ResFragmentLightData);
298 
299     if (description.isAnimationEnabled &&
300         resFragmentLight.GetAnimGroupsCount() > 0)
301     {
302         AnimGroup::Builder()
303             .ResAnimGroup(resFragmentLight.GetAnimGroups(0))
304             .UseOriginalValue(true)
305             .GetMemorySizeInternal(&size);
306     }
307 }
308 
309 } // namespace gfx
310 } // namespace nw
311