Merge "Add ECORE_IMF_CALLBACK_SELECTION_SET to IMFContext" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scene3d-view / gltf-loader.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/scene3d-view/gltf-loader.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
23 #include <dali/devel-api/adaptor-framework/file-stream.h>
24 #include <dali/devel-api/adaptor-framework/image-loading.h>
25 #include <dali/integration-api/debug.h>
26
27 namespace Dali
28 {
29 namespace Toolkit
30 {
31 namespace Internal
32 {
33 namespace Gltf
34 {
35 namespace
36 {
37 // Utility functions
38 const TreeNode* Tidx(const TreeNode* node, uint32_t index)
39 {
40   uint32_t i = 0;
41   for(auto it = node->CBegin(), end = node->CEnd(); it != end; ++it, ++i)
42   {
43     if(i == index)
44     {
45       return &((*it).second);
46     }
47   }
48   return NULL;
49 }
50
51 bool ReadBool(const TreeNode* node, bool& num)
52 {
53   if(!node)
54   {
55     return false;
56   }
57   bool returnValue = false;
58
59   if(node->GetType() == TreeNode::BOOLEAN)
60   {
61     num         = node->GetBoolean();
62     returnValue = true;
63   }
64
65   return returnValue;
66 }
67
68 bool ReadInt(const TreeNode* node, int32_t& num)
69 {
70   if(!node)
71   {
72     return false;
73   }
74   bool returnValue = false;
75   if(node->GetType() == TreeNode::INTEGER)
76   {
77     num         = node->GetInteger();
78     returnValue = true;
79   }
80   else if(node->GetType() == TreeNode::FLOAT)
81   {
82     num         = node->GetFloat();
83     returnValue = true;
84   }
85
86   return returnValue;
87 }
88
89 bool ReadFloat(const TreeNode* node, float& num)
90 {
91   if(!node)
92   {
93     return false;
94   }
95   bool returnValue = false;
96
97   if(node->GetType() == TreeNode::FLOAT)
98   {
99     num         = node->GetFloat();
100     returnValue = true;
101   }
102   else if(node->GetType() == TreeNode::INTEGER)
103   {
104     int32_t tempNum = 0;
105     ReadInt(node, tempNum);
106     num         = static_cast<float>(tempNum);
107     returnValue = true;
108   }
109
110   return returnValue;
111 }
112
113 bool ReadVector(const TreeNode* node, float* num, uint32_t size)
114 {
115   if(!node)
116   {
117     return false;
118   }
119   bool returnValue = false;
120
121   if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
122   {
123     uint32_t offset = 0u;
124     for(auto it = node->CBegin(); offset < size; ++it, ++offset)
125     {
126       const TreeNode& coord = (*it).second;
127       if(!ReadFloat(&coord, *(num + offset)))
128       {
129         return false;
130       }
131     }
132     returnValue = true;
133   }
134
135   return returnValue;
136 }
137
138 bool ReadString(const TreeNode* node, std::string& strValue)
139 {
140   if(!node)
141   {
142     return false;
143   }
144   bool returnValue = false;
145   if(node->GetType() == TreeNode::STRING)
146   {
147     strValue    = node->GetString();
148     returnValue = true;
149   }
150   return returnValue;
151 }
152
153 template<typename T>
154 float IntToFloat(T element, bool normalize)
155 {
156   if(!normalize)
157   {
158     return static_cast<float>(element);
159   }
160
161   if(std::is_same<T, int8_t>::value)
162   {
163     return std::max(static_cast<float>(element) / 127.0, -1.0);
164   }
165   if(std::is_same<T, uint8_t>::value)
166   {
167     return static_cast<float>(element) / 255.0;
168   }
169   if(std::is_same<T, int16_t>::value)
170   {
171     return std::max(static_cast<float>(element) / 32767.0, -1.0);
172   }
173   if(std::is_same<T, uint16_t>::value)
174   {
175     return static_cast<float>(element) / 65535.0;
176   }
177   return -1.0;
178 }
179
180 template<typename Td, typename Ts>
181 void FitBuffer(Dali::Vector<Td>& bufferDestination, Dali::Vector<Ts>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
182 {
183   bufferDestination.Resize(bufferSize);
184   int32_t count = bufferSource.Size() / elementNumOfByteStride;
185   for(int32_t i = 0; i < count; ++i)
186   {
187     bufferDestination[i] = static_cast<Td>(bufferSource[i * elementNumOfByteStride]);
188   }
189 }
190
191 template<typename T>
192 void FitBuffer(Dali::Vector<Vector2>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
193 {
194   bufferDestination.Resize(bufferSize);
195   int32_t count = bufferSource.Size() / elementNumOfByteStride;
196   for(int32_t i = 0; i < count; ++i)
197   {
198     bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
199     bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
200   }
201 }
202
203 template<typename T>
204 void FitBuffer(Dali::Vector<Vector3>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
205 {
206   bufferDestination.Resize(bufferSize);
207   int32_t count = bufferSource.Size() / elementNumOfByteStride;
208   for(int32_t i = 0; i < count; ++i)
209   {
210     bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
211     bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
212     bufferDestination[i].z = IntToFloat(bufferSource[i * elementNumOfByteStride + 2], normalize);
213   }
214 }
215
216 template<typename T>
217 void FitBuffer(Dali::Vector<Vector4>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize)
218 {
219   bufferDestination.Resize(bufferSize);
220   int32_t count = bufferSource.Size() / elementNumOfByteStride;
221   for(int32_t i = 0; i < count; ++i)
222   {
223     bufferDestination[i].x = IntToFloat(bufferSource[i * elementNumOfByteStride], normalize);
224     bufferDestination[i].y = IntToFloat(bufferSource[i * elementNumOfByteStride + 1], normalize);
225     bufferDestination[i].z = IntToFloat(bufferSource[i * elementNumOfByteStride + 2], normalize);
226     bufferDestination[i].w = IntToFloat(bufferSource[i * elementNumOfByteStride + 3], normalize);
227   }
228 }
229
230 // Template functions
231 template<typename T>
232 bool ReadBinFile(Vector<T>& dataBuffer, std::string url, int32_t offset, int32_t count)
233 {
234   size_t readCount = 0;
235   Dali::FileStream fileStream(url, FileStream::READ | FileStream::BINARY);
236   FILE*            fp = fileStream.GetFile();
237   if(fp)
238   {
239     dataBuffer.Resize(count);
240     if(!fseek(fp, offset, SEEK_SET))
241     {
242       readCount = fread(&dataBuffer[0], sizeof(T), count, fp);
243       dataBuffer.Resize(readCount);
244     }
245   }
246
247   return (readCount > 0);
248 }
249
250 template<typename T>
251 void LoadDataFromAccessor(int32_t accessorIdx, Dali::Vector<T>& bufferData, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray)
252 {
253   AccessorInfo   accessor   = accessorArray[accessorIdx];
254   BufferViewInfo bufferView = bufferViewArray[accessor.bufferView];
255   std::string    load_uri   = bufferArray[bufferView.buffer].uri;
256
257   // In the glTF 2.0 Specification, 5121 is UNSIGNED BYTE, 5123 is UNSIGNED SHORT
258   int32_t elementByteSize = (accessor.componentType <= 5121) ? 1 : ((accessor.componentType <= 5123) ? 2 : 4);
259   int32_t elementNum      = 1;
260   if(accessor.type == "VEC2")
261   {
262     elementNum = 2;
263   }
264   else if(accessor.type == "VEC3")
265   {
266     elementNum = 3;
267   }
268   else if(accessor.type == "VEC4" || accessor.type == "MAT2")
269   {
270     elementNum = 4;
271   }
272   else if(accessor.type == "MAT3")
273   {
274     elementNum = 9;
275   }
276   else if(accessor.type == "MAT4")
277   {
278     elementNum = 16;
279   }
280   else
281   {
282     elementNum = 1;
283   }
284   int32_t elementNumOfByteStride = elementNum;
285   if(bufferView.byteStride > 0)
286   {
287     elementNumOfByteStride = bufferView.byteStride / elementByteSize;
288   }
289
290   /**
291    * glTF 2.0 Specification
292    * Component Type
293    * 5120 : BYTE
294    * 5121 : UNSIGNED_BYTE
295    * 5122 : SHORT
296    * 5123 : UNSIGNED_SHORT
297    * 5125 : UNSIGNED_INT
298    * 5126 : FLOAT
299    */
300   if(accessor.componentType == 5120)
301   {
302     Dali::Vector<int8_t> inputBufferData;
303     if(ReadBinFile<int8_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
304     {
305       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
306     }
307   }
308   else if(accessor.componentType == 5121)
309   {
310     Dali::Vector<uint8_t> inputBufferData;
311     if(ReadBinFile<uint8_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
312     {
313       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
314     }
315   }
316   else if(accessor.componentType == 5122)
317   {
318     Dali::Vector<int16_t> inputBufferData;
319     if(ReadBinFile<int16_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
320     {
321       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
322     }
323   }
324   else if(accessor.componentType == 5123)
325   {
326     Dali::Vector<uint16_t> inputBufferData;
327     if(ReadBinFile<uint16_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
328     {
329       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
330     }
331   }
332   else if(accessor.componentType == 5125)
333   {
334     Dali::Vector<uint32_t> inputBufferData;
335     if(ReadBinFile<uint32_t>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
336     {
337       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
338     }
339   }
340   else if(accessor.componentType == 5126)
341   {
342     Dali::Vector<float> inputBufferData;
343     if(ReadBinFile<float>(inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count))
344     {
345       FitBuffer(bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized);
346     }
347   }
348 }
349
350 void SetMeshInfoAndCanonize(MeshInfo& meshInfo, Dali::Vector<Dali::Vector3>& vertexBufferData)
351 {
352   Vector3 pointMin(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
353   Vector3 pointMax(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
354   for(auto&& data : vertexBufferData)
355   {
356     pointMin.x = std::min(data.x, pointMin.x);
357     pointMin.y = std::min(data.y, pointMin.y);
358     pointMin.z = std::min(data.z, pointMin.z);
359
360     pointMax.x = std::max(data.x, pointMax.x);
361     pointMax.y = std::max(data.y, pointMax.y);
362     pointMax.z = std::max(data.z, pointMax.z);
363   }
364   meshInfo.size    = pointMax - pointMin;
365   meshInfo.pivot.x = (-pointMin.x) / (pointMax.x - pointMin.x);
366   meshInfo.pivot.y = (-pointMin.y) / (pointMax.y - pointMin.y);
367   meshInfo.pivot.z = (-pointMin.z) / (pointMax.z - pointMin.z);
368
369   Vector3 center = meshInfo.size * 0.5 + pointMin;
370   for(auto&& data : vertexBufferData)
371   {
372     data   = data - center;
373     data.x = data.x / meshInfo.size.x;
374     data.y = data.y / meshInfo.size.y;
375     data.z = data.z / meshInfo.size.z;
376   }
377 }
378
379 template<typename T>
380 VertexBuffer CreateVertexBuffer(Vector<T> bufferData, std::string map, int32_t type)
381 {
382   Property::Map positionMap;
383   positionMap[map] = type;
384
385   VertexBuffer vertexBuffer = VertexBuffer::New(positionMap);
386   vertexBuffer.SetData(bufferData.Begin(), bufferData.Count());
387   return vertexBuffer;
388 }
389
390 void SetVertexBufferData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type)
391 {
392   if(accessorIdx >= 0)
393   {
394     Dali::Vector<Vector3> bufferData;
395     LoadDataFromAccessor(accessorIdx, bufferData, path, accessorArray, bufferViewArray, bufferArray);
396     SetMeshInfoAndCanonize(meshInfo, bufferData);
397
398     VertexBuffer vertexBuffer = CreateVertexBuffer<Vector3>(bufferData, map, type);
399     meshInfo.geometry.AddVertexBuffer(vertexBuffer);
400   }
401 }
402
403 template<typename T>
404 void SetAttributeBufferData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type)
405 {
406   if(accessorIdx >= 0)
407   {
408     Dali::Vector<T> bufferData;
409     LoadDataFromAccessor(accessorIdx, bufferData, path, accessorArray, bufferViewArray, bufferArray);
410
411     VertexBuffer vertexBuffer = CreateVertexBuffer<T>(bufferData, map, type);
412     meshInfo.geometry.AddVertexBuffer(vertexBuffer);
413   }
414 }
415
416 void SetIndexBuffersData(MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t indexIdx)
417 {
418   Dali::Vector<uint16_t> indexBufferData;
419   LoadDataFromAccessor(indexIdx, indexBufferData, path, accessorArray, bufferViewArray, bufferArray);
420   meshInfo.geometry.SetIndexBuffer(&indexBufferData[0], indexBufferData.Size());
421 }
422
423 template<typename T>
424 float LoadKeyFrames(const AnimationSamplerInfo& currentSampler, const Property::Index propIndex, KeyFrames& keyframes, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray)
425 {
426   Dali::Vector<float> inputBufferData;
427   Dali::Vector<T>     outputBufferData;
428
429   LoadDataFromAccessor<float>(currentSampler.input, inputBufferData, path, accessorArray, bufferViewArray, bufferArray);
430   LoadDataFromAccessor<T>(currentSampler.output, outputBufferData, path, accessorArray, bufferViewArray, bufferArray);
431
432   uint32_t keyframeNum     = inputBufferData.Size();
433   float    lengthAnimation = inputBufferData[inputBufferData.Size() - 1];
434   for(uint32_t i = 0; i < keyframeNum; i++)
435   {
436     if(propIndex == Dali::Actor::Property::ORIENTATION)
437     {
438       Vector4 vectorOrientation(outputBufferData[i]);
439       float   vW          = vectorOrientation.w;
440       vW                  = (vW < 0.0f) ? std::max(vW, -1.0f) : std::min(vW, 1.0f);
441       vectorOrientation.w = vW;
442       keyframes.Add(inputBufferData[i] / lengthAnimation, Quaternion(Vector4(vectorOrientation)));
443     }
444     else if(propIndex == Dali::Actor::Property::POSITION)
445     {
446       keyframes.Add(inputBufferData[i] / lengthAnimation, Vector3(outputBufferData[i]));
447     }
448     else if(propIndex == Dali::Actor::Property::SCALE)
449     {
450       keyframes.Add(inputBufferData[i] / lengthAnimation, Vector3(outputBufferData[i]));
451     }
452   }
453   return lengthAnimation;
454 }
455
456 bool LoadBuffer(const TreeNode& buffer, std::vector<BufferInfo>& bufferArray)
457 {
458   BufferInfo bufferInfo;
459
460   const TreeNode* uriNode = buffer.GetChild("uri");
461   if(uriNode)
462   {
463     ReadString(uriNode, bufferInfo.uri);
464   }
465
466   const TreeNode* byteLengthNode = buffer.GetChild("byteLength");
467   if(byteLengthNode)
468   {
469     ReadInt(byteLengthNode, bufferInfo.byteLength);
470     if(bufferInfo.byteLength < 0)
471     {
472       return false;
473     }
474   }
475
476   const TreeNode* nameNode = buffer.GetChild("name");
477   if(nameNode)
478   {
479     ReadString(nameNode, bufferInfo.name);
480   }
481
482   bufferArray.push_back(bufferInfo);
483
484   return true;
485 }
486
487 bool LoadBufferView(const TreeNode& buffer, std::vector<BufferViewInfo>& bufferViewArray)
488 {
489   BufferViewInfo bufferViewInfo;
490
491   const TreeNode* bufferNode = buffer.GetChild("buffer");
492   if(bufferNode)
493   {
494     ReadInt(bufferNode, bufferViewInfo.buffer);
495     if(bufferViewInfo.buffer < 0)
496     {
497       return false;
498     }
499   }
500
501   const TreeNode* byteOffsetNode = buffer.GetChild("byteOffset");
502   if(byteOffsetNode)
503   {
504     ReadInt(byteOffsetNode, bufferViewInfo.byteOffset);
505   }
506
507   const TreeNode* byteLengthNode = buffer.GetChild("byteLength");
508   if(byteLengthNode)
509   {
510     ReadInt(byteLengthNode, bufferViewInfo.byteLength);
511     if(bufferViewInfo.byteLength < 0)
512     {
513       return false;
514     }
515   }
516
517   const TreeNode* byteStrideNode = buffer.GetChild("byteStride");
518   if(byteStrideNode)
519   {
520     ReadInt(byteStrideNode, bufferViewInfo.byteStride);
521   }
522
523   const TreeNode* targetNode = buffer.GetChild("target");
524   if(targetNode)
525   {
526     ReadInt(targetNode, bufferViewInfo.target);
527   }
528
529   const TreeNode* nameNode = buffer.GetChild("name");
530   if(nameNode)
531   {
532     ReadString(nameNode, bufferViewInfo.name);
533   }
534
535   bufferViewArray.push_back(bufferViewInfo);
536
537   return true;
538 }
539
540 bool LoadAccessor(const TreeNode& buffer, std::vector<AccessorInfo>& accessorArray)
541 {
542   AccessorInfo accessorInfo;
543
544   const TreeNode* bufferViewNode = buffer.GetChild("bufferView");
545   if(bufferViewNode)
546   {
547     ReadInt(bufferViewNode, accessorInfo.bufferView);
548   }
549
550   const TreeNode* byteOffsetNode = buffer.GetChild("byteOffset");
551   if(byteOffsetNode)
552   {
553     ReadInt(byteOffsetNode, accessorInfo.byteOffset);
554   }
555
556   const TreeNode* componentTypeNode = buffer.GetChild("componentType");
557   if(componentTypeNode)
558   {
559     ReadInt(componentTypeNode, accessorInfo.componentType);
560     if(accessorInfo.componentType < 0)
561     {
562       return false;
563     }
564   }
565
566   const TreeNode* normalizedNode = buffer.GetChild("normalized");
567   if(normalizedNode)
568   {
569     ReadBool(normalizedNode, accessorInfo.normalized);
570   }
571
572   const TreeNode* countNode = buffer.GetChild("count");
573   if(countNode)
574   {
575     ReadInt(countNode, accessorInfo.count);
576     if(accessorInfo.count < 0)
577     {
578       return false;
579     }
580   }
581
582   const TreeNode* typeNode = buffer.GetChild("type");
583   if(typeNode)
584   {
585     ReadString(typeNode, accessorInfo.type);
586     if(accessorInfo.type == "")
587     {
588       return false;
589     }
590   }
591
592   const TreeNode* maxNode = buffer.GetChild("max");
593   if(maxNode)
594   {
595     ReadInt(maxNode, accessorInfo.max);
596   }
597
598   const TreeNode* minNode = buffer.GetChild("min");
599   if(minNode)
600   {
601     ReadInt(minNode, accessorInfo.min);
602   }
603
604   const TreeNode* nameNode = buffer.GetChild("name");
605   if(nameNode)
606   {
607     ReadString(nameNode, accessorInfo.name);
608   }
609
610   accessorArray.push_back(accessorInfo);
611
612   return true;
613 }
614
615 bool LoadBinaryData(const TreeNode& root, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
616 {
617   const TreeNode* buffersNode = root.GetChild("buffers");
618   if(!buffersNode)
619   {
620     return false;
621   }
622   for(auto bufferIter = buffersNode->CBegin(), end = buffersNode->CEnd(); bufferIter != end; ++bufferIter)
623   {
624     LoadBuffer((*bufferIter).second, bufferArray);
625   }
626
627   const TreeNode* bufferViewsNode = root.GetChild("bufferViews");
628   if(!bufferViewsNode)
629   {
630     return false;
631   }
632   for(auto bufferViewIter = bufferViewsNode->CBegin(), end = bufferViewsNode->CEnd(); bufferViewIter != end; ++bufferViewIter)
633   {
634     LoadBufferView((*bufferViewIter).second, bufferViewArray);
635   }
636
637   const TreeNode* accessorsNode = root.GetChild("accessors");
638   if(!accessorsNode)
639   {
640     return false;
641   }
642   for(auto accesorIter = accessorsNode->CBegin(), end = accessorsNode->CEnd(); accesorIter != end; ++accesorIter)
643   {
644     LoadAccessor((*accesorIter).second, accessorArray);
645   }
646
647   return true;
648 }
649
650 FilterMode::Type GetFilterMode(uint32_t mode)
651 {
652   FilterMode::Type retValue = FilterMode::DEFAULT;
653   /**
654    * glTF 2.0 Specification
655    * Filter Code
656    * 9728 : NEAREST
657    * 9729 : LINEAR
658    * 9984 : NEAREST_MIPMAP_NEAREST
659    * 9985 : LINEAR_MIPMAP_NEAREST
660    * 9986 : NEAREST_MIPMAP_LINEAR
661    * 9987 : LINEAR_MIPMAP_LINEAR
662    */
663   switch(mode)
664   {
665     case 9728:
666     {
667       retValue = FilterMode::NEAREST;
668       break;
669     }
670     case 9729:
671     {
672       retValue = FilterMode::LINEAR;
673       break;
674     }
675     case 9984:
676     {
677       retValue = FilterMode::NEAREST_MIPMAP_NEAREST;
678       break;
679     }
680     case 9985:
681     {
682       retValue = FilterMode::LINEAR_MIPMAP_NEAREST;
683       break;
684     }
685     case 9986:
686     {
687       retValue = FilterMode::NEAREST_MIPMAP_LINEAR;
688       break;
689     }
690     case 9987:
691     {
692       retValue = FilterMode::LINEAR_MIPMAP_LINEAR;
693       break;
694     }
695   }
696
697   return retValue;
698 }
699
700 WrapMode::Type GetWrapMode(uint32_t mode)
701 {
702   WrapMode::Type retValue = WrapMode::REPEAT;
703   /**
704    * glTF 2.0 Specification
705    * Wrapping mode Code
706    * 33071 : CLAMP_TO_EDGE
707    * 33648 : MIRRORED_REPEAT
708    * 10497 : REPEAT
709    */
710   switch(mode)
711   {
712     case 33071:
713     {
714       retValue = WrapMode::CLAMP_TO_EDGE;
715       break;
716     }
717     case 33648:
718     {
719       retValue = WrapMode::MIRRORED_REPEAT;
720       break;
721     }
722     case 10497:
723     {
724       retValue = WrapMode::REPEAT;
725       break;
726     }
727   }
728
729   return retValue;
730 }
731
732 Texture LoadTexture(const char* imageUrl, bool generateMipmaps)
733 {
734   Texture            texture;
735   Devel::PixelBuffer pixelBuffer = LoadImageFromFile(imageUrl);
736   if(pixelBuffer)
737   {
738     texture             = Texture::New(TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
739     PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
740     texture.Upload(pixelData);
741
742     if(generateMipmaps)
743     {
744       texture.GenerateMipmaps();
745     }
746   }
747
748   return texture;
749 }
750
751 Sampler LoadSampler(const TreeNode& samplerNode)
752 {
753   Sampler sampler = Sampler::New();
754
755   FilterMode::Type minFilter     = FilterMode::DEFAULT;
756   FilterMode::Type magFilter     = FilterMode::DEFAULT;
757   const TreeNode*  magFilterNode = samplerNode.GetChild("magFilter");
758   if(magFilterNode)
759   {
760     int32_t magFilter_integer = 0;
761     ReadInt(magFilterNode, magFilter_integer);
762     magFilter = GetFilterMode(magFilter_integer);
763   }
764
765   const TreeNode* minFilterNode = samplerNode.GetChild("minFilter");
766   if(minFilterNode)
767   {
768     int32_t minFilter_integer = 0;
769     ReadInt(minFilterNode, minFilter_integer);
770     minFilter = GetFilterMode(minFilter_integer);
771   }
772
773   WrapMode::Type  wrapR    = WrapMode::REPEAT;
774   WrapMode::Type  wrapS    = WrapMode::REPEAT;
775   WrapMode::Type  wrapT    = WrapMode::REPEAT;
776   const TreeNode* wrapNode = samplerNode.GetChild("wrapS");
777   if(wrapNode)
778   {
779     wrapS = GetWrapMode(wrapNode->GetInteger());
780   }
781
782   wrapNode = samplerNode.GetChild("wrapT");
783   if(wrapNode)
784   {
785     wrapT = GetWrapMode(wrapNode->GetInteger());
786   }
787
788   sampler.SetFilterMode(minFilter, magFilter);
789   sampler.SetWrapMode(wrapR, wrapS, wrapT);
790
791   return sampler;
792 }
793
794 bool LoadTextureArray(const TreeNode& root, std::string path, std::vector<Texture>& sourceArray, std::vector<Sampler>& samplerArray, std::vector<TextureInfo>& textureArray)
795 {
796   const TreeNode* imagesNode = root.GetChild("images");
797   if(imagesNode)
798   {
799     for(auto imageIter = imagesNode->CBegin(), end = imagesNode->CEnd(); imageIter != end; ++imageIter)
800     {
801       std::string     imageUrl;
802       const TreeNode* uriNode = (&((*imageIter).second))->GetChild("uri");
803       if(uriNode)
804       {
805         std::string uri;
806         ReadString(uriNode, uri);
807         imageUrl = path + uri;
808       }
809
810       sourceArray.push_back(LoadTexture(imageUrl.c_str(), true));
811     }
812   }
813
814   const TreeNode* samplersNode = root.GetChild("samplers");
815   if(samplersNode)
816   {
817     for(auto samplerIter = samplersNode->CBegin(), end = samplersNode->CEnd(); samplerIter != end; ++samplerIter)
818     {
819       samplerArray.push_back(LoadSampler(((*samplerIter).second)));
820     }
821   }
822
823   const TreeNode* texturesNode = root.GetChild("textures");
824   if(texturesNode)
825   {
826     for(auto textureIter = texturesNode->CBegin(), end = texturesNode->CEnd(); textureIter != end; ++textureIter)
827     {
828       const TreeNode* TextureNode = &((*textureIter).second);
829
830       TextureInfo     texture;
831       const TreeNode* sourceNode = TextureNode->GetChild("source");
832       if(sourceNode)
833       {
834         ReadInt(sourceNode, texture.sourceIdx);
835       }
836
837       const TreeNode* samplerNode = TextureNode->GetChild("sampler");
838       if(samplerNode)
839       {
840         ReadInt(samplerNode, texture.samplerIdx);
841       }
842
843       textureArray.push_back(texture);
844     }
845   }
846   return true;
847 }
848
849 bool LoadPbrMetallicRoughness(const TreeNode& material, MaterialInfo& materialInfo)
850 {
851   float           floatVec[4];
852   const TreeNode* pbrMetallicRoughnessNode = material.GetChild("pbrMetallicRoughness");
853   if(!pbrMetallicRoughnessNode)
854   {
855     return true;
856   }
857
858   const TreeNode* tempNode;
859   tempNode = pbrMetallicRoughnessNode->GetChild("metallicFactor");
860   if(tempNode)
861   {
862     ReadFloat(tempNode, materialInfo.metallicFactor);
863   }
864
865   tempNode = pbrMetallicRoughnessNode->GetChild("roughnessFactor");
866   if(tempNode)
867   {
868     ReadFloat(tempNode, materialInfo.roughnessFactor);
869   }
870
871   tempNode = pbrMetallicRoughnessNode->GetChild("baseColorFactor");
872   if(tempNode && ReadVector(tempNode, floatVec, 4))
873   {
874     materialInfo.baseColorFactor = Vector4(floatVec[0], floatVec[1], floatVec[2], floatVec[3]);
875   }
876
877   const TreeNode* baseColorTextureNode = pbrMetallicRoughnessNode->GetChild("baseColorTexture");
878   if(baseColorTextureNode)
879   {
880     tempNode = baseColorTextureNode->GetChild("index");
881     if(tempNode)
882     {
883       materialInfo.baseColorTexture.index = tempNode->GetInteger();
884     }
885
886     tempNode = baseColorTextureNode->GetChild("texCoord");
887     if(tempNode)
888     {
889       materialInfo.baseColorTexture.texCoord = tempNode->GetInteger();
890     }
891   }
892
893   const TreeNode* metallicRoughnessTextureNode = pbrMetallicRoughnessNode->GetChild("metallicRoughnessTexture");
894   if(metallicRoughnessTextureNode)
895   {
896     tempNode = metallicRoughnessTextureNode->GetChild("index");
897     if(tempNode)
898     {
899       materialInfo.metallicRoughnessTexture.index = tempNode->GetInteger();
900     }
901
902     tempNode = metallicRoughnessTextureNode->GetChild("texCoord");
903     if(tempNode)
904     {
905       materialInfo.metallicRoughnessTexture.texCoord = tempNode->GetInteger();
906     }
907   }
908
909   return true;
910 }
911
912 bool LoadMaterialSetArray(const TreeNode& root, std::vector<MaterialInfo>& materialArray)
913 {
914   const TreeNode* materialsNode = root.GetChild("materials");
915   if(!materialsNode)
916   {
917     return false;
918   }
919
920   for(auto materialIter = materialsNode->CBegin(), end = materialsNode->CEnd(); materialIter != end; ++materialIter)
921   {
922     MaterialInfo materialInfo;
923     LoadPbrMetallicRoughness(((*materialIter).second), materialInfo);
924
925     const TreeNode* materialNode = &((*materialIter).second);
926     const TreeNode* tempNode     = materialNode->GetChild("name");
927     if(tempNode)
928     {
929       ReadString(tempNode, materialInfo.name);
930     }
931
932     materialInfo.alphaMode = "OPAQUE";
933     tempNode               = materialNode->GetChild("alphaMode");
934     if(tempNode)
935     {
936       ReadString(tempNode, materialInfo.alphaMode);
937     }
938
939     materialInfo.alphaCutoff = 1.0;
940     tempNode                 = materialNode->GetChild("alphaCutoff");
941     if(tempNode)
942     {
943       ReadFloat(tempNode, materialInfo.alphaCutoff);
944     }
945
946     materialInfo.doubleSided = false;
947     tempNode                 = materialNode->GetChild("doubleSided");
948     if(tempNode)
949     {
950       ReadBool(tempNode, materialInfo.doubleSided);
951     }
952
953     float floatVec[3];
954     tempNode = materialNode->GetChild("emissiveFactor");
955     if(tempNode && ReadVector(tempNode, floatVec, 3))
956     {
957       materialInfo.emissiveFactor = Vector3(floatVec[0], floatVec[1], floatVec[2]);
958     }
959
960     const TreeNode* texture = materialNode->GetChild("normalTexture");
961     if(texture)
962     {
963       tempNode = texture->GetChild("index");
964       if(tempNode)
965       {
966         materialInfo.normalTexture.index = tempNode->GetInteger();
967       }
968
969       tempNode = texture->GetChild("texCoord");
970       if(tempNode)
971       {
972         materialInfo.normalTexture.texCoord = tempNode->GetInteger();
973       }
974
975       materialInfo.normalTexture.value = 1.0;
976       tempNode                         = texture->GetChild("scale");
977       if(tempNode)
978       {
979         ReadFloat(tempNode, materialInfo.normalTexture.value);
980       }
981     }
982
983     texture = materialNode->GetChild("occlusionTexture");
984     if(texture)
985     {
986       tempNode = texture->GetChild("index");
987       if(tempNode)
988       {
989         materialInfo.occlusionTexture.index = tempNode->GetInteger();
990       }
991
992       tempNode = texture->GetChild("texCoord");
993       if(tempNode)
994       {
995         materialInfo.occlusionTexture.texCoord = tempNode->GetInteger();
996       }
997
998       tempNode = texture->GetChild("strength");
999       if(tempNode)
1000       {
1001         ReadFloat(tempNode, materialInfo.occlusionTexture.value);
1002       }
1003     }
1004
1005     texture = materialNode->GetChild("emissiveTexture");
1006     if(texture)
1007     {
1008       tempNode = texture->GetChild("index");
1009       if(tempNode)
1010       {
1011         materialInfo.emissiveTexture.index = tempNode->GetInteger();
1012       }
1013
1014       tempNode = texture->GetChild("texCoord");
1015       if(tempNode)
1016       {
1017         materialInfo.emissiveTexture.texCoord = tempNode->GetInteger();
1018       }
1019     }
1020     materialArray.push_back(materialInfo);
1021   }
1022   return true;
1023 }
1024
1025 bool LoadAttribute(const TreeNode* primitive, MeshInfo& meshInfo)
1026 {
1027   const TreeNode* attrbuteNode = primitive->GetChild("attributes");
1028   if(!attrbuteNode)
1029   {
1030     return false;
1031   }
1032
1033   const TreeNode* tempNode;
1034   tempNode = attrbuteNode->GetChild("POSITION");
1035   if(tempNode)
1036   {
1037     meshInfo.attribute.POSITION = tempNode->GetInteger();
1038   }
1039
1040   tempNode = attrbuteNode->GetChild("NORMAL");
1041   if(tempNode)
1042   {
1043     meshInfo.attribute.NORMAL = tempNode->GetInteger();
1044   }
1045
1046   tempNode = attrbuteNode->GetChild("TANGENT");
1047   if(tempNode)
1048   {
1049     meshInfo.attribute.TANGENT = tempNode->GetInteger();
1050   }
1051
1052   uint32_t index = 0;
1053   meshInfo.attribute.TEXCOORD.clear();
1054   tempNode = attrbuteNode->GetChild("TEXCOORD_" + std::to_string(index));
1055   while(tempNode)
1056   {
1057     uint32_t value = tempNode->GetInteger();
1058     meshInfo.attribute.TEXCOORD.push_back(value);
1059     tempNode = attrbuteNode->GetChild("TEXCOORD_" + std::to_string(++index));
1060   }
1061
1062   index = 0;
1063   meshInfo.attribute.COLOR.clear();
1064   tempNode = attrbuteNode->GetChild("COLOR_" + std::to_string(index));
1065   while(tempNode)
1066   {
1067     uint32_t value = tempNode->GetInteger();
1068     meshInfo.attribute.COLOR.push_back(value);
1069     tempNode = attrbuteNode->GetChild("COLOR" + std::to_string(++index));
1070   }
1071
1072   return true;
1073 }
1074
1075 bool LoadPrimitive(const TreeNode& mesh, MeshInfo& meshInfo)
1076 {
1077   const TreeNode* primitivesNode = mesh.GetChild("primitives");
1078   if(!primitivesNode)
1079   {
1080     return false;
1081   }
1082
1083   for(auto primitiveIter = primitivesNode->CBegin(), end = primitivesNode->CEnd(); primitiveIter != end; ++primitiveIter)
1084   {
1085     const TreeNode* primitiveNode = (&(*primitiveIter).second);
1086     const TreeNode* tempNode;
1087
1088     tempNode = primitiveNode->GetChild("indices");
1089     if(tempNode)
1090     {
1091       meshInfo.indicesIdx = tempNode->GetInteger();
1092     }
1093
1094     tempNode = primitiveNode->GetChild("material");
1095     if(tempNode)
1096     {
1097       meshInfo.materialsIdx = tempNode->GetInteger();
1098     }
1099
1100     tempNode = primitiveNode->GetChild("mode");
1101     if(tempNode)
1102     {
1103       meshInfo.mode = tempNode->GetInteger();
1104     }
1105
1106     LoadAttribute(primitiveNode, meshInfo);
1107   }
1108
1109   return true;
1110 }
1111
1112 bool SetGeometry(MeshInfo& meshInfo, std::string path, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
1113 {
1114   int32_t indicesIdx = meshInfo.indicesIdx;
1115
1116   if(meshInfo.mode != 0)
1117   {
1118     meshInfo.geometry.SetType((Dali::Geometry::Type)meshInfo.mode);
1119   }
1120
1121   if(indicesIdx >= 0)
1122   {
1123     SetIndexBuffersData(meshInfo, path, accessorArray, bufferViewArray, bufferArray, indicesIdx);
1124   }
1125
1126   SetVertexBufferData(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.POSITION, "aPosition", Property::VECTOR3);
1127   SetAttributeBufferData<Vector3>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.NORMAL, "aNormal", Property::VECTOR3);
1128   SetAttributeBufferData<Vector4>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.TANGENT, "aTangent", Property::VECTOR4);
1129
1130   for(uint32_t i = 0; i < meshInfo.attribute.TEXCOORD.size(); ++i)
1131   {
1132     int32_t            accessorIdx = meshInfo.attribute.TEXCOORD[i];
1133     std::ostringstream texCoordString;
1134     texCoordString << "aTexCoord" << i;
1135     SetAttributeBufferData<Vector2>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, texCoordString.str(), Property::VECTOR2);
1136   }
1137
1138   for(auto&& accessorIdx : meshInfo.attribute.COLOR)
1139   {
1140     if(accessorIdx < 0)
1141     {
1142       break;
1143     }
1144
1145     if(accessorArray[accessorIdx].type == "VEC3")
1146     {
1147       Dali::Vector<Vector3> inputBufferData;
1148       LoadDataFromAccessor(accessorIdx, inputBufferData, path, accessorArray, bufferViewArray, bufferArray);
1149
1150       Dali::Vector<Vector4> bufferData;
1151       bufferData.Resize(inputBufferData.Size());
1152       for(uint32_t i = 0; i < inputBufferData.Size(); ++i)
1153       {
1154         bufferData[i].x = inputBufferData[i].x;
1155         bufferData[i].y = inputBufferData[i].y;
1156         bufferData[i].z = inputBufferData[i].z;
1157         bufferData[i].w = 1.0;
1158       }
1159       VertexBuffer vertexBuffer = CreateVertexBuffer<Vector4>(bufferData, "aVertexColor", Property::VECTOR4);
1160       meshInfo.geometry.AddVertexBuffer(vertexBuffer);
1161     }
1162     else if(accessorArray[accessorIdx].type == "VEC4")
1163     {
1164       SetAttributeBufferData<Vector4>(meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, "aVertexColor", Property::VECTOR4);
1165     }
1166   }
1167   return true;
1168 }
1169
1170 bool LoadMeshArray(const TreeNode& root, std::string path, std::vector<MeshInfo>& meshArray, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray)
1171 {
1172   const TreeNode* meshesNode = root.GetChild("meshes");
1173   if(!meshesNode)
1174   {
1175     return false;
1176   }
1177
1178   for(auto meshIter = meshesNode->CBegin(), end = meshesNode->CEnd(); meshIter != end; ++meshIter)
1179   {
1180     MeshInfo        meshInfo;
1181     const TreeNode* nameNode = (&(*meshIter).second)->GetChild("name");
1182     if(nameNode)
1183     {
1184       ReadString(nameNode, meshInfo.name);
1185     }
1186     meshInfo.geometry = Geometry::New();
1187
1188     //Need to add weights for Morph targets.
1189     LoadPrimitive((*meshIter).second, meshInfo);
1190     SetGeometry(meshInfo, path, bufferArray, bufferViewArray, accessorArray);
1191     meshArray.push_back(meshInfo);
1192   }
1193
1194   return true;
1195 }
1196
1197 } // namespace
1198
1199 Loader::Loader()
1200 : mNodes(NULL),
1201   mRoot(NULL)
1202 {
1203 }
1204
1205 Loader::~Loader()
1206 {
1207 }
1208
1209 bool Loader::LoadScene(const std::string& filePath, Internal::Scene3dView& scene3dView)
1210 {
1211   // Extracting directory path from full path to load resources.
1212   if(std::string::npos != filePath.rfind('/'))
1213   {
1214     mPath = filePath.substr(0, filePath.rfind('/')) + "/";
1215   }
1216
1217   if(!ParseGltf(filePath))
1218   {
1219     DALI_LOG_ERROR("Fail to parse json file\n");
1220     return false;
1221   }
1222
1223   mRoot = mParser.GetRoot();
1224   if(mRoot &&
1225      LoadAssets() &&
1226      CreateScene(scene3dView))
1227   {
1228     return true;
1229   }
1230   return false;
1231 }
1232
1233 bool Loader::ParseGltf(const std::string& filePath)
1234 {
1235   std::streampos     bufferSize = 0;
1236   Dali::Vector<char> buffer;
1237   std::string        fileBuffer;
1238   if(!Dali::FileLoader::ReadFile(filePath, bufferSize, buffer, FileLoader::FileType::BINARY))
1239   {
1240     return false;
1241   }
1242
1243   fileBuffer.assign(&buffer[0], bufferSize);
1244   mParser = Dali::Toolkit::JsonParser::New();
1245   return mParser.Parse(fileBuffer);
1246 }
1247
1248 bool Loader::LoadAssets()
1249 {
1250   if(LoadBinaryData(*mRoot, mBufferArray, mBufferViewArray, mAccessorArray) &&
1251      LoadTextureArray(*mRoot, mPath, mSourceArray, mSamplerArray, mTextureArray) &&
1252      LoadMaterialSetArray(*mRoot, mMaterialArray) &&
1253      LoadMeshArray(*mRoot, mPath, mMeshArray, mBufferArray, mBufferViewArray, mAccessorArray))
1254   {
1255     return true;
1256   }
1257   return false;
1258 }
1259
1260 bool Loader::CreateScene(Internal::Scene3dView& scene3dView)
1261 {
1262   scene3dView.SetDefaultCamera(Dali::Camera::LOOK_AT_TARGET, 0.01, Vector3::ZERO);
1263   LoadCamera(scene3dView);
1264
1265   if(LoadSceneNodes(scene3dView) &&
1266      LoadAnimation(scene3dView))
1267   {
1268     return true;
1269   }
1270   return false;
1271 }
1272
1273 void Loader::LoadCamera(Scene3dView& scene3dView)
1274 {
1275   const TreeNode* camerasNode = mRoot->GetChild("cameras");
1276   if(!camerasNode)
1277   {
1278     return;
1279   }
1280
1281   for(auto cameraIter = camerasNode->CBegin(), end = camerasNode->CEnd(); cameraIter != end; ++cameraIter)
1282   {
1283     const TreeNode* tempNode = (&(*cameraIter).second)->GetChild("name");
1284     CameraInfo      cameraInfo;
1285     if(tempNode)
1286     {
1287       ReadString(tempNode, cameraInfo.name);
1288     }
1289
1290     tempNode = (&(*cameraIter).second)->GetChild("type");
1291     if(tempNode)
1292     {
1293       ReadString(tempNode, cameraInfo.type);
1294     }
1295
1296     CameraActor cameraActor = CameraActor::New();
1297     cameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1298     cameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
1299
1300     if(cameraInfo.type == "orthographic")
1301     {
1302       LoadOrthoGraphic((*cameraIter).second, cameraInfo);
1303       float xMag_2 = cameraInfo.orthographic.xmag / 2.0;
1304       float yMag_2 = cameraInfo.orthographic.ymag / 2.0;
1305       cameraActor.SetOrthographicProjection(-xMag_2, xMag_2, yMag_2, -yMag_2, cameraInfo.orthographic.znear, cameraInfo.orthographic.zfar);
1306     }
1307     else if(cameraInfo.type == "perspective")
1308     {
1309       if(!LoadPerspective((*cameraIter).second, cameraInfo))
1310       {
1311         return;
1312       }
1313       cameraActor.SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
1314       cameraActor.SetFieldOfView(cameraInfo.perspective.yfov);
1315       cameraActor.SetNearClippingPlane(cameraInfo.perspective.znear);
1316
1317       if(cameraInfo.perspective.zfar > 0.0)
1318       {
1319         cameraActor.SetFarClippingPlane(cameraInfo.perspective.zfar);
1320       }
1321       if(cameraInfo.perspective.aspectRatio > 0.0)
1322       {
1323         cameraActor.SetAspectRatio(cameraInfo.perspective.aspectRatio);
1324       }
1325     }
1326
1327     scene3dView.AddCamera(cameraActor);
1328   }
1329 }
1330
1331 bool Loader::LoadOrthoGraphic(const TreeNode& camera, CameraInfo& cameraInfo)
1332 {
1333   const TreeNode* orthographicNode = camera.GetChild("orthographic");
1334   if(!orthographicNode)
1335   {
1336     return false;
1337   }
1338
1339   const TreeNode* tempNode;
1340   tempNode = orthographicNode->GetChild("xmag");
1341   if(tempNode)
1342   {
1343     ReadFloat(tempNode, cameraInfo.orthographic.xmag);
1344   }
1345
1346   tempNode = orthographicNode->GetChild("ymag");
1347   if(tempNode)
1348   {
1349     ReadFloat(tempNode, cameraInfo.orthographic.ymag);
1350   }
1351
1352   tempNode = orthographicNode->GetChild("zfar");
1353   if(tempNode)
1354   {
1355     ReadFloat(tempNode, cameraInfo.orthographic.zfar);
1356   }
1357
1358   tempNode = orthographicNode->GetChild("znear");
1359   if(tempNode)
1360   {
1361     ReadFloat(tempNode, cameraInfo.orthographic.znear);
1362   }
1363
1364   return true;
1365 }
1366
1367 bool Loader::LoadPerspective(const TreeNode& camera, CameraInfo& cameraInfo)
1368 {
1369   const TreeNode* perspectiveNode = camera.GetChild("perspective");
1370   if(!perspectiveNode)
1371   {
1372     return false;
1373   }
1374
1375   const TreeNode* tempNode;
1376   tempNode = perspectiveNode->GetChild("aspectRatio");
1377   if(tempNode)
1378   {
1379     ReadFloat(tempNode, cameraInfo.perspective.aspectRatio);
1380   }
1381
1382   tempNode = perspectiveNode->GetChild("yfov");
1383   if(tempNode)
1384   {
1385     ReadFloat(tempNode, cameraInfo.perspective.yfov);
1386   }
1387
1388   tempNode = perspectiveNode->GetChild("zfar");
1389   if(tempNode)
1390   {
1391     ReadFloat(tempNode, cameraInfo.perspective.zfar);
1392   }
1393
1394   tempNode = perspectiveNode->GetChild("znear");
1395   if(tempNode)
1396   {
1397     ReadFloat(tempNode, cameraInfo.perspective.znear);
1398   }
1399
1400   return true;
1401 }
1402
1403 bool Loader::LoadSceneNodes(Scene3dView& scene3dView)
1404 {
1405   const TreeNode* sceneNode = mRoot->GetChild("scene");
1406   uint32_t        sceneNum  = 0;
1407   if(sceneNode)
1408   {
1409     sceneNum = sceneNode->GetInteger();
1410   }
1411
1412   const TreeNode* scenesNode = mRoot->GetChild("scenes");
1413   if(!(scenesNode && (mNodes = mRoot->GetChild("nodes"))))
1414   {
1415     return false;
1416   }
1417
1418   const TreeNode* tempNode = Tidx(scenesNode, sceneNum);
1419   if(!tempNode)
1420   {
1421     return false;
1422   }
1423
1424   tempNode = tempNode->GetChild("nodes");
1425   if(!tempNode)
1426   {
1427     return false;
1428   }
1429
1430   for(auto nodeIter = tempNode->CBegin(), end = tempNode->CEnd(); nodeIter != end; ++nodeIter)
1431   {
1432     Actor actor = AddNode(scene3dView, ((*nodeIter).second).GetInteger());
1433     actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1434     scene3dView.GetRoot().Add(actor);
1435   }
1436
1437   return true;
1438 }
1439
1440 Actor Loader::AddNode(Scene3dView& scene3dView, uint32_t index)
1441 {
1442   const TreeNode* node  = Tidx(mNodes, index);
1443   Actor           actor = Actor::New();
1444   Vector3         actorSize(Vector3::ONE);
1445
1446   Vector3    translation = Vector3(0.0, 0.0, 0.0);
1447   Vector3    scale       = Vector3(1.0, 1.0, 1.0);
1448   Quaternion orientation(Vector4(0.0, 0.0, 0.0, 1.0));
1449
1450   Vector3 anchorPoint = AnchorPoint::CENTER;
1451
1452   const TreeNode* tempNode = NULL;
1453   if((tempNode = node->GetChild("translation")))
1454   {
1455     float floatVec[3] = {0.0, 0.0, 0.0};
1456     if(tempNode && ReadVector(tempNode, floatVec, 3))
1457     {
1458       translation = Vector3(floatVec[0], floatVec[1], floatVec[2]);
1459     }
1460   }
1461
1462   if((tempNode = node->GetChild("scale")))
1463   {
1464     float floatVec[3] = {1.0, 1.0, 1.0};
1465     if(tempNode && ReadVector(tempNode, floatVec, 3))
1466     {
1467       scale = Vector3(floatVec[0], floatVec[1], floatVec[2]);
1468     }
1469   }
1470
1471   if((tempNode = node->GetChild("rotation")))
1472   {
1473     float floatVec[4] = {0.0, 0.0, 0.0, 1.0};
1474     if(tempNode && ReadVector(tempNode, floatVec, 4))
1475     {
1476       orientation = Quaternion(Vector4(floatVec[0], floatVec[1], floatVec[2], floatVec[3]));
1477     }
1478   }
1479
1480   if((tempNode = node->GetChild("matrix")))
1481   {
1482     float floatVec[16] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0};
1483     if(tempNode && ReadVector(tempNode, floatVec, 16))
1484     {
1485       Matrix nodeMatrix = Matrix(floatVec);
1486       nodeMatrix.GetTransformComponents(translation, orientation, scale);
1487     }
1488   }
1489
1490   if((tempNode = node->GetChild("mesh")))
1491   {
1492     MeshInfo meshInfo   = mMeshArray[tempNode->GetInteger()];
1493     bool     isMaterial = (meshInfo.materialsIdx >= 0);
1494
1495     TextureSet textureSet;
1496     textureSet = TextureSet::New();
1497
1498     int32_t addIdx                     = 0;
1499     int32_t shaderTypeIndex            = 0;
1500     int32_t maxMipmapLevel             = 0;
1501     bool    isBaseColorTexture         = false;
1502     bool    isMetallicRoughnessTexture = false;
1503     bool    isNormalTexture            = false;
1504     bool    isOcclusionTexture         = false;
1505     bool    isEmissiveTexture          = false;
1506
1507     std::string VERTEX_SHADER, FRAGMENT_SHADER;
1508     VERTEX_SHADER = SHADER_GLTF_GLES_VERSION_300_DEF.data();
1509     VERTEX_SHADER += SHADER_GLTF_PHYSICALLY_BASED_SHADER_VERT.data();
1510     FRAGMENT_SHADER = SHADER_GLTF_GLES_VERSION_300_DEF.data();
1511
1512     bool useIBL = (scene3dView.GetLightType() >= Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT);
1513     if(isMaterial)
1514     {
1515       MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1516       if(SetTextureAndSampler(textureSet, materialInfo.baseColorTexture.index, FRAGMENT_SHADER, SHADER_GLTF_BASECOLOR_TEXTURE_DEF.data(), addIdx))
1517       {
1518         shaderTypeIndex += static_cast<int32_t>(ShaderType::BASECOLOR_SHADER);
1519         isBaseColorTexture = true;
1520       }
1521       if(SetTextureAndSampler(textureSet, materialInfo.metallicRoughnessTexture.index, FRAGMENT_SHADER, SHADER_GLTF_METALLICROUGHNESS_TEXTURE_DEF.data(), addIdx))
1522       {
1523         shaderTypeIndex += static_cast<int32_t>(ShaderType::METALLICROUGHNESS_SHADER);
1524         isMetallicRoughnessTexture = true;
1525       }
1526       if(SetTextureAndSampler(textureSet, materialInfo.normalTexture.index, FRAGMENT_SHADER, SHADER_GLTF_NORMAL_TEXTURE_DEF.data(), addIdx))
1527       {
1528         shaderTypeIndex += static_cast<int32_t>(ShaderType::NORMAL_SHADER);
1529         isNormalTexture = true;
1530       }
1531       if(SetTextureAndSampler(textureSet, materialInfo.occlusionTexture.index, FRAGMENT_SHADER, SHADER_GLTF_OCCULUSION_TEXTURE_DEF.data(), addIdx))
1532       {
1533         shaderTypeIndex += static_cast<int32_t>(ShaderType::OCCLUSION_SHADER);
1534         isOcclusionTexture = true;
1535       }
1536       if(SetTextureAndSampler(textureSet, materialInfo.emissiveTexture.index, FRAGMENT_SHADER, SHADER_GLTF_EMIT_TEXTURE_DEF.data(), addIdx))
1537       {
1538         shaderTypeIndex += static_cast<int32_t>(ShaderType::EMIT_SHADER);
1539         isEmissiveTexture = true;
1540       }
1541
1542       if(useIBL)
1543       {
1544         shaderTypeIndex += static_cast<int32_t>(ShaderType::IBL_SHADER);
1545         FRAGMENT_SHADER += SHADER_GLTF_IBL_TEXTURE_DEF.data();
1546
1547         Sampler sampler = Sampler::New();
1548         sampler.SetFilterMode(FilterMode::DEFAULT, FilterMode::DEFAULT);
1549         sampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT);
1550
1551         textureSet.SetTexture(addIdx, scene3dView.GetBRDFTexture());
1552         textureSet.SetSampler(addIdx++, sampler);
1553         Sampler samplerIBL = Sampler::New();
1554         samplerIBL.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR);
1555         samplerIBL.SetWrapMode(WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
1556         textureSet.SetTexture(addIdx, scene3dView.GetDiffuseTexture());
1557         textureSet.SetSampler(addIdx++, samplerIBL);
1558         Texture specularTexture = scene3dView.GetSpecularTexture();
1559         textureSet.SetTexture(addIdx, specularTexture);
1560         textureSet.SetSampler(addIdx++, samplerIBL);
1561
1562         int32_t textureSize = std::min(specularTexture.GetWidth(), specularTexture.GetHeight());
1563         maxMipmapLevel      = 0;
1564         while(textureSize >= 1)
1565         {
1566           maxMipmapLevel++;
1567           textureSize /= 2;
1568         }
1569       }
1570     }
1571
1572     FRAGMENT_SHADER += SHADER_GLTF_PHYSICALLY_BASED_SHADER_FRAG.data();
1573     if(!mShaderCache[shaderTypeIndex])
1574     {
1575       mShaderCache[shaderTypeIndex] = Shader::New(VERTEX_SHADER, FRAGMENT_SHADER);
1576       scene3dView.AddShader(mShaderCache[shaderTypeIndex]);
1577     }
1578     Shader shader = mShaderCache[shaderTypeIndex];
1579
1580     Renderer renderer = Renderer::New(meshInfo.geometry, shader);
1581     renderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON);
1582     renderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
1583     renderer.SetTextures(textureSet);
1584
1585     anchorPoint = meshInfo.pivot;
1586     actor.SetProperty(Actor::Property::ANCHOR_POINT, anchorPoint);
1587
1588     actor.SetProperty(Actor::Property::SIZE, Vector3(meshInfo.size.x, meshInfo.size.y, meshInfo.size.z));
1589     actor.AddRenderer(renderer);
1590
1591     actor.SetProperty(Actor::Property::SCALE, scale);
1592     actor.RotateBy(orientation);
1593     actor.SetProperty(Actor::Property::POSITION, translation);
1594
1595     shader.RegisterProperty("uLightType", (scene3dView.GetLightType() & ~Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT));
1596     shader.RegisterProperty("uLightVector", scene3dView.GetLightVector());
1597     shader.RegisterProperty("uLightColor", scene3dView.GetLightColor());
1598
1599     actor.RegisterProperty("uIsColor", meshInfo.attribute.COLOR.size() > 0);
1600     if(isMaterial)
1601     {
1602       MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1603       actor.RegisterProperty("uBaseColorFactor", materialInfo.baseColorFactor);
1604       actor.RegisterProperty("uMetallicRoughnessFactors", Vector2(materialInfo.metallicFactor, materialInfo.roughnessFactor));
1605
1606       if(materialInfo.alphaMode == "OPAQUE")
1607       {
1608         actor.RegisterProperty("alphaMode", 0);
1609       }
1610       else if(materialInfo.alphaMode == "MASK")
1611       {
1612         actor.RegisterProperty("alphaMode", 1);
1613       }
1614       else
1615       {
1616         actor.RegisterProperty("alphaMode", 2);
1617       }
1618       actor.RegisterProperty("alphaCutoff", materialInfo.alphaCutoff);
1619
1620       if(isBaseColorTexture)
1621       {
1622         actor.RegisterProperty("uBaseColorTexCoordIndex", materialInfo.baseColorTexture.texCoord);
1623       }
1624       if(isMetallicRoughnessTexture)
1625       {
1626         actor.RegisterProperty("uMetallicRoughnessTexCoordIndex", materialInfo.metallicRoughnessTexture.texCoord);
1627       }
1628       if(isNormalTexture)
1629       {
1630         actor.RegisterProperty("uNormalScale", materialInfo.normalTexture.value);
1631         actor.RegisterProperty("uNormalTexCoordIndex", materialInfo.normalTexture.texCoord);
1632       }
1633       if(isOcclusionTexture)
1634       {
1635         actor.RegisterProperty("uOcclusionTexCoordIndex", materialInfo.occlusionTexture.texCoord);
1636         actor.RegisterProperty("uOcclusionStrength", materialInfo.occlusionTexture.value);
1637       }
1638       if(isEmissiveTexture)
1639       {
1640         actor.RegisterProperty("uEmissiveTexCoordIndex", materialInfo.emissiveTexture.texCoord);
1641         actor.RegisterProperty("uEmissiveFactor", materialInfo.emissiveFactor);
1642       }
1643     }
1644
1645     if(isMaterial && useIBL)
1646     {
1647       actor.RegisterProperty("uScaleIBLAmbient", scene3dView.GetIBLScaleFactor());
1648       actor.RegisterProperty("uMipmapLevel", static_cast<float>(maxMipmapLevel));
1649     }
1650   }
1651   else
1652   {
1653     actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
1654     actor.SetProperty(Actor::Property::POSITION, translation);
1655     actor.RotateBy(orientation);
1656     actor.SetProperty(Actor::Property::SIZE, actorSize);
1657   }
1658
1659   tempNode = node->GetChild("camera");
1660   if(tempNode)
1661   {
1662     int32_t     cameraNum   = tempNode->GetInteger();
1663     CameraActor cameraActor = scene3dView.GetCamera(cameraNum);
1664     if(cameraActor)
1665     {
1666       actor.Add(cameraActor);
1667     }
1668   }
1669
1670   tempNode = node->GetChild("name");
1671   if(tempNode)
1672   {
1673     std::string nameString;
1674     ReadString(tempNode, nameString);
1675     actor.SetProperty(Dali::Actor::Property::NAME, nameString);
1676   }
1677
1678   SetActorCache(actor, index);
1679   if((tempNode = node->GetChild("children")))
1680   {
1681     for(auto childIter = tempNode->CBegin(), end = tempNode->CEnd(); childIter != end; ++childIter)
1682     {
1683       Actor childActor = AddNode(scene3dView, ((*childIter).second).GetInteger());
1684       childActor.SetProperty(Actor::Property::PARENT_ORIGIN, anchorPoint);
1685       actor.Add(childActor);
1686     }
1687   }
1688
1689   return actor;
1690 }
1691
1692 void Loader::SetActorCache(Actor& actor, uint32_t index)
1693 {
1694   if(mActorCache.size() < index + 1)
1695   {
1696     mActorCache.resize(index + 1);
1697   }
1698   mActorCache[index] = actor;
1699 }
1700
1701 bool Loader::SetTextureAndSampler(TextureSet& textureSet, int32_t textureIdx, std::string& toShader, std::string shader, int32_t& addIdx)
1702 {
1703   if(textureIdx >= 0)
1704   {
1705     toShader += shader;
1706     TextureInfo textureInfo = mTextureArray[textureIdx];
1707     if(textureInfo.sourceIdx >= 0)
1708     {
1709       textureSet.SetTexture(addIdx, mSourceArray[textureInfo.sourceIdx]);
1710     }
1711     if(textureInfo.samplerIdx >= 0)
1712     {
1713       textureSet.SetSampler(addIdx, mSamplerArray[textureInfo.samplerIdx]);
1714     }
1715     else
1716     {
1717       Sampler sampler = Sampler::New();
1718       sampler.SetFilterMode(FilterMode::DEFAULT, FilterMode::DEFAULT);
1719       sampler.SetWrapMode(WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT);
1720       textureSet.SetSampler(addIdx, sampler);
1721     }
1722     addIdx++;
1723     return true;
1724   }
1725   return false;
1726 }
1727
1728 bool Loader::LoadAnimation(Scene3dView& scene3dView)
1729 {
1730   const TreeNode* animationsNode = mRoot->GetChild("animations");
1731   if(!animationsNode)
1732   {
1733     return true;
1734   }
1735
1736   for(auto animationIter = animationsNode->CBegin(), end = animationsNode->CEnd(); animationIter != end; ++animationIter)
1737   {
1738     const TreeNode* nameNode = (&(*animationIter).second)->GetChild("name");
1739     AnimationInfo   animationInfo;
1740     if(nameNode)
1741     {
1742       ReadString(nameNode, animationInfo.name);
1743     }
1744
1745     Property::Index propIndex = Property::INVALID_INDEX;
1746     LoadAnimationChannels((*animationIter).second, animationInfo);
1747     if(animationInfo.channelArray.size() == 0)
1748     {
1749       continue;
1750     }
1751
1752     LoadAnimationSamplers((*animationIter).second, animationInfo);
1753
1754     for(auto&& currentChannel : animationInfo.channelArray)
1755     {
1756       if(currentChannel.path == "rotation")
1757       {
1758         propIndex = Dali::Actor::Property::ORIENTATION;
1759       }
1760       else if(currentChannel.path == "translation")
1761       {
1762         propIndex = Dali::Actor::Property::POSITION;
1763       }
1764       else if(currentChannel.path == "scale")
1765       {
1766         propIndex = Dali::Actor::Property::SCALE;
1767       }
1768
1769       float     duration  = 0.0f;
1770       KeyFrames keyframes = KeyFrames::New();
1771       if(propIndex == Dali::Actor::Property::ORIENTATION)
1772       {
1773         duration = LoadKeyFrames<Vector4>(animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray);
1774       }
1775       else
1776       {
1777         duration = LoadKeyFrames<Vector3>(animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray);
1778       }
1779
1780       Animation                animation     = Animation::New(duration);
1781       Animation::Interpolation interpolation = Animation::Interpolation::LINEAR;
1782       if(animationInfo.samplerArray[currentChannel.sampler].interpolation == "CUBICSPLINE")
1783       {
1784         interpolation = Animation::Interpolation::CUBIC;
1785       }
1786       if(animationInfo.samplerArray[currentChannel.sampler].interpolation == "STEP")
1787       {
1788       }
1789
1790       animation.AnimateBetween(Property(mActorCache[currentChannel.targetNode], propIndex), keyframes, interpolation);
1791
1792       animation.SetLooping(false);
1793       scene3dView.AddAnimation(animation);
1794     }
1795   }
1796
1797   return true;
1798 }
1799
1800 bool Loader::LoadAnimationChannels(const TreeNode& animation, AnimationInfo& animationInfo)
1801 {
1802   const TreeNode* channelsNode = animation.GetChild("channels");
1803   if(!channelsNode)
1804   {
1805     return false;
1806   }
1807
1808   for(auto channelIter = channelsNode->CBegin(), end = channelsNode->CEnd(); channelIter != end; ++channelIter)
1809   {
1810     AnimationChannelInfo animationChannelInfo;
1811     const TreeNode*      channelNode = (&(*channelIter).second);
1812     const TreeNode*      samplerNode = channelNode->GetChild("sampler");
1813     if(samplerNode)
1814     {
1815       animationChannelInfo.sampler = samplerNode->GetInteger();
1816     }
1817
1818     const TreeNode* targetNode = channelNode->GetChild("target");
1819     if(targetNode)
1820     {
1821       const TreeNode* tempNode = targetNode->GetChild("node");
1822       if(tempNode)
1823       {
1824         animationChannelInfo.targetNode = tempNode->GetInteger();
1825       }
1826       else
1827       {
1828         continue;
1829       }
1830
1831       tempNode = targetNode->GetChild("path");
1832       if(tempNode)
1833       {
1834         ReadString(tempNode, animationChannelInfo.path);
1835       }
1836     }
1837
1838     animationInfo.channelArray.push_back(animationChannelInfo);
1839   }
1840   return true;
1841 }
1842
1843 bool Loader::LoadAnimationSamplers(const TreeNode& animation, AnimationInfo& animationInfo)
1844 {
1845   const TreeNode* samplersNode = animation.GetChild("samplers");
1846   if(!samplersNode)
1847   {
1848     return false;
1849   }
1850
1851   for(auto sampler = samplersNode->CBegin(), end = samplersNode->CEnd(); sampler != end; ++sampler)
1852   {
1853     AnimationSamplerInfo animationSamplerInfo;
1854     const TreeNode*      samplerNode = (&(*sampler).second);
1855     const TreeNode*      tempNode    = samplerNode->GetChild("input");
1856     if(tempNode)
1857     {
1858       animationSamplerInfo.input = tempNode->GetInteger();
1859     }
1860
1861     tempNode = samplerNode->GetChild("output");
1862     if(tempNode)
1863     {
1864       animationSamplerInfo.output = tempNode->GetInteger();
1865     }
1866
1867     tempNode = samplerNode->GetChild("interpolation");
1868     if(tempNode)
1869     {
1870       ReadString(tempNode, animationSamplerInfo.interpolation);
1871     }
1872
1873     animationInfo.samplerArray.push_back(animationSamplerInfo);
1874   }
1875
1876   return true;
1877 }
1878
1879 } //namespace Gltf
1880
1881 } //namespace Internal
1882
1883 } //namespace Toolkit
1884
1885 } //namespace Dali