1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_FragmentLight.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/os/os_Memory.h>
21 
22 #include <nw/gfx/gfx_FragmentLight.h>
23 #include <nw/gfx/gfx_ISceneVisitor.h>
24 
25 #include <cstring>
26 
27 namespace nw
28 {
29 namespace gfx
30 {
31 
32 NW_UT_RUNTIME_TYPEINFO_DEFINITION(FragmentLight, Light);
33 
34 //----------------------------------------
35 FragmentLight*
Create(os::IAllocator * allocator)36 FragmentLight::DynamicBuilder::Create(
37     os::IAllocator* allocator
38 )
39 {
40     NW_NULL_ASSERT(allocator);
41 
42     // CreateResFragmentLight で名前を指定するようにしたら
43     // GetMemorySize も修正する必要がある。
44 
45     ResPtr resource(
46         CreateResFragmentLight(allocator),
47         ResFragmentLightDataDestroyer(allocator));
48 
49     void* memory = allocator->Alloc(sizeof(FragmentLight));
50     NW_NULL_ASSERT(memory);
51     FragmentLight* light = new(memory) FragmentLight(
52         allocator,
53         resource,
54         m_Description);
55 
56     Result result = light->Initialize(allocator);
57     NW_ASSERT(result.IsSuccess());
58 
59     return light;
60 }
61 
62 //----------------------------------------------------------
63 size_t
GetMemorySize(size_t alignment) const64 FragmentLight::DynamicBuilder::GetMemorySize( size_t alignment ) const
65 {
66     NW_ASSERT(this->m_Description.isFixedSizeMemory);
67 
68     os::MemorySizeCalculator size(alignment);
69 
70     // FragmentLight::CreateResFragmentLight
71     size += sizeof(ResFragmentLightData);
72     size += sizeof(ResReferenceLookupTable);
73     size += sizeof(ResLightingLookupTable);
74     size += sizeof(ResReferenceLookupTable);
75 
76     size += sizeof(FragmentLight);
77 
78     // FragmentLight::Initialize
79     TransformNode::GetMemorySizeForInitialize(
80         &size,
81         ResTransformNode(),
82         m_Description);
83 
84     // FragmentLight::CreateOriginalValue
85     size += sizeof(ResFragmentLightData);
86 
87     // Light::CreateAnimGroup
88     // DynamicBuilder 使用時には何も行なわれない。
89 
90     return size.GetSizeWithPadding(alignment);
91 }
92 
93 //----------------------------------------------------------
94 size_t
GetMemorySizeForCreateClone(ResFragmentLight resource,Description description,size_t alignment)95 FragmentLight::GetMemorySizeForCreateClone(
96     ResFragmentLight resource,
97     Description description,
98     size_t alignment
99 )
100 {
101     os::MemorySizeCalculator size(alignment);
102 
103     // FragmentLight::CloneResFragmentLight
104     size += sizeof(ResFragmentLightData);
105     size += sizeof(ResReferenceLookupTableData);
106     size += sizeof(ResLightingLookupTable);
107     if (resource.GetAngleSampler().IsValid())
108     {
109         size += sizeof(ResReferenceLookupTableData);
110     }
111 
112     GetMemorySizeInternal(&size, resource, description);
113 
114     return size.GetSizeWithPadding(alignment);
115 }
116 
117 //----------------------------------------
118 FragmentLight*
Create(SceneNode * parent,ResSceneObject resource,const FragmentLight::Description & description,os::IAllocator * allocator)119 FragmentLight::Create(
120     SceneNode* parent,
121     ResSceneObject resource,
122     const FragmentLight::Description& description,
123     os::IAllocator* allocator
124 )
125 {
126     NW_NULL_ASSERT(allocator);
127 
128     ResFragmentLight resNode = ResDynamicCast<ResFragmentLight>(resource);
129     NW_ASSERT(resNode.IsValid());
130     NW_ASSERT( internal::ResCheckRevision( resNode ) );
131 
132     void* memory = allocator->Alloc(sizeof(FragmentLight));
133     NW_NULL_ASSERT(memory);
134 
135     FragmentLight* light = new(memory) FragmentLight(
136         allocator,
137         resNode,
138         description);
139 
140     Result result = light->Initialize(allocator);
141     NW_ASSERT(result.IsSuccess());
142 
143     if (parent)
144     {
145         bool isAttached = parent->AttachChild(light);
146         NW_ASSERT(isAttached);
147     }
148 
149     return light;
150 }
151 
152 
153 //----------------------------------------
154 FragmentLight*
CreateClone(SceneNode * parent,ResFragmentLight resource,const FragmentLight::Description & description,os::IAllocator * allocator)155 FragmentLight::CreateClone(
156     SceneNode* parent,
157     ResFragmentLight resource,
158     const FragmentLight::Description& description,
159     os::IAllocator* allocator
160 )
161 {
162     NW_NULL_ASSERT(allocator);
163 
164     ResPtr clonedResource(
165         CloneResFragmentLight(resource, allocator),
166         ResFragmentLightDataDestroyer(allocator));
167 
168     void* memory = allocator->Alloc(sizeof(FragmentLight));
169     NW_NULL_ASSERT(memory);
170     FragmentLight* light = new(memory) FragmentLight(
171         allocator,
172         clonedResource,
173         description);
174 
175     Result result = light->Initialize(allocator);
176     NW_ASSERT(result.IsSuccess());
177 
178     if (parent)
179     {
180         bool isAttached = parent->AttachChild(light);
181         NW_ASSERT(isAttached);
182     }
183 
184     return light;
185 }
186 
187 //----------------------------------------
188 void
UpdateDirection()189 FragmentLight::UpdateDirection()
190 {
191     ResFragmentLight resLight = this->GetResFragmentLight();
192 
193     if (ut::CheckFlag(resLight.GetFlags(), ResFragmentLightData::FLAG_IS_INHERITING_DIRECTION_ROTATE))
194     {
195         this->CalcInheritingDiretion(this->Direction(), resLight.GetDirection());
196     }
197     else
198     {
199         this->Direction() = resLight.GetDirection();
200     }
201 }
202 
203 
204 //----------------------------------------
205 void
Accept(ISceneVisitor * visitor)206 FragmentLight::Accept(
207     ISceneVisitor* visitor
208 )
209 {
210     visitor->VisitFragmentLight(this);
211     AcceptChildren(visitor);
212 }
213 
214 
215 //-----------------------------------------
216 /* static*/ ResFragmentLightData*
CreateResFragmentLight(os::IAllocator * allocator,const char * name)217 FragmentLight::CreateResFragmentLight(os::IAllocator* allocator, const char* name /* = NULL */)
218 {
219     // TODO: 細かくアロケートする実装になっているが、まとめて確保できる仕組みも追加予定。
220 
221     ResFragmentLightData* resFragmentLight =
222         AllocateAndFillN<ResFragmentLightData>(allocator, sizeof(ResFragmentLightData), 0);
223 
224     //--------------------------------
225     // ResSceneObjectData のメンバ初期化
226     resFragmentLight->typeInfo = ResFragmentLight::TYPE_INFO;
227     resFragmentLight->m_Header.revision = ResLight::BINARY_REVISION;
228     resFragmentLight->m_Header.signature = ResLight::SIGNATURE;
229 
230     resFragmentLight->m_UserDataDicCount = 0;
231     resFragmentLight->toUserDataDic.set_ptr( NULL );
232 
233     resFragmentLight->toName.set_ptr(AllocateAndCopyString(name, allocator, MAX_NAME_LENGTH));
234 
235     //--------------------------------
236     // ResSceneNodeData のメンバ初期化
237     resFragmentLight->m_ChildrenTableCount = 0;
238     resFragmentLight->toChildrenTable.set_ptr( NULL );
239     resFragmentLight->m_AnimGroupsDicCount = 0;
240     resFragmentLight->toAnimGroupsDic.set_ptr( NULL );
241 
242     //--------------------------------
243     // ResTransformNode のメンバ初期化
244     const math::VEC3 scale(1.0f, 1.0f, 1.0f);
245     const math::VEC3 rotate(0.0f, 0.0f, 0.0f);
246     const math::VEC3 translate(0.0f, 0.0f, 0.0f);
247     resFragmentLight->m_Transform = math::Transform3(scale, rotate, translate);
248     resFragmentLight->m_WorldMatrix = math::MTX34::Identity();
249     ResTransformNode(resFragmentLight).SetBranchVisible(true);
250 
251     //--------------------------------
252     // ResFragmentLightData のメンバ初期化
253     ResReferenceLookupTableData* distanceSampler =
254         AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
255 
256     distanceSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
257     distanceSampler->toTargetLut.set_ptr(NULL);
258     distanceSampler->toPath.set_ptr(NULL);
259 
260     ResLightingLookupTableData* angleSampler =
261         AllocateAndFill<ResLightingLookupTableData>(allocator, 0);
262 
263     ResReferenceLookupTableData* referenceAngleSampler =
264         AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
265 
266     referenceAngleSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
267     referenceAngleSampler->toPath.set_ptr(NULL);
268     referenceAngleSampler->toTargetLut.set_ptr(NULL);
269 
270     angleSampler->toSampler.set_ptr(referenceAngleSampler);
271     angleSampler->m_Input = ResLightingLookupTable::INPUT_NH;
272     angleSampler->m_Scale = ResLightingLookupTable::SCALE_1;
273 
274     resFragmentLight->toDistanceSampler.set_ptr( distanceSampler );
275     resFragmentLight->toAngleSampler.set_ptr( angleSampler );
276 
277     return resFragmentLight;
278 }
279 
280 //-----------------------------------------
281 /* static*/ ResFragmentLightData*
CloneResFragmentLight(ResFragmentLight resource,os::IAllocator * allocator)282 FragmentLight::CloneResFragmentLight(ResFragmentLight resource, os::IAllocator* allocator)
283 {
284     ResFragmentLightData* resFragmentLight =
285         AllocateAndFillN<ResFragmentLightData>(allocator, sizeof(ResFragmentLightData), 0);
286     ResFragmentLightData* source = resource.ptr();
287 
288     //--------------------------------
289     // ResSceneObjectData のメンバコピー
290     resFragmentLight->typeInfo =                    source->typeInfo;
291     resFragmentLight->m_Header =                    source->m_Header;
292 
293     resFragmentLight->toName.set_ptr(               NULL );
294 
295     resFragmentLight->m_UserDataDicCount =          0;
296     resFragmentLight->toUserDataDic.set_ptr(        NULL );
297 
298     //--------------------------------
299     // ResSceneNodeData のメンバコピー
300     resFragmentLight->m_Flags =                     source->m_Flags;
301     resFragmentLight->m_IsBranchVisible =           source->m_IsBranchVisible;
302     resFragmentLight->m_ChildrenTableCount =        0;
303     resFragmentLight->toChildrenTable.set_ptr(      NULL );
304     resFragmentLight->m_AnimGroupsDicCount =        0;
305     resFragmentLight->toAnimGroupsDic.set_ptr(      NULL );
306 
307     //--------------------------------
308     // ResTransformNode のメンバコピー
309     resFragmentLight->m_Transform =                 source->m_Transform;
310     resFragmentLight->m_LocalMatrix =               source->m_LocalMatrix;
311     resFragmentLight->m_WorldMatrix =               source->m_WorldMatrix;
312 
313     //--------------------------------
314     // ResLight のメンバコピー
315     resFragmentLight->m_IsLightEnabled =            source->m_IsLightEnabled;
316 
317     //--------------------------------
318     // ResFragmentLightData のメンバコピー
319     ResLookupTable srcDistanceSampler = resource.GetDistanceSampler();
320 
321     ResReferenceLookupTableData* distanceSampler =
322         AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
323 
324     distanceSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
325     if (srcDistanceSampler.IsValid())
326     {
327         distanceSampler->toTargetLut.set_ptr(srcDistanceSampler.Dereference().ptr());
328     }
329     else
330     {
331         distanceSampler->toTargetLut.set_ptr(NULL);
332     }
333     distanceSampler->toTableName.set_ptr(NULL);
334     distanceSampler->toPath.set_ptr(NULL);
335 
336     resFragmentLight->toDistanceSampler.set_ptr( distanceSampler );
337 
338 
339 
340     ResLightingLookupTable srcAngleSampler = resource.GetAngleSampler();
341 
342     ResLightingLookupTableData* angleSampler =
343         AllocateAndFill<ResLightingLookupTableData>(allocator, 0);
344 
345     if (srcAngleSampler.IsValid())
346     {
347         ResLookupTable srcReferenceAngleSampler = srcAngleSampler.GetSampler();
348 
349         ResReferenceLookupTableData* referenceAngleSampler =
350             AllocateAndFill<ResReferenceLookupTableData>(allocator, 0);
351 
352         referenceAngleSampler->typeInfo = ResReferenceLookupTable_TYPE_INFO;
353         if (srcReferenceAngleSampler.IsValid())
354         {
355             referenceAngleSampler->toTargetLut.set_ptr(srcReferenceAngleSampler.Dereference().ptr());
356         }
357         else
358         {
359             referenceAngleSampler->toTargetLut.set_ptr(NULL);
360         }
361         referenceAngleSampler->toTableName.set_ptr(NULL);
362         referenceAngleSampler->toPath.set_ptr(NULL);
363 
364         angleSampler->toSampler.set_ptr(referenceAngleSampler);
365         angleSampler->m_Input = srcAngleSampler.GetInput();
366         angleSampler->m_Scale = srcAngleSampler.GetScale();
367     }
368     else
369     {
370         angleSampler->toSampler.set_ptr(NULL);
371     }
372 
373     resFragmentLight->toAngleSampler.set_ptr( angleSampler );
374 
375     resFragmentLight->m_LightKind =                 source->m_LightKind;
376     resFragmentLight->m_Ambient =                   source->m_Ambient;
377     resFragmentLight->m_Diffuse =                   source->m_Diffuse;
378     resFragmentLight->m_Specular0 =                 source->m_Specular0;
379     resFragmentLight->m_Specular1 =                 source->m_Specular1;
380     resFragmentLight->m_AmbientU32 =                source->m_AmbientU32;
381     resFragmentLight->m_DiffuseU32 =                source->m_DiffuseU32;
382     resFragmentLight->m_Specular0U32 =              source->m_Specular0U32;
383     resFragmentLight->m_Specular1U32 =              source->m_Specular1U32;
384     resFragmentLight->m_Direction =                 source->m_Direction;
385     resFragmentLight->m_DistanceAttenuationStart =  source->m_DistanceAttenuationStart;
386     resFragmentLight->m_DistanceAttenuationEnd =    source->m_DistanceAttenuationEnd;
387     resFragmentLight->m_DistanceAttenuationScale =  source->m_DistanceAttenuationScale;
388     resFragmentLight->m_DistanceAttenuationBias =   source->m_DistanceAttenuationBias;
389 
390     return resFragmentLight;
391 }
392 
393 
394 //-----------------------------------------
395 /* static */ void
DestroyResFragmentLight(os::IAllocator * allocator,ResFragmentLightData * resFragmentLight)396 FragmentLight::DestroyResFragmentLight(
397     os::IAllocator* allocator,
398     ResFragmentLightData* resFragmentLight
399 )
400 {
401     NW_NULL_ASSERT( allocator );
402     NW_NULL_ASSERT( resFragmentLight );
403 
404     allocator->Free( resFragmentLight->toDistanceSampler.to_ptr() );
405 
406     ResLightingLookupTableData* angleSampler =
407         reinterpret_cast<ResLightingLookupTableData*>(resFragmentLight->toAngleSampler.to_ptr());
408     if ( angleSampler->toSampler.to_ptr() != NULL )
409     {
410         allocator->Free( angleSampler->toSampler.to_ptr() );
411     }
412     allocator->Free( angleSampler );
413     if ( resFragmentLight->toName.to_ptr() != NULL )
414     {
415         allocator->Free( const_cast<char*>( resFragmentLight->toName.to_ptr() ) );
416     }
417 
418     allocator->Free( resFragmentLight );
419 }
420 
421 
422 //-----------------------------------------
423 Result
CreateOriginalValue(os::IAllocator * allocator)424 FragmentLight::CreateOriginalValue(os::IAllocator* allocator)
425 {
426     Result result = INITIALIZE_RESULT_OK;
427 
428     void* buffer = allocator->Alloc(sizeof(ResFragmentLightData));
429     NW_NULL_ASSERT(buffer);
430 
431     // リソースをコピー
432     ResFragmentLightData* originalValue = new(buffer) ResFragmentLightData(GetResFragmentLight().ref());
433     m_OriginalValue = ResFragmentLight(originalValue);
434 
435     m_OriginalTransform = this->GetResTransformNode().GetTransform();
436 
437     return result;
438 }
439 
440 //----------------------------------------
441 Result
Initialize(os::IAllocator * allocator)442 FragmentLight::Initialize(os::IAllocator* allocator)
443 {
444     Result result = INITIALIZE_RESULT_OK;
445 
446     result |= TransformNode::Initialize(allocator);
447     NW_ENSURE_AND_RETURN(result);
448 
449     result |= CreateOriginalValue(allocator);
450     NW_ENSURE_AND_RETURN(result);
451 
452     result |= CreateAnimGroup(allocator);
453     NW_ENSURE_AND_RETURN(result);
454 
455     return result;
456 }
457 
458 //----------------------------------------------------------
459 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResFragmentLight resFragmentLight,Description description)460 FragmentLight::GetMemorySizeInternal(
461     os::MemorySizeCalculator* pSize,
462     ResFragmentLight resFragmentLight,
463     Description description
464     )
465 {
466     NW_ASSERT(description.isFixedSizeMemory);
467 
468     os::MemorySizeCalculator& size = *pSize;
469 
470     size += sizeof(FragmentLight);
471 
472     // FragmentLight::Initialize
473     TransformNode::GetMemorySizeForInitialize(
474         &size,
475         resFragmentLight,
476         description);
477 
478     size += sizeof(ResFragmentLightData);
479 
480     if (description.isAnimationEnabled &&
481         resFragmentLight.GetAnimGroupsCount() > 0)
482     {
483         AnimGroup::Builder()
484             .ResAnimGroup(resFragmentLight.GetAnimGroups(0))
485             .UseOriginalValue(true)
486             .GetMemorySizeInternal(&size);
487     }
488 }
489 
490 } // namespace gfx
491 } // namespace nw
492