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