1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Material.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: 25777 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/gfx_Material.h>
19 #include <nw/gfx/gfx_Model.h>
20 #include <nw/gfx/res/gfx_ResMaterial.h>
21 #include <nw/gfx/res/gfx_ResShader.h>
22 #include <nw/gfx/gfx_AnimObject.h>
23 
24 namespace
25 {
GetAvailableResMaterial(nw::gfx::Material * material,nw::gfx::Model::BufferOption bufferOption)26 nw::gfx::ResMaterial GetAvailableResMaterial(
27     nw::gfx::Material* material, nw::gfx::Model::BufferOption bufferOption)
28 {
29     return nw::ut::CheckFlag(material->GetOwnerModel()->GetBufferOption(), bufferOption)
30         ? material->GetBuffer()
31         : material->GetOriginal();
32 }
33 }
34 
35 namespace nw
36 {
37 namespace gfx
38 {
39 
40 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Material, SceneObject);
41 
42 //----------------------------------------
Material(os::IAllocator * allocator,ResMaterial resMaterial,s32 bufferCount,Model * owner)43 Material::Material(
44     os::IAllocator* allocator,
45     ResMaterial resMaterial,
46     s32 bufferCount,
47     Model* owner)
48 : SceneObject(
49     allocator,
50     resMaterial),
51     m_Owner(owner),
52     m_BufferCount(bufferCount)
53 {
54     ResBinaryShader resShader = resMaterial.GetShader().Dereference();
55 
56     NW_ASSERT(resShader.IsValid());
57     m_ProgramDescription =
58         resShader.GetDescriptions(resMaterial.GetShaderProgramDescriptionIndex());
59 }
60 
61 //----------------------------------------
62 Material*
Create(ResMaterial resource,s32 bufferCount,Model * parent,os::IAllocator * allocator)63 Material::Create(
64     ResMaterial resource,
65     s32 bufferCount,
66     Model* parent,
67     os::IAllocator* allocator
68 )
69 {
70     NW_NULL_ASSERT(allocator);
71     NW_ASSERT(resource.IsValid());
72 
73     // マテリアルバッファは1つのみ作成可能です。
74     NW_ASSERTMSG(bufferCount <= 1, "Material Buffer Count must be 0 or 1.");
75 
76     void* memory = allocator->Alloc(sizeof(Material));
77     if (memory == NULL)
78     {
79         return NULL;
80     }
81 
82     Material* material = new(memory) Material(
83         allocator,
84         resource,
85         bufferCount,
86         parent);
87 
88     Result result = material->Initialize(allocator);
89     if (result.IsSuccess())
90     {
91         material->m_ShaderParameterResMaterial =
92             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADER_PARAMETER);
93         material->m_ShadingParameterResMaterial =
94             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADING_PARAMETER);
95         material->m_MaterialColorResMaterial =
96             GetAvailableResMaterial(material, Model::FLAG_BUFFER_MATERIAL_COLOR);
97         material->m_RasterizationResMaterial =
98             GetAvailableResMaterial(material, Model::FLAG_BUFFER_RASTERIZATION);
99         material->m_TextureCoordinatorResMaterial =
100             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
101         material->m_TextureMapperResMaterial =
102             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_MAPPER);
103         material->m_FragmentLightingResMaterial =
104             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING);
105         material->m_FragmentLightingTableResMaterial =
106             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE);
107         material->m_TextureCombinerResMaterial =
108             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COMBINER);
109         material->m_AlphaTestResMaterial =
110             GetAvailableResMaterial(material, Model::FLAG_BUFFER_ALPHA_TEST);
111         material->m_FragmentOperationResMaterial =
112             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
113         material->m_SceneEnvironmentResMaterial =
114             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SCENE_ENVIRONMENT);
115         return material;
116     }
117     else
118     {
119         SafeDestroy(material);
120         return NULL;
121     }
122 }
123 
124 //----------------------------------------
125 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResMaterial resMaterial,s32 bufferCount,bit32 bufferOption)126 Material::GetMemorySizeInternal(
127     os::MemorySizeCalculator* pSize,
128     ResMaterial resMaterial,
129     s32 bufferCount,
130     bit32 bufferOption)
131 {
132     os::MemorySizeCalculator& size = *pSize;
133 
134     // Material::Create
135     size += sizeof(Material);
136 
137     // Material::Initialize
138 
139     // Material::CreateBuffers
140     size += sizeof(ResMaterial) * bufferCount;
141     if (bufferCount > 0)
142     {
143         // TODO: 要検証
144         // Material::CopyResMaterial
145         os::MemorySizeCalculator bufferSize(size.GetAlignment());
146 
147         bufferSize += sizeof(ResMaterialData);
148 
149         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
150         {
151             bufferSize += sizeof(ut::Offset) * resMaterial.GetShaderParametersCount();
152 
153             for (int i = 0; i < resMaterial.GetShaderParametersCount(); ++i)
154             {
155                 const int parameterLength = resMaterial.GetShaderParameters(i).GetParameterLength();
156 
157                 bufferSize += sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1);
158             }
159         }
160 
161         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
162         {
163             for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
164             {
165                 ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
166                 if (resTextureMapper.IsValid())
167                 {
168                     resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
169                 }
170             }
171         }
172 
173         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
174         {
175             ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
176             if (resTextureMapper.IsValid())
177             {
178                 resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
179             }
180         }
181 
182         if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
183         {
184             if (resMaterial.GetFragmentShader().IsValid())
185             {
186                 bufferSize += sizeof(ResFragmentShaderData);
187 
188                 if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
189                 {
190                     // Material::CopyResFragmentLightingTable
191                     ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
192 
193                     if (resFragmentShader.GetFragmentLightingTable().IsValid())
194                     {
195                         ResFragmentLightingTable resFragmentLightingTable =
196                             resFragmentShader.GetFragmentLightingTable();
197 
198                         bufferSize += sizeof(ResFragmentLightingTableData);
199                         if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
200                         {
201                             bufferSize += sizeof(ResLightingLookupTableData);
202                         }
203                         if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
204                         {
205                             bufferSize += sizeof(ResLightingLookupTableData);
206                         }
207                         if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
208                         {
209                             bufferSize += sizeof(ResLightingLookupTableData);
210                         }
211                         if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
212                         {
213                             bufferSize += sizeof(ResLightingLookupTableData);
214                         }
215                         if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
216                         {
217                             bufferSize += sizeof(ResLightingLookupTableData);
218                         }
219                         if (resFragmentLightingTable.GetFresnelSampler().IsValid())
220                         {
221                             bufferSize += sizeof(ResLightingLookupTableData);
222                         }
223                     }
224                 }
225             }
226         }
227 
228         bufferSize *= bufferCount;
229         size += bufferSize.GetSizeWithPadding(size.GetAlignment());
230     }
231 }
232 
233 //----------------------------------------
~Material()234 Material::~Material()
235 {
236     std::for_each(
237         m_Buffers.begin(), m_Buffers.end(), ResMaterialDestroyer(&this->GetAllocator()));
238 }
239 
240 //----------------------------------------
241 bool
CanUseBuffer(u32 objectType) const242 Material::CanUseBuffer(u32 objectType) const
243 {
244     if (0 < m_BufferCount)
245     {
246         bit32 option = this->GetOwnerModel()->GetBufferOption();
247         switch (objectType)
248         {
249         case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
250             return ut::CheckFlag(option, Model::FLAG_BUFFER_MATERIAL_COLOR);
251         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
252             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
253         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
254             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
255         case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
256             return ut::CheckFlag(option, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
257         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
258             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
259         default:
260             NW_ASSERT(false);
261         }
262     }
263     return false;
264 }
265 
266 //-----------------------------------------
267 Result
CreateBuffers(os::IAllocator * allocator)268 Material::CreateBuffers(os::IAllocator* allocator)
269 {
270     Result result = INITIALIZE_RESULT_OK;
271 
272     NW_NULL_ASSERT(this->m_Owner);
273     bit32 bufferOption = m_Owner->GetBufferOption();
274 
275     if (m_BufferCount != 0)
276     {
277         void* memory = allocator->Alloc(sizeof(ResMaterial) * m_BufferCount);
278         if (memory == NULL)
279         {
280             result |= Result::MASK_FAIL_BIT;
281         }
282 
283         NW_ENSURE_AND_RETURN(result);
284 
285         m_Buffers = ResMaterialArray(memory, m_BufferCount, allocator);
286 
287         for (int bufferIndex = 0; bufferIndex < m_BufferCount; bufferIndex++)
288         {
289             NW_ENSURE_AND_RETURN(result);
290             ::std::pair<ResMaterial, Result> copyResult = this->CopyResMaterial(allocator, bufferOption);
291 
292             if (copyResult.second.IsSuccess())
293             {
294                 m_Buffers.push_back(copyResult.first);
295             }
296             else
297             {
298                 DestroyResMaterial(allocator, copyResult.first);
299                 result |= Result::MASK_FAIL_BIT;
300             }
301         }
302     }
303 
304     return result;
305 }
306 
307 //-----------------------------------------
308 ::std::pair<ResMaterial, Result>
CopyResMaterial(os::IAllocator * allocator,bit32 bufferOption)309 Material::CopyResMaterial(
310     os::IAllocator* allocator,
311     bit32 bufferOption)
312 {
313     Result result = INITIALIZE_RESULT_OK;
314 
315     ResMaterial resMaterial = this->GetOriginal();
316 
317     void* materialMemory = allocator->Alloc(sizeof(ResMaterialData));
318     if (materialMemory == NULL)
319     {
320         result |= Result::MASK_FAIL_BIT;
321         return ::std::make_pair(ResMaterial(NULL), result);
322     }
323 
324     ResMaterialData* buffer =
325         new(materialMemory) ResMaterialData(this->GetOriginal().ref());
326 
327     ResMaterial copyMaterial = ResMaterial(buffer);
328 
329     // 判定に用いるために NULL でクリアしておく
330     buffer->toName.set_ptr(NULL);
331     buffer->toShader.set_ptr(NULL);
332     buffer->m_ShaderParametersTableCount = 0;
333     buffer->toShaderParametersTable.set_ptr(NULL);
334     buffer->toTextureMappers[0].set_ptr(NULL);
335     buffer->toTextureMappers[1].set_ptr(NULL);
336     buffer->toTextureMappers[2].set_ptr(NULL);
337     buffer->toProceduralTextureMapper.set_ptr(NULL);
338     buffer->toFragmentShader.set_ptr(NULL);
339 
340     // ハッシュ無効化
341     buffer->m_AlphaTestHash = 0x0;
342     buffer->m_FragmentLightingHash = 0x0;
343     buffer->m_FragmentLightingTableHash = 0x0;
344     buffer->m_FragmentLightingTableParametersHash = 0x0;
345     buffer->m_FragmentOperationHash = 0x0;
346     buffer->m_MaterialColorHash = 0x0;
347     buffer->m_RasterizationHash = 0x0;
348     buffer->m_ShaderParametersHash = 0x0;
349     buffer->m_ShadingParameterHash = 0x0;
350     buffer->m_TextureCombinersHash = 0x0;
351     buffer->m_TextureCoordinatorsHash = 0x0;
352     buffer->m_TextureMappersHash = 0x0;
353     buffer->m_TextureSamplersHash = 0x0;
354 
355     // シェーダーパラメータのコピー
356     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
357     {
358         buffer->m_ShaderParametersTableCount = resMaterial.GetShaderParametersCount();
359 
360         ut::Offset* offsets = NULL;
361         if (buffer->m_ShaderParametersTableCount != 0)
362         {
363             offsets = allocator->AllocAndConstruct<ut::Offset>(resMaterial.GetShaderParametersCount());
364 
365             if (offsets == NULL)
366             {
367                 result |= Result::MASK_FAIL_BIT;
368                 return ::std::make_pair(copyMaterial, result);
369             }
370 
371             buffer->toShaderParametersTable.set_ptr(offsets);
372         }
373 
374         // メモリ解放を容易にするために NULL で初期化しておく
375         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
376         {
377             offsets[i].set_ptr(NULL);
378         }
379 
380         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
381         {
382             ResShaderParameter resShaderParameter = resMaterial.GetShaderParameters(i);
383             ResShaderParameterValue resShaderParameterValue = resShaderParameter.GetParameter();
384 
385             const int parameterLength = resShaderParameter.GetParameterLength();
386 
387             // sizeof(ResShaderParameterData)で32ビット分の Value の領域が確保されるので-1をする。
388             void* parameterMemory = allocator->Alloc(sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1));
389             if (parameterMemory == NULL)
390             {
391                 result |= Result::MASK_FAIL_BIT;
392                 return ::std::make_pair(copyMaterial, result);
393             }
394 
395             ResShaderParameterData* shaderParameter = static_cast<ResShaderParameterData*>(parameterMemory);
396             *shaderParameter = ResShaderParameterData(resShaderParameter.ref());
397 
398             for (int j = 0; j < parameterLength; ++j)
399             {
400                 shaderParameter->m_Parameter.m_Value[j] = resShaderParameterValue.ref().m_Value[j];
401             }
402 
403             offsets[i].set_ptr(shaderParameter);
404         }
405     }
406 
407     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
408     {
409         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
410         {
411             ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
412             if (resTextureMapper.IsValid())
413             {
414                 ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
415 
416                 if (!textureMapper.IsValid())
417                 {
418                     result |= Result::MASK_FAIL_BIT;
419                     return ::std::make_pair(copyMaterial, result);
420                 }
421 
422                 buffer->toTextureMappers[i].set_ptr(textureMapper.ptr());
423             }
424         }
425     }
426 
427     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
428     {
429         ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
430         if (resTextureMapper.IsValid())
431         {
432             ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
433 
434             if (!textureMapper.IsValid())
435             {
436                 result |= Result::MASK_FAIL_BIT;
437                 return ::std::make_pair(copyMaterial, result);
438             }
439 
440             buffer->toProceduralTextureMapper.set_ptr(textureMapper.ptr());
441         }
442     }
443 
444     if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
445     {
446         ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
447         if (resFragmentShader.IsValid())
448         {
449             void* shaderMemory = allocator->Alloc(sizeof(ResFragmentShaderData));
450 
451             if (shaderMemory == NULL)
452             {
453                 result |= Result::MASK_FAIL_BIT;
454                 return ::std::make_pair(copyMaterial, result);
455             }
456 
457             ResFragmentShaderData* fragmentShader =
458                 new(shaderMemory) ResFragmentShaderData(resFragmentShader.ref());
459 
460             buffer->toFragmentShader.set_ptr(fragmentShader);
461 
462             // 判定に用いるために NULL でクリアしておく
463             fragmentShader->toFragmentLightingTable.set_ptr(NULL);
464 
465             if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
466             {
467                 ResFragmentLightingTable resFragmentLightingTable =
468                     resFragmentShader.GetFragmentLightingTable();
469                 if (resFragmentLightingTable.IsValid())
470                 {
471                     ::std::pair<ResFragmentLightingTable, Result> copyResult =
472                         this->CopyResFragmentLightingTable(allocator, resFragmentLightingTable);
473 
474                     fragmentShader->toFragmentLightingTable.set_ptr(copyResult.first.ptr());
475 
476                     if (copyResult.second.IsFailure())
477                     {
478                         result |= Result::MASK_FAIL_BIT;
479                         return ::std::make_pair(copyMaterial, result);
480                     }
481                 }
482             }
483         }
484     }
485 
486     return ::std::make_pair(copyMaterial, result);
487 }
488 
489 //-----------------------------------------
490 void
DestroyResMaterial(os::IAllocator * allocator,ResMaterial resMaterial)491 Material::DestroyResMaterial(os::IAllocator* allocator, ResMaterial resMaterial)
492 {
493     NW_NULL_ASSERT( allocator );
494     if (resMaterial.IsValid())
495     {
496         resMaterial.Cleanup();
497 
498         DestroyResFragmentShader(allocator, resMaterial.GetFragmentShader());
499 
500         if (resMaterial.GetProceduralTextureMapper().IsValid())
501         {
502             resMaterial.GetProceduralTextureMapper().DestroyDynamic();
503         }
504 
505         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
506         {
507             if (resMaterial.GetTextureMappers(i).IsValid())
508             {
509                 resMaterial.GetTextureMappers(i).DestroyDynamic();
510             }
511         }
512 
513         // シェーダーパラメータのメモリ解放
514         if (resMaterial.ref().toShaderParametersTable.to_ptr() != NULL)
515         {
516             for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
517             {
518                 DestroyResShaderParameter(allocator, resMaterial.GetShaderParameters(i));
519             }
520             allocator->Free(resMaterial.ref().toShaderParametersTable.to_ptr());
521         }
522 
523         allocator->Free(resMaterial.ptr());
524     }
525 }
526 
527 //-----------------------------------------
528 void
DestroyResFragmentShader(os::IAllocator * allocator,ResFragmentShader resFragmentShader)529 Material::DestroyResFragmentShader(
530     os::IAllocator* allocator,
531     ResFragmentShader resFragmentShader)
532 {
533     if (resFragmentShader.IsValid())
534     {
535         ResFragmentLightingTable resFragmentLightingTable = resFragmentShader.GetFragmentLightingTable();
536 
537         if (resFragmentLightingTable.IsValid())
538         {
539             if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
540             {
541                 allocator->Free(resFragmentLightingTable.GetReflectanceRSampler().ptr());
542             }
543 
544             if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
545             {
546                 allocator->Free(resFragmentLightingTable.GetReflectanceGSampler().ptr());
547             }
548 
549             if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
550             {
551                 allocator->Free(resFragmentLightingTable.GetReflectanceBSampler().ptr());
552             }
553 
554             if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
555             {
556                 allocator->Free(resFragmentLightingTable.GetDistribution0Sampler().ptr());
557             }
558 
559             if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
560             {
561                 allocator->Free(resFragmentLightingTable.GetDistribution1Sampler().ptr());
562             }
563 
564             if (resFragmentLightingTable.GetFresnelSampler().IsValid())
565             {
566                 allocator->Free(resFragmentLightingTable.GetFresnelSampler().ptr());
567             }
568 
569             allocator->Free(resFragmentLightingTable.ptr());
570         }
571 
572         allocator->Free(resFragmentShader.ptr());
573     }
574 }
575 
576 //-----------------------------------------
577 void
DestroyResShaderParameter(os::IAllocator * allocator,ResShaderParameter resShaderParameter)578 Material::DestroyResShaderParameter(
579     os::IAllocator* allocator,
580     ResShaderParameter resShaderParameter)
581 {
582     if (resShaderParameter.IsValid())
583     {
584         allocator->Free(resShaderParameter.ptr());
585     }
586 }
587 
588 //-----------------------------------------
589 ::std::pair<ResFragmentLightingTable, Result>
CopyResFragmentLightingTable(os::IAllocator * allocator,ResFragmentLightingTable resFragmentLightingTable)590 Material::CopyResFragmentLightingTable(
591     os::IAllocator* allocator,
592     ResFragmentLightingTable resFragmentLightingTable)
593 {
594     Result result = INITIALIZE_RESULT_OK;
595 
596     void* tableMemory = allocator->Alloc(sizeof(ResFragmentLightingTableData));
597     if (tableMemory == NULL)
598     {
599         result |= Result::MASK_FAIL_BIT;
600         return ::std::make_pair(ResFragmentLightingTable(NULL), result);
601     }
602 
603     ResFragmentLightingTableData* fragmentLightingTable =
604         new(tableMemory) ResFragmentLightingTableData(resFragmentLightingTable.ref());
605 
606     fragmentLightingTable->toReflectanceRSampler.set_ptr(NULL);
607     fragmentLightingTable->toReflectanceGSampler.set_ptr(NULL);
608     fragmentLightingTable->toReflectanceBSampler.set_ptr(NULL);
609     fragmentLightingTable->toDistribution0Sampler.set_ptr(NULL);
610     fragmentLightingTable->toDistribution1Sampler.set_ptr(NULL);
611     fragmentLightingTable->toFresnelSampler.set_ptr(NULL);
612 
613     if (resFragmentLightingTable.GetReflectanceRSampler().IsValid() && result.IsSuccess())
614     {
615         ::std::pair<ResLightingLookupTable, Result> copyResult =
616             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceRSampler());
617 
618         fragmentLightingTable->toReflectanceRSampler.set_ptr(copyResult.first.ptr());
619 
620         result |= copyResult.second;
621     }
622 
623     if (resFragmentLightingTable.GetReflectanceGSampler().IsValid() && result.IsSuccess())
624     {
625         ::std::pair<ResLightingLookupTable, Result> copyResult =
626             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceGSampler());
627 
628         fragmentLightingTable->toReflectanceGSampler.set_ptr(copyResult.first.ptr());
629 
630         result |= copyResult.second;
631     }
632 
633     if (resFragmentLightingTable.GetReflectanceBSampler().IsValid() && result.IsSuccess())
634     {
635         ::std::pair<ResLightingLookupTable, Result> copyResult =
636             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceBSampler());
637 
638         fragmentLightingTable->toReflectanceBSampler.set_ptr(copyResult.first.ptr());
639 
640         result |= copyResult.second;
641     }
642 
643     if (resFragmentLightingTable.GetDistribution0Sampler().IsValid() && result.IsSuccess())
644     {
645         ::std::pair<ResLightingLookupTable, Result> copyResult =
646             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution0Sampler());
647 
648         fragmentLightingTable->toDistribution0Sampler.set_ptr(copyResult.first.ptr());
649 
650         result |= copyResult.second;
651     }
652 
653     if (resFragmentLightingTable.GetDistribution1Sampler().IsValid() && result.IsSuccess())
654     {
655         ::std::pair<ResLightingLookupTable, Result> copyResult =
656             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution1Sampler());
657 
658         fragmentLightingTable->toDistribution1Sampler.set_ptr(copyResult.first.ptr());
659 
660         result |= copyResult.second;
661     }
662 
663     if (resFragmentLightingTable.GetFresnelSampler().IsValid() && result.IsSuccess())
664     {
665         ::std::pair<ResLightingLookupTable, Result> copyResult =
666             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetFresnelSampler());
667 
668         fragmentLightingTable->toFresnelSampler.set_ptr(copyResult.first.ptr());
669 
670         result |= copyResult.second;
671     }
672 
673     return ::std::make_pair(ResFragmentLightingTable(fragmentLightingTable), result);
674 }
675 
676 //-----------------------------------------
677 ::std::pair<ResLightingLookupTable, Result>
CopyResLightingLookupTable(os::IAllocator * allocator,ResLightingLookupTable resLightingLookupTable)678 Material::CopyResLightingLookupTable(
679     os::IAllocator* allocator,
680     ResLightingLookupTable resLightingLookupTable)
681 {
682     Result result = INITIALIZE_RESULT_OK;
683 
684     void* tableMemory = allocator->Alloc(sizeof(ResLightingLookupTableData));
685 
686     if (tableMemory == NULL)
687     {
688         result |= Result::MASK_FAIL_BIT;
689         return ::std::make_pair(ResLightingLookupTable(NULL), result);
690     }
691 
692     ResLightingLookupTableData* lightingLookupTable =
693         new(tableMemory) ResLightingLookupTableData(resLightingLookupTable.ref());
694 
695     lightingLookupTable->m_Input = resLightingLookupTable.GetInput();
696     lightingLookupTable->m_Scale = resLightingLookupTable.GetScale();
697     lightingLookupTable->toSampler.set_ptr(resLightingLookupTable.GetSampler().ptr());
698 
699     return ::std::make_pair(ResLightingLookupTable(lightingLookupTable), result);
700 }
701 
702 //-----------------------------------------
703 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim,const ResMaterial resMaterial)704 Material::GetAnimTargetObject(const anim::ResAnimGroupMember& anim, const ResMaterial resMaterial)
705 {
706     u32 objectType = anim.GetObjectType();
707     ResMaterial mat = resMaterial;
708 
709     switch (objectType)
710     {
711     case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
712         {
713             anim::ResMaterialColorMember member = ResStaticCast<anim::ResMaterialColorMember>(anim);
714             const char* matName = member.GetMaterialName();
715 
716             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
717             ResMaterialColorData* ptr = mat.GetMaterialColor().ptr();
718             return ptr;
719         }
720 
721     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
722         {
723             anim::ResTextureSamplerMember member = ResStaticCast<anim::ResTextureSamplerMember>(anim);
724             const char* matName = member.GetMaterialName();
725             int mapperIndex = member.GetTextureMapperIndex();
726 
727             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
728 
729             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
730             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
731             // Samplerの変更を反映させるにはMapperのSetSampler()を呼ぶ必要があるので、
732             // Mapperのポインタを返す
733             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
734             return ptr;
735         }
736 
737     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
738         {
739             anim::ResTextureMapperMember member = ResStaticCast<anim::ResTextureMapperMember>(anim);
740             const char* matName = member.GetMaterialName();
741             int mapperIndex = member.GetTextureMapperIndex();
742 
743             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
744             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
745 
746             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
747             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
748             return ptr;
749         }
750 
751     case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
752         {
753             anim::ResBlendOperationMember member = ResStaticCast<anim::ResBlendOperationMember>(anim);
754             const char* matName = member.GetMaterialName();
755 
756             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
757             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
758 
759             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
760             ResBlendOperationData* ptr = mat.GetFragmentOperation().GetBlendOperation().ptr();
761             return ptr;
762         }
763 
764     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
765         {
766             anim::ResTextureCoordinatorMember member = ResStaticCast<anim::ResTextureCoordinatorMember>(anim);
767             const char* matName = member.GetMaterialName();
768             int coordinatorIndex = member.GetTextureCoordinatorIndex();
769 
770             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
771             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
772 
773             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
774             ResTextureCoordinatorData* ptr =mat.GetTextureCoordinators(coordinatorIndex).ptr();
775             return ptr;
776         }
777 
778     default:
779         NW_ASSERT(false);
780         return NULL;
781     }
782 }
783 
784 //-----------------------------------------
785 Result
Initialize(os::IAllocator * allocator)786 Material::Initialize(os::IAllocator* allocator)
787 {
788     Result result = INITIALIZE_RESULT_OK;
789 
790     result |= CreateBuffers(allocator);
791     NW_ENSURE_AND_RETURN(result);
792 
793     return result;
794 }
795 
796 } // namespace gfx
797 } // namespace nw
798