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