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