2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/scene/gltf-loader.h>
20 #include <dali-toolkit/internal/controls/scene/gltf-shader.h>
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>
29 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
31 using namespace Dali::Toolkit::Internal::GLTF;
45 // Maximum path length of linux.
46 const unsigned int MAX_PATH_LENGTH = 4096;
50 GltfLoader::GltfLoader()
56 GltfLoader::~GltfLoader()
60 bool GltfLoader::LoadScene( const std::string& filePath, Internal::Scene& scene )
62 // Extracting directory path from full path to load resources.
63 if( std::string::npos != filePath.rfind('/') )
65 mPath = filePath.substr( 0, filePath.rfind('/') ) + "/";
68 if( !ParseGltf( filePath ) )
70 DALI_LOG_ERROR( "Fail to parse json file\n" );
74 mRoot = mParser.GetRoot();
77 CreateScene( scene ) )
84 bool GltfLoader::ParseGltf( const std::string& filePath )
86 if( filePath.length() > MAX_PATH_LENGTH )
88 DALI_LOG_ERROR( "File path is too long.\n" );
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();
96 return mParser.Parse( fileBuffer );
99 bool GltfLoader::LoadAssets()
101 if( LoadBinaryData( mRoot ) &&
102 LoadTextureArray( mRoot ) &&
103 LoadMaterialSetArray( mRoot ) &&
104 LoadMeshArray( mRoot )
112 bool GltfLoader::LoadBinaryData( const TreeNode* root )
114 const TreeNode* buffersNode = root->GetChild( "buffers" );
119 for( TreeNode::ConstIterator bufferIter = ( *buffersNode ).CBegin(); bufferIter != ( *buffersNode ).CEnd(); ++bufferIter )
121 LoadBuffer( ( *bufferIter ).second );
124 const TreeNode* bufferViewsNode = root->GetChild( "bufferViews" );
125 if( !bufferViewsNode )
129 for( TreeNode::ConstIterator bufferViewIter = ( *bufferViewsNode ).CBegin(); bufferViewIter != ( *bufferViewsNode ).CEnd(); ++bufferViewIter )
131 LoadBufferView( ( *bufferViewIter ).second );
134 const TreeNode* accessorsNode = root->GetChild( "accessors" );
139 for( TreeNode::ConstIterator accesorIter = ( *accessorsNode ).CBegin(); accesorIter != ( *accessorsNode ).CEnd(); ++accesorIter )
141 LoadAccessor( ( *accesorIter ).second );
147 bool GltfLoader::LoadBuffer( const TreeNode& buffer )
149 BufferInfo bufferInfo;
151 const TreeNode* uriNode = buffer.GetChild( "uri" );
154 ReadString( uriNode, bufferInfo.uri );
157 const TreeNode* byteLengthNode = buffer.GetChild( "byteLength" );
160 ReadInt( byteLengthNode, bufferInfo.byteLength );
161 if( bufferInfo.byteLength < 0 )
167 const TreeNode* nameNode = buffer.GetChild( "name" );
170 ReadString( nameNode, bufferInfo.name );
173 mBufferArray.push_back( bufferInfo );
178 bool GltfLoader::LoadBufferView( const TreeNode& buffer )
180 BufferViewInfo bufferViewInfo;
182 const TreeNode* bufferNode = buffer.GetChild( "buffer" );
185 ReadInt( bufferNode, bufferViewInfo.buffer );
186 if( bufferViewInfo.buffer < 0 )
192 const TreeNode* byteOffsetNode = buffer.GetChild( "byteOffset" );
195 ReadInt( byteOffsetNode, bufferViewInfo.byteOffset );
198 const TreeNode* byteLengthNode = buffer.GetChild( "byteLength" );
201 ReadInt( byteLengthNode, bufferViewInfo.byteLength );
202 if( bufferViewInfo.byteLength < 0 )
208 const TreeNode* byteStrideNode = buffer.GetChild( "byteStride" );
211 ReadInt( byteStrideNode, bufferViewInfo.byteStride );
214 const TreeNode* targetNode = buffer.GetChild( "target" );
217 ReadInt( targetNode, bufferViewInfo.target );
220 const TreeNode* nameNode = buffer.GetChild( "name" );
223 ReadString( nameNode, bufferViewInfo.name );
226 mBufferViewArray.push_back( bufferViewInfo );
231 bool GltfLoader::LoadAccessor( const TreeNode& buffer )
233 AccessorInfo accessorInfo;
235 const TreeNode* bufferViewNode = buffer.GetChild( "bufferView" );
238 ReadInt( bufferViewNode, accessorInfo.bufferView );
241 const TreeNode* byteOffsetNode = buffer.GetChild( "byteOffset" );
244 ReadInt( byteOffsetNode, accessorInfo.byteOffset );
247 const TreeNode* componentTypeNode = buffer.GetChild( "componentType" );
248 if( componentTypeNode )
250 ReadInt( componentTypeNode, accessorInfo.componentType );
251 if( accessorInfo.componentType < 0 )
257 const TreeNode* normalizedNode = buffer.GetChild( "normalized" );
260 ReadBool( normalizedNode, accessorInfo.normalized );
263 const TreeNode* countNode = buffer.GetChild( "count" );
266 ReadInt( countNode, accessorInfo.count );
267 if( accessorInfo.count < 0 )
273 const TreeNode* typeNode = buffer.GetChild( "type" );
276 ReadString( typeNode, accessorInfo.type );
277 if( accessorInfo.type == "" )
283 const TreeNode* maxNode = buffer.GetChild( "max" );
286 ReadInt( maxNode, accessorInfo.max );
289 const TreeNode* minNode = buffer.GetChild( "min" );
292 ReadInt( minNode, accessorInfo.min );
295 const TreeNode* nameNode = buffer.GetChild( "name" );
298 ReadString( nameNode, accessorInfo.name );
301 mAccessorArray.push_back( accessorInfo );
306 bool GltfLoader::LoadTextureArray( const TreeNode* root )
308 const TreeNode* imagesNode = root->GetChild( "images" );
311 for( TreeNode::ConstIterator imageIter = imagesNode->CBegin(); imageIter != imagesNode->CEnd(); ++imageIter )
313 std::string imageUrl;
314 const TreeNode* uriNode = ( &( ( *imageIter ).second ) )->GetChild( "uri" );
318 ReadString( uriNode, uri );
319 imageUrl = mPath + uri;
322 mSourceArray.push_back( LoadTexture( imageUrl.c_str(), true ) );
326 const TreeNode* samplersNode = root->GetChild( "samplers" );
329 for( TreeNode::ConstIterator samplerIter = samplersNode->CBegin(); samplerIter != samplersNode->CEnd(); ++samplerIter )
331 mSamplerArray.push_back( LoadSampler( ( ( *samplerIter ).second ) ) );
335 const TreeNode* texturesNode = root->GetChild( "textures" );
338 for( TreeNode::ConstIterator textureIter = texturesNode->CBegin(); textureIter != texturesNode->CEnd(); ++textureIter )
340 const TreeNode* TextureNode = &( ( *textureIter ).second );
343 const TreeNode* sourceNode = TextureNode->GetChild( "source" );
346 ReadInt( sourceNode, texture.sourceIdx );
349 const TreeNode* samplerNode = TextureNode->GetChild( "sampler" );
352 ReadInt( samplerNode, texture.samplerIdx );
355 mTextureArray.push_back( texture );
361 Texture GltfLoader::LoadTexture( const char* imageUrl, bool generateMipmaps )
364 if( std::string( imageUrl ).length() > MAX_PATH_LENGTH )
366 DALI_LOG_ERROR( "Image path is too long.\n" );
369 Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
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 )
377 texture.GenerateMipmaps();
384 Sampler GltfLoader::LoadSampler( const TreeNode& samplerNode )
386 Sampler sampler = Sampler::New();
388 FilterMode::Type minFilter = FilterMode::DEFAULT;
389 FilterMode::Type magFilter = FilterMode::DEFAULT;
390 const TreeNode* magFilterNode = samplerNode.GetChild( "magFilter" );
393 int magFilter_integer = 0;
394 ReadInt( magFilterNode, magFilter_integer );
395 magFilter = GetFilterMode( magFilter_integer );
398 const TreeNode* minFilterNode = samplerNode.GetChild( "minFilter" );
401 int minFilter_integer = 0;
402 ReadInt( minFilterNode, minFilter_integer );
403 minFilter = GetFilterMode( minFilter_integer );
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" );
412 wrapS = GetWrapMode( wrapNode->GetInteger() );
415 wrapNode = samplerNode.GetChild( "wrapT" );
418 wrapT = GetWrapMode( wrapNode->GetInteger() );
421 sampler.SetFilterMode( minFilter, magFilter );
422 sampler.SetWrapMode( wrapR, wrapS, wrapT );
427 FilterMode::Type GltfLoader::GetFilterMode( int mode )
429 FilterMode::Type retValue = FilterMode::DEFAULT;
431 * glTF 2.0 Specification
435 * 9984 : NEAREST_MIPMAP_NEAREST
436 * 9985 : LINEAR_MIPMAP_NEAREST
437 * 9986 : NEAREST_MIPMAP_LINEAR
438 * 9987 : LINEAR_MIPMAP_LINEAR
444 retValue = FilterMode::NEAREST;
449 retValue = FilterMode::LINEAR;
454 retValue = FilterMode::NEAREST_MIPMAP_NEAREST;
459 retValue = FilterMode::LINEAR_MIPMAP_NEAREST;
464 retValue = FilterMode::NEAREST_MIPMAP_LINEAR;
469 retValue = FilterMode::LINEAR_MIPMAP_LINEAR;
477 WrapMode::Type GltfLoader::GetWrapMode( int mode )
479 WrapMode::Type retValue = WrapMode::REPEAT;
481 * glTF 2.0 Specification
483 * 33071 : CLAMP_TO_EDGE
484 * 33648 : MIRRORED_REPEAT
491 retValue = WrapMode::CLAMP_TO_EDGE;
496 retValue = WrapMode::MIRRORED_REPEAT;
501 retValue = WrapMode::REPEAT;
509 bool GltfLoader::LoadMaterialSetArray( const TreeNode* root )
511 const TreeNode* materialsNode = root->GetChild( "materials" );
517 for( TreeNode::ConstIterator materialIter = materialsNode->CBegin(); materialIter != materialsNode->CEnd(); ++materialIter )
519 GLTF::MaterialInfo materialInfo;
520 LoadPbrMetallicRoughness( ( ( *materialIter ).second ), materialInfo );
522 const TreeNode* materialNode = &( ( *materialIter ).second );
523 const TreeNode* tempNode = materialNode->GetChild( "name" );
526 ReadString( tempNode, materialInfo.name );
529 materialInfo.alphaMode = "OPAQUE";
530 tempNode = materialNode->GetChild( "alphaMode" );
533 ReadString( tempNode, materialInfo.alphaMode );
536 materialInfo.alphaCutoff = 1.0;
537 tempNode = materialNode->GetChild( "alphaCutoff" );
540 ReadFloat( tempNode, materialInfo.alphaCutoff );
543 materialInfo.doubleSided = false;
544 tempNode = materialNode->GetChild( "doubleSided" );
547 ReadBool( tempNode, materialInfo.doubleSided );
551 tempNode = materialNode->GetChild( "emissiveFactor" );
552 if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
554 materialInfo.emissiveFactor = Vector3( floatVec[0], floatVec[1], floatVec[2] );
557 const TreeNode* texture = materialNode->GetChild( "normalTexture" );
560 tempNode = texture->GetChild( "index" );
563 materialInfo.normalTexture.index = tempNode->GetInteger();
566 tempNode = texture->GetChild( "texCoord" );
569 materialInfo.normalTexture.texCoord = tempNode->GetInteger();
572 materialInfo.normalTexture.value = 1.0;
573 tempNode = texture->GetChild( "scale" );
576 ReadFloat( tempNode, materialInfo.normalTexture.value );
580 texture = materialNode->GetChild( "occlusionTexture" );
583 tempNode = texture->GetChild( "index" );
586 materialInfo.occlusionTexture.index = tempNode->GetInteger();
589 tempNode = texture->GetChild( "texCoord" );
592 materialInfo.occlusionTexture.texCoord = tempNode->GetInteger();
596 tempNode = texture->GetChild( "strength" );
599 ReadFloat( tempNode, materialInfo.occlusionTexture.value );
603 texture = materialNode->GetChild( "emissiveTexture" );
606 tempNode = texture->GetChild( "index" );
609 materialInfo.emissiveTexture.index = tempNode->GetInteger();
612 tempNode = texture->GetChild( "texCoord" );
615 materialInfo.emissiveTexture.texCoord = tempNode->GetInteger();
618 mMaterialArray.push_back( materialInfo );
623 bool GltfLoader::LoadPbrMetallicRoughness( const TreeNode& material, MaterialInfo& materialInfo )
626 const TreeNode* pbrMetallicRoughnessNode = material.GetChild( "pbrMetallicRoughness" );
627 if( !pbrMetallicRoughnessNode )
632 const TreeNode* tempNode;
633 tempNode = pbrMetallicRoughnessNode->GetChild( "metallicFactor" );
636 ReadFloat( tempNode, materialInfo.metallicFactor );
639 tempNode = pbrMetallicRoughnessNode->GetChild( "roughnessFactor" );
642 ReadFloat( tempNode, materialInfo.roughnessFactor );
645 tempNode = pbrMetallicRoughnessNode->GetChild( "baseColorFactor" );
646 if( tempNode && ReadVector( tempNode, floatVec, 4 ) )
648 materialInfo.baseColorFactor = Vector4( floatVec[0], floatVec[1], floatVec[2], floatVec[3] );
651 const TreeNode* baseColorTextureNode = pbrMetallicRoughnessNode->GetChild( "baseColorTexture" );
652 if( baseColorTextureNode )
654 tempNode = baseColorTextureNode->GetChild( "index" );
657 materialInfo.baseColorTexture.index = tempNode->GetInteger();
660 tempNode = baseColorTextureNode->GetChild( "texCoord" );
663 materialInfo.baseColorTexture.texCoord = tempNode->GetInteger();
667 const TreeNode* metallicRoughnessTextureNode = pbrMetallicRoughnessNode->GetChild( "metallicRoughnessTexture" );
668 if( metallicRoughnessTextureNode )
670 tempNode = metallicRoughnessTextureNode->GetChild( "index" );
673 materialInfo.metallicRoughnessTexture.index = tempNode->GetInteger();
676 tempNode = metallicRoughnessTextureNode->GetChild( "texCoord" );
679 materialInfo.metallicRoughnessTexture.texCoord = tempNode->GetInteger();
686 bool GltfLoader::LoadMeshArray( const TreeNode* root )
688 const TreeNode* meshesNode = root->GetChild( "meshes" );
694 for( TreeNode::ConstIterator meshIter = ( *meshesNode ).CBegin(); meshIter != ( *meshesNode ).CEnd(); ++meshIter )
697 const TreeNode* nameNode = ( &( *meshIter ).second )->GetChild( "name" );
700 ReadString( nameNode, meshInfo.name );
702 meshInfo.geometry = Geometry::New();
704 //Need to add weights for Morph targets.
705 LoadPrimitive( ( *meshIter ).second, meshInfo );
706 SetGeometry( meshInfo );
707 mMeshArray.push_back( meshInfo );
713 bool GltfLoader::LoadPrimitive( const TreeNode& mesh, MeshInfo& meshInfo )
715 const TreeNode* primitivesNode = mesh.GetChild( "primitives" );
716 if( !primitivesNode )
721 for( TreeNode::ConstIterator primitiveIter = ( *primitivesNode ).CBegin(); primitiveIter != ( *primitivesNode ).CEnd(); ++primitiveIter )
723 const TreeNode* primitiveNode = ( &( *primitiveIter ).second );
724 const TreeNode* tempNode;
726 tempNode = primitiveNode->GetChild( "indices" );
729 meshInfo.indicesIdx = tempNode->GetInteger();
732 tempNode = primitiveNode->GetChild( "material" );
735 meshInfo.materialsIdx = tempNode->GetInteger();
738 tempNode = primitiveNode->GetChild( "mode" );
741 meshInfo.mode = tempNode->GetInteger();
744 LoadAttribute( primitiveNode, meshInfo );
750 bool GltfLoader::LoadAttribute( const TreeNode* primitive, MeshInfo& meshInfo )
752 const TreeNode* attrbuteNode = primitive->GetChild( "attributes" );
758 const TreeNode* tempNode;
759 tempNode = attrbuteNode->GetChild( "POSITION" );
762 meshInfo.attribute.POSITION = tempNode->GetInteger();
765 tempNode = attrbuteNode->GetChild( "NORMAL" );
768 meshInfo.attribute.NORMAL = tempNode->GetInteger();
771 tempNode = attrbuteNode->GetChild( "TANGENT" );
774 meshInfo.attribute.TANGENT = tempNode->GetInteger();
778 meshInfo.attribute.TEXCOORD.clear();
779 tempNode = attrbuteNode->GetChild( "TEXCOORD_" + std::to_string( index ) );
782 int value = tempNode->GetInteger();
783 meshInfo.attribute.TEXCOORD.push_back( value );
784 tempNode = attrbuteNode->GetChild( "TEXCOORD_" + std::to_string( ++index ) );
788 meshInfo.attribute.COLOR.clear();
789 tempNode = attrbuteNode->GetChild( "COLOR_" + std::to_string( index ) );
792 int value = tempNode->GetInteger();
793 meshInfo.attribute.COLOR.push_back( value );
794 tempNode = attrbuteNode->GetChild( "COLOR" + std::to_string( ++index ) );
800 bool GltfLoader::SetGeometry( MeshInfo& meshInfo )
802 int indicesIdx = meshInfo.indicesIdx;
804 if( meshInfo.mode != 0 )
806 meshInfo.geometry.SetType( ( Dali::Geometry::Type )meshInfo.mode );
809 if( indicesIdx >= 0 )
811 SetIndexBuffersData( meshInfo, indicesIdx );
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 );
818 for( unsigned int i = 0; i < meshInfo.attribute.TEXCOORD.size(); ++i )
820 int accessorIdx = meshInfo.attribute.TEXCOORD[i];
821 std::ostringstream texCoordString;
822 texCoordString << "aTexCoord" << i;
823 SetAttributeBufferData<Vector2>( meshInfo, accessorIdx, texCoordString.str(), Property::VECTOR2 );
826 for( unsigned int i = 0; i < meshInfo.attribute.COLOR.size(); ++i )
828 int accessorIdx = meshInfo.attribute.COLOR[i];
829 if( accessorIdx < 0 )
834 if( mAccessorArray[accessorIdx].type == "VEC3" )
836 Dali::Vector<Vector3> inputBufferData;
837 LoadDataFromAccessor( accessorIdx, inputBufferData );
839 Dali::Vector<Vector4> bufferData;
840 bufferData.Resize( inputBufferData.Size() );
841 for( unsigned int i = 0; i<inputBufferData.Size(); ++i )
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;
848 PropertyBuffer propertyBuffer = CreatePropertyBuffer<Vector4>( bufferData, "aVertexColor", Property::VECTOR4 );
849 meshInfo.geometry.AddVertexBuffer( propertyBuffer );
851 else if( mAccessorArray[accessorIdx].type == "VEC4" )
853 SetAttributeBufferData<Vector4>( meshInfo, accessorIdx, "aVertexColor", Property::VECTOR4 );
859 void GltfLoader::SetMeshInfoAndCanonize( MeshInfo& meshInfo, Dali::Vector<Dali::Vector3> &vertexBufferData )
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 )
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 );
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 );
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 );
879 Vector3 center = meshInfo.size * 0.5 + pointMin;
880 for( unsigned int i = 0; i < vertexSize; ++i )
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;
889 bool GltfLoader::CreateScene( Internal::Scene& scene )
891 scene.SetDefaultCamera( Dali::Camera::LOOK_AT_TARGET, 0.01, Vector3::ZERO );
894 if( !LoadSceneNodes( scene ) )
899 if( !LoadAnimation( scene ) )
907 void GltfLoader::LoadCamera( Scene& scene )
909 const TreeNode* camerasNode = mRoot->GetChild( "cameras" );
915 for( TreeNode::ConstIterator cameraIter = ( *camerasNode ).CBegin(); cameraIter != ( *camerasNode ).CEnd(); ++cameraIter )
917 const TreeNode* tempNode = ( &( *cameraIter ).second )->GetChild( "name" );
918 CameraInfo cameraInfo;
921 ReadString( tempNode, cameraInfo.name );
924 tempNode = ( &( *cameraIter ).second )->GetChild( "type" );
927 ReadString( tempNode, cameraInfo.type );
930 CameraActor cameraActor = CameraActor::New();
931 cameraActor.SetParentOrigin( ParentOrigin::CENTER );
932 cameraActor.SetAnchorPoint( AnchorPoint::CENTER );
934 if( cameraInfo.type == "orthographic" )
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 );
942 else if( cameraInfo.type == "perspective" )
944 if( !LoadPerspective( ( *cameraIter ).second, cameraInfo ) )
948 cameraActor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
949 cameraActor.SetFieldOfView( cameraInfo.perspective.yfov );
950 cameraActor.SetNearClippingPlane( cameraInfo.perspective.znear );
952 if( cameraInfo.perspective.zfar > 0.0 )
954 cameraActor.SetFarClippingPlane( cameraInfo.perspective.zfar );
956 if( cameraInfo.perspective.aspectRatio > 0.0 )
958 cameraActor.SetAspectRatio( cameraInfo.perspective.aspectRatio );
962 scene.AddCamera( cameraActor );
966 bool GltfLoader::LoadOrthoGraphic( const TreeNode& camera, CameraInfo& cameraInfo )
968 const TreeNode* orthographicNode = camera.GetChild( "orthographic" );
969 if( !orthographicNode )
974 const TreeNode* tempNode;
975 tempNode = orthographicNode->GetChild( "xmag" );
978 ReadFloat( tempNode, cameraInfo.orthographic.xmag );
981 tempNode = orthographicNode->GetChild( "ymag" );
984 ReadFloat( tempNode, cameraInfo.orthographic.ymag );
987 tempNode = orthographicNode->GetChild( "zfar" );
990 ReadFloat( tempNode, cameraInfo.orthographic.zfar );
993 tempNode = orthographicNode->GetChild( "znear" );
996 ReadFloat( tempNode, cameraInfo.orthographic.znear );
1002 bool GltfLoader::LoadPerspective( const TreeNode& camera, CameraInfo& cameraInfo )
1004 const TreeNode* perspectiveNode = camera.GetChild( "perspective" );
1005 if( !perspectiveNode )
1010 const TreeNode* tempNode;
1011 tempNode = perspectiveNode->GetChild( "aspectRatio" );
1014 ReadFloat( tempNode, cameraInfo.perspective.aspectRatio );
1017 tempNode = perspectiveNode->GetChild( "yfov" );
1020 ReadFloat( tempNode, cameraInfo.perspective.yfov );
1023 tempNode = perspectiveNode->GetChild( "zfar" );
1026 ReadFloat( tempNode, cameraInfo.perspective.zfar );
1029 tempNode = perspectiveNode->GetChild( "znear" );
1032 ReadFloat( tempNode, cameraInfo.perspective.znear );
1038 bool GltfLoader::LoadSceneNodes( Scene& scene )
1040 const TreeNode* sceneNode = mRoot->GetChild( "scene" );
1044 sceneNum = sceneNode->GetInteger();
1047 const TreeNode* scenesNode = mRoot->GetChild( "scenes" );
1048 if( !( scenesNode && ( mNodes = mRoot->GetChild( "nodes" ) ) ) )
1053 const TreeNode* tempNode = Tidx( scenesNode, sceneNum );
1059 tempNode = tempNode->GetChild( "nodes" );
1065 for( TreeNode::ConstIterator nodeIter = ( *tempNode ).CBegin(); nodeIter != ( *tempNode ).CEnd(); ++nodeIter )
1067 Actor actor = AddNode( scene, ( ( *nodeIter ).second ).GetInteger() );
1068 actor.SetParentOrigin( ParentOrigin::CENTER );
1069 scene.GetRoot().Add( actor );
1075 Actor GltfLoader::AddNode( Scene& scene, int index )
1077 const TreeNode* node = Tidx( mNodes, index );
1078 Actor actor = Actor::New();
1079 Vector3 actorSize( Vector3::ONE );
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 ) );
1085 Vector3 anchorPoint = AnchorPoint::CENTER;
1087 const TreeNode* tempNode = NULL;
1088 if( ( tempNode = node->GetChild( "translation" ) ) )
1090 float floatVec[3] = { 0.0, 0.0, 0.0 };
1091 if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
1093 translation = Vector3( floatVec[0], floatVec[1], floatVec[2] );
1097 if( ( tempNode = node->GetChild( "scale" ) ) )
1099 float floatVec[3] = { 1.0, 1.0, 1.0 };
1100 if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
1102 scale = Vector3( floatVec[0], floatVec[1], floatVec[2] );
1106 if( ( tempNode = node->GetChild( "rotation" ) ) )
1108 float floatVec[4] = { 0.0, 0.0, 0.0, 1.0 };
1109 if( tempNode && ReadVector( tempNode, floatVec, 4 ) )
1111 orientation = Quaternion( Vector4( floatVec[0], floatVec[1], floatVec[2], floatVec[3] ) );
1115 if( ( tempNode = node->GetChild( "matrix" ) ) )
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 ) )
1120 Matrix nodeMatrix = Matrix( floatVec );
1121 nodeMatrix.GetTransformComponents( translation, orientation, scale );
1125 if( ( tempNode = node->GetChild( "mesh" ) ) )
1127 MeshInfo meshInfo = mMeshArray[tempNode->GetInteger()];
1128 bool isMaterial = ( meshInfo.materialsIdx >= 0 );
1130 TextureSet textureSet;
1131 textureSet = TextureSet::New();
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;
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;
1147 bool useIBL = ( scene.GetLightType() >= Toolkit::Scene::LightType::IMAGE_BASED_LIGHT );
1150 GLTF::MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1151 if( SetTextureAndSampler( textureSet, materialInfo.baseColorTexture.index, FRAGMENT_SHADER, DEFINE_BASECOLOR_TEXTURE, addIdx ) )
1153 shaderTypeIndex += static_cast<int>( ShaderType::BASECOLOR_SHADER );
1154 isBaseColorTexture = true;
1156 if( SetTextureAndSampler( textureSet, materialInfo.metallicRoughnessTexture.index, FRAGMENT_SHADER, DEFINE_METALLICROUGHNESS_TEXTURE, addIdx ) )
1158 shaderTypeIndex += static_cast<int>( ShaderType::METALLICROUGHNESS_SHADER );
1159 isMetallicRoughnessTexture = true;
1161 if( SetTextureAndSampler( textureSet, materialInfo.normalTexture.index, FRAGMENT_SHADER, DEFINE_NORMAL_TEXTURE, addIdx ) )
1163 shaderTypeIndex += static_cast<int>( ShaderType::NORMAL_SHADER );
1164 isNormalTexture = true;
1166 if( SetTextureAndSampler( textureSet, materialInfo.occlusionTexture.index, FRAGMENT_SHADER, DEFINE_OCCLUSION_TEXTURE, addIdx ) )
1168 shaderTypeIndex += static_cast<int>( ShaderType::OCCLUSION_SHADER );
1169 isOcclusionTexture = true;
1171 if( SetTextureAndSampler( textureSet, materialInfo.emissiveTexture.index, FRAGMENT_SHADER, DEFINE_EMIT_TEXTURE, addIdx ) )
1173 shaderTypeIndex += static_cast<int>( ShaderType::EMIT_SHADER );
1174 isEmissiveTexture = true;
1179 shaderTypeIndex += static_cast<int>( ShaderType::IBL_SHADER );
1180 FRAGMENT_SHADER += DEFINE_IBL_TEXTURE;
1182 Sampler sampler = Sampler::New();
1183 sampler.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
1184 sampler.SetWrapMode( WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT );
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 );
1197 int textureSize = std::min( specularTexture.GetWidth(), specularTexture.GetHeight() );
1199 while( textureSize >= 1 )
1207 FRAGMENT_SHADER += PHYSICALLY_BASED_FRAGMENT_SHADER;
1208 if( !mShaderCache[shaderTypeIndex] )
1210 mShaderCache[shaderTypeIndex] = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
1211 scene.AddShader( mShaderCache[shaderTypeIndex] );
1213 Shader shader = mShaderCache[shaderTypeIndex];
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 );
1220 anchorPoint = meshInfo.pivot;
1221 actor.SetAnchorPoint( anchorPoint );
1223 actor.SetSize( Vector3( meshInfo.size.x, meshInfo.size.y, meshInfo.size.z ) );
1224 actor.AddRenderer( renderer );
1226 actor.SetScale( scale );
1227 actor.RotateBy( orientation );
1228 actor.SetPosition( translation );
1230 shader.RegisterProperty( "uLightType", ( scene.GetLightType() & ~Toolkit::Scene::LightType::IMAGE_BASED_LIGHT ) );
1231 shader.RegisterProperty( "uLightVector", scene.GetLightVector() );
1232 shader.RegisterProperty( "uLightColor", scene.GetLightColor() );
1234 actor.RegisterProperty( "uIsColor", meshInfo.attribute.COLOR.size() > 0 );
1237 GLTF::MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
1238 actor.RegisterProperty( "uBaseColorFactor", materialInfo.baseColorFactor );
1239 actor.RegisterProperty( "uMetallicRoughnessFactors", Vector2( materialInfo.metallicFactor, materialInfo.roughnessFactor ) );
1241 if( materialInfo.alphaMode == "OPAQUE" )
1243 actor.RegisterProperty( "alphaMode", 0 );
1245 else if( materialInfo.alphaMode == "MASK" )
1247 actor.RegisterProperty( "alphaMode", 1 );
1251 actor.RegisterProperty( "alphaMode", 2 );
1253 actor.RegisterProperty( "alphaCutoff", materialInfo.alphaCutoff );
1255 if( isBaseColorTexture )
1257 actor.RegisterProperty( "uBaseColorTexCoordIndex", materialInfo.baseColorTexture.texCoord );
1259 if( isMetallicRoughnessTexture )
1261 actor.RegisterProperty( "uMetallicRoughnessTexCoordIndex", materialInfo.metallicRoughnessTexture.texCoord );
1263 if( isNormalTexture )
1265 actor.RegisterProperty( "uNormalScale", materialInfo.normalTexture.value );
1266 actor.RegisterProperty( "uNormalTexCoordIndex", materialInfo.normalTexture.texCoord );
1268 if( isOcclusionTexture )
1270 actor.RegisterProperty( "uOcclusionTexCoordIndex", materialInfo.occlusionTexture.texCoord );
1271 actor.RegisterProperty( "uOcclusionStrength", materialInfo.occlusionTexture.value );
1273 if( isEmissiveTexture )
1275 actor.RegisterProperty( "uEmissiveTexCoordIndex", materialInfo.emissiveTexture.texCoord );
1276 actor.RegisterProperty( "uEmissiveFactor", materialInfo.emissiveFactor );
1280 if( isMaterial && useIBL )
1282 actor.RegisterProperty( "uScaleIBLAmbient", scene.GetIBLScaleFactor() );
1283 actor.RegisterProperty( "uMipmapLevel", static_cast<float>( maxMipmapLevel ) );
1288 actor.SetAnchorPoint( AnchorPoint::CENTER );
1289 actor.SetPosition( translation );
1290 actor.RotateBy( orientation );
1291 actor.SetSize( actorSize );
1294 tempNode = node->GetChild( "camera" );
1297 int cameraNum = tempNode->GetInteger();
1298 actor.Add( scene.GetCamera( cameraNum ) );
1301 tempNode = node->GetChild( "name" );
1304 std::string nameString;
1305 ReadString( tempNode, nameString );
1306 actor.SetName( nameString );
1309 SetActorCache( actor, index );
1310 if( ( tempNode = node->GetChild( "children" ) ) )
1312 for( TreeNode::ConstIterator childIter = ( *tempNode ).CBegin(); childIter != ( *tempNode ).CEnd(); ++childIter )
1314 Actor childActor = AddNode( scene, ( ( *childIter ).second ).GetInteger() );
1315 childActor.SetParentOrigin( anchorPoint );
1316 actor.Add( childActor );
1323 void GltfLoader::SetActorCache( Actor& actor, const int index )
1325 if( mActorCache.size() < static_cast<unsigned int>( index + 1 ) )
1327 mActorCache.resize( index + 1 );
1329 mActorCache[index] = actor;
1332 bool GltfLoader::SetTextureAndSampler( TextureSet& textureSet, int textureIdx, std::string& toShader, std::string shader, int& addIdx )
1334 if( textureIdx >= 0 )
1337 TextureInfo textureInfo = mTextureArray[textureIdx];
1338 if( textureInfo.sourceIdx >= 0 )
1340 textureSet.SetTexture( addIdx, mSourceArray[textureInfo.sourceIdx] );
1342 if( textureInfo.samplerIdx >= 0 )
1344 textureSet.SetSampler( addIdx, mSamplerArray[textureInfo.samplerIdx] );
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 );
1359 bool GltfLoader::LoadAnimation( Scene& scene )
1361 const TreeNode* animationsNode = mRoot->GetChild( "animations" );
1362 if( !animationsNode )
1367 for( TreeNode::ConstIterator animationIter = ( *animationsNode ).CBegin(); animationIter != ( *animationsNode ).CEnd(); ++animationIter )
1369 const TreeNode* nameNode = ( &( *animationIter ).second )->GetChild( "name" );
1370 AnimationInfo animationInfo;
1373 ReadString( nameNode, animationInfo.name );
1376 Property::Index propIndex = Property::INVALID_INDEX;
1377 LoadAnimationChannels( ( *animationIter ).second, animationInfo );
1378 if( animationInfo.channelArray.size() == 0 )
1383 LoadAnimationSamplers( ( *animationIter ).second, animationInfo );
1385 int channelNum = animationInfo.channelArray.size();
1386 for( int i = 0; i < channelNum; i++ )
1388 AnimationChannelInfo currentChannel = animationInfo.channelArray[i];
1390 if( currentChannel.path == "rotation" )
1392 propIndex = Dali::Actor::Property::ORIENTATION;
1394 else if( currentChannel.path == "translation" )
1396 propIndex = Dali::Actor::Property::POSITION;
1398 else if( currentChannel.path == "scale" )
1400 propIndex = Dali::Actor::Property::SCALE;
1403 float duration = 0.0f;
1404 KeyFrames keyframes = KeyFrames::New();
1405 if( propIndex == Dali::Actor::Property::ORIENTATION )
1407 duration = LoadKeyFrames<Vector4>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes );
1411 duration = LoadKeyFrames<Vector3>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes );
1414 Animation animation = Animation::New( duration );
1415 Animation::Interpolation interpolation = Animation::Interpolation::Linear;
1416 if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "CUBICSPLINE" )
1418 interpolation = Animation::Interpolation::Cubic;
1420 if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "STEP" )
1424 animation.AnimateBetween( Property( mActorCache[currentChannel.targetNode], propIndex ), keyframes, interpolation );
1426 animation.SetLooping( false );
1427 scene.AddAnimation( animation );
1434 bool GltfLoader::LoadAnimationChannels( const TreeNode& animation, AnimationInfo& animationInfo )
1436 const TreeNode* channelsNode = animation.GetChild( "channels" );
1442 for( TreeNode::ConstIterator channelIter = ( *channelsNode ).CBegin(); channelIter != ( *channelsNode ).CEnd(); ++channelIter )
1444 AnimationChannelInfo animationChannelInfo;
1445 const TreeNode* channelNode = ( &( *channelIter ).second );
1446 const TreeNode* samplerNode = channelNode->GetChild( "sampler" );
1449 animationChannelInfo.sampler = samplerNode->GetInteger();
1452 const TreeNode* targetNode = channelNode->GetChild( "target" );
1455 const TreeNode* tempNode = targetNode->GetChild( "node" );
1458 animationChannelInfo.targetNode = tempNode->GetInteger();
1465 tempNode = targetNode->GetChild( "path" );
1468 ReadString( tempNode, animationChannelInfo.path );
1472 animationInfo.channelArray.push_back( animationChannelInfo );
1477 bool GltfLoader::LoadAnimationSamplers( const TreeNode& animation, AnimationInfo& animationInfo )
1479 const TreeNode* samplersNode = animation.GetChild( "samplers" );
1485 for( TreeNode::ConstIterator sampler = ( *samplersNode ).CBegin(); sampler != ( *samplersNode ).CEnd(); ++sampler )
1487 AnimationSamplerInfo animationSamplerInfo;
1488 const TreeNode* samplerNode = ( &( *sampler ).second );
1489 const TreeNode* tempNode = samplerNode->GetChild( "input" );
1492 animationSamplerInfo.input = tempNode->GetInteger();
1495 tempNode = samplerNode->GetChild( "output" );
1498 animationSamplerInfo.output = tempNode->GetInteger();
1501 tempNode = samplerNode->GetChild( "interpolation" );
1504 ReadString( tempNode, animationSamplerInfo.interpolation );
1507 animationInfo.samplerArray.push_back( animationSamplerInfo );
1513 // Template functions
1514 template <typename T>
1515 bool GltfLoader::ReadBinFile( Vector<T> &dataBuffer, std::string url, int offset, int count )
1517 if( url.length() > MAX_PATH_LENGTH )
1519 DALI_LOG_ERROR( "Binary file path is too long.\n" );
1522 dataBuffer.Resize( count );
1523 FILE* fp = fopen( url.c_str(), "rb" );
1528 ssize_t result = -1;
1529 if( !fseek( fp, offset, SEEK_SET ) )
1531 result = fread( &dataBuffer[0], sizeof( T ), count, fp );
1535 return ( result >= 0 );
1538 template <typename T>
1539 float GltfLoader::IntToFloat( T element, bool normalize )
1543 return static_cast<float>( element );
1546 if( std::is_same<T, char>::value )
1548 return std::max( static_cast<float>( element ) / 127.0, -1.0 );
1550 if( std::is_same<T, unsigned char>::value )
1552 return static_cast<float>( element ) / 255.0;
1554 if( std::is_same<T, short>::value )
1556 return std::max( static_cast<float>( element ) / 32767.0, -1.0 );
1558 if( std::is_same<T, unsigned short>::value )
1560 return static_cast<float>( element ) / 65535.0;
1565 template <typename Td, typename Ts>
1566 void GltfLoader::FitBuffer( Dali::Vector<Td>& bufferDestiny, Dali::Vector<Ts>& bufferSource, int bufferSize, int elementNumOfByteStride, bool normalize )
1568 bufferDestiny.Resize( bufferSize );
1569 int count = bufferSource.Size() / elementNumOfByteStride;
1570 for( int i = 0; i<count; ++i )
1572 bufferDestiny[i] = static_cast<Td>( bufferSource[i * elementNumOfByteStride] );
1576 template <typename T>
1577 void GltfLoader::FitBuffer( Dali::Vector<Vector2>& bufferDestiny, Dali::Vector<T>& bufferSource, int bufferSize, int elementNumOfByteStride, bool normalize )
1579 bufferDestiny.Resize( bufferSize );
1580 int count = bufferSource.Size() / elementNumOfByteStride;
1581 for( int i = 0; i<count; ++i )
1583 bufferDestiny[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
1584 bufferDestiny[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
1588 template <typename T>
1589 void GltfLoader::FitBuffer( Dali::Vector<Vector3>& bufferDestiny, Dali::Vector<T>& bufferSource, int bufferSize, int elementNumOfByteStride, bool normalize )
1591 bufferDestiny.Resize( bufferSize );
1592 int count = bufferSource.Size() / elementNumOfByteStride;
1593 for( int i = 0; i<count; ++i )
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 );
1601 template <typename T>
1602 void GltfLoader::FitBuffer( Dali::Vector<Vector4>& bufferDestiny, Dali::Vector<T>& bufferSource, int bufferSize, int elementNumOfByteStride, bool normalize )
1604 bufferDestiny.Resize( bufferSize );
1605 int count = bufferSource.Size() / elementNumOfByteStride;
1606 for( int i = 0; i<count; ++i )
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 );
1615 template <typename T>
1616 void GltfLoader::LoadDataFromAccessor( int accessorIdx, Dali::Vector<T>& bufferData )
1618 AccessorInfo accessor = mAccessorArray[accessorIdx];
1619 BufferViewInfo bufferView = mBufferViewArray[accessor.bufferView];
1620 BufferInfo buffer = mBufferArray[bufferView.buffer];
1621 std::string load_uri = buffer.uri;
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 );
1627 if( accessor.type == "VEC2" )
1631 else if( accessor.type == "VEC3" )
1635 else if( accessor.type == "VEC4" || accessor.type == "MAT2" )
1639 else if( accessor.type == "MAT3" )
1643 else if( accessor.type == "MAT4" )
1651 int elementNumOfByteStride = elementNum;
1652 if( bufferView.byteStride > 0 )
1654 elementNumOfByteStride = bufferView.byteStride / elementByteSize;
1658 * glTF 2.0 Specification
1661 * 5121 : UNSIGNED_BYTE
1663 * 5123 : UNSIGNED_SHORT
1664 * 5125 : UNSIGNED_INT
1667 if( accessor.componentType == 5120 )
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 );
1673 else if( accessor.componentType == 5121 )
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 );
1679 else if( accessor.componentType == 5122 )
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 );
1685 else if( accessor.componentType == 5123 )
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 );
1691 else if( accessor.componentType == 5125 )
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 );
1697 else if( accessor.componentType == 5126 )
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 );
1705 template <typename T>
1706 PropertyBuffer GltfLoader::CreatePropertyBuffer( Vector<T> bufferData, std::string map, int type )
1708 Property::Map positionMap;
1709 positionMap[map] = type;
1711 PropertyBuffer propertyBuffer = PropertyBuffer::New( positionMap );
1712 propertyBuffer.SetData( bufferData.Begin(), bufferData.Count() );
1713 return propertyBuffer;
1717 void GltfLoader::SetVertexBufferData( MeshInfo& meshInfo, int accessorIdx, std::string map, int type )
1719 if( accessorIdx >= 0 )
1721 Dali::Vector<Vector3> bufferData;
1722 LoadDataFromAccessor( accessorIdx, bufferData );
1723 SetMeshInfoAndCanonize( meshInfo, bufferData );
1725 PropertyBuffer propertyBuffer = CreatePropertyBuffer<Vector3>( bufferData, map, type );
1726 meshInfo.geometry.AddVertexBuffer( propertyBuffer );
1730 template <typename T>
1731 void GltfLoader::SetAttributeBufferData( MeshInfo& meshInfo, int accessorIdx, std::string map, int type )
1733 if( accessorIdx >= 0 )
1735 Dali::Vector<T> bufferData;
1736 LoadDataFromAccessor( accessorIdx, bufferData );
1738 PropertyBuffer propertyBuffer = CreatePropertyBuffer<T>( bufferData, map, type );
1739 meshInfo.geometry.AddVertexBuffer( propertyBuffer );
1743 void GltfLoader::SetIndexBuffersData( MeshInfo& meshInfo, int indexIdx )
1745 Dali::Vector<unsigned short> indexBufferData;
1746 LoadDataFromAccessor( indexIdx, indexBufferData );
1747 meshInfo.geometry.SetIndexBuffer( &indexBufferData[0], indexBufferData.Size() );
1750 template<typename T>
1751 float GltfLoader::LoadKeyFrames( const AnimationSamplerInfo& currentSampler, const Property::Index propIndex, KeyFrames& keyframes )
1753 Dali::Vector<float> inputBufferData;
1754 Dali::Vector<T> outputBufferData;
1756 LoadDataFromAccessor<float>( currentSampler.input, inputBufferData );
1757 LoadDataFromAccessor<T>( currentSampler.output, outputBufferData );
1759 int keyframeNum = inputBufferData.Size();
1760 float lengthAnimation = inputBufferData[keyframeNum - 1];
1761 for( int i = 0; i < keyframeNum; i++ )
1763 if( propIndex == Dali::Actor::Property::ORIENTATION )
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 ) ) );
1771 else if( propIndex == Dali::Actor::Property::POSITION )
1773 keyframes.Add( inputBufferData[i] / lengthAnimation, Vector3( outputBufferData[i] ) );
1775 else if( propIndex == Dali::Actor::Property::SCALE )
1777 keyframes.Add( inputBufferData[i] / lengthAnimation, Vector3( outputBufferData[i] ) );
1780 return lengthAnimation;
1783 // Utility functions
1784 const TreeNode* GltfLoader::Tidx( const TreeNode *node, int index )
1787 for( TreeNode::ConstIterator it = ( *node ).CBegin(); it != ( *node ).CEnd(); ++it, ++i )
1791 return &( ( *it ).second );
1797 bool GltfLoader::ReadBool( const TreeNode* node, bool& num )
1803 bool returnValue = false;
1805 if( node->GetType() == TreeNode::BOOLEAN )
1807 num = node->GetBoolean();
1814 bool GltfLoader::ReadInt( const TreeNode* node, int& num )
1820 bool returnValue = false;
1821 if( node->GetType() == TreeNode::INTEGER )
1823 num = node->GetInteger();
1826 else if( node->GetType() == TreeNode::FLOAT )
1828 num = node->GetFloat();
1835 bool GltfLoader::ReadFloat( const TreeNode* node, float& num )
1841 bool returnValue = false;
1843 if( node->GetType() == TreeNode::FLOAT )
1845 num = node->GetFloat();
1848 else if( node->GetType() == TreeNode::INTEGER )
1851 ReadInt( node, tempNum );
1852 num = static_cast<float>( tempNum );
1859 bool GltfLoader::ReadVector( const TreeNode* node, float* num, unsigned int size )
1865 bool returnValue = false;
1867 if( ( node->Size() >= size ) && ( node->GetType() == TreeNode::ARRAY ) )
1869 unsigned int offset = 0u;
1870 for( TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset )
1872 const TreeNode& coord = ( *it ).second;
1873 if( !ReadFloat( &coord, *( num + offset ) ) )
1884 bool GltfLoader::ReadString( const TreeNode* node, std::string& strValue )
1890 bool returnValue = false;
1891 if( node->GetType() == TreeNode::STRING )
1893 strValue = node->GetString();
1899 }//namespace Internal
1901 }//namespace Toolkit