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