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