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