Merge "Use FileStream API in gltf-loader." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scene3d-view / gltf-loader.cpp
1 /*
2  * Copyright (c) 2019 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 <dali/integration-api/debug.h>
24 #include <dali/devel-api/adaptor-framework/image-loading.h>
25 #include <dali/devel-api/adaptor-framework/file-stream.h>
26
27 namespace Dali
28 {
29
30 namespace Toolkit
31 {
32
33 namespace Internal
34 {
35
36 namespace Gltf
37 {
38
39 namespace
40 {
41
42 // Utility functions
43 const TreeNode* Tidx( const TreeNode *node, uint32_t index )
44 {
45   uint32_t i = 0;
46   for( auto it = node->CBegin(), end = node->CEnd(); it != end; ++it, ++i )
47   {
48     if( i == index )
49     {
50       return &( ( *it ).second );
51     }
52   }
53   return NULL;
54 }
55
56 bool ReadBool( const TreeNode* node, bool& num )
57 {
58   if( !node )
59   {
60     return false;
61   }
62   bool returnValue = false;
63
64   if( node->GetType() == TreeNode::BOOLEAN )
65   {
66     num = node->GetBoolean();
67     returnValue = true;
68   }
69
70   return returnValue;
71 }
72
73 bool ReadInt( const TreeNode* node, int32_t& num )
74 {
75   if( !node )
76   {
77     return false;
78   }
79   bool returnValue = false;
80   if( node->GetType() == TreeNode::INTEGER )
81   {
82     num = node->GetInteger();
83     returnValue = true;
84   }
85   else  if( node->GetType() == TreeNode::FLOAT )
86   {
87     num = node->GetFloat();
88     returnValue = true;
89   }
90
91   return returnValue;
92 }
93
94 bool ReadFloat( const TreeNode* node, float& num )
95 {
96   if( !node )
97   {
98     return false;
99   }
100   bool returnValue = false;
101
102   if( node->GetType() == TreeNode::FLOAT )
103   {
104     num = node->GetFloat();
105     returnValue = true;
106   }
107   else if( node->GetType() == TreeNode::INTEGER )
108   {
109     int32_t tempNum;
110     ReadInt( node, tempNum );
111     num = static_cast<float>( tempNum );
112     returnValue = true;
113   }
114
115   return returnValue;
116 }
117
118 bool ReadVector( const TreeNode* node, float* num, uint32_t size )
119 {
120   if( !node )
121   {
122     return false;
123   }
124   bool returnValue = false;
125
126   if( ( node->Size() >= size ) && ( node->GetType() == TreeNode::ARRAY ) )
127   {
128     uint32_t offset = 0u;
129     for( auto it = node->CBegin(); offset < size; ++it, ++offset )
130     {
131       const TreeNode& coord = ( *it ).second;
132       if( !ReadFloat( &coord, *( num + offset ) ) )
133       {
134         return false;
135       }
136     }
137     returnValue = true;
138   }
139
140   return returnValue;
141 }
142
143 bool ReadString( const TreeNode* node, std::string& strValue )
144 {
145   if( !node )
146   {
147     return false;
148   }
149   bool returnValue = false;
150   if( node->GetType() == TreeNode::STRING )
151   {
152     strValue = node->GetString();
153     returnValue = true;
154   }
155   return returnValue;
156 }
157
158 template <typename T>
159 float IntToFloat( T element, bool normalize )
160 {
161   if( !normalize )
162   {
163     return static_cast<float>( element );
164   }
165
166   if( std::is_same<T, int8_t>::value )
167   {
168     return std::max( static_cast<float>( element ) / 127.0, -1.0 );
169   }
170   if( std::is_same<T, uint8_t>::value )
171   {
172     return static_cast<float>( element ) / 255.0;
173   }
174   if( std::is_same<T, int16_t>::value )
175   {
176     return std::max( static_cast<float>( element ) / 32767.0, -1.0 );
177   }
178   if( std::is_same<T, uint16_t>::value )
179   {
180     return static_cast<float>( element ) / 65535.0;
181   }
182   return -1.0;
183 }
184
185 template <typename Td, typename Ts>
186 void FitBuffer( Dali::Vector<Td>& bufferDestination, Dali::Vector<Ts>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
187 {
188   bufferDestination.Resize( bufferSize );
189   int32_t count = bufferSource.Size() / elementNumOfByteStride;
190   for( int32_t i = 0; i<count; ++i )
191   {
192     bufferDestination[i] = static_cast<Td>( bufferSource[i * elementNumOfByteStride] );
193   }
194 }
195
196 template <typename T>
197 void FitBuffer( Dali::Vector<Vector2>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
198 {
199   bufferDestination.Resize( bufferSize );
200   int32_t count = bufferSource.Size() / elementNumOfByteStride;
201   for( int32_t i = 0; i<count; ++i )
202   {
203     bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
204     bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
205   }
206 }
207
208 template <typename T>
209 void FitBuffer( Dali::Vector<Vector3>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
210 {
211   bufferDestination.Resize( bufferSize );
212   int32_t count = bufferSource.Size() / elementNumOfByteStride;
213   for( int32_t i = 0; i<count; ++i )
214   {
215     bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
216     bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
217     bufferDestination[i].z = IntToFloat( bufferSource[i * elementNumOfByteStride + 2], normalize );
218   }
219 }
220
221 template <typename T>
222 void FitBuffer( Dali::Vector<Vector4>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
223 {
224   bufferDestination.Resize( bufferSize );
225   int32_t count = bufferSource.Size() / elementNumOfByteStride;
226   for( int32_t i = 0; i<count; ++i )
227   {
228     bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
229     bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
230     bufferDestination[i].z = IntToFloat( bufferSource[i * elementNumOfByteStride + 2], normalize );
231     bufferDestination[i].w = IntToFloat( bufferSource[i * elementNumOfByteStride + 3], normalize );
232   }
233 }
234
235 // Template functions
236 template <typename T>
237 bool ReadBinFile( Vector<T> &dataBuffer, std::string url, int32_t offset, int32_t count )
238 {
239   Dali::FileStream fileStream( url, FileStream::READ || FileStream::BINARY );
240   FILE* fp = fileStream.GetFile();
241   if( !fp )
242   {
243     return false;
244   }
245
246   dataBuffer.Resize( count );
247   ssize_t result = -1;
248   if( !fseek( fp, offset, SEEK_SET ) )
249   {
250     result = fread( &dataBuffer[0], sizeof( T ), count, fp );
251   }
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::streampos bufferSize = 0;
1232   Dali::Vector<char> buffer;
1233   std::string fileBuffer;
1234   if( !Dali::FileLoader::ReadFile( filePath, bufferSize, buffer, FileLoader::FileType::BINARY ) )
1235   {
1236     return false;
1237   }
1238
1239   fileBuffer.assign( &buffer[0], bufferSize );
1240   mParser = Dali::Toolkit::JsonParser::New();
1241   return mParser.Parse( fileBuffer );
1242 }
1243
1244 bool Loader::LoadAssets()
1245 {
1246   if( LoadBinaryData( *mRoot, mBufferArray, mBufferViewArray, mAccessorArray ) &&
1247       LoadTextureArray( *mRoot, mPath, mSourceArray, mSamplerArray, mTextureArray ) &&
1248       LoadMaterialSetArray( *mRoot, mMaterialArray ) &&
1249       LoadMeshArray( *mRoot, mPath, mMeshArray, mBufferArray, mBufferViewArray, mAccessorArray )
1250     )
1251   {
1252     return true;
1253   }
1254   return false;
1255 }
1256
1257 bool Loader::CreateScene( Internal::Scene3dView& scene3dView )
1258 {
1259   scene3dView.SetDefaultCamera( Dali::Camera::LOOK_AT_TARGET, 0.01, Vector3::ZERO );
1260   LoadCamera( scene3dView );
1261
1262   if( LoadSceneNodes( scene3dView ) &&
1263       LoadAnimation( scene3dView ) )
1264   {
1265     return true;
1266   }
1267   return false;
1268 }
1269
1270 void Loader::LoadCamera( Scene3dView& scene3dView )
1271 {
1272   const TreeNode* camerasNode = mRoot->GetChild( "cameras" );
1273   if( !camerasNode )
1274   {
1275     return;
1276   }
1277
1278   for( auto cameraIter = camerasNode->CBegin(), end = camerasNode->CEnd(); cameraIter != end; ++cameraIter )
1279   {
1280     const TreeNode* tempNode = ( &( *cameraIter ).second )->GetChild( "name" );
1281     CameraInfo cameraInfo;
1282     if( tempNode )
1283     {
1284       ReadString( tempNode, cameraInfo.name );
1285     }
1286
1287     tempNode = ( &( *cameraIter ).second )->GetChild( "type" );
1288     if( tempNode )
1289     {
1290       ReadString( tempNode, cameraInfo.type );
1291     }
1292
1293     CameraActor cameraActor = CameraActor::New();
1294     cameraActor.SetParentOrigin( ParentOrigin::CENTER );
1295     cameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1296
1297     if( cameraInfo.type == "orthographic" )
1298     {
1299       LoadOrthoGraphic( ( *cameraIter ).second, cameraInfo );
1300       float xMag_2 = cameraInfo.orthographic.xmag / 2.0;
1301       float yMag_2 = cameraInfo.orthographic.ymag / 2.0;
1302       cameraActor.SetOrthographicProjection( -xMag_2, xMag_2, yMag_2, -yMag_2,
1303                                              cameraInfo.orthographic.znear, cameraInfo.orthographic.zfar );
1304     }
1305     else if( cameraInfo.type == "perspective" )
1306     {
1307       if( !LoadPerspective( ( *cameraIter ).second, cameraInfo ) )
1308       {
1309         return;
1310       }
1311       cameraActor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
1312       cameraActor.SetFieldOfView( cameraInfo.perspective.yfov );
1313       cameraActor.SetNearClippingPlane( cameraInfo.perspective.znear );
1314
1315       if( cameraInfo.perspective.zfar > 0.0 )
1316       {
1317         cameraActor.SetFarClippingPlane( cameraInfo.perspective.zfar );
1318       }
1319       if( cameraInfo.perspective.aspectRatio > 0.0 )
1320       {
1321         cameraActor.SetAspectRatio( cameraInfo.perspective.aspectRatio );
1322       }
1323     }
1324
1325     scene3dView.AddCamera( cameraActor );
1326   }
1327 }
1328
1329 bool Loader::LoadOrthoGraphic( const TreeNode& camera, CameraInfo& cameraInfo )
1330 {
1331   const TreeNode* orthographicNode = camera.GetChild( "orthographic" );
1332   if( !orthographicNode )
1333   {
1334     return false;
1335   }
1336
1337   const TreeNode* tempNode;
1338   tempNode = orthographicNode->GetChild( "xmag" );
1339   if( tempNode )
1340   {
1341     ReadFloat( tempNode, cameraInfo.orthographic.xmag );
1342   }
1343
1344   tempNode = orthographicNode->GetChild( "ymag" );
1345   if( tempNode )
1346   {
1347     ReadFloat( tempNode, cameraInfo.orthographic.ymag );
1348   }
1349
1350   tempNode = orthographicNode->GetChild( "zfar" );
1351   if( tempNode )
1352   {
1353     ReadFloat( tempNode, cameraInfo.orthographic.zfar );
1354   }
1355
1356   tempNode = orthographicNode->GetChild( "znear" );
1357   if( tempNode )
1358   {
1359     ReadFloat( tempNode, cameraInfo.orthographic.znear );
1360   }
1361
1362   return true;
1363 }
1364
1365 bool Loader::LoadPerspective( const TreeNode& camera, CameraInfo& cameraInfo )
1366 {
1367   const TreeNode* perspectiveNode = camera.GetChild( "perspective" );
1368   if( !perspectiveNode )
1369   {
1370     return false;
1371   }
1372
1373   const TreeNode* tempNode;
1374   tempNode = perspectiveNode->GetChild( "aspectRatio" );
1375   if( tempNode )
1376   {
1377     ReadFloat( tempNode, cameraInfo.perspective.aspectRatio );
1378   }
1379
1380   tempNode = perspectiveNode->GetChild( "yfov" );
1381   if( tempNode )
1382   {
1383     ReadFloat( tempNode, cameraInfo.perspective.yfov );
1384   }
1385
1386   tempNode = perspectiveNode->GetChild( "zfar" );
1387   if( tempNode )
1388   {
1389     ReadFloat( tempNode, cameraInfo.perspective.zfar );
1390   }
1391
1392   tempNode = perspectiveNode->GetChild( "znear" );
1393   if( tempNode )
1394   {
1395     ReadFloat( tempNode, cameraInfo.perspective.znear );
1396   }
1397
1398   return true;
1399 }
1400
1401 bool Loader::LoadSceneNodes( Scene3dView& scene3dView )
1402 {
1403   const TreeNode* sceneNode = mRoot->GetChild( "scene" );
1404   uint32_t sceneNum = 0;
1405   if( sceneNode )
1406   {
1407     sceneNum = sceneNode->GetInteger();
1408   }
1409
1410   const TreeNode* scenesNode = mRoot->GetChild( "scenes" );
1411   if( !( scenesNode && ( mNodes = mRoot->GetChild( "nodes" ) ) ) )
1412   {
1413     return false;
1414   }
1415
1416   const TreeNode* tempNode = Tidx( scenesNode, sceneNum );
1417   if( !tempNode )
1418   {
1419     return false;
1420   }
1421
1422   tempNode = tempNode->GetChild( "nodes" );
1423   if( !tempNode )
1424   {
1425     return false;
1426   }
1427
1428   for( auto nodeIter = tempNode->CBegin(), end = tempNode->CEnd(); nodeIter != end; ++nodeIter )
1429   {
1430     Actor actor = AddNode( scene3dView, ( ( *nodeIter ).second ).GetInteger() );
1431     actor.SetParentOrigin( ParentOrigin::CENTER );
1432     scene3dView.GetRoot().Add( actor );
1433   }
1434
1435   return true;
1436 }
1437
1438 Actor Loader::AddNode( Scene3dView& scene3dView, uint32_t index )
1439 {
1440   const TreeNode* node = Tidx( mNodes, index );
1441   Actor actor = Actor::New();
1442   Vector3 actorSize( Vector3::ONE );
1443
1444   Vector3 translation = Vector3( 0.0, 0.0, 0.0 );
1445   Vector3 scale = Vector3( 1.0, 1.0, 1.0 );
1446   Quaternion orientation( Vector4( 0.0, 0.0, 0.0, 1.0 ) );
1447
1448   Vector3 anchorPoint = AnchorPoint::CENTER;
1449
1450   const TreeNode* tempNode = NULL;
1451   if( ( tempNode = node->GetChild( "translation" ) ) )
1452   {
1453     float floatVec[3] = { 0.0, 0.0, 0.0 };
1454     if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
1455     {
1456       translation = Vector3( floatVec[0], floatVec[1], floatVec[2] );
1457     }
1458   }
1459
1460   if( ( tempNode = node->GetChild( "scale" ) ) )
1461   {
1462     float floatVec[3] = { 1.0, 1.0, 1.0 };
1463     if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
1464     {
1465       scale = Vector3( floatVec[0], floatVec[1], floatVec[2] );
1466     }
1467   }
1468
1469   if( ( tempNode = node->GetChild( "rotation" ) ) )
1470   {
1471     float floatVec[4] = { 0.0, 0.0, 0.0, 1.0 };
1472     if( tempNode && ReadVector( tempNode, floatVec, 4 ) )
1473     {
1474       orientation = Quaternion( Vector4( floatVec[0], floatVec[1], floatVec[2], floatVec[3] ) );
1475     }
1476   }
1477
1478   if( ( tempNode = node->GetChild( "matrix" ) ) )
1479   {
1480     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 };
1481     if( tempNode && ReadVector( tempNode, floatVec, 16 ) )
1482     {
1483       Matrix nodeMatrix = Matrix( floatVec );
1484       nodeMatrix.GetTransformComponents( translation, orientation, scale );
1485     }
1486   }
1487
1488   if( ( tempNode = node->GetChild( "mesh" ) ) )
1489   {
1490     MeshInfo meshInfo = mMeshArray[tempNode->GetInteger()];
1491     bool isMaterial = ( meshInfo.materialsIdx >= 0 );
1492
1493     TextureSet textureSet;
1494     textureSet = TextureSet::New();
1495
1496     int32_t addIdx = 0;
1497     int32_t shaderTypeIndex = 0;
1498     int32_t maxMipmapLevel = 0;
1499     bool isBaseColorTexture = false;
1500     bool isMetallicRoughnessTexture = false;
1501     bool isNormalTexture = false;
1502     bool isOcclusionTexture = false;
1503     bool isEmissiveTexture = false;
1504
1505     std::string VERTEX_SHADER, FRAGMENT_SHADER;
1506     VERTEX_SHADER = GLES_VERSION_300;
1507     VERTEX_SHADER += PHYSICALLY_BASED_VERTEX_SHADER;
1508     FRAGMENT_SHADER = GLES_VERSION_300;
1509
1510     bool useIBL = ( scene3dView.GetLightType() >= Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT );
1511     if( isMaterial )
1512     {
1513       MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1514       if( SetTextureAndSampler( textureSet, materialInfo.baseColorTexture.index, FRAGMENT_SHADER, DEFINE_BASECOLOR_TEXTURE, addIdx ) )
1515       {
1516         shaderTypeIndex += static_cast<int32_t>( ShaderType::BASECOLOR_SHADER );
1517         isBaseColorTexture = true;
1518       }
1519       if( SetTextureAndSampler( textureSet, materialInfo.metallicRoughnessTexture.index, FRAGMENT_SHADER, DEFINE_METALLICROUGHNESS_TEXTURE, addIdx ) )
1520       {
1521         shaderTypeIndex += static_cast<int32_t>( ShaderType::METALLICROUGHNESS_SHADER );
1522         isMetallicRoughnessTexture = true;
1523       }
1524       if( SetTextureAndSampler( textureSet, materialInfo.normalTexture.index, FRAGMENT_SHADER, DEFINE_NORMAL_TEXTURE, addIdx ) )
1525       {
1526         shaderTypeIndex += static_cast<int32_t>( ShaderType::NORMAL_SHADER );
1527         isNormalTexture = true;
1528       }
1529       if( SetTextureAndSampler( textureSet, materialInfo.occlusionTexture.index, FRAGMENT_SHADER, DEFINE_OCCLUSION_TEXTURE, addIdx ) )
1530       {
1531         shaderTypeIndex += static_cast<int32_t>( ShaderType::OCCLUSION_SHADER );
1532         isOcclusionTexture = true;
1533       }
1534       if( SetTextureAndSampler( textureSet, materialInfo.emissiveTexture.index, FRAGMENT_SHADER, DEFINE_EMIT_TEXTURE, addIdx ) )
1535       {
1536         shaderTypeIndex += static_cast<int32_t>( ShaderType::EMIT_SHADER );
1537         isEmissiveTexture = true;
1538       }
1539
1540       if( useIBL )
1541       {
1542         shaderTypeIndex += static_cast<int32_t>( ShaderType::IBL_SHADER );
1543         FRAGMENT_SHADER += DEFINE_IBL_TEXTURE;
1544
1545         Sampler sampler = Sampler::New();
1546         sampler.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
1547         sampler.SetWrapMode( WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT );
1548
1549         textureSet.SetTexture( addIdx, scene3dView.GetBRDFTexture() );
1550         textureSet.SetSampler( addIdx++, sampler );
1551         Sampler samplerIBL = Sampler::New();
1552         samplerIBL.SetFilterMode( FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR );
1553         samplerIBL.SetWrapMode( WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE );
1554         textureSet.SetTexture( addIdx, scene3dView.GetDiffuseTexture() );
1555         textureSet.SetSampler( addIdx++, samplerIBL );
1556         Texture specularTexture = scene3dView.GetSpecularTexture();
1557         textureSet.SetTexture( addIdx, specularTexture );
1558         textureSet.SetSampler( addIdx++, samplerIBL );
1559
1560         int32_t textureSize = std::min( specularTexture.GetWidth(), specularTexture.GetHeight() );
1561         maxMipmapLevel = 0;
1562         while( textureSize >= 1 )
1563         {
1564           maxMipmapLevel++;
1565           textureSize /= 2;
1566         }
1567       }
1568     }
1569
1570     FRAGMENT_SHADER += PHYSICALLY_BASED_FRAGMENT_SHADER;
1571     if( !mShaderCache[shaderTypeIndex] )
1572     {
1573       mShaderCache[shaderTypeIndex] = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
1574       scene3dView.AddShader( mShaderCache[shaderTypeIndex] );
1575     }
1576     Shader shader = mShaderCache[shaderTypeIndex];
1577
1578     Renderer renderer = Renderer::New( meshInfo.geometry, shader );
1579     renderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
1580     renderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON );
1581     renderer.SetTextures( textureSet );
1582
1583     anchorPoint = meshInfo.pivot;
1584     actor.SetAnchorPoint( anchorPoint );
1585
1586     actor.SetSize( Vector3( meshInfo.size.x, meshInfo.size.y, meshInfo.size.z ) );
1587     actor.AddRenderer( renderer );
1588
1589     actor.SetScale( scale );
1590     actor.RotateBy( orientation );
1591     actor.SetPosition( translation );
1592
1593     shader.RegisterProperty( "uLightType", ( scene3dView.GetLightType() & ~Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) );
1594     shader.RegisterProperty( "uLightVector", scene3dView.GetLightVector() );
1595     shader.RegisterProperty( "uLightColor", scene3dView.GetLightColor() );
1596
1597     actor.RegisterProperty( "uIsColor", meshInfo.attribute.COLOR.size() > 0 );
1598     if( isMaterial )
1599     {
1600       MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1601       actor.RegisterProperty( "uBaseColorFactor", materialInfo.baseColorFactor );
1602       actor.RegisterProperty( "uMetallicRoughnessFactors", Vector2( materialInfo.metallicFactor, materialInfo.roughnessFactor ) );
1603
1604       if( materialInfo.alphaMode == "OPAQUE" )
1605       {
1606         actor.RegisterProperty( "alphaMode", 0 );
1607       }
1608       else if( materialInfo.alphaMode == "MASK" )
1609       {
1610         actor.RegisterProperty( "alphaMode", 1 );
1611       }
1612       else
1613       {
1614         actor.RegisterProperty( "alphaMode", 2 );
1615       }
1616       actor.RegisterProperty( "alphaCutoff", materialInfo.alphaCutoff );
1617
1618       if( isBaseColorTexture )
1619       {
1620         actor.RegisterProperty( "uBaseColorTexCoordIndex", materialInfo.baseColorTexture.texCoord );
1621       }
1622       if( isMetallicRoughnessTexture )
1623       {
1624         actor.RegisterProperty( "uMetallicRoughnessTexCoordIndex", materialInfo.metallicRoughnessTexture.texCoord );
1625       }
1626       if( isNormalTexture )
1627       {
1628         actor.RegisterProperty( "uNormalScale", materialInfo.normalTexture.value );
1629         actor.RegisterProperty( "uNormalTexCoordIndex", materialInfo.normalTexture.texCoord );
1630       }
1631       if( isOcclusionTexture )
1632       {
1633         actor.RegisterProperty( "uOcclusionTexCoordIndex", materialInfo.occlusionTexture.texCoord );
1634         actor.RegisterProperty( "uOcclusionStrength", materialInfo.occlusionTexture.value );
1635       }
1636       if( isEmissiveTexture )
1637       {
1638         actor.RegisterProperty( "uEmissiveTexCoordIndex", materialInfo.emissiveTexture.texCoord );
1639         actor.RegisterProperty( "uEmissiveFactor", materialInfo.emissiveFactor );
1640       }
1641     }
1642
1643     if( isMaterial && useIBL )
1644     {
1645       actor.RegisterProperty( "uScaleIBLAmbient", scene3dView.GetIBLScaleFactor() );
1646       actor.RegisterProperty( "uMipmapLevel", static_cast<float>( maxMipmapLevel ) );
1647     }
1648   }
1649   else
1650   {
1651     actor.SetAnchorPoint( AnchorPoint::CENTER );
1652     actor.SetPosition( translation );
1653     actor.RotateBy( orientation );
1654     actor.SetSize( actorSize );
1655   }
1656
1657   tempNode = node->GetChild( "camera" );
1658   if( tempNode )
1659   {
1660     int32_t cameraNum = tempNode->GetInteger();
1661     CameraActor cameraActor = scene3dView.GetCamera( cameraNum );
1662     if( cameraActor )
1663     {
1664       actor.Add( cameraActor );
1665     }
1666   }
1667
1668   tempNode = node->GetChild( "name" );
1669   if( tempNode )
1670   {
1671     std::string nameString;
1672     ReadString( tempNode, nameString );
1673     actor.SetName( nameString );
1674   }
1675
1676   SetActorCache( actor, index );
1677   if( ( tempNode = node->GetChild( "children" ) ) )
1678   {
1679     for( auto childIter = tempNode->CBegin(), end = tempNode->CEnd(); childIter != end; ++childIter )
1680     {
1681       Actor childActor = AddNode( scene3dView, ( ( *childIter ).second ).GetInteger() );
1682       childActor.SetParentOrigin( anchorPoint );
1683       actor.Add( childActor );
1684     }
1685   }
1686
1687   return actor;
1688 }
1689
1690 void Loader::SetActorCache( Actor& actor, uint32_t index )
1691 {
1692   if( mActorCache.size() < index + 1 )
1693   {
1694     mActorCache.resize( index + 1 );
1695   }
1696   mActorCache[index] = actor;
1697 }
1698
1699 bool Loader::SetTextureAndSampler( TextureSet& textureSet, int32_t textureIdx, std::string& toShader, std::string shader, int32_t& addIdx )
1700 {
1701   if( textureIdx >= 0 )
1702   {
1703     toShader += shader;
1704     TextureInfo textureInfo = mTextureArray[textureIdx];
1705     if( textureInfo.sourceIdx >= 0 )
1706     {
1707       textureSet.SetTexture( addIdx, mSourceArray[textureInfo.sourceIdx] );
1708     }
1709     if( textureInfo.samplerIdx >= 0 )
1710     {
1711       textureSet.SetSampler( addIdx, mSamplerArray[textureInfo.samplerIdx] );
1712     }
1713     else
1714     {
1715       Sampler sampler = Sampler::New();
1716       sampler.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
1717       sampler.SetWrapMode( WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT );
1718       textureSet.SetSampler( addIdx, sampler );
1719     }
1720     addIdx++;
1721     return true;
1722   }
1723   return false;
1724 }
1725
1726 bool Loader::LoadAnimation( Scene3dView& scene3dView )
1727 {
1728   const TreeNode* animationsNode = mRoot->GetChild( "animations" );
1729   if( !animationsNode )
1730   {
1731     return true;
1732   }
1733
1734   for( auto animationIter = animationsNode->CBegin(), end = animationsNode->CEnd(); animationIter != end; ++animationIter )
1735   {
1736     const TreeNode* nameNode = ( &( *animationIter ).second )->GetChild( "name" );
1737     AnimationInfo animationInfo;
1738     if( nameNode )
1739     {
1740       ReadString( nameNode, animationInfo.name );
1741     }
1742
1743     Property::Index propIndex = Property::INVALID_INDEX;
1744     LoadAnimationChannels( ( *animationIter ).second, animationInfo );
1745     if( animationInfo.channelArray.size() == 0 )
1746     {
1747       continue;
1748     }
1749
1750     LoadAnimationSamplers( ( *animationIter ).second, animationInfo );
1751
1752     for( auto&& currentChannel : animationInfo.channelArray )
1753     {
1754       if( currentChannel.path == "rotation" )
1755       {
1756         propIndex = Dali::Actor::Property::ORIENTATION;
1757       }
1758       else if( currentChannel.path == "translation" )
1759       {
1760         propIndex = Dali::Actor::Property::POSITION;
1761       }
1762       else if( currentChannel.path == "scale" )
1763       {
1764         propIndex = Dali::Actor::Property::SCALE;
1765       }
1766
1767       float duration = 0.0f;
1768       KeyFrames keyframes = KeyFrames::New();
1769       if( propIndex == Dali::Actor::Property::ORIENTATION )
1770       {
1771         duration = LoadKeyFrames<Vector4>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray );
1772       }
1773       else
1774       {
1775         duration = LoadKeyFrames<Vector3>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray );
1776       }
1777
1778       Animation animation = Animation::New( duration );
1779       Animation::Interpolation interpolation = Animation::Interpolation::Linear;
1780       if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "CUBICSPLINE" )
1781       {
1782         interpolation = Animation::Interpolation::Cubic;
1783       }
1784       if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "STEP" )
1785       {
1786       }
1787
1788       animation.AnimateBetween( Property( mActorCache[currentChannel.targetNode], propIndex ), keyframes, interpolation );
1789
1790       animation.SetLooping( false );
1791       scene3dView.AddAnimation( animation );
1792     }
1793   }
1794
1795   return true;
1796 }
1797
1798 bool Loader::LoadAnimationChannels( const TreeNode& animation, AnimationInfo& animationInfo )
1799 {
1800   const TreeNode* channelsNode = animation.GetChild( "channels" );
1801   if( !channelsNode )
1802   {
1803     return false;
1804   }
1805
1806   for( auto channelIter = channelsNode->CBegin(), end = channelsNode->CEnd(); channelIter != end; ++channelIter )
1807   {
1808     AnimationChannelInfo animationChannelInfo;
1809     const TreeNode* channelNode = ( &( *channelIter ).second );
1810     const TreeNode* samplerNode = channelNode->GetChild( "sampler" );
1811     if( samplerNode )
1812     {
1813       animationChannelInfo.sampler = samplerNode->GetInteger();
1814     }
1815
1816     const TreeNode* targetNode = channelNode->GetChild( "target" );
1817     if( targetNode )
1818     {
1819       const TreeNode* tempNode = targetNode->GetChild( "node" );
1820       if( tempNode )
1821       {
1822         animationChannelInfo.targetNode = tempNode->GetInteger();
1823       }
1824       else
1825       {
1826         continue;
1827       }
1828
1829       tempNode = targetNode->GetChild( "path" );
1830       if( tempNode )
1831       {
1832         ReadString( tempNode, animationChannelInfo.path );
1833       }
1834     }
1835
1836     animationInfo.channelArray.push_back( animationChannelInfo );
1837   }
1838   return true;
1839 }
1840
1841 bool Loader::LoadAnimationSamplers( const TreeNode& animation, AnimationInfo& animationInfo )
1842 {
1843   const TreeNode* samplersNode = animation.GetChild( "samplers" );
1844   if( !samplersNode )
1845   {
1846     return false;
1847   }
1848
1849   for( auto sampler = samplersNode->CBegin(), end = samplersNode->CEnd(); sampler != end; ++sampler )
1850   {
1851     AnimationSamplerInfo animationSamplerInfo;
1852     const TreeNode* samplerNode = ( &( *sampler ).second );
1853     const TreeNode* tempNode = samplerNode->GetChild( "input" );
1854     if( tempNode )
1855     {
1856       animationSamplerInfo.input = tempNode->GetInteger();
1857     }
1858
1859     tempNode = samplerNode->GetChild( "output" );
1860     if( tempNode )
1861     {
1862       animationSamplerInfo.output = tempNode->GetInteger();
1863     }
1864
1865     tempNode = samplerNode->GetChild( "interpolation" );
1866     if( tempNode )
1867     {
1868       ReadString( tempNode, animationSamplerInfo.interpolation );
1869     }
1870
1871     animationInfo.samplerArray.push_back( animationSamplerInfo );
1872   }
1873
1874   return true;
1875 }
1876
1877 }//namespace Gltf
1878
1879 }//namespace Internal
1880
1881 }//namespace Toolkit
1882
1883 }//namespace Dali