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