Scene and glTF Loader 84/188684/37
authorSeungho, Baek <sbsh.baek@samsung.com>
Fri, 7 Sep 2018 08:43:50 +0000 (17:43 +0900)
committerSeungho, Baek <sbsh.baek@samsung.com>
Thu, 11 Oct 2018 05:36:43 +0000 (14:36 +0900)
 - Scene for the 3D Mesh object(Animated or not).
 - PBR rendering with Image Based Lighting
 - glTF Loader that loads scene from glTF( TODO: sparse accessor, skeletal animation, morphing. )
 - UTC

Change-Id: I4ee6b5db3315b8d165bbf90269ce01c86cc70531
Signed-off-by: Seungho, Baek <sbsh.baek@samsung.com>
19 files changed:
automated-tests/resources/AnimatedCube.bin [new file with mode: 0644]
automated-tests/resources/AnimatedCube.gltf [new file with mode: 0644]
automated-tests/resources/AnimatedCube_BaseColor.png [new file with mode: 0644]
automated-tests/resources/AnimatedCube_MetallicRoughness.png [new file with mode: 0644]
automated-tests/resources/forest_diffuse_cubemap.png [new file with mode: 0644]
automated-tests/resources/forest_specular_cubemap.png [new file with mode: 0644]
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-Scene3dView.cpp [new file with mode: 0644]
build/tizen/dali-toolkit/Makefile.am
dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.cpp [new file with mode: 0644]
dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h [new file with mode: 0644]
dali-toolkit/devel-api/file.list
dali-toolkit/internal/controls/scene3d-view/gltf-loader.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/scene3d-view/gltf-loader.h [new file with mode: 0644]
dali-toolkit/internal/controls/scene3d-view/gltf-shader.h [new file with mode: 0644]
dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h [new file with mode: 0644]
dali-toolkit/internal/file.list
dali-toolkit/styles/images-common/brdfLUT.png [new file with mode: 0644]

diff --git a/automated-tests/resources/AnimatedCube.bin b/automated-tests/resources/AnimatedCube.bin
new file mode 100644 (file)
index 0000000..72f7d2d
Binary files /dev/null and b/automated-tests/resources/AnimatedCube.bin differ
diff --git a/automated-tests/resources/AnimatedCube.gltf b/automated-tests/resources/AnimatedCube.gltf
new file mode 100644 (file)
index 0000000..2f78e20
--- /dev/null
@@ -0,0 +1,401 @@
+{
+   "accessors" : [
+      {
+         "bufferView" : 0,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 3,
+         "max" : [
+            2.000000
+         ],
+         "min" : [
+            0.000000
+         ],
+         "type" : "SCALAR"
+      },
+      {
+         "bufferView" : 1,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 3,
+         "max" : [
+            0.000000,
+            1.000000,
+            0.000000,
+            1.000000
+         ],
+         "min" : [
+            0.000000,
+            -8.742278e-008,
+            0.000000,
+            -1.000000
+         ],
+         "type" : "VEC4"
+      },
+      {
+         "bufferView" : 2,
+         "byteOffset" : 0,
+         "componentType" : 5123,
+         "count" : 36,
+         "max" : [
+            35
+         ],
+         "min" : [
+            0
+         ],
+         "type" : "SCALAR"
+      },
+      {
+         "bufferView" : 3,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000,
+            1.000001
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC3"
+      },
+      {
+         "bufferView" : 4,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000,
+            1.000000
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC3"
+      },
+      {
+         "bufferView" : 5,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            -0.000000,
+            -0.000000,
+            1.000000
+         ],
+         "min" : [
+            0.000000,
+            -0.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC4"
+      },
+      {
+         "bufferView" : 6,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC2"
+      }
+   ],
+   "animations" : [
+    {
+       "channels" : [
+          {
+             "sampler" : 0,
+             "target" : {
+                "node" : 0,
+                "path" : "rotation"
+             }
+          }
+       ],
+       "name" : "animation_AnimatedCube",
+       "samplers" : [
+          {
+             "input" : 0,
+             "interpolation" : "LINEAR",
+             "output" : 1
+          }
+       ]
+    }
+   ],
+   "asset" : {
+      "generator" : "VKTS glTF 2.0 exporter",
+      "version" : "2.0"
+   },
+   "bufferViews" : [
+      {
+         "buffer" : 0,
+         "byteLength" : 12,
+         "byteOffset" : 0
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 48,
+         "byteOffset" : 12
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 72,
+         "byteOffset" : 60,
+         "target" : 34963
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 432,
+         "byteOffset" : 132,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 432,
+         "byteOffset" : 564,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 576,
+         "byteOffset" : 996,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 288,
+         "byteOffset" : 1572,
+         "target" : 34962
+      }
+   ],
+   "buffers" : [
+      {
+         "byteLength" : 1860,
+         "uri" : "AnimatedCube.bin"
+      }
+   ],
+   "images" : [
+      {
+         "uri" : "AnimatedCube_BaseColor.png"
+      },
+      {
+         "uri" : "AnimatedCube_MetallicRoughness.png"
+      }
+   ],
+   "materials" : [
+      {
+         "name" : "AnimatedCube",
+         "pbrMetallicRoughness" : {
+            "baseColorTexture" : {
+               "index" : 0
+            },
+            "metallicRoughnessTexture" : {
+               "index" : 1
+            },
+            "baseColorFactor": [ 1.000, 0.766, 0.336, 1.0 ],
+            "metallicFactor": 1.0,
+            "roughnessFactor": 0.0
+         },
+         "normalTexture": {
+          "scale": 1,
+          "index": 0
+         },
+         "occlusionTexture": {
+          "index": 0
+         },
+         "emissiveTexture": {
+          "index": 0
+         },
+         "emissiveFactor": [ 0.2, 0.1, 0.0 ],
+         "doubleSided": false,
+         "alphaMode": "MASK",
+         "alphaCutoff": 0.5
+      },
+      {
+         "name" : "AnimatedCube2",
+         "pbrMetallicRoughness" : {
+            "baseColorTexture" : {
+               "index" : 0
+            },
+            "metallicRoughnessTexture" : {
+               "index" : 1
+            },
+            "baseColorFactor": [ 1.000, 0.766, 0.336, 1.0 ],
+            "metallicFactor": 1.0,
+            "roughnessFactor": 0.0
+         },
+         "normalTexture": {
+          "scale": 1,
+          "index": 0
+         },
+         "occlusionTexture": {
+          "index": 0
+         },
+         "emissiveTexture": {
+          "index": 0
+         },
+         "emissiveFactor": [ 0.2, 0.1, 0.0 ],
+         "doubleSided": false,
+         "alphaMode": "OPAQUE"
+      }
+   ],
+   "meshes" : [
+      {
+         "name" : "AnimatedCube",
+         "primitives" : [
+            {
+               "attributes" : {
+                  "NORMAL" : 4,
+                  "POSITION" : 3,
+                  "TANGENT" : 5,
+                  "TEXCOORD_0" : 6,
+                  "COLOR_0" : 3
+               },
+               "indices" : 2,
+               "material" : 0,
+               "mode" : 4
+            }
+         ]
+      },
+      {
+         "name" : "AnimatedCube2",
+         "primitives" : [
+            {
+               "attributes" : {
+                  "NORMAL" : 4,
+                  "POSITION" : 3,
+                  "TANGENT" : 5,
+                  "TEXCOORD_0" : 6,
+                  "COLOR_0" : 3
+               },
+               "indices" : 2,
+               "material" : 1,
+               "mode" : 4
+            }
+         ]
+      }
+   ],
+   "nodes" : [
+      {
+         "mesh" : 0,
+         "name" : "AnimatedCube",
+         "rotation" : [
+            0.000000,
+            -1.000000,
+            0.000000,
+            0.000000
+         ]
+      },
+      {
+         "mesh" : 1,
+         "name" : "AnimatedCube2"
+      },
+      {
+
+        "camera" : 0,
+        "scale" : [ 0.5, 0.5, 3.0 ]
+      },
+      {
+        "camera" : 1,
+        "translation" : [ 0.5, 0.5, 3.0 ],
+        "children": [
+          4
+        ]
+      },
+      {
+        "camera" : 2,
+        "matrix": [
+            1.0,
+            0.0,
+            0.0,
+            0.0,
+            0.0,
+            0.0,
+            -1.0,
+            0.0,
+            0.0,
+            1.0,
+            0.0,
+            0.0,
+            0.0,
+            0.0,
+            0.0,
+            1.0
+        ]
+      }
+   ],
+   "scene" : 0,
+   "scenes" : [
+      {
+         "nodes" : [
+            0, 1, 2, 3
+         ]
+      }
+   ],
+   "textures" : [
+      {
+         "sampler" : 0,
+         "source" : 0
+      },
+      {
+         "sampler" : 1,
+         "source" : 1
+      }
+   ],
+   "cameras" : [
+    {
+      "type": "perspective",
+      "perspective": {
+        "aspectRatio": 1.0,
+        "yfov": 0.7,
+        "zfar": 100.0,
+        "znear": 0.01
+      }
+    },
+    {
+      "type": "orthographic",
+      "orthographic": {
+        "xmag": 1.0,
+        "ymag": 1.0,
+        "zfar": 100.0,
+        "znear": 0.01
+      }
+    },
+    {
+      "type": "orthographic",
+      "orthographic": {
+        "xmag": 1.0,
+        "ymag": 1.0,
+        "zfar": 100.0,
+        "znear": 0.01
+      }
+    }
+   ],
+   "samplers": [
+    {
+        "magFilter": 9729,
+        "minFilter": 9987,
+        "wrapS": 33071,
+        "wrapT": 10497
+    },
+    {
+        "magFilter": 9728,
+        "minFilter": 9986,
+        "wrapS": 33071,
+        "wrapT": 33648
+    }
+   ]
+}
\ No newline at end of file
diff --git a/automated-tests/resources/AnimatedCube_BaseColor.png b/automated-tests/resources/AnimatedCube_BaseColor.png
new file mode 100644 (file)
index 0000000..5e5cb20
Binary files /dev/null and b/automated-tests/resources/AnimatedCube_BaseColor.png differ
diff --git a/automated-tests/resources/AnimatedCube_MetallicRoughness.png b/automated-tests/resources/AnimatedCube_MetallicRoughness.png
new file mode 100644 (file)
index 0000000..efd2026
Binary files /dev/null and b/automated-tests/resources/AnimatedCube_MetallicRoughness.png differ
diff --git a/automated-tests/resources/forest_diffuse_cubemap.png b/automated-tests/resources/forest_diffuse_cubemap.png
new file mode 100644 (file)
index 0000000..ff3e237
Binary files /dev/null and b/automated-tests/resources/forest_diffuse_cubemap.png differ
diff --git a/automated-tests/resources/forest_specular_cubemap.png b/automated-tests/resources/forest_specular_cubemap.png
new file mode 100644 (file)
index 0000000..d5cb909
Binary files /dev/null and b/automated-tests/resources/forest_specular_cubemap.png differ
index 9d79595..f193458 100755 (executable)
@@ -27,6 +27,7 @@ SET(TC_SOURCES
   utc-Dali-KeyInputFocusManager.cpp
   utc-Dali-Layouting.cpp
   utc-Dali-PageTurnView.cpp
+  utc-Dali-Scene3dView.cpp
   utc-Dali-Script.cpp
   utc-Dali-ScrollBar.cpp
   utc-Dali-ScrollView.cpp
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Scene3dView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Scene3dView.cpp
new file mode 100644 (file)
index 0000000..7c8dad4
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void dali_scene_view_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void dali_scene_view_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+/**
+ * For the AnimatedCube.gltf and its Assets
+ * Donated by Norbert Nopper for glTF testing.
+ * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube
+ */
+const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf";
+/**
+ * For the diffuse and specular cube map texture.
+ * These textures are based off version of Wave engine sample
+ * Take from https://github.com/WaveEngine/Samples
+ *
+ * Copyright (c) 2016 Wave Coorporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_diffuse_cubemap.png";
+const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_specular_cubemap.png";
+}
+
+int UtcDaliScene3dViewConstructorP(void)
+{
+  TestApplication application;
+
+  Scene3dView scene3dView;
+
+  DALI_TEST_CHECK( !scene3dView );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewCopyConstructorP(void)
+{
+  TestApplication application;
+
+  // Initialize an object, ref count == 1
+  Scene3dView scene3dView = Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  Scene3dView copy( scene3dView );
+  DALI_TEST_CHECK( copy );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewCopyConstructor2P(void)
+{
+  TestApplication application;
+
+  // Initialize an object, ref count == 1
+  Toolkit::Scene3dView scene3dView = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME, TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE, Vector4::ONE );
+
+  Scene3dView copy( scene3dView );
+  DALI_TEST_CHECK( copy );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  Scene3dView scene3dView = Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  Scene3dView copy( scene3dView );
+  DALI_TEST_CHECK( copy );
+
+  DALI_TEST_CHECK( scene3dView == copy );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewNewP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewNewP");
+
+  // Create the Slider actor
+  Scene3dView scene3dView;
+  DALI_TEST_CHECK( !scene3dView );
+
+  scene3dView = Scene3dView::New( TEST_GLTF_FILE_NAME );
+  DALI_TEST_CHECK( scene3dView );
+
+  END_TEST;
+}
+
+int UtcDaliScene3dViewDestructorP(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3dView* scene3dView = new Scene3dView();
+  delete scene3dView;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewDownCast");
+
+  Toolkit::Scene3dView view = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME );
+  BaseHandle handle(view);
+
+  Toolkit::Scene3dView scene3dView = Toolkit::Scene3dView::DownCast( handle );
+  DALI_TEST_CHECK( view );
+  DALI_TEST_CHECK( scene3dView );
+  DALI_TEST_CHECK( scene3dView == view );
+  END_TEST;
+}
+
+int UtcDaliScene3dViewSetLight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewSetLight");
+
+  Toolkit::Scene3dView view = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  bool lightSet = view.SetLight( Scene3dView::LightType::DIRECTIONAL_LIGHT, Vector3( 1.0, 1.0, -1.0 ), Vector3( 0.3, 0.3, 0.3 ) );
+  DALI_TEST_CHECK( lightSet );
+  bool lightSet2 = view.SetLight( Scene3dView::LightType::POINT_LIGHT, Vector3( 1.0, 1.0, -1.0 ), Vector3( 0.3, 0.3, 0.3 ) );
+  DALI_TEST_CHECK( lightSet2 );
+
+  END_TEST;
+}
+
+int UtcDaliScene3dViewGetCamera(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewGetCamera");
+
+  Toolkit::Scene3dView view = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  CameraActor camera = view.GetDefaultCamera();
+  DALI_TEST_CHECK( camera );
+
+  CameraActor camera2 = view.GetCamera( -1 );
+  DALI_TEST_CHECK( !camera2 );
+
+  CameraActor camera3 = view.GetCamera( 0 );
+  DALI_TEST_CHECK( camera3 );
+
+  CameraActor camera4 = view.GetCamera( view.GetCameraCount() - 1 );
+  DALI_TEST_CHECK( camera4 );
+
+  END_TEST;
+}
+
+int UtcDaliScene3dViewAnimations(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewAnimations");
+
+  Toolkit::Scene3dView view = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  bool playAnimation = view.PlayAnimations();
+  DALI_TEST_CHECK( playAnimation );
+
+  END_TEST;
+}
+
+int UtcDaliScene3dViewAnimations2(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliScene3dViewAnimations2");
+
+  Toolkit::Scene3dView view = Toolkit::Scene3dView::New( TEST_GLTF_FILE_NAME );
+
+  bool animated = true;
+  unsigned int animationCount = view.GetAnimationCount();
+  for( unsigned int i = 0; i < animationCount; ++i )
+  {
+    animated = ( animated && view.PlayAnimation( i ) );
+  }
+  DALI_TEST_CHECK( animated );
+
+  END_TEST;
+}
index 62fa7ae..3d77bb8 100644 (file)
@@ -142,6 +142,7 @@ develapimagnifierdir =          $(develapicontrolsdir)/magnifier
 develapinavigationviewdir =     $(develapicontrolsdir)/navigation-view
 develapipageturnviewdir =       $(develapicontrolsdir)/page-turn-view
 develapipopupdir =              $(develapicontrolsdir)/popup
+develapiscene3dviewdir =        $(develapicontrolsdir)/scene3d-view
 develapishadowviewdir =         $(develapicontrolsdir)/shadow-view
 develapisuperblurviewdir =      $(develapicontrolsdir)/super-blur-view
 develapiwebviewdir =            $(develapicontrolsdir)/web-view
@@ -180,6 +181,7 @@ develapipopup_HEADERS =             $(devel_api_popup_header_files)
 develapivisualfactory_HEADERS =     $(devel_api_visual_factory_header_files)
 develapivisuals_HEADERS =           $(devel_api_visuals_header_files)
 develapiscripting_HEADERS =         $(devel_api_scripting_header_files)
+develapiscene3dview_HEADERS =       $(devel_api_scene3d_view_header_files)
 develapishadowview_HEADERS =        $(devel_api_shadow_view_header_files)
 develapishadereffects_HEADERS =     $(devel_api_shader_effects_header_files)
 develapistyling_HEADERS =           $(devel_api_styling_header_files)
diff --git a/dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.cpp b/dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.cpp
new file mode 100644 (file)
index 0000000..605d146
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+Scene3dView::Scene3dView()
+{
+}
+
+Scene3dView::~Scene3dView()
+{
+}
+
+Scene3dView::Scene3dView( const Scene3dView& handle )
+  : Control( handle )
+{
+}
+
+Scene3dView& Scene3dView::operator=( const Scene3dView& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+Scene3dView Scene3dView::New( const std::string& filePath )
+{
+  return Internal::Scene3dView::New( filePath );
+}
+
+Scene3dView Scene3dView::New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )
+{
+  return Internal::Scene3dView::New( filePath, diffuseTexturePath, specularTexturePath, scaleFactor );
+}
+
+Scene3dView::Scene3dView( Internal::Scene3dView& implementation )
+  : Control( implementation )
+{
+}
+
+Scene3dView::Scene3dView( Dali::Internal::CustomActor* internal )
+  : Control( internal )
+{
+  VerifyCustomActorPointer<Internal::Scene3dView>( internal );
+}
+
+Scene3dView Scene3dView::DownCast( BaseHandle handle )
+{
+  return Control::DownCast<Scene3dView, Internal::Scene3dView>( handle );
+}
+
+uint32_t Scene3dView::GetAnimationCount()
+{
+  return GetImpl( *this ).GetAnimationCount();
+}
+
+bool Scene3dView::PlayAnimation( uint32_t index )
+{
+  return GetImpl( *this ).PlayAnimation( index );
+}
+
+bool Scene3dView::PlayAnimations()
+{
+  return GetImpl( *this ).PlayAnimations();
+}
+
+bool Scene3dView::SetLight( LightType type, Vector3 lightVector, Vector3 lightColor )
+{
+  return GetImpl( *this ).SetLight( type, lightVector, lightColor );
+}
+
+CameraActor Scene3dView::GetDefaultCamera()
+{
+  return GetImpl( *this ).GetDefaultCamera();
+}
+
+uint32_t Scene3dView::GetCameraCount()
+{
+  return GetImpl( *this ).GetCameraCount();
+}
+
+CameraActor Scene3dView::GetCamera( uint32_t cameraIndex )
+{
+  return GetImpl( *this ).GetCamera( cameraIndex );
+}
+
+}//namespace Toolkit
+
+}//namespace Dali
+
diff --git a/dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h b/dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h
new file mode 100644 (file)
index 0000000..0e6d6b1
--- /dev/null
@@ -0,0 +1,210 @@
+#ifndef DALI_TOOLKIT_SCENE3D_VIEW_H\r
+#define DALI_TOOLKIT_SCENE3D_VIEW_H\r
+\r
+/*\r
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <dali/public-api/actors/camera-actor.h>\r
+\r
+// INTERNAL INCLUDES\r
+#include <dali-toolkit/public-api/controls/control.h>\r
+\r
+namespace Dali\r
+{\r
+\r
+namespace Toolkit\r
+{\r
+\r
+namespace Internal DALI_INTERNAL\r
+{\r
+\r
+/**\r
+ * Scene3dView implementation class\r
+ */\r
+class Scene3dView;\r
+\r
+}\r
+\r
+/**\r
+ *\r
+ * Scene3dView is a class for containing scene elements loaded from scene format file(e.g., glTF). Scene elements mean scene graph, cameras, and animations.\r
+ *\r
+ * Basic idea:-\r
+ *\r
+ * 1) The Scene3dView is initialized with diffuse and specular cube map for the Image Based Lighting.\n\r
+ *    If the Scene3dView initialized without cube map, the objects of the Scene3dView cannot be rendered with IBL.\n\r
+ * 2) The Scene3dView is loaded from each scene format file(e.g., glTF).\n\r
+ * 3) The Scene3dView can have a point light or a directional light.(optional)\n\r
+ * 4) The Scene3dView playes each actor's animation.\n\r
+ *\r
+ *\r
+ * Usage example: -\r
+ *\r
+ * @code\r
+ *\r
+ * void Scene3dViewExample::Create( Application& application )\r
+ * {\r
+ *   // Use 'Scene3dView::New( URL_SCENE_FILE )', if you don't want to render with IBL.\r
+ *   Scene3dView scene3dView = Scene3dView::New( URL_SCENE_FILE, URL_DIFFUSE_TEXTURE, URL_SPECULAR_TEXTURE );\r
+ *\r
+ *   Stage::GetCurrent().Add( scene3dView );\r
+ *   scene3dView.PlayAnimations();\r
+ *\r
+ *   scene3dView.SetLight( Scene3dView::LightType::DIRECTIONAL_LIGHT, Vector3( 1.0, 1.0, -1.0 ), Vector3( 0.3, 0.3, 0.3 ) );\r
+ * }\r
+ *\r
+ * @endcode\r
+ *\r
+ * @remarks This control makes 3D Layer internally. Therefore, if any 2D UI\r
+ * control is added as a child of this Scene3dView, the functionality of the 2D UI\r
+ * may not work well.\r
+ */\r
+\r
+class DALI_TOOLKIT_API Scene3dView : public Control\r
+{\r
+public:\r
+\r
+  enum LightType\r
+  {\r
+    // Scene doesn't use both of point and directional light\r
+    NONE = 0,\r
+    // Scene use point light\r
+    POINT_LIGHT,\r
+    // Scene use directional light\r
+    DIRECTIONAL_LIGHT,\r
+    // Scene use Image Based Lighting\r
+    IMAGE_BASED_LIGHT,\r
+    // Scene use Image Based Lighting and point light\r
+    IMAGE_BASED_LIGHT_AND_POINT_LIGHT,\r
+    // Scene use Image Based Lighting and directional light\r
+    IMAGE_BASED_LIGHT_AND_DIRECTIONAL_LIGHT\r
+  };\r
+\r
+  /**\r
+   * @brief Create an uninitialized Scene3dView; this can be initialized with Scene3dView::New()\r
+   * Calling member functions with an uninitialized Dali::Object is not allowed.\r
+   */\r
+  Scene3dView();\r
+\r
+  /**\r
+   * @brief Copy constructor. Creates another handle that points to the same real object\r
+   */\r
+  Scene3dView( const Scene3dView& handle );\r
+\r
+  /**\r
+   * @brief Assignment operator. Changes this handle to point to another real object\r
+   */\r
+  Scene3dView& operator=( const Scene3dView& handle );\r
+\r
+  /**\r
+   * @brief Destructor\r
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.\r
+   */\r
+  ~Scene3dView();\r
+\r
+  /**\r
+   * @brief Downcast an Object handle to Scene3dView. If handle points to a Scene3dView the\r
+   * downcast produces valid handle. If not the returned handle is left uninitialized.\r
+   * @param[in] handle Handle to an object\r
+   * @return handle to a Scene3dView or an uninitialized handle\r
+   */\r
+  static Scene3dView DownCast( BaseHandle handle );\r
+\r
+  /**\r
+   * @brief Create an initialized Scene3dView.\r
+   * @param[in] filePath File path of scene format file (e.g., glTF).\r
+   * @return A handle to a newly allocated Dali resource\r
+   */\r
+  static Scene3dView New( const std::string& filePath );\r
+\r
+  /**\r
+   * @brief Create an initialized Scene3dView.\r
+   * @param[in] filePath File path of scene format file (e.g., glTF).\r
+   * @param[in] diffuseTexturePath The texture path of diffuse cube map that used to render with Image Based Lighting.\r
+   * @param[in] specularTexturePath The texture path of specular cube map that used to render with Image Based Lighting.\r
+   * @param[in] scaleFactor Scaling factor for the Image Based Lighting.\r
+   * @return A handle to a newly allocated Dali resource\r
+   */\r
+  static Scene3dView New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor );\r
+\r
+  /**\r
+   * @brief Get animation count.\r
+   * @return number of animations.\r
+   */\r
+  uint32_t GetAnimationCount();\r
+\r
+  /**\r
+   * @brief Play an animation.\r
+   * @param[in] index Animation index\r
+   * @return true if animation is played.\r
+   */\r
+  bool PlayAnimation( uint32_t index );\r
+\r
+  /**\r
+   * @brief Play all animations.\r
+   * @return true if animations are played.\r
+   */\r
+  bool PlayAnimations();\r
+\r
+  /**\r
+   * @brief Set point light or directional light. If SetLight is not called, this scene doesn't use these kind of light.\r
+   * @param[in] type The light type. If the light is point light set this LightType::POINT_LIGHT,\r
+   * or if the light is directional light set this LightType::DIRECTIONAL_LIGHT.\r
+   * @param[in] lightVector The point light position when light type is LightType::POINT_LIGHT.\r
+   * The light direction when light type is LightType::DIRECTIONAL_LIGHT.\r
+   * @param[in] lightColor Vector3 value that denotes the light color of point light or directional light. Since this is the light color, we don't need to use alpha value.\r
+   * @return true if point light or directional light is set.\r
+   */\r
+  bool SetLight( LightType type, Vector3 lightVector, Vector3 lightColor );\r
+\r
+  /**\r
+   * @brief Get default CameraActor. Dali::Camera::Type = Dali::Camera::LOOK_AT_TARGET , near clipping plane = 0.1, and camera position = Vector3( 0.0, 0.0, 0.0 ).\r
+   * @return CameraActor.\r
+   */\r
+  CameraActor GetDefaultCamera();\r
+\r
+  /**\r
+   * @brief Get camera count.\r
+   * @return number of cameras.\r
+   */\r
+  uint32_t GetCameraCount();\r
+\r
+  /**\r
+   * @brief Get CameraActor. If there is no CameraActor in the list, then returns default CameraActor.\r
+   * @param[in] cameraIndex Index of CameraActor list.\r
+   * @return CameraActor.\r
+   */\r
+  CameraActor GetCamera( uint32_t cameraIndex );\r
+\r
+  // Not intended for developer use\r
+public:\r
+\r
+  /**\r
+   * @brief Creates a handle using the Toolkit::Internal implementation.\r
+   * @param[in]  implementation  The UI Control implementation.\r
+   */\r
+  DALI_INTERNAL Scene3dView( Toolkit::Internal::Scene3dView& implementation );\r
+\r
+  explicit DALI_INTERNAL Scene3dView( Dali::Internal::CustomActor* internal );\r
+};\r
+\r
+} // namespace Toolkit\r
+\r
+} // namespace Dali\r
+\r
+#endif // DALI_TOOLKIT_SCENE3D_VIEW_H\r
index 48e1214..3627396 100755 (executable)
@@ -19,6 +19,7 @@ devel_api_src_files = \
   $(devel_api_src_dir)/controls/page-turn-view/page-turn-view.cpp \
   $(devel_api_src_dir)/controls/popup/confirmation-popup.cpp \
   $(devel_api_src_dir)/controls/popup/popup.cpp \
+  $(devel_api_src_dir)/controls/scene3d-view/scene3d-view.cpp \
   $(devel_api_src_dir)/controls/shadow-view/shadow-view.cpp \
   $(devel_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \
   $(devel_api_src_dir)/controls/text-controls/text-editor-devel.cpp \
@@ -132,6 +133,9 @@ devel_api_visuals_header_files = \
   $(devel_api_src_dir)/visuals/text-visual-properties-devel.h \
   $(devel_api_src_dir)/visuals/visual-properties-devel.h
 
+devel_api_scene3d_view_header_files = \
+  $(devel_api_src_dir)/controls/scene3d-view/scene3d-view.h
+
 devel_api_shadow_view_header_files = \
   $(devel_api_src_dir)/controls/shadow-view/shadow-view.h
 
diff --git a/dali-toolkit/internal/controls/scene3d-view/gltf-loader.cpp b/dali-toolkit/internal/controls/scene3d-view/gltf-loader.cpp
new file mode 100644 (file)
index 0000000..4115fb7
--- /dev/null
@@ -0,0 +1,1878 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/scene3d-view/gltf-loader.h>
+#include <dali-toolkit/internal/controls/scene3d-view/gltf-shader.h>
+
+// EXTERNAL INCLUDES
+#include <fstream>
+#include <dali/integration-api/debug.h>
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/adaptor-framework/file-loader.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace Gltf
+{
+
+namespace
+{
+
+// Utility functions
+const TreeNode* Tidx( const TreeNode *node, uint32_t index )
+{
+  uint32_t i = 0;
+  for( auto it = node->CBegin(), end = node->CEnd(); it != end; ++it, ++i )
+  {
+    if( i == index )
+    {
+      return &( ( *it ).second );
+    }
+  }
+  return NULL;
+}
+
+bool ReadBool( const TreeNode* node, bool& num )
+{
+  if( !node )
+  {
+    return false;
+  }
+  bool returnValue = false;
+
+  if( node->GetType() == TreeNode::BOOLEAN )
+  {
+    num = node->GetBoolean();
+    returnValue = true;
+  }
+
+  return returnValue;
+}
+
+bool ReadInt( const TreeNode* node, int32_t& num )
+{
+  if( !node )
+  {
+    return false;
+  }
+  bool returnValue = false;
+  if( node->GetType() == TreeNode::INTEGER )
+  {
+    num = node->GetInteger();
+    returnValue = true;
+  }
+  else  if( node->GetType() == TreeNode::FLOAT )
+  {
+    num = node->GetFloat();
+    returnValue = true;
+  }
+
+  return returnValue;
+}
+
+bool ReadFloat( const TreeNode* node, float& num )
+{
+  if( !node )
+  {
+    return false;
+  }
+  bool returnValue = false;
+
+  if( node->GetType() == TreeNode::FLOAT )
+  {
+    num = node->GetFloat();
+    returnValue = true;
+  }
+  else if( node->GetType() == TreeNode::INTEGER )
+  {
+    int32_t tempNum;
+    ReadInt( node, tempNum );
+    num = static_cast<float>( tempNum );
+    returnValue = true;
+  }
+
+  return returnValue;
+}
+
+bool ReadVector( const TreeNode* node, float* num, uint32_t size )
+{
+  if( !node )
+  {
+    return false;
+  }
+  bool returnValue = false;
+
+  if( ( node->Size() >= size ) && ( node->GetType() == TreeNode::ARRAY ) )
+  {
+    uint32_t offset = 0u;
+    for( auto it = node->CBegin(); offset < size; ++it, ++offset )
+    {
+      const TreeNode& coord = ( *it ).second;
+      if( !ReadFloat( &coord, *( num + offset ) ) )
+      {
+        return false;
+      }
+    }
+    returnValue = true;
+  }
+
+  return returnValue;
+}
+
+bool ReadString( const TreeNode* node, std::string& strValue )
+{
+  if( !node )
+  {
+    return false;
+  }
+  bool returnValue = false;
+  if( node->GetType() == TreeNode::STRING )
+  {
+    strValue = node->GetString();
+    returnValue = true;
+  }
+  return returnValue;
+}
+
+template <typename T>
+float IntToFloat( T element, bool normalize )
+{
+  if( !normalize )
+  {
+    return static_cast<float>( element );
+  }
+
+  if( std::is_same<T, int8_t>::value )
+  {
+    return std::max( static_cast<float>( element ) / 127.0, -1.0 );
+  }
+  if( std::is_same<T, uint8_t>::value )
+  {
+    return static_cast<float>( element ) / 255.0;
+  }
+  if( std::is_same<T, int16_t>::value )
+  {
+    return std::max( static_cast<float>( element ) / 32767.0, -1.0 );
+  }
+  if( std::is_same<T, uint16_t>::value )
+  {
+    return static_cast<float>( element ) / 65535.0;
+  }
+  return -1.0;
+}
+
+template <typename Td, typename Ts>
+void FitBuffer( Dali::Vector<Td>& bufferDestination, Dali::Vector<Ts>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
+{
+  bufferDestination.Resize( bufferSize );
+  int32_t count = bufferSource.Size() / elementNumOfByteStride;
+  for( int32_t i = 0; i<count; ++i )
+  {
+    bufferDestination[i] = static_cast<Td>( bufferSource[i * elementNumOfByteStride] );
+  }
+}
+
+template <typename T>
+void FitBuffer( Dali::Vector<Vector2>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
+{
+  bufferDestination.Resize( bufferSize );
+  int32_t count = bufferSource.Size() / elementNumOfByteStride;
+  for( int32_t i = 0; i<count; ++i )
+  {
+    bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
+    bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
+  }
+}
+
+template <typename T>
+void FitBuffer( Dali::Vector<Vector3>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
+{
+  bufferDestination.Resize( bufferSize );
+  int32_t count = bufferSource.Size() / elementNumOfByteStride;
+  for( int32_t i = 0; i<count; ++i )
+  {
+    bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
+    bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
+    bufferDestination[i].z = IntToFloat( bufferSource[i * elementNumOfByteStride + 2], normalize );
+  }
+}
+
+template <typename T>
+void FitBuffer( Dali::Vector<Vector4>& bufferDestination, Dali::Vector<T>& bufferSource, int32_t bufferSize, int32_t elementNumOfByteStride, bool normalize )
+{
+  bufferDestination.Resize( bufferSize );
+  int32_t count = bufferSource.Size() / elementNumOfByteStride;
+  for( int32_t i = 0; i<count; ++i )
+  {
+    bufferDestination[i].x = IntToFloat( bufferSource[i * elementNumOfByteStride], normalize );
+    bufferDestination[i].y = IntToFloat( bufferSource[i * elementNumOfByteStride + 1], normalize );
+    bufferDestination[i].z = IntToFloat( bufferSource[i * elementNumOfByteStride + 2], normalize );
+    bufferDestination[i].w = IntToFloat( bufferSource[i * elementNumOfByteStride + 3], normalize );
+  }
+}
+
+// Template functions
+template <typename T>
+bool ReadBinFile( Vector<T> &dataBuffer, std::string url, int32_t offset, int32_t count )
+{
+  dataBuffer.Resize( count );
+  FILE* fp = fopen( url.c_str(), "rb" );
+  if( fp == NULL )
+  {
+    return false;
+  }
+  ssize_t result = -1;
+  if( !fseek( fp, offset, SEEK_SET ) )
+  {
+    result = fread( &dataBuffer[0], sizeof( T ), count, fp );
+  }
+  fclose( fp );
+
+  return ( result >= 0 );
+}
+
+template <typename T>
+void LoadDataFromAccessor( int32_t accessorIdx, Dali::Vector<T>& bufferData, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray )
+{
+  AccessorInfo accessor = accessorArray[accessorIdx];
+  BufferViewInfo bufferView = bufferViewArray[accessor.bufferView];
+  std::string load_uri = bufferArray[bufferView.buffer].uri;
+
+  // In the glTF 2.0 Specification, 5121 is UNSIGNED BYTE, 5123 is UNSIGNED SHORT
+  int32_t elementByteSize = ( accessor.componentType <= 5121 ) ? 1 :
+    ( ( accessor.componentType <= 5123 ) ? 2 : 4 );
+  int32_t elementNum = 1;
+  if( accessor.type == "VEC2" )
+  {
+    elementNum = 2;
+  }
+  else if( accessor.type == "VEC3" )
+  {
+    elementNum = 3;
+  }
+  else if( accessor.type == "VEC4" || accessor.type == "MAT2" )
+  {
+    elementNum = 4;
+  }
+  else if( accessor.type == "MAT3" )
+  {
+    elementNum = 9;
+  }
+  else if( accessor.type == "MAT4" )
+  {
+    elementNum = 16;
+  }
+  else
+  {
+    elementNum = 1;
+  }
+  int32_t elementNumOfByteStride = elementNum;
+  if( bufferView.byteStride > 0 )
+  {
+    elementNumOfByteStride = bufferView.byteStride / elementByteSize;
+  }
+
+  /**
+   * glTF 2.0 Specification
+   * Component Type
+   * 5120 : BYTE
+   * 5121 : UNSIGNED_BYTE
+   * 5122 : SHORT
+   * 5123 : UNSIGNED_SHORT
+   * 5125 : UNSIGNED_INT
+   * 5126 : FLOAT
+   */
+  if( accessor.componentType == 5120 )
+  {
+    Dali::Vector<int8_t> inputBufferData;
+    ReadBinFile<int8_t>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+  else if( accessor.componentType == 5121 )
+  {
+    Dali::Vector<uint8_t> inputBufferData;
+    ReadBinFile<uint8_t>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+  else if( accessor.componentType == 5122 )
+  {
+    Dali::Vector<int16_t> inputBufferData;
+    ReadBinFile<int16_t>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+  else if( accessor.componentType == 5123 )
+  {
+    Dali::Vector<uint16_t> inputBufferData;
+    ReadBinFile<uint16_t>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+  else if( accessor.componentType == 5125 )
+  {
+    Dali::Vector<uint32_t> inputBufferData;
+    ReadBinFile<uint32_t>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+  else if( accessor.componentType == 5126 )
+  {
+    Dali::Vector<float> inputBufferData;
+    ReadBinFile<float>( inputBufferData, path + load_uri, bufferView.byteOffset + accessor.byteOffset, elementNumOfByteStride * accessor.count );
+    FitBuffer( bufferData, inputBufferData, accessor.count, elementNumOfByteStride, accessor.normalized );
+  }
+}
+
+void SetMeshInfoAndCanonize( MeshInfo& meshInfo, Dali::Vector<Dali::Vector3> &vertexBufferData )
+{
+  Vector3 pointMin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() );
+  Vector3 pointMax( std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min() );
+  for( auto&& data : vertexBufferData )
+  {
+    pointMin.x = std::min( data.x, pointMin.x );
+    pointMin.y = std::min( data.y, pointMin.y );
+    pointMin.z = std::min( data.z, pointMin.z );
+
+    pointMax.x = std::max( data.x, pointMax.x );
+    pointMax.y = std::max( data.y, pointMax.y );
+    pointMax.z = std::max( data.z, pointMax.z );
+  }
+  meshInfo.size = pointMax - pointMin;
+  meshInfo.pivot.x = ( -pointMin.x ) / ( pointMax.x - pointMin.x );
+  meshInfo.pivot.y = ( -pointMin.y ) / ( pointMax.y - pointMin.y );
+  meshInfo.pivot.z = ( -pointMin.z ) / ( pointMax.z - pointMin.z );
+
+  Vector3 center = meshInfo.size * 0.5 + pointMin;
+  for( auto&& data : vertexBufferData )
+  {
+    data   = data - center;
+    data.x = data.x / meshInfo.size.x;
+    data.y = data.y / meshInfo.size.y;
+    data.z = data.z / meshInfo.size.z;
+  }
+}
+
+template <typename T>
+PropertyBuffer CreatePropertyBuffer( Vector<T> bufferData, std::string map, int32_t type )
+{
+  Property::Map positionMap;
+  positionMap[map] = type;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( positionMap );
+  propertyBuffer.SetData( bufferData.Begin(), bufferData.Count() );
+  return propertyBuffer;
+}
+
+void SetVertexBufferData( MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type )
+{
+  if( accessorIdx >= 0 )
+  {
+    Dali::Vector<Vector3> bufferData;
+    LoadDataFromAccessor( accessorIdx, bufferData, path, accessorArray, bufferViewArray, bufferArray );
+    SetMeshInfoAndCanonize( meshInfo, bufferData );
+
+    PropertyBuffer propertyBuffer = CreatePropertyBuffer<Vector3>( bufferData, map, type );
+    meshInfo.geometry.AddVertexBuffer( propertyBuffer );
+  }
+}
+
+template <typename T>
+void SetAttributeBufferData( MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t accessorIdx, std::string map, int32_t type )
+{
+  if( accessorIdx >= 0 )
+  {
+    Dali::Vector<T> bufferData;
+    LoadDataFromAccessor( accessorIdx, bufferData, path, accessorArray, bufferViewArray, bufferArray );
+
+    PropertyBuffer propertyBuffer = CreatePropertyBuffer<T>( bufferData, map, type );
+    meshInfo.geometry.AddVertexBuffer( propertyBuffer );
+  }
+}
+
+void SetIndexBuffersData( MeshInfo& meshInfo, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray, int32_t indexIdx )
+{
+  Dali::Vector<uint16_t> indexBufferData;
+  LoadDataFromAccessor( indexIdx, indexBufferData, path, accessorArray, bufferViewArray, bufferArray );
+  meshInfo.geometry.SetIndexBuffer( &indexBufferData[0], indexBufferData.Size() );
+}
+
+template<typename T>
+float LoadKeyFrames( const AnimationSamplerInfo& currentSampler, const Property::Index propIndex, KeyFrames& keyframes, std::string path, std::vector<AccessorInfo>& accessorArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<BufferInfo>& bufferArray )
+{
+  Dali::Vector<float> inputBufferData;
+  Dali::Vector<T> outputBufferData;
+
+  LoadDataFromAccessor<float>( currentSampler.input, inputBufferData, path, accessorArray, bufferViewArray, bufferArray );
+  LoadDataFromAccessor<T>( currentSampler.output, outputBufferData, path, accessorArray, bufferViewArray, bufferArray );
+
+  uint32_t keyframeNum = inputBufferData.Size();
+  float lengthAnimation = inputBufferData[inputBufferData.Size() - 1];
+  for( uint32_t i = 0; i < keyframeNum; i++ )
+  {
+    if( propIndex == Dali::Actor::Property::ORIENTATION )
+    {
+      Vector4 vectorOrientation( outputBufferData[i] );
+      float vW = vectorOrientation.w;
+      vW = ( vW < 0.0f ) ? std::max( vW, -1.0f ) : std::min( vW, 1.0f );
+      vectorOrientation.w = vW;
+      keyframes.Add( inputBufferData[i] / lengthAnimation, Quaternion( Vector4( vectorOrientation ) ) );
+    }
+    else if( propIndex == Dali::Actor::Property::POSITION )
+    {
+      keyframes.Add( inputBufferData[i] / lengthAnimation, Vector3( outputBufferData[i] ) );
+    }
+    else if( propIndex == Dali::Actor::Property::SCALE )
+    {
+      keyframes.Add( inputBufferData[i] / lengthAnimation, Vector3( outputBufferData[i] ) );
+    }
+  }
+  return lengthAnimation;
+}
+
+bool LoadBuffer( const TreeNode& buffer, std::vector<BufferInfo>& bufferArray )
+{
+  BufferInfo bufferInfo;
+
+  const TreeNode* uriNode = buffer.GetChild( "uri" );
+  if( uriNode )
+  {
+    ReadString( uriNode, bufferInfo.uri );
+  }
+
+  const TreeNode* byteLengthNode = buffer.GetChild( "byteLength" );
+  if( byteLengthNode )
+  {
+    ReadInt( byteLengthNode, bufferInfo.byteLength );
+    if( bufferInfo.byteLength < 0 )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* nameNode = buffer.GetChild( "name" );
+  if( nameNode )
+  {
+    ReadString( nameNode, bufferInfo.name );
+  }
+
+  bufferArray.push_back( bufferInfo );
+
+  return true;
+}
+
+bool LoadBufferView( const TreeNode& buffer, std::vector<BufferViewInfo>& bufferViewArray )
+{
+  BufferViewInfo bufferViewInfo;
+
+  const TreeNode* bufferNode = buffer.GetChild( "buffer" );
+  if( bufferNode )
+  {
+    ReadInt( bufferNode, bufferViewInfo.buffer );
+    if( bufferViewInfo.buffer < 0 )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* byteOffsetNode = buffer.GetChild( "byteOffset" );
+  if( byteOffsetNode )
+  {
+    ReadInt( byteOffsetNode, bufferViewInfo.byteOffset );
+  }
+
+  const TreeNode* byteLengthNode = buffer.GetChild( "byteLength" );
+  if( byteLengthNode )
+  {
+    ReadInt( byteLengthNode, bufferViewInfo.byteLength );
+    if( bufferViewInfo.byteLength < 0 )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* byteStrideNode = buffer.GetChild( "byteStride" );
+  if( byteStrideNode )
+  {
+    ReadInt( byteStrideNode, bufferViewInfo.byteStride );
+  }
+
+  const TreeNode* targetNode = buffer.GetChild( "target" );
+  if( targetNode )
+  {
+    ReadInt( targetNode, bufferViewInfo.target );
+  }
+
+  const TreeNode* nameNode = buffer.GetChild( "name" );
+  if( nameNode )
+  {
+    ReadString( nameNode, bufferViewInfo.name );
+  }
+
+  bufferViewArray.push_back( bufferViewInfo );
+
+  return true;
+}
+
+bool LoadAccessor( const TreeNode& buffer, std::vector<AccessorInfo>& accessorArray )
+{
+  AccessorInfo accessorInfo;
+
+  const TreeNode* bufferViewNode = buffer.GetChild( "bufferView" );
+  if( bufferViewNode )
+  {
+    ReadInt( bufferViewNode, accessorInfo.bufferView );
+  }
+
+  const TreeNode* byteOffsetNode = buffer.GetChild( "byteOffset" );
+  if( byteOffsetNode )
+  {
+    ReadInt( byteOffsetNode, accessorInfo.byteOffset );
+  }
+
+  const TreeNode* componentTypeNode = buffer.GetChild( "componentType" );
+  if( componentTypeNode )
+  {
+    ReadInt( componentTypeNode, accessorInfo.componentType );
+    if( accessorInfo.componentType < 0 )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* normalizedNode = buffer.GetChild( "normalized" );
+  if( normalizedNode )
+  {
+    ReadBool( normalizedNode, accessorInfo.normalized );
+  }
+
+  const TreeNode* countNode = buffer.GetChild( "count" );
+  if( countNode )
+  {
+    ReadInt( countNode, accessorInfo.count );
+    if( accessorInfo.count < 0 )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* typeNode = buffer.GetChild( "type" );
+  if( typeNode )
+  {
+    ReadString( typeNode, accessorInfo.type );
+    if( accessorInfo.type == "" )
+    {
+      return false;
+    }
+  }
+
+  const TreeNode* maxNode = buffer.GetChild( "max" );
+  if( maxNode )
+  {
+    ReadInt( maxNode, accessorInfo.max );
+  }
+
+  const TreeNode* minNode = buffer.GetChild( "min" );
+  if( minNode )
+  {
+    ReadInt( minNode, accessorInfo.min );
+  }
+
+  const TreeNode* nameNode = buffer.GetChild( "name" );
+  if( nameNode )
+  {
+    ReadString( nameNode, accessorInfo.name );
+  }
+
+  accessorArray.push_back( accessorInfo );
+
+  return true;
+}
+
+bool LoadBinaryData( const TreeNode& root, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray )
+{
+  const TreeNode* buffersNode = root.GetChild( "buffers" );
+  if( !buffersNode )
+  {
+    return false;
+  }
+  for( auto bufferIter = buffersNode->CBegin(), end = buffersNode->CEnd(); bufferIter != end; ++bufferIter )
+  {
+    LoadBuffer( ( *bufferIter ).second, bufferArray );
+  }
+
+  const TreeNode* bufferViewsNode = root.GetChild( "bufferViews" );
+  if( !bufferViewsNode )
+  {
+    return false;
+  }
+  for( auto bufferViewIter = bufferViewsNode->CBegin(), end = bufferViewsNode->CEnd(); bufferViewIter != end; ++bufferViewIter )
+  {
+    LoadBufferView( ( *bufferViewIter ).second, bufferViewArray );
+  }
+
+  const TreeNode* accessorsNode = root.GetChild( "accessors" );
+  if( !accessorsNode )
+  {
+    return false;
+  }
+  for( auto accesorIter = accessorsNode->CBegin(), end = accessorsNode->CEnd(); accesorIter != end; ++accesorIter )
+  {
+    LoadAccessor( ( *accesorIter ).second, accessorArray );
+  }
+
+  return true;
+}
+
+FilterMode::Type GetFilterMode( uint32_t mode )
+{
+  FilterMode::Type retValue = FilterMode::DEFAULT;
+  /**
+   * glTF 2.0 Specification
+   * Filter Code
+   * 9728 : NEAREST
+   * 9729 : LINEAR
+   * 9984 : NEAREST_MIPMAP_NEAREST
+   * 9985 : LINEAR_MIPMAP_NEAREST
+   * 9986 : NEAREST_MIPMAP_LINEAR
+   * 9987 : LINEAR_MIPMAP_LINEAR
+   */
+  switch( mode )
+  {
+    case 9728:
+    {
+      retValue = FilterMode::NEAREST;
+      break;
+    }
+    case 9729:
+    {
+      retValue = FilterMode::LINEAR;
+      break;
+    }
+    case 9984:
+    {
+      retValue = FilterMode::NEAREST_MIPMAP_NEAREST;
+      break;
+    }
+    case 9985:
+    {
+      retValue = FilterMode::LINEAR_MIPMAP_NEAREST;
+      break;
+    }
+    case 9986:
+    {
+      retValue = FilterMode::NEAREST_MIPMAP_LINEAR;
+      break;
+    }
+    case 9987:
+    {
+      retValue = FilterMode::LINEAR_MIPMAP_LINEAR;
+      break;
+    }
+  }
+
+  return retValue;
+}
+
+WrapMode::Type GetWrapMode( uint32_t mode )
+{
+  WrapMode::Type retValue = WrapMode::REPEAT;
+  /**
+   * glTF 2.0 Specification
+   * Wrapping mode Code
+   * 33071 : CLAMP_TO_EDGE
+   * 33648 : MIRRORED_REPEAT
+   * 10497 : REPEAT
+   */
+  switch( mode )
+  {
+    case 33071:
+    {
+      retValue = WrapMode::CLAMP_TO_EDGE;
+      break;
+    }
+    case 33648:
+    {
+      retValue = WrapMode::MIRRORED_REPEAT;
+      break;
+    }
+    case 10497:
+    {
+      retValue = WrapMode::REPEAT;
+      break;
+    }
+  }
+
+  return retValue;
+}
+
+Texture LoadTexture( const char* imageUrl, bool generateMipmaps )
+{
+  Texture texture;
+  Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
+  if( pixelBuffer )
+  {
+    texture = Texture::New( TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
+    PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
+    texture.Upload( pixelData );
+
+    if( generateMipmaps )
+    {
+      texture.GenerateMipmaps();
+    }
+  }
+
+  return texture;
+}
+
+Sampler LoadSampler( const TreeNode& samplerNode )
+{
+  Sampler sampler = Sampler::New();
+
+  FilterMode::Type minFilter = FilterMode::DEFAULT;
+  FilterMode::Type magFilter = FilterMode::DEFAULT;
+  const TreeNode* magFilterNode = samplerNode.GetChild( "magFilter" );
+  if( magFilterNode )
+  {
+    int32_t magFilter_integer = 0;
+    ReadInt( magFilterNode, magFilter_integer );
+    magFilter = GetFilterMode( magFilter_integer );
+  }
+
+  const TreeNode* minFilterNode = samplerNode.GetChild( "minFilter" );
+  if( minFilterNode )
+  {
+    int32_t minFilter_integer = 0;
+    ReadInt( minFilterNode, minFilter_integer );
+    minFilter = GetFilterMode( minFilter_integer );
+  }
+
+  WrapMode::Type wrapR = WrapMode::REPEAT;
+  WrapMode::Type wrapS = WrapMode::REPEAT;
+  WrapMode::Type wrapT = WrapMode::REPEAT;
+  const TreeNode* wrapNode = samplerNode.GetChild( "wrapS" );
+  if( wrapNode )
+  {
+    wrapS = GetWrapMode( wrapNode->GetInteger() );
+  }
+
+  wrapNode = samplerNode.GetChild( "wrapT" );
+  if( wrapNode )
+  {
+    wrapT = GetWrapMode( wrapNode->GetInteger() );
+  }
+
+  sampler.SetFilterMode( minFilter, magFilter );
+  sampler.SetWrapMode( wrapR, wrapS, wrapT );
+
+  return sampler;
+}
+
+bool LoadTextureArray( const TreeNode& root, std::string path, std::vector<Texture>& sourceArray, std::vector<Sampler>& samplerArray, std::vector<TextureInfo>& textureArray )
+{
+  const TreeNode* imagesNode = root.GetChild( "images" );
+  if( imagesNode )
+  {
+    for( auto imageIter = imagesNode->CBegin(), end = imagesNode->CEnd(); imageIter != end; ++imageIter )
+    {
+      std::string imageUrl;
+      const TreeNode* uriNode = ( &( ( *imageIter ).second ) )->GetChild( "uri" );
+      if( uriNode )
+      {
+        std::string uri;
+        ReadString( uriNode, uri );
+        imageUrl = path + uri;
+      }
+
+      sourceArray.push_back( LoadTexture( imageUrl.c_str(), true ) );
+    }
+  }
+
+  const TreeNode* samplersNode = root.GetChild( "samplers" );
+  if( samplersNode )
+  {
+    for( auto samplerIter = samplersNode->CBegin(), end = samplersNode->CEnd(); samplerIter != end; ++samplerIter )
+    {
+      samplerArray.push_back( LoadSampler( ( ( *samplerIter ).second ) ) );
+    }
+  }
+
+  const TreeNode* texturesNode = root.GetChild( "textures" );
+  if( texturesNode )
+  {
+    for( auto textureIter = texturesNode->CBegin(), end = texturesNode->CEnd(); textureIter != end; ++textureIter )
+    {
+      const TreeNode* TextureNode = &( ( *textureIter ).second );
+
+      TextureInfo texture;
+      const TreeNode* sourceNode = TextureNode->GetChild( "source" );
+      if( sourceNode )
+      {
+        ReadInt( sourceNode, texture.sourceIdx );
+      }
+
+      const TreeNode* samplerNode = TextureNode->GetChild( "sampler" );
+      if( samplerNode )
+      {
+        ReadInt( samplerNode, texture.samplerIdx );
+      }
+
+      textureArray.push_back( texture );
+    }
+  }
+  return true;
+}
+
+bool LoadPbrMetallicRoughness( const TreeNode& material, MaterialInfo& materialInfo )
+{
+  float floatVec[4];
+  const TreeNode* pbrMetallicRoughnessNode = material.GetChild( "pbrMetallicRoughness" );
+  if( !pbrMetallicRoughnessNode )
+  {
+    return true;
+  }
+
+  const TreeNode* tempNode;
+  tempNode = pbrMetallicRoughnessNode->GetChild( "metallicFactor" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, materialInfo.metallicFactor );
+  }
+
+  tempNode = pbrMetallicRoughnessNode->GetChild( "roughnessFactor" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, materialInfo.roughnessFactor );
+  }
+
+  tempNode = pbrMetallicRoughnessNode->GetChild( "baseColorFactor" );
+  if( tempNode && ReadVector( tempNode, floatVec, 4 ) )
+  {
+    materialInfo.baseColorFactor = Vector4( floatVec[0], floatVec[1], floatVec[2], floatVec[3] );
+  }
+
+  const TreeNode* baseColorTextureNode = pbrMetallicRoughnessNode->GetChild( "baseColorTexture" );
+  if( baseColorTextureNode )
+  {
+    tempNode = baseColorTextureNode->GetChild( "index" );
+    if( tempNode )
+    {
+      materialInfo.baseColorTexture.index = tempNode->GetInteger();
+    }
+
+    tempNode = baseColorTextureNode->GetChild( "texCoord" );
+    if( tempNode )
+    {
+      materialInfo.baseColorTexture.texCoord = tempNode->GetInteger();
+    }
+  }
+
+  const TreeNode* metallicRoughnessTextureNode = pbrMetallicRoughnessNode->GetChild( "metallicRoughnessTexture" );
+  if( metallicRoughnessTextureNode )
+  {
+    tempNode = metallicRoughnessTextureNode->GetChild( "index" );
+    if( tempNode )
+    {
+      materialInfo.metallicRoughnessTexture.index = tempNode->GetInteger();
+    }
+
+    tempNode = metallicRoughnessTextureNode->GetChild( "texCoord" );
+    if( tempNode )
+    {
+      materialInfo.metallicRoughnessTexture.texCoord = tempNode->GetInteger();
+    }
+  }
+
+  return true;
+}
+
+bool LoadMaterialSetArray( const TreeNode& root, std::vector<MaterialInfo>& materialArray )
+{
+  const TreeNode* materialsNode = root.GetChild( "materials" );
+  if( !materialsNode )
+  {
+    return false;
+  }
+
+  for( auto materialIter = materialsNode->CBegin(), end = materialsNode->CEnd(); materialIter != end; ++materialIter )
+  {
+    MaterialInfo materialInfo;
+    LoadPbrMetallicRoughness( ( ( *materialIter ).second ), materialInfo );
+
+    const TreeNode* materialNode = &( ( *materialIter ).second );
+    const TreeNode* tempNode = materialNode->GetChild( "name" );
+    if( tempNode )
+    {
+      ReadString( tempNode, materialInfo.name );
+    }
+
+    materialInfo.alphaMode = "OPAQUE";
+    tempNode = materialNode->GetChild( "alphaMode" );
+    if( tempNode )
+    {
+      ReadString( tempNode, materialInfo.alphaMode );
+    }
+
+    materialInfo.alphaCutoff = 1.0;
+    tempNode = materialNode->GetChild( "alphaCutoff" );
+    if( tempNode )
+    {
+      ReadFloat( tempNode, materialInfo.alphaCutoff );
+    }
+
+    materialInfo.doubleSided = false;
+    tempNode = materialNode->GetChild( "doubleSided" );
+    if( tempNode )
+    {
+      ReadBool( tempNode, materialInfo.doubleSided );
+    }
+
+    float floatVec[3];
+    tempNode = materialNode->GetChild( "emissiveFactor" );
+    if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
+    {
+      materialInfo.emissiveFactor = Vector3( floatVec[0], floatVec[1], floatVec[2] );
+    }
+
+    const TreeNode* texture = materialNode->GetChild( "normalTexture" );
+    if( texture )
+    {
+      tempNode = texture->GetChild( "index" );
+      if( tempNode )
+      {
+        materialInfo.normalTexture.index = tempNode->GetInteger();
+      }
+
+      tempNode = texture->GetChild( "texCoord" );
+      if( tempNode )
+      {
+        materialInfo.normalTexture.texCoord = tempNode->GetInteger();
+      }
+
+      materialInfo.normalTexture.value = 1.0;
+      tempNode = texture->GetChild( "scale" );
+      if( tempNode )
+      {
+        ReadFloat( tempNode, materialInfo.normalTexture.value );
+      }
+    }
+
+    texture = materialNode->GetChild( "occlusionTexture" );
+    if( texture )
+    {
+      tempNode = texture->GetChild( "index" );
+      if( tempNode )
+      {
+        materialInfo.occlusionTexture.index = tempNode->GetInteger();
+      }
+
+      tempNode = texture->GetChild( "texCoord" );
+      if( tempNode )
+      {
+        materialInfo.occlusionTexture.texCoord = tempNode->GetInteger();
+      }
+
+
+      tempNode = texture->GetChild( "strength" );
+      if( tempNode )
+      {
+        ReadFloat( tempNode, materialInfo.occlusionTexture.value );
+      }
+    }
+
+    texture = materialNode->GetChild( "emissiveTexture" );
+    if( texture )
+    {
+      tempNode = texture->GetChild( "index" );
+      if( tempNode )
+      {
+        materialInfo.emissiveTexture.index = tempNode->GetInteger();
+      }
+
+      tempNode = texture->GetChild( "texCoord" );
+      if( tempNode )
+      {
+        materialInfo.emissiveTexture.texCoord = tempNode->GetInteger();
+      }
+    }
+    materialArray.push_back( materialInfo );
+  }
+  return true;
+}
+
+bool LoadAttribute( const TreeNode* primitive, MeshInfo& meshInfo )
+{
+  const TreeNode* attrbuteNode = primitive->GetChild( "attributes" );
+  if( !attrbuteNode )
+  {
+    return false;
+  }
+
+  const TreeNode* tempNode;
+  tempNode = attrbuteNode->GetChild( "POSITION" );
+  if( tempNode )
+  {
+    meshInfo.attribute.POSITION = tempNode->GetInteger();
+  }
+
+  tempNode = attrbuteNode->GetChild( "NORMAL" );
+  if( tempNode )
+  {
+    meshInfo.attribute.NORMAL = tempNode->GetInteger();
+  }
+
+  tempNode = attrbuteNode->GetChild( "TANGENT" );
+  if( tempNode )
+  {
+    meshInfo.attribute.TANGENT = tempNode->GetInteger();
+  }
+
+  uint32_t index = 0;
+  meshInfo.attribute.TEXCOORD.clear();
+  tempNode = attrbuteNode->GetChild( "TEXCOORD_" + std::to_string( index ) );
+  while( tempNode )
+  {
+    uint32_t value = tempNode->GetInteger();
+    meshInfo.attribute.TEXCOORD.push_back( value );
+    tempNode = attrbuteNode->GetChild( "TEXCOORD_" + std::to_string( ++index ) );
+  }
+
+  index = 0;
+  meshInfo.attribute.COLOR.clear();
+  tempNode = attrbuteNode->GetChild( "COLOR_" + std::to_string( index ) );
+  while( tempNode )
+  {
+    uint32_t value = tempNode->GetInteger();
+    meshInfo.attribute.COLOR.push_back( value );
+    tempNode = attrbuteNode->GetChild( "COLOR" + std::to_string( ++index ) );
+  }
+
+  return true;
+}
+
+bool LoadPrimitive( const TreeNode& mesh, MeshInfo& meshInfo )
+{
+  const TreeNode* primitivesNode = mesh.GetChild( "primitives" );
+  if( !primitivesNode )
+  {
+    return false;
+  }
+
+  for( auto primitiveIter = primitivesNode->CBegin(), end = primitivesNode->CEnd(); primitiveIter != end; ++primitiveIter )
+  {
+    const TreeNode* primitiveNode = ( &( *primitiveIter ).second );
+    const TreeNode* tempNode;
+
+    tempNode = primitiveNode->GetChild( "indices" );
+    if( tempNode )
+    {
+      meshInfo.indicesIdx = tempNode->GetInteger();
+    }
+
+    tempNode = primitiveNode->GetChild( "material" );
+    if( tempNode )
+    {
+      meshInfo.materialsIdx = tempNode->GetInteger();
+    }
+
+    tempNode = primitiveNode->GetChild( "mode" );
+    if( tempNode )
+    {
+      meshInfo.mode = tempNode->GetInteger();
+    }
+
+    LoadAttribute( primitiveNode, meshInfo );
+  }
+
+  return true;
+}
+
+bool SetGeometry( MeshInfo& meshInfo, std::string path, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray )
+{
+  int32_t indicesIdx = meshInfo.indicesIdx;
+
+  if( meshInfo.mode != 0 )
+  {
+    meshInfo.geometry.SetType( ( Dali::Geometry::Type )meshInfo.mode );
+  }
+
+  if( indicesIdx >= 0 )
+  {
+    SetIndexBuffersData( meshInfo, path, accessorArray, bufferViewArray, bufferArray, indicesIdx );
+  }
+
+  SetVertexBufferData( meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.POSITION, "aPosition", Property::VECTOR3 );
+  SetAttributeBufferData<Vector3>( meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.NORMAL, "aNormal", Property::VECTOR3 );
+  SetAttributeBufferData<Vector4>( meshInfo, path, accessorArray, bufferViewArray, bufferArray, meshInfo.attribute.TANGENT, "aTangent", Property::VECTOR4 );
+
+  for( uint32_t i = 0; i < meshInfo.attribute.TEXCOORD.size(); ++i )
+  {
+    int32_t accessorIdx = meshInfo.attribute.TEXCOORD[i];
+    std::ostringstream texCoordString;
+    texCoordString << "aTexCoord" << i;
+    SetAttributeBufferData<Vector2>( meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, texCoordString.str(), Property::VECTOR2 );
+  }
+
+  for( auto&& accessorIdx : meshInfo.attribute.COLOR )
+  {
+    if( accessorIdx < 0 )
+    {
+      break;
+    }
+
+    if( accessorArray[accessorIdx].type == "VEC3" )
+    {
+      Dali::Vector<Vector3> inputBufferData;
+      LoadDataFromAccessor( accessorIdx, inputBufferData, path, accessorArray, bufferViewArray, bufferArray );
+
+      Dali::Vector<Vector4> bufferData;
+      bufferData.Resize( inputBufferData.Size() );
+      for( uint32_t i = 0; i<inputBufferData.Size(); ++i )
+      {
+        bufferData[i].x = inputBufferData[i].x;
+        bufferData[i].y = inputBufferData[i].y;
+        bufferData[i].z = inputBufferData[i].z;
+        bufferData[i].w = 1.0;
+      }
+      PropertyBuffer propertyBuffer = CreatePropertyBuffer<Vector4>( bufferData, "aVertexColor", Property::VECTOR4 );
+      meshInfo.geometry.AddVertexBuffer( propertyBuffer );
+    }
+    else if( accessorArray[accessorIdx].type == "VEC4" )
+    {
+      SetAttributeBufferData<Vector4>( meshInfo, path, accessorArray, bufferViewArray, bufferArray, accessorIdx, "aVertexColor", Property::VECTOR4 );
+    }
+  }
+  return true;
+}
+
+bool LoadMeshArray( const TreeNode& root, std::string path, std::vector<MeshInfo>& meshArray, std::vector<BufferInfo>& bufferArray, std::vector<BufferViewInfo>& bufferViewArray, std::vector<AccessorInfo>& accessorArray )
+{
+  const TreeNode* meshesNode = root.GetChild( "meshes" );
+  if( !meshesNode )
+  {
+    return false;
+  }
+
+  for( auto meshIter = meshesNode->CBegin(), end = meshesNode->CEnd(); meshIter != end; ++meshIter )
+  {
+    MeshInfo meshInfo;
+    const TreeNode* nameNode = ( &( *meshIter ).second )->GetChild( "name" );
+    if( nameNode )
+    {
+      ReadString( nameNode, meshInfo.name );
+    }
+    meshInfo.geometry = Geometry::New();
+
+    //Need to add weights for Morph targets.
+    LoadPrimitive( ( *meshIter ).second, meshInfo );
+    SetGeometry( meshInfo, path, bufferArray, bufferViewArray, accessorArray );
+    meshArray.push_back( meshInfo );
+  }
+
+  return true;
+}
+
+} // namespace
+
+Loader::Loader()
+  : mNodes( NULL ),
+  mRoot( NULL )
+{
+}
+
+Loader::~Loader()
+{
+}
+
+bool Loader::LoadScene( const std::string& filePath, Internal::Scene3dView& scene3dView )
+{
+  // Extracting directory path from full path to load resources.
+  if( std::string::npos != filePath.rfind('/') )
+  {
+    mPath = filePath.substr( 0, filePath.rfind('/') ) + "/";
+  }
+
+  if( !ParseGltf( filePath ) )
+  {
+    DALI_LOG_ERROR( "Fail to parse json file\n" );
+    return false;
+  }
+
+  mRoot = mParser.GetRoot();
+  if( mRoot &&
+      LoadAssets() &&
+      CreateScene( scene3dView ) )
+  {
+    return true;
+  }
+  return false;
+}
+
+bool Loader::ParseGltf( const std::string& filePath )
+{
+  std::ifstream fileStream( filePath.c_str() );
+  std::string fileBuffer( ( std::istreambuf_iterator<char>( fileStream ) ),
+    ( std::istreambuf_iterator<char>() ) );
+  mParser = Dali::Toolkit::JsonParser::New();
+
+  return mParser.Parse( fileBuffer );
+}
+
+bool Loader::LoadAssets()
+{
+  if( LoadBinaryData( *mRoot, mBufferArray, mBufferViewArray, mAccessorArray ) &&
+      LoadTextureArray( *mRoot, mPath, mSourceArray, mSamplerArray, mTextureArray ) &&
+      LoadMaterialSetArray( *mRoot, mMaterialArray ) &&
+      LoadMeshArray( *mRoot, mPath, mMeshArray, mBufferArray, mBufferViewArray, mAccessorArray )
+    )
+  {
+    return true;
+  }
+  return false;
+}
+
+bool Loader::CreateScene( Internal::Scene3dView& scene3dView )
+{
+  scene3dView.SetDefaultCamera( Dali::Camera::LOOK_AT_TARGET, 0.01, Vector3::ZERO );
+  LoadCamera( scene3dView );
+
+  if( LoadSceneNodes( scene3dView ) &&
+      LoadAnimation( scene3dView ) )
+  {
+    return true;
+  }
+  return false;
+}
+
+void Loader::LoadCamera( Scene3dView& scene3dView )
+{
+  const TreeNode* camerasNode = mRoot->GetChild( "cameras" );
+  if( !camerasNode )
+  {
+    return;
+  }
+
+  for( auto cameraIter = camerasNode->CBegin(), end = camerasNode->CEnd(); cameraIter != end; ++cameraIter )
+  {
+    const TreeNode* tempNode = ( &( *cameraIter ).second )->GetChild( "name" );
+    CameraInfo cameraInfo;
+    if( tempNode )
+    {
+      ReadString( tempNode, cameraInfo.name );
+    }
+
+    tempNode = ( &( *cameraIter ).second )->GetChild( "type" );
+    if( tempNode )
+    {
+      ReadString( tempNode, cameraInfo.type );
+    }
+
+    CameraActor cameraActor = CameraActor::New();
+    cameraActor.SetParentOrigin( ParentOrigin::CENTER );
+    cameraActor.SetAnchorPoint( AnchorPoint::CENTER );
+
+    if( cameraInfo.type == "orthographic" )
+    {
+      LoadOrthoGraphic( ( *cameraIter ).second, cameraInfo );
+      float xMag_2 = cameraInfo.orthographic.xmag / 2.0;
+      float yMag_2 = cameraInfo.orthographic.ymag / 2.0;
+      cameraActor.SetOrthographicProjection( -xMag_2, xMag_2, yMag_2, -yMag_2,
+                                             cameraInfo.orthographic.znear, cameraInfo.orthographic.zfar );
+    }
+    else if( cameraInfo.type == "perspective" )
+    {
+      if( !LoadPerspective( ( *cameraIter ).second, cameraInfo ) )
+      {
+        return;
+      }
+      cameraActor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
+      cameraActor.SetFieldOfView( cameraInfo.perspective.yfov );
+      cameraActor.SetNearClippingPlane( cameraInfo.perspective.znear );
+
+      if( cameraInfo.perspective.zfar > 0.0 )
+      {
+        cameraActor.SetFarClippingPlane( cameraInfo.perspective.zfar );
+      }
+      if( cameraInfo.perspective.aspectRatio > 0.0 )
+      {
+        cameraActor.SetAspectRatio( cameraInfo.perspective.aspectRatio );
+      }
+    }
+
+    scene3dView.AddCamera( cameraActor );
+  }
+}
+
+bool Loader::LoadOrthoGraphic( const TreeNode& camera, CameraInfo& cameraInfo )
+{
+  const TreeNode* orthographicNode = camera.GetChild( "orthographic" );
+  if( !orthographicNode )
+  {
+    return false;
+  }
+
+  const TreeNode* tempNode;
+  tempNode = orthographicNode->GetChild( "xmag" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.orthographic.xmag );
+  }
+
+  tempNode = orthographicNode->GetChild( "ymag" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.orthographic.ymag );
+  }
+
+  tempNode = orthographicNode->GetChild( "zfar" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.orthographic.zfar );
+  }
+
+  tempNode = orthographicNode->GetChild( "znear" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.orthographic.znear );
+  }
+
+  return true;
+}
+
+bool Loader::LoadPerspective( const TreeNode& camera, CameraInfo& cameraInfo )
+{
+  const TreeNode* perspectiveNode = camera.GetChild( "perspective" );
+  if( !perspectiveNode )
+  {
+    return false;
+  }
+
+  const TreeNode* tempNode;
+  tempNode = perspectiveNode->GetChild( "aspectRatio" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.perspective.aspectRatio );
+  }
+
+  tempNode = perspectiveNode->GetChild( "yfov" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.perspective.yfov );
+  }
+
+  tempNode = perspectiveNode->GetChild( "zfar" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.perspective.zfar );
+  }
+
+  tempNode = perspectiveNode->GetChild( "znear" );
+  if( tempNode )
+  {
+    ReadFloat( tempNode, cameraInfo.perspective.znear );
+  }
+
+  return true;
+}
+
+bool Loader::LoadSceneNodes( Scene3dView& scene3dView )
+{
+  const TreeNode* sceneNode = mRoot->GetChild( "scene" );
+  uint32_t sceneNum = 0;
+  if( sceneNode )
+  {
+    sceneNum = sceneNode->GetInteger();
+  }
+
+  const TreeNode* scenesNode = mRoot->GetChild( "scenes" );
+  if( !( scenesNode && ( mNodes = mRoot->GetChild( "nodes" ) ) ) )
+  {
+    return false;
+  }
+
+  const TreeNode* tempNode = Tidx( scenesNode, sceneNum );
+  if( !tempNode )
+  {
+    return false;
+  }
+
+  tempNode = tempNode->GetChild( "nodes" );
+  if( !tempNode )
+  {
+    return false;
+  }
+
+  for( auto nodeIter = tempNode->CBegin(), end = tempNode->CEnd(); nodeIter != end; ++nodeIter )
+  {
+    Actor actor = AddNode( scene3dView, ( ( *nodeIter ).second ).GetInteger() );
+    actor.SetParentOrigin( ParentOrigin::CENTER );
+    scene3dView.GetRoot().Add( actor );
+  }
+
+  return true;
+}
+
+Actor Loader::AddNode( Scene3dView& scene3dView, uint32_t index )
+{
+  const TreeNode* node = Tidx( mNodes, index );
+  Actor actor = Actor::New();
+  Vector3 actorSize( Vector3::ONE );
+
+  Vector3 translation = Vector3( 0.0, 0.0, 0.0 );
+  Vector3 scale = Vector3( 1.0, 1.0, 1.0 );
+  Quaternion orientation( Vector4( 0.0, 0.0, 0.0, 1.0 ) );
+
+  Vector3 anchorPoint = AnchorPoint::CENTER;
+
+  const TreeNode* tempNode = NULL;
+  if( ( tempNode = node->GetChild( "translation" ) ) )
+  {
+    float floatVec[3] = { 0.0, 0.0, 0.0 };
+    if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
+    {
+      translation = Vector3( floatVec[0], floatVec[1], floatVec[2] );
+    }
+  }
+
+  if( ( tempNode = node->GetChild( "scale" ) ) )
+  {
+    float floatVec[3] = { 1.0, 1.0, 1.0 };
+    if( tempNode && ReadVector( tempNode, floatVec, 3 ) )
+    {
+      scale = Vector3( floatVec[0], floatVec[1], floatVec[2] );
+    }
+  }
+
+  if( ( tempNode = node->GetChild( "rotation" ) ) )
+  {
+    float floatVec[4] = { 0.0, 0.0, 0.0, 1.0 };
+    if( tempNode && ReadVector( tempNode, floatVec, 4 ) )
+    {
+      orientation = Quaternion( Vector4( floatVec[0], floatVec[1], floatVec[2], floatVec[3] ) );
+    }
+  }
+
+  if( ( tempNode = node->GetChild( "matrix" ) ) )
+  {
+    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 };
+    if( tempNode && ReadVector( tempNode, floatVec, 16 ) )
+    {
+      Matrix nodeMatrix = Matrix( floatVec );
+      nodeMatrix.GetTransformComponents( translation, orientation, scale );
+    }
+  }
+
+  if( ( tempNode = node->GetChild( "mesh" ) ) )
+  {
+    MeshInfo meshInfo = mMeshArray[tempNode->GetInteger()];
+    bool isMaterial = ( meshInfo.materialsIdx >= 0 );
+
+    TextureSet textureSet;
+    textureSet = TextureSet::New();
+
+    int32_t addIdx = 0;
+    int32_t shaderTypeIndex = 0;
+    int32_t maxMipmapLevel = 0;
+    bool isBaseColorTexture = false;
+    bool isMetallicRoughnessTexture = false;
+    bool isNormalTexture = false;
+    bool isOcclusionTexture = false;
+    bool isEmissiveTexture = false;
+
+    std::string VERTEX_SHADER, FRAGMENT_SHADER;
+    VERTEX_SHADER = GLES_VERSION_300;
+    VERTEX_SHADER += PHYSICALLY_BASED_VERTEX_SHADER;
+    FRAGMENT_SHADER = GLES_VERSION_300;
+
+    bool useIBL = ( scene3dView.GetLightType() >= Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT );
+    if( isMaterial )
+    {
+      MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
+      if( SetTextureAndSampler( textureSet, materialInfo.baseColorTexture.index, FRAGMENT_SHADER, DEFINE_BASECOLOR_TEXTURE, addIdx ) )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::BASECOLOR_SHADER );
+        isBaseColorTexture = true;
+      }
+      if( SetTextureAndSampler( textureSet, materialInfo.metallicRoughnessTexture.index, FRAGMENT_SHADER, DEFINE_METALLICROUGHNESS_TEXTURE, addIdx ) )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::METALLICROUGHNESS_SHADER );
+        isMetallicRoughnessTexture = true;
+      }
+      if( SetTextureAndSampler( textureSet, materialInfo.normalTexture.index, FRAGMENT_SHADER, DEFINE_NORMAL_TEXTURE, addIdx ) )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::NORMAL_SHADER );
+        isNormalTexture = true;
+      }
+      if( SetTextureAndSampler( textureSet, materialInfo.occlusionTexture.index, FRAGMENT_SHADER, DEFINE_OCCLUSION_TEXTURE, addIdx ) )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::OCCLUSION_SHADER );
+        isOcclusionTexture = true;
+      }
+      if( SetTextureAndSampler( textureSet, materialInfo.emissiveTexture.index, FRAGMENT_SHADER, DEFINE_EMIT_TEXTURE, addIdx ) )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::EMIT_SHADER );
+        isEmissiveTexture = true;
+      }
+
+      if( useIBL )
+      {
+        shaderTypeIndex += static_cast<int32_t>( ShaderType::IBL_SHADER );
+        FRAGMENT_SHADER += DEFINE_IBL_TEXTURE;
+
+        Sampler sampler = Sampler::New();
+        sampler.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+        sampler.SetWrapMode( WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT );
+
+        textureSet.SetTexture( addIdx, scene3dView.GetBRDFTexture() );
+        textureSet.SetSampler( addIdx++, sampler );
+        Sampler samplerIBL = Sampler::New();
+        samplerIBL.SetFilterMode( FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR );
+        samplerIBL.SetWrapMode( WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE );
+        textureSet.SetTexture( addIdx, scene3dView.GetDiffuseTexture() );
+        textureSet.SetSampler( addIdx++, samplerIBL );
+        Texture specularTexture = scene3dView.GetSpecularTexture();
+        textureSet.SetTexture( addIdx, specularTexture );
+        textureSet.SetSampler( addIdx++, samplerIBL );
+
+        int32_t textureSize = std::min( specularTexture.GetWidth(), specularTexture.GetHeight() );
+        maxMipmapLevel = 0;
+        while( textureSize >= 1 )
+        {
+          maxMipmapLevel++;
+          textureSize /= 2;
+        }
+      }
+    }
+
+    FRAGMENT_SHADER += PHYSICALLY_BASED_FRAGMENT_SHADER;
+    if( !mShaderCache[shaderTypeIndex] )
+    {
+      mShaderCache[shaderTypeIndex] = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+      scene3dView.AddShader( mShaderCache[shaderTypeIndex] );
+    }
+    Shader shader = mShaderCache[shaderTypeIndex];
+
+    Renderer renderer = Renderer::New( meshInfo.geometry, shader );
+    renderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
+    renderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON );
+    renderer.SetTextures( textureSet );
+
+    anchorPoint = meshInfo.pivot;
+    actor.SetAnchorPoint( anchorPoint );
+
+    actor.SetSize( Vector3( meshInfo.size.x, meshInfo.size.y, meshInfo.size.z ) );
+    actor.AddRenderer( renderer );
+
+    actor.SetScale( scale );
+    actor.RotateBy( orientation );
+    actor.SetPosition( translation );
+
+    shader.RegisterProperty( "uLightType", ( scene3dView.GetLightType() & ~Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) );
+    shader.RegisterProperty( "uLightVector", scene3dView.GetLightVector() );
+    shader.RegisterProperty( "uLightColor", scene3dView.GetLightColor() );
+
+    actor.RegisterProperty( "uIsColor", meshInfo.attribute.COLOR.size() > 0 );
+    if( isMaterial )
+    {
+      MaterialInfo materialInfo = mMaterialArray[meshInfo.materialsIdx];
+      actor.RegisterProperty( "uBaseColorFactor", materialInfo.baseColorFactor );
+      actor.RegisterProperty( "uMetallicRoughnessFactors", Vector2( materialInfo.metallicFactor, materialInfo.roughnessFactor ) );
+
+      if( materialInfo.alphaMode == "OPAQUE" )
+      {
+        actor.RegisterProperty( "alphaMode", 0 );
+      }
+      else if( materialInfo.alphaMode == "MASK" )
+      {
+        actor.RegisterProperty( "alphaMode", 1 );
+      }
+      else
+      {
+        actor.RegisterProperty( "alphaMode", 2 );
+      }
+      actor.RegisterProperty( "alphaCutoff", materialInfo.alphaCutoff );
+
+      if( isBaseColorTexture )
+      {
+        actor.RegisterProperty( "uBaseColorTexCoordIndex", materialInfo.baseColorTexture.texCoord );
+      }
+      if( isMetallicRoughnessTexture )
+      {
+        actor.RegisterProperty( "uMetallicRoughnessTexCoordIndex", materialInfo.metallicRoughnessTexture.texCoord );
+      }
+      if( isNormalTexture )
+      {
+        actor.RegisterProperty( "uNormalScale", materialInfo.normalTexture.value );
+        actor.RegisterProperty( "uNormalTexCoordIndex", materialInfo.normalTexture.texCoord );
+      }
+      if( isOcclusionTexture )
+      {
+        actor.RegisterProperty( "uOcclusionTexCoordIndex", materialInfo.occlusionTexture.texCoord );
+        actor.RegisterProperty( "uOcclusionStrength", materialInfo.occlusionTexture.value );
+      }
+      if( isEmissiveTexture )
+      {
+        actor.RegisterProperty( "uEmissiveTexCoordIndex", materialInfo.emissiveTexture.texCoord );
+        actor.RegisterProperty( "uEmissiveFactor", materialInfo.emissiveFactor );
+      }
+    }
+
+    if( isMaterial && useIBL )
+    {
+      actor.RegisterProperty( "uScaleIBLAmbient", scene3dView.GetIBLScaleFactor() );
+      actor.RegisterProperty( "uMipmapLevel", static_cast<float>( maxMipmapLevel ) );
+    }
+  }
+  else
+  {
+    actor.SetAnchorPoint( AnchorPoint::CENTER );
+    actor.SetPosition( translation );
+    actor.RotateBy( orientation );
+    actor.SetSize( actorSize );
+  }
+
+  tempNode = node->GetChild( "camera" );
+  if( tempNode )
+  {
+    int32_t cameraNum = tempNode->GetInteger();
+    CameraActor cameraActor = scene3dView.GetCamera( cameraNum );
+    if( cameraActor )
+    {
+      actor.Add( cameraActor );
+    }
+  }
+
+  tempNode = node->GetChild( "name" );
+  if( tempNode )
+  {
+    std::string nameString;
+    ReadString( tempNode, nameString );
+    actor.SetName( nameString );
+  }
+
+  SetActorCache( actor, index );
+  if( ( tempNode = node->GetChild( "children" ) ) )
+  {
+    for( auto childIter = tempNode->CBegin(), end = tempNode->CEnd(); childIter != end; ++childIter )
+    {
+      Actor childActor = AddNode( scene3dView, ( ( *childIter ).second ).GetInteger() );
+      childActor.SetParentOrigin( anchorPoint );
+      actor.Add( childActor );
+    }
+  }
+
+  return actor;
+}
+
+void Loader::SetActorCache( Actor& actor, uint32_t index )
+{
+  if( mActorCache.size() < index + 1 )
+  {
+    mActorCache.resize( index + 1 );
+  }
+  mActorCache[index] = actor;
+}
+
+bool Loader::SetTextureAndSampler( TextureSet& textureSet, int32_t textureIdx, std::string& toShader, std::string shader, int32_t& addIdx )
+{
+  if( textureIdx >= 0 )
+  {
+    toShader += shader;
+    TextureInfo textureInfo = mTextureArray[textureIdx];
+    if( textureInfo.sourceIdx >= 0 )
+    {
+      textureSet.SetTexture( addIdx, mSourceArray[textureInfo.sourceIdx] );
+    }
+    if( textureInfo.samplerIdx >= 0 )
+    {
+      textureSet.SetSampler( addIdx, mSamplerArray[textureInfo.samplerIdx] );
+    }
+    else
+    {
+      Sampler sampler = Sampler::New();
+      sampler.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+      sampler.SetWrapMode( WrapMode::REPEAT, WrapMode::REPEAT, WrapMode::REPEAT );
+      textureSet.SetSampler( addIdx, sampler );
+    }
+    addIdx++;
+    return true;
+  }
+  return false;
+}
+
+bool Loader::LoadAnimation( Scene3dView& scene3dView )
+{
+  const TreeNode* animationsNode = mRoot->GetChild( "animations" );
+  if( !animationsNode )
+  {
+    return true;
+  }
+
+  for( auto animationIter = animationsNode->CBegin(), end = animationsNode->CEnd(); animationIter != end; ++animationIter )
+  {
+    const TreeNode* nameNode = ( &( *animationIter ).second )->GetChild( "name" );
+    AnimationInfo animationInfo;
+    if( nameNode )
+    {
+      ReadString( nameNode, animationInfo.name );
+    }
+
+    Property::Index propIndex = Property::INVALID_INDEX;
+    LoadAnimationChannels( ( *animationIter ).second, animationInfo );
+    if( animationInfo.channelArray.size() == 0 )
+    {
+      continue;
+    }
+
+    LoadAnimationSamplers( ( *animationIter ).second, animationInfo );
+
+    for( auto&& currentChannel : animationInfo.channelArray )
+    {
+      if( currentChannel.path == "rotation" )
+      {
+        propIndex = Dali::Actor::Property::ORIENTATION;
+      }
+      else if( currentChannel.path == "translation" )
+      {
+        propIndex = Dali::Actor::Property::POSITION;
+      }
+      else if( currentChannel.path == "scale" )
+      {
+        propIndex = Dali::Actor::Property::SCALE;
+      }
+
+      float duration = 0.0f;
+      KeyFrames keyframes = KeyFrames::New();
+      if( propIndex == Dali::Actor::Property::ORIENTATION )
+      {
+        duration = LoadKeyFrames<Vector4>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray );
+      }
+      else
+      {
+        duration = LoadKeyFrames<Vector3>( animationInfo.samplerArray[currentChannel.sampler], propIndex, keyframes, mPath, mAccessorArray, mBufferViewArray, mBufferArray );
+      }
+
+      Animation animation = Animation::New( duration );
+      Animation::Interpolation interpolation = Animation::Interpolation::Linear;
+      if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "CUBICSPLINE" )
+      {
+        interpolation = Animation::Interpolation::Cubic;
+      }
+      if( animationInfo.samplerArray[currentChannel.sampler].interpolation == "STEP" )
+      {
+      }
+
+      animation.AnimateBetween( Property( mActorCache[currentChannel.targetNode], propIndex ), keyframes, interpolation );
+
+      animation.SetLooping( false );
+      scene3dView.AddAnimation( animation );
+    }
+  }
+
+  return true;
+}
+
+bool Loader::LoadAnimationChannels( const TreeNode& animation, AnimationInfo& animationInfo )
+{
+  const TreeNode* channelsNode = animation.GetChild( "channels" );
+  if( !channelsNode )
+  {
+    return false;
+  }
+
+  for( auto channelIter = channelsNode->CBegin(), end = channelsNode->CEnd(); channelIter != end; ++channelIter )
+  {
+    AnimationChannelInfo animationChannelInfo;
+    const TreeNode* channelNode = ( &( *channelIter ).second );
+    const TreeNode* samplerNode = channelNode->GetChild( "sampler" );
+    if( samplerNode )
+    {
+      animationChannelInfo.sampler = samplerNode->GetInteger();
+    }
+
+    const TreeNode* targetNode = channelNode->GetChild( "target" );
+    if( targetNode )
+    {
+      const TreeNode* tempNode = targetNode->GetChild( "node" );
+      if( tempNode )
+      {
+        animationChannelInfo.targetNode = tempNode->GetInteger();
+      }
+      else
+      {
+        continue;
+      }
+
+      tempNode = targetNode->GetChild( "path" );
+      if( tempNode )
+      {
+        ReadString( tempNode, animationChannelInfo.path );
+      }
+    }
+
+    animationInfo.channelArray.push_back( animationChannelInfo );
+  }
+  return true;
+}
+
+bool Loader::LoadAnimationSamplers( const TreeNode& animation, AnimationInfo& animationInfo )
+{
+  const TreeNode* samplersNode = animation.GetChild( "samplers" );
+  if( !samplersNode )
+  {
+    return false;
+  }
+
+  for( auto sampler = samplersNode->CBegin(), end = samplersNode->CEnd(); sampler != end; ++sampler )
+  {
+    AnimationSamplerInfo animationSamplerInfo;
+    const TreeNode* samplerNode = ( &( *sampler ).second );
+    const TreeNode* tempNode = samplerNode->GetChild( "input" );
+    if( tempNode )
+    {
+      animationSamplerInfo.input = tempNode->GetInteger();
+    }
+
+    tempNode = samplerNode->GetChild( "output" );
+    if( tempNode )
+    {
+      animationSamplerInfo.output = tempNode->GetInteger();
+    }
+
+    tempNode = samplerNode->GetChild( "interpolation" );
+    if( tempNode )
+    {
+      ReadString( tempNode, animationSamplerInfo.interpolation );
+    }
+
+    animationInfo.samplerArray.push_back( animationSamplerInfo );
+  }
+
+  return true;
+}
+
+}//namespace Gltf
+
+}//namespace Internal
+
+}//namespace Toolkit
+
+}//namespace Dali
diff --git a/dali-toolkit/internal/controls/scene3d-view/gltf-loader.h b/dali-toolkit/internal/controls/scene3d-view/gltf-loader.h
new file mode 100644 (file)
index 0000000..42ee4dd
--- /dev/null
@@ -0,0 +1,496 @@
+#ifndef DALI_TOOLKIT_INTERNAL_GLTF_LOADER_H\r
+#define DALI_TOOLKIT_INTERNAL_GLTF_LOADER_H\r
+\r
+/*\r
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <dali/public-api/actors/layer.h>\r
+#include <dali/public-api/rendering/renderer.h>\r
+#include <dali/public-api/rendering/shader.h>\r
+#include <dali/public-api/animation/animation.h>\r
+\r
+// INTERNAL INCLUDES\r
+#include <dali-toolkit/devel-api/builder/json-parser.h>\r
+#include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>\r
+\r
+using namespace Dali;\r
+\r
+namespace Dali\r
+{\r
+\r
+namespace Toolkit\r
+{\r
+\r
+namespace Internal\r
+{\r
+\r
+namespace Gltf\r
+{\r
+\r
+enum ShaderType\r
+{\r
+  NO_TEXTURE_SHADER,\r
+  BASECOLOR_SHADER,\r
+  METALLICROUGHNESS_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_SHADER,\r
+  NORMAL_SHADER,\r
+  BASECOLOR_NORMAL_SHADER,\r
+  METALLICROUGHNESS_NORMAL_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_NORMAL_SHADER,\r
+  OCCLUSION_SHADER,\r
+  BASECOLOR_OCCLUSION_SHADER,\r
+  METALLICROUGHNESS_OCCLUSION_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_OCCLUSION_SHADER,\r
+  NORMAL_OCCLUSION_SHADER,\r
+  BASECOLOR_NORMAL_OCCLUSION_SHADER,\r
+  METALLICROUGHNESS_NORMAL_OCCLUSION_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_NORMAL_OCCLUSION_SHADER,\r
+  EMIT_SHADER,\r
+  BASECOLOR_EMIT_SHADER,\r
+  METALLICROUGHNESS_EMIT_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_EMIT_SHADER,\r
+  NORMAL_EMIT_SHADER,\r
+  BASECOLOR_NORMAL_EMIT_SHADER,\r
+  METALLICROUGHNESS_NORMAL_EMIT_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_NORMAL_EMIT_SHADER,\r
+  OCCLUSION_EMIT_SHADER,\r
+  BASECOLOR_OCCLUSION_EMIT_SHADER,\r
+  METALLICROUGHNESS_OCCLUSION_EMIT_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_OCCLUSION_EMIT_SHADER,\r
+  NORMAL_OCCLUSION_EMIT_SHADER,\r
+  BASECOLOR_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  METALLICROUGHNESS_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  BASECOLOR_METALLICROUGHNESS_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  IBL_SHADER,\r
+  IBL_BASECOLOR_SHADER,\r
+  IBL_METALLICROUGHNESS_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_SHADER,\r
+  IBL_NORMAL_SHADER,\r
+  IBL_BASECOLOR_NORMAL_SHADER,\r
+  IBL_METALLICROUGHNESS_NORMAL_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_NORMAL_SHADER,\r
+  IBL_OCCLUSION_SHADER,\r
+  IBL_BASECOLOR_OCCLUSION_SHADER,\r
+  IBL_METALLICROUGHNESS_OCCLUSION_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_OCCLUSION_SHADER,\r
+  IBL_NORMAL_OCCLUSION_SHADER,\r
+  IBL_BASECOLOR_NORMAL_OCCLUSION_SHADER,\r
+  IBL_METALLICROUGHNESS_NORMAL_OCCLUSION_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_NORMAL_OCCLUSION_SHADER,\r
+  IBL_EMIT_SHADER,\r
+  IBL_BASECOLOR_EMIT_SHADER,\r
+  IBL_METALLICROUGHNESS_EMIT_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_EMIT_SHADER,\r
+  IBL_NORMAL_EMIT_SHADER,\r
+  IBL_BASECOLOR_NORMAL_EMIT_SHADER,\r
+  IBL_METALLICROUGHNESS_NORMAL_EMIT_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_NORMAL_EMIT_SHADER,\r
+  IBL_OCCLUSION_EMIT_SHADER,\r
+  IBL_BASECOLOR_OCCLUSION_EMIT_SHADER,\r
+  IBL_METALLICROUGHNESS_OCCLUSION_EMIT_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_OCCLUSION_EMIT_SHADER,\r
+  IBL_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  IBL_BASECOLOR_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  IBL_METALLICROUGHNESS_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  IBL_BASECOLOR_METALLICROUGHNESS_NORMAL_OCCLUSION_EMIT_SHADER,\r
+  SHADER_TYPE_MAX = IBL_BASECOLOR_METALLICROUGHNESS_NORMAL_OCCLUSION_EMIT_SHADER\r
+};\r
+\r
+struct BufferInfo\r
+{\r
+  BufferInfo()\r
+    : byteLength( -1 ),\r
+    uri( "" ),\r
+    name( "" )\r
+  {\r
+  }\r
+\r
+  ~BufferInfo()\r
+  {\r
+  }\r
+\r
+  int32_t byteLength;\r
+  std::string uri;\r
+  std::string name;\r
+};\r
+\r
+struct BufferViewInfo\r
+{\r
+  BufferViewInfo()\r
+    : buffer( -1 ),\r
+    byteOffset( 0 ),\r
+    byteLength( 0 ),\r
+    byteStride( 0 ),\r
+    target( 0 ),\r
+    name( "" )\r
+  {\r
+  }\r
+\r
+  ~BufferViewInfo()\r
+  {\r
+  }\r
+\r
+  int32_t buffer;\r
+  int32_t byteOffset;\r
+  int32_t byteLength;\r
+  int32_t byteStride;\r
+  int32_t target;\r
+  std::string name;\r
+};\r
+\r
+struct TextureInfo\r
+{\r
+  TextureInfo()\r
+    : sourceIdx( -1 ),\r
+    samplerIdx( -1 )\r
+  {\r
+  }\r
+\r
+  ~TextureInfo()\r
+  {\r
+  }\r
+  int32_t sourceIdx;\r
+  int32_t samplerIdx;\r
+};\r
+\r
+struct PbrTextureInfo\r
+{\r
+  PbrTextureInfo()\r
+    : index( -1 ),\r
+    texCoord( 0 ),\r
+    value( 0.0 )\r
+  {\r
+  }\r
+  ~PbrTextureInfo()\r
+  {\r
+  }\r
+\r
+  int32_t index;\r
+  int32_t texCoord;\r
+  float value;\r
+};\r
+\r
+struct MaterialInfo\r
+{\r
+  MaterialInfo()\r
+    : baseColorFactor( 1, 1, 1, 1 ),\r
+    metallicFactor( 1.0 ),\r
+    roughnessFactor( 1.0 ),\r
+    emissiveFactor( 0.0, 0.0, 0.0 ),\r
+    alphaMode( "OPAQUE" ),\r
+    alphaCutoff( 0.5 ),\r
+    doubleSided( false ),\r
+    name( "" )\r
+  {\r
+  }\r
+\r
+  ~MaterialInfo()\r
+  {\r
+  }\r
+\r
+  Vector4 baseColorFactor;\r
+  float metallicFactor;\r
+  float roughnessFactor;\r
+  Vector3 emissiveFactor;\r
+  std::string alphaMode;\r
+  float alphaCutoff;\r
+  bool doubleSided;\r
+\r
+  PbrTextureInfo baseColorTexture;\r
+  PbrTextureInfo metallicRoughnessTexture;\r
+  PbrTextureInfo normalTexture;\r
+  PbrTextureInfo occlusionTexture;\r
+  PbrTextureInfo emissiveTexture;\r
+\r
+  std::string name;\r
+  //need to add max, min\r
+};\r
+\r
+struct AccessorInfo\r
+{\r
+  AccessorInfo()\r
+    : bufferView( -1 ),\r
+    byteOffset( 0 ),\r
+    componentType( -1 ),\r
+    normalized( false ),\r
+    count( 0 ),\r
+    type( "" ),\r
+    max( 0 ),\r
+    min( 0 ),\r
+    name( "" )\r
+  {\r
+  }\r
+\r
+  ~AccessorInfo()\r
+  {\r
+  }\r
+\r
+  int32_t bufferView;\r
+  int32_t byteOffset;\r
+  int32_t componentType;\r
+  bool normalized;\r
+  int32_t count;\r
+  std::string type;\r
+  int32_t max;\r
+  int32_t min;\r
+  std::string name;\r
+  //need to add max, min\r
+};\r
+\r
+struct Attribute\r
+{\r
+  Attribute()\r
+    : POSITION( -1 ),\r
+    NORMAL( -1 ),\r
+    TANGENT( -1 )\r
+  {\r
+  }\r
+\r
+  ~Attribute()\r
+  {\r
+  }\r
+\r
+  int32_t POSITION;\r
+  int32_t NORMAL;\r
+  int32_t TANGENT;\r
+\r
+  std::vector<int32_t> TEXCOORD;\r
+  std::vector<int32_t> COLOR;\r
+};\r
+\r
+struct MeshInfo\r
+{\r
+  MeshInfo()\r
+    : indicesIdx( -1 ),\r
+    materialsIdx( -1 ),\r
+    mode( 4 )\r
+  {\r
+  }\r
+\r
+  ~MeshInfo()\r
+  {\r
+  }\r
+  Geometry geometry;\r
+  std::string name;\r
+\r
+  int32_t indicesIdx;\r
+  int32_t materialsIdx;\r
+  int32_t mode;\r
+\r
+  Vector3 size;\r
+  Vector3 pivot;\r
+\r
+  Attribute attribute;\r
+  //need to add max, min\r
+};\r
+\r
+struct AnimationChannelInfo\r
+{\r
+  AnimationChannelInfo()\r
+    : sampler( -1 ),\r
+    targetNode( -1 ),\r
+    path( "" )\r
+  {\r
+  }\r
+\r
+  ~AnimationChannelInfo()\r
+  {\r
+  }\r
+\r
+  int32_t sampler;\r
+  int32_t targetNode;\r
+  std::string path;\r
+\r
+};\r
+\r
+struct AnimationSamplerInfo\r
+{\r
+  AnimationSamplerInfo()\r
+    : input( -1 ),\r
+    output( -1 ),\r
+    interpolation( "" )\r
+  {\r
+  }\r
+\r
+  ~AnimationSamplerInfo()\r
+  {\r
+  }\r
+\r
+  int32_t input;\r
+  int32_t output;\r
+  std::string interpolation;\r
+};\r
+\r
+struct AnimationInfo\r
+{\r
+  AnimationInfo()\r
+    : name( "" )\r
+  {\r
+  }\r
+\r
+  ~AnimationInfo()\r
+  {\r
+  }\r
+\r
+  std::string name;\r
+  std::vector<AnimationChannelInfo> channelArray;\r
+  std::vector<AnimationSamplerInfo> samplerArray;\r
+};\r
+\r
+struct OrthographicInfo\r
+{\r
+  OrthographicInfo()\r
+    : xmag( 0.0f ),\r
+    ymag( 0.0f ),\r
+    zfar( 0.0f ),\r
+    znear( 0.0f )\r
+  {\r
+  }\r
+\r
+  ~OrthographicInfo()\r
+  {\r
+  }\r
+\r
+  float xmag;\r
+  float ymag;\r
+  float zfar;\r
+  float znear;\r
+};\r
+\r
+struct PerspectiveInfo\r
+{\r
+  PerspectiveInfo()\r
+    : aspectRatio( 0.0f ),\r
+    yfov( 0.0f ),\r
+    zfar( 0.0f ),\r
+    znear( 0.0f )\r
+  {\r
+  }\r
+\r
+  ~PerspectiveInfo()\r
+  {\r
+  }\r
+\r
+  float aspectRatio;\r
+  float yfov;\r
+  float zfar;\r
+  float znear;\r
+};\r
+\r
+struct CameraInfo\r
+{\r
+  CameraInfo()\r
+    : name( "" ),\r
+    type( "" )\r
+  {\r
+  }\r
+\r
+  ~CameraInfo()\r
+  {\r
+  }\r
+\r
+  std::string name;\r
+  std::string type;\r
+  OrthographicInfo orthographic;\r
+  PerspectiveInfo perspective;\r
+};\r
+\r
+/**\r
+ *\r
+ * Loader is a class to parse glTf, to load data from file, and to generate Scene.\r
+ * This glTF loader supports glTF 2.0 features.\r
+ *\r
+ * @remarks glTF loader didn't support such features.\r
+ *  - Sparse accessor\r
+ *  - Morphing\r
+ *  - Skeletal Animation\r
+ * These features will be supported soon.\r
+ *\r
+ */\r
+class Loader\r
+{\r
+public:\r
+\r
+  /**\r
+   * @brief Create an uninitialized Loader.\r
+   */\r
+  Loader();\r
+\r
+  /**\r
+   * @brief Destructor\r
+   */\r
+  ~Loader();\r
+\r
+  /**\r
+   * @brief Load Scene3dView from scene format file(e.g., glTF).\r
+   * @param[in] filePath Path of scene format file.\r
+   * @param[in] scene3dView Scene3dView data loaded from file.\r
+   * @return true if scene is successfully loaded\r
+   */\r
+  bool LoadScene( const std::string& filePath, Internal::Scene3dView& scene3dView );\r
+\r
+private:\r
+  bool ParseGltf( const std::string& filePath );\r
+  bool LoadAssets();\r
+\r
+  bool CreateScene( Internal::Scene3dView& scene3dView );\r
+\r
+  void LoadCamera( Scene3dView& scene3dView );\r
+  bool LoadOrthoGraphic( const TreeNode& camera, CameraInfo& cameraInfo );\r
+  bool LoadPerspective( const TreeNode& camera, CameraInfo& cameraInfo );\r
+\r
+  bool LoadSceneNodes( Scene3dView& scene3dView );\r
+  Actor AddNode( Scene3dView& scene3dView, uint32_t index );\r
+  void SetActorCache( Actor& actor, uint32_t index );\r
+  bool SetTextureAndSampler( TextureSet& textureSet, int32_t textureIdx, std::string& toShader, std::string shader, int32_t& addIdx );\r
+\r
+  bool LoadAnimation( Scene3dView& scene3dView );\r
+  bool LoadAnimationChannels( const TreeNode& animation, AnimationInfo& animationInfo );\r
+  bool LoadAnimationSamplers( const TreeNode& animation, AnimationInfo& animationInfo );\r
+\r
+private:\r
+  Dali::Toolkit::JsonParser mParser;\r
+  const TreeNode* mNodes;\r
+  const TreeNode* mRoot;\r
+\r
+  std::string mPath;\r
+\r
+  std::vector<Actor> mActorCache;\r
+  Shader mShaderCache[ShaderType::SHADER_TYPE_MAX + 1];\r
+\r
+  std::vector<BufferInfo> mBufferArray;\r
+  std::vector<BufferViewInfo> mBufferViewArray;\r
+  std::vector<AccessorInfo> mAccessorArray;\r
+\r
+  std::vector<MeshInfo> mMeshArray;\r
+  std::vector<MaterialInfo> mMaterialArray;\r
+  std::vector<TextureInfo> mTextureArray;\r
+\r
+  std::vector<Texture> mSourceArray;\r
+  std::vector<Sampler> mSamplerArray;\r
+};\r
+\r
+}//namespace Gltf\r
+\r
+}//namespace Internal\r
+\r
+}//namespace Toolkit\r
+\r
+}//namespace Dali\r
+\r
+#endif // DALI_TOOLKIT_INTERNAL_GLTF_LOADER_H\r
diff --git a/dali-toolkit/internal/controls/scene3d-view/gltf-shader.h b/dali-toolkit/internal/controls/scene3d-view/gltf-shader.h
new file mode 100644 (file)
index 0000000..e51b77c
--- /dev/null
@@ -0,0 +1,346 @@
+#ifndef DALI_TOOLKIT_INTERNAL_GLTF_SHADER_H
+#define DALI_TOOLKIT_INTERNAL_GLTF_SHADER_H
+
+/*
+ * Belows Vertex Shader and Fragment Shader code are based off glTF WebGL PBR.
+ * https://github.com/KhronosGroup/glTF-WebGL-PBR/
+ *
+ * Copyright (c) 2016-2017 Mohamad Moneimne and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+const char* GLES_VERSION_300 = {
+  "#version 300 es\n\n"
+  "precision highp float;\n\n"
+};
+
+const char* DEFINE_BASECOLOR_TEXTURE = {
+  "#define TEXTURE_BASECOLOR\n\n"
+  "uniform sampler2D uBaseColorSampler;\n"
+  "uniform int uBaseColorTexCoordIndex;\n\n"
+};
+
+const char* DEFINE_METALLICROUGHNESS_TEXTURE = {
+  "#define TEXTURE_METALLICROUGHNESS\n\n"
+  "uniform sampler2D uMetallicRoughnessSampler;\n"
+  "uniform int uMetallicRoughnessTexCoordIndex;\n\n"
+};
+
+const char* DEFINE_NORMAL_TEXTURE = {
+  "#define TEXTURE_NORMAL\n\n"
+  "uniform sampler2D uNormalSampler;\n"
+  "uniform float uNormalScale;\n"
+  "uniform int uNormalTexCoordIndex;\n\n"
+};
+
+const char* DEFINE_OCCLUSION_TEXTURE = {
+  "#define TEXTURE_OCCLUSION\n\n"
+  "uniform sampler2D uOcclusionSampler;\n"
+  "uniform int uOcclusionTexCoordIndex;\n"
+  "uniform float uOcclusionStrength;\n\n"
+};
+
+const char* DEFINE_EMIT_TEXTURE = {
+  "#define TEXTURE_EMIT\n\n"
+  "uniform sampler2D uEmissiveSampler;\n"
+  "uniform int uEmissiveTexCoordIndex;\n"
+  "uniform vec3 uEmissiveFactor;\n\n"
+};
+
+const char* DEFINE_IBL_TEXTURE = {
+  "#define TEXTURE_IBL\n\n"
+  "uniform sampler2D ubrdfLUT;\n"
+  "uniform samplerCube uDiffuseEnvSampler;\n"
+  "uniform samplerCube uSpecularEnvSampler;\n"
+  "uniform vec4 uScaleIBLAmbient;\n"
+  "uniform highp float uMipmapLevel;\n"
+};
+
+const char* PHYSICALLY_BASED_VERTEX_SHADER = {
+  "in highp vec3 aPosition;\n"
+  "in mediump vec2 aTexCoord0;\n"
+  "in mediump vec2 aTexCoord1;\n"
+  "in lowp vec3 aNormal;\n"
+  "in lowp vec4 aTangent;\n"
+  "in lowp vec4 aVertexColor;\n"
+
+  "uniform mediump vec3 uSize;\n"
+  "uniform mediump mat4 uModelMatrix;\n"
+  "uniform mediump mat4 uViewMatrix;\n"
+  "uniform mediump mat4 uProjection;\n"
+  "uniform lowp int uLightType;\n"
+  "uniform mediump vec3 uLightVector;\n"
+  "uniform lowp int uIsColor;\n"
+
+  "out lowp vec2 vUV[2];\n"
+  "out lowp mat3 vTBN;\n"
+  "out lowp vec4 vColor;\n"
+  "flat out int visLight;\n"
+  "out highp vec3 vLightDirection;\n"
+  "out highp vec3 vPositionToCamera;\n"
+
+  "void main()\n"
+  "{\n"
+  "  highp vec4 invY = vec4(1.0, -1.0, 1.0, 1.0);\n"
+  "  highp vec4 positionW = uModelMatrix * vec4( aPosition * uSize, 1.0 );\n"
+  "  highp vec4 positionV = uViewMatrix * ( invY * positionW );\n"
+
+  "  vPositionToCamera = transpose( mat3( uViewMatrix ) ) * ( -vec3( positionV.xyz / positionV.w ) );\n"
+  "  vPositionToCamera *= invY.xyz;\n"
+
+  "  lowp vec3 bitangent = cross(aNormal, aTangent.xyz) * aTangent.w;\n"
+  "  vTBN = mat3( uModelMatrix ) * mat3(aTangent.xyz, bitangent, aNormal);\n"
+
+  "  vUV[0] = aTexCoord0;\n"
+  "  vUV[1] = aTexCoord1;\n"
+
+  "  visLight = 1;\n"
+  "  if( uLightType == 1 )\n"
+  "  {\n"
+  "    vLightDirection = ( invY.xyz * uLightVector ) - ( positionW.xyz / positionW.w );\n"
+  "  }\n"
+  "  else if( uLightType == 2 )\n"
+  "  {\n"
+  "    vLightDirection = -( invY.xyz * uLightVector );\n"
+  "  }\n"
+  "  else\n"
+  "  {\n"
+  "    visLight = 0;\n"
+  "  }\n"
+
+  "  vColor = vec4( 1.0 );\n"
+  "  if( uIsColor == 1 )\n"
+  "  {\n"
+  "    vColor = aVertexColor;\n"
+  "  }\n"
+
+  "  gl_Position = uProjection * positionV;\n" // needs w for proper perspective correction
+  "  gl_Position = gl_Position/gl_Position.w;\n"
+  "}\n"
+};
+
+const char* PHYSICALLY_BASED_FRAGMENT_SHADER = {
+  "uniform lowp vec3 uLightColor;\n"
+  "uniform lowp vec4 uBaseColorFactor;\n"
+  "uniform lowp vec2 uMetallicRoughnessFactors;\n"
+  "uniform lowp int alphaMode;\n"
+  "uniform lowp float alphaCutoff;\n"
+
+  "in lowp vec2 vUV[2];\n"
+  "in lowp mat3 vTBN;\n"
+  "in lowp vec4 vColor;\n"
+  "flat in int visLight;\n"
+  "in highp vec3 vLightDirection;\n"
+  "in highp vec3 vPositionToCamera;\n"
+
+  "out vec4 FragColor;"
+
+  "struct PBRInfo\n"
+  "{\n"
+  "  mediump float NdotL;\n"                  // cos angle between normal and light direction
+  "  mediump float NdotV;\n"                  // cos angle between normal and view direction
+  "  mediump float NdotH;\n"                  // cos angle between normal and half vector
+  "  mediump float VdotH;\n"                  // cos angle between view direction and half vector
+  "  mediump vec3 reflectance0;\n"            // full reflectance color (normal incidence angle)
+  "  mediump vec3 reflectance90;\n"           // reflectance color at grazing angle
+  "  lowp float alphaRoughness;\n"         // roughness mapped to a more linear change in the roughness (proposed by [2])
+  "};\n"
+
+  "const float M_PI = 3.141592653589793;\n"
+  "const float c_MinRoughness = 0.04;\n"
+
+  "vec3 getNormal()\n"
+  "{\n"
+  "#ifdef TEXTURE_NORMAL\n"
+  "  lowp vec3 n = texture( uNormalSampler, vUV[uNormalTexCoordIndex] ).rgb;\n"
+  "  n = normalize( vTBN * ( ( 2.0 * n - 1.0 ) * vec3( uNormalScale, uNormalScale, 1.0 ) ) );\n"
+  "#else\n"
+  "  lowp vec3 n = normalize( vTBN[2].xyz );\n"
+  "#endif\n"
+  "  return n;\n"
+  "}\n"
+
+  "vec3 specularReflection( PBRInfo pbrInputs )\n"
+  "{\n"
+  "  return pbrInputs.reflectance0 + ( pbrInputs.reflectance90 - pbrInputs.reflectance0 ) * pow( clamp( 1.0 - pbrInputs.VdotH, 0.0, 1.0 ), 5.0 );\n"
+  "}\n"
+
+  "float geometricOcclusion( PBRInfo pbrInputs )\n"
+  "{\n"
+  "  mediump float NdotL = pbrInputs.NdotL;\n"
+  "  mediump float NdotV = pbrInputs.NdotV;\n"
+  "  lowp float r = pbrInputs.alphaRoughness;\n"
+
+  "  lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\n"
+  "  lowp float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\n"
+  "  return attenuationL * attenuationV;\n"
+  "}\n"
+
+  "float microfacetDistribution(PBRInfo pbrInputs)\n"
+  "{\n"
+  "  mediump float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;\n"
+  "  lowp float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;\n"
+  "  return roughnessSq / (M_PI * f * f);\n"
+  "}\n"
+
+  "vec3 linear( vec3 color )\n"
+  "{\n"
+  "  return pow(color,vec3(2.2));\n"
+  "}\n"
+
+  "void main()\n"
+  "{\n"
+  // Metallic and Roughness material properties are packed together
+  // In glTF, these factors can be specified by fixed scalar values
+  // or from a metallic-roughness map
+  "  lowp float metallic = uMetallicRoughnessFactors.x;\n"
+  "  lowp float perceptualRoughness = uMetallicRoughnessFactors.y;\n"
+
+  // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
+  // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
+  "#ifdef TEXTURE_METALLICROUGHNESS\n"
+  "  lowp vec4 metrou = texture(uMetallicRoughnessSampler, vUV[uMetallicRoughnessTexCoordIndex]);\n"
+  "  metallic = metrou.b * metallic;\n"
+  "  perceptualRoughness = metrou.g * perceptualRoughness;\n"
+  "#endif\n"
+
+  "  metallic = clamp(metallic, 0.0, 1.0);\n"
+  "  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\n"
+  // Roughness is authored as perceptual roughness; as is convention,
+  // convert to material roughness by squaring the perceptual roughness [2].
+  "  lowp float alphaRoughness = perceptualRoughness * perceptualRoughness;\n"
+
+  "#ifdef TEXTURE_BASECOLOR\n"
+  // The albedo may be defined from a base texture or a flat color
+  "  lowp vec4 baseColor = texture(uBaseColorSampler, vUV[uBaseColorTexCoordIndex]) * uBaseColorFactor;\n"
+  "  baseColor = vec4(linear(baseColor.rgb), baseColor.w);\n"
+  "#else\n"
+  "  lowp vec4 baseColor = vColor * uBaseColorFactor;\n"
+  "#endif\n"
+
+  "  if( alphaMode == 0 )\n"
+  "  {\n"
+  "    baseColor.w = 1.0;\n"
+  "  }\n"
+  "  else if( alphaMode == 1 )\n"
+  "  {\n"
+  "    if( baseColor.w >= alphaCutoff )"
+  "    {\n"
+  "      baseColor.w = 1.0;\n"
+  "    }\n"
+  "    else\n"
+  "    {\n"
+  "      baseColor.w = 0.0;\n"
+  "    }\n"
+  "  }\n"
+
+  "  lowp vec3 f0 = vec3(0.04);\n"
+  "  lowp vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);\n"
+  "  diffuseColor *= ( 1.0 - metallic );\n"
+  "  lowp vec3 specularColor = mix(f0, baseColor.rgb, metallic);\n"
+
+  // Compute reflectance.
+  "  lowp float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n"
+
+  // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
+  // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
+  "  lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n"
+  "  lowp vec3 specularEnvironmentR0 = specularColor.rgb;\n"
+  "  lowp vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\n"
+
+  "  mediump vec3 n = getNormal();\n"                            // normal at surface point
+  "  mediump vec3 v = normalize(vPositionToCamera);\n"           // Vector from surface point to camera
+  "  mediump vec3 l = normalize(vLightDirection);\n"             // Vector from light to surface point
+  "  mediump vec3 h = normalize(l+v);\n"                         // Half vector between both l and v
+  "  mediump vec3 reflection = -normalize(reflect(v, n));\n"
+
+  "  mediump float NdotL = clamp(dot(n, l), 0.001, 1.0);\n"
+  "  mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);\n"
+  "  mediump float NdotH = dot(n, h);\n"
+  "  mediump float LdotH = dot(l, h);\n"
+  "  mediump float VdotH = dot(v, h);\n"
+
+  "  PBRInfo pbrInputs = PBRInfo(\n"
+  "    NdotL,\n"
+  "    NdotV,\n"
+  "    NdotH,\n"
+  "    VdotH,\n"
+  "    specularEnvironmentR0,\n"
+  "    specularEnvironmentR90,\n"
+  "    alphaRoughness\n"
+  "  );\n"
+
+  // Calculate the shading terms for the microfacet specular shading model
+  "  lowp vec3 color = vec3(0.0);\n"
+  "  if( visLight == 1 )\n"
+  "  {\n"
+  "    lowp vec3 F = specularReflection( pbrInputs );\n"
+  "    lowp float G = geometricOcclusion( pbrInputs );\n"
+  "    lowp float D = microfacetDistribution( pbrInputs );\n"
+
+  // Calculation of analytical lighting contribution
+  "    lowp vec3 diffuseContrib = ( 1.0 - F ) * ( diffuseColor / M_PI );\n"
+  "    lowp vec3 specContrib = F * G * D / ( 4.0 * NdotL * NdotV );\n"
+  // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
+  "    color = NdotL * uLightColor * (diffuseContrib + specContrib);\n"
+  "  }\n"
+
+  "#ifdef TEXTURE_IBL\n"
+  "  lowp float lod = ( perceptualRoughness * uMipmapLevel );\n"
+  // retrieve a scale and bias to F0. See [1], Figure 3
+  "  lowp vec3 brdf = linear( texture( ubrdfLUT, vec2( NdotV, 1.0 - perceptualRoughness ) ).rgb );\n"
+  "  lowp vec3 diffuseLight = linear( texture( uDiffuseEnvSampler, n ).rgb );\n"
+  "  lowp vec3 specularLight = linear( textureLod( uSpecularEnvSampler, reflection, lod ).rgb );\n"
+
+  "  lowp vec3 diffuse = diffuseLight * diffuseColor * uScaleIBLAmbient.x;\n"
+  "  lowp vec3 specular = specularLight * ( specularColor * brdf.x + brdf.y ) * uScaleIBLAmbient.y;\n"
+  "  color += ( diffuse + specular );\n"
+  "#endif\n"
+
+  "#ifdef TEXTURE_OCCLUSION\n"
+  "  lowp float ao = texture( uOcclusionSampler, vUV[uOcclusionTexCoordIndex] ).r;\n"
+  "  color = mix( color, color * ao, uOcclusionStrength );\n"
+  "#endif\n"
+
+  "#ifdef TEXTURE_EMIT\n"
+  "  lowp vec3 emissive = linear( texture( uEmissiveSampler, vUV[uEmissiveTexCoordIndex] ).rgb ) * uEmissiveFactor;\n"
+  "  color += emissive;\n"
+  "#endif\n"
+
+  "  FragColor = vec4( pow( color,vec3( 1.0 / 2.2 ) ), baseColor.a );\n"
+  "}\n"
+};
+
+} // namespace internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_GLTF_SHADER_H
\ No newline at end of file
diff --git a/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp b/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp
new file mode 100644 (file)
index 0000000..3ec462b
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// glTF file extension
+const std::string GLTF_EXT( ".gltf" );
+
+/**
+ * cube map face index
+ */
+const uint32_t CUBEMAP_INDEX_X[2][6] = { { 2, 0, 1, 1, 1, 3 }, { 0, 1, 2, 3, 4, 5 } };
+const uint32_t CUBEMAP_INDEX_Y[2][6] = { { 1, 1, 0, 2, 1, 1 }, { 0, 0, 0, 0, 0, 0 } };
+
+}//namespace
+
+Scene3dView::Scene3dView()
+  : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
+  mRoot( Actor::New() ),
+  mShaderArray(),
+  mCameraActorArray(),
+  mDefaultCamera( CameraActor::New() ),
+  mAnimationArray(),
+  mLightType( Toolkit::Scene3dView::LightType::NONE ),
+  mLightVector( Vector3::ONE ),
+  mLightColor( Vector3::ONE )
+{
+}
+
+Scene3dView::~Scene3dView()
+{
+}
+
+Toolkit::Scene3dView Scene3dView::New( const std::string& filePath )
+{
+  Scene3dView* impl = new Scene3dView();
+
+  Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView( *impl );
+
+  // Second-phase init of the implementation
+  // This can only be done after the CustomActor connection has been made...
+  impl->mFilePath = filePath;
+  impl->Initialize();
+
+  return handle;
+}
+
+Toolkit::Scene3dView Scene3dView::New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )
+{
+  Scene3dView* impl = new Scene3dView();
+
+  Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView( *impl );
+
+  // Second-phase init of the implementation
+  // This can only be done after the CustomActor connection has been made...
+  impl->mFilePath = filePath;
+  impl->SetCubeMap( diffuseTexturePath, specularTexturePath, scaleFactor );
+  impl->Initialize();
+
+  return handle;
+}
+
+bool Scene3dView::CreateScene()
+{
+  if( std::string::npos != mFilePath.rfind( GLTF_EXT ) )
+  {
+    Internal::Gltf::Loader gltfloader;
+    return( gltfloader.LoadScene( mFilePath, *this ) );
+  }
+
+  return false;
+}
+
+uint32_t Scene3dView::GetAnimationCount()
+{
+  return mAnimationArray.size();
+}
+
+bool Scene3dView::PlayAnimation( uint32_t index )
+{
+  if( GetAnimationCount() <= index )
+  {
+    return false;
+  }
+
+  mAnimationArray[index].Play();
+  return true;
+}
+
+bool Scene3dView::PlayAnimations()
+{
+  for( auto&& animation : mAnimationArray )
+  {
+    animation.Play();
+  }
+
+  return true;
+}
+
+bool Scene3dView::SetLight( Toolkit::Scene3dView::LightType type, Vector3 lightVector, Vector3 lightColor )
+{
+  if( type > Toolkit::Scene3dView::LightType::DIRECTIONAL_LIGHT )
+  {
+    return false;
+  }
+
+  mLightType = static_cast<Toolkit::Scene3dView::LightType>(
+               ( mLightType >= Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) ?
+               Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT + type :
+               type );
+
+  mLightVector = lightVector;
+  mLightColor = lightColor;
+
+  for( auto&& shader : mShaderArray )
+  {
+    shader.RegisterProperty( "uLightType", ( GetLightType() & ~Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) );
+    shader.RegisterProperty( "uLightVector", lightVector );
+    shader.RegisterProperty( "uLightColor", lightColor );
+  }
+
+  return true;
+}
+
+uint8_t* Scene3dView::GetCroppedBuffer( uint8_t* sourceBuffer, uint32_t bytesPerPixel, uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset, uint32_t xFaceSize, uint32_t yFaceSize )
+{
+  uint32_t byteSize = bytesPerPixel * xFaceSize * yFaceSize;
+  uint8_t* destBuffer = reinterpret_cast<uint8_t*>( malloc( byteSize + 4u ) );
+
+  int32_t srcStride = width * bytesPerPixel;
+  int32_t destStride = xFaceSize * bytesPerPixel;
+  int32_t srcOffset = xOffset * bytesPerPixel + yOffset * srcStride;
+  int32_t destOffset = 0;
+  for( uint16_t row = yOffset; row < yOffset + yFaceSize; ++row )
+  {
+    memcpy( destBuffer + destOffset, sourceBuffer + srcOffset, destStride );
+    srcOffset += srcStride;
+    destOffset += destStride;
+  }
+
+  return destBuffer;
+}
+
+void Scene3dView::UploadTextureFace( Texture& texture, Devel::PixelBuffer pixelBuffer, uint32_t faceIndex )
+{
+  uint8_t* imageBuffer = pixelBuffer.GetBuffer();
+  uint32_t bytesPerPixel = Pixel::GetBytesPerPixel( pixelBuffer.GetPixelFormat() );
+  uint32_t imageWidth = pixelBuffer.GetWidth();
+  uint32_t imageHeight = pixelBuffer.GetHeight();
+
+  CubeType cubeType = ( imageWidth / 4 == imageHeight / 3 ) ? CROSS_HORIZONTAL :
+    ( ( imageWidth / 6 == imageHeight ) ? ARRAY_HORIZONTAL : NONE );
+
+  uint32_t faceSize = 0;
+  if( cubeType == CROSS_HORIZONTAL )
+  {
+    faceSize = imageWidth / 4;
+  }
+  else if( cubeType == ARRAY_HORIZONTAL )
+  {
+    faceSize = imageWidth / 6;
+  }
+  else
+  {
+    return;
+  }
+
+  uint32_t xOffset = CUBEMAP_INDEX_X[cubeType][faceIndex] * faceSize;
+  uint32_t yOffset = CUBEMAP_INDEX_Y[cubeType][faceIndex] * faceSize;
+
+  uint8_t* tempImageBuffer = GetCroppedBuffer( imageBuffer, bytesPerPixel, imageWidth, imageHeight, xOffset, yOffset, faceSize, faceSize );
+  PixelData pixelData = PixelData::New( tempImageBuffer, faceSize * faceSize * bytesPerPixel, faceSize, faceSize, pixelBuffer.GetPixelFormat(), PixelData::FREE );
+  texture.Upload( pixelData, CubeMapLayer::POSITIVE_X + faceIndex, 0, 0, 0, faceSize, faceSize );
+}
+
+void Scene3dView::SetCubeMap( const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )
+{
+  mLightType = Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT;
+
+  // BRDF texture
+  std::string imageBrdfUrl = DALI_IMAGE_DIR "brdfLUT.png";
+  mBRDFTexture = LoadTexture( imageBrdfUrl.c_str(), true );
+  if( !mBRDFTexture )
+  {
+    return;
+  }
+
+  // Diffuse Cube Map
+  Devel::PixelBuffer diffusePixelBuffer = LoadImageFromFile( diffuseTexturePath );
+  uint32_t diffuseFaceSize = diffusePixelBuffer.GetWidth() / 4;
+  mDiffuseTexture = Texture::New( TextureType::TEXTURE_CUBE, diffusePixelBuffer.GetPixelFormat(), diffuseFaceSize, diffuseFaceSize );
+  for( uint32_t i = 0; i < 6; ++i )
+  {
+    UploadTextureFace( mDiffuseTexture, diffusePixelBuffer, i );
+  }
+  mDiffuseTexture.GenerateMipmaps();
+
+  // Specular Cube Map
+  Devel::PixelBuffer specularPixelBuffer = LoadImageFromFile( specularTexturePath );
+  uint32_t specularFaceSize = specularPixelBuffer.GetWidth() / 4;
+  mSpecularTexture = Texture::New( TextureType::TEXTURE_CUBE, specularPixelBuffer.GetPixelFormat(), specularFaceSize, specularFaceSize );
+  for( uint32_t i = 0; i < 6; ++i )
+  {
+    UploadTextureFace( mSpecularTexture, specularPixelBuffer, i );
+  }
+  mSpecularTexture.GenerateMipmaps();
+
+  mIBLScaleFactor = scaleFactor;
+}
+
+bool Scene3dView::SetDefaultCamera( const Dali::Camera::Type type, const float nearPlane, const Vector3 cameraPosition )
+{
+  mDefaultCamera.SetParentOrigin( ParentOrigin::CENTER );
+  mDefaultCamera.SetAnchorPoint( AnchorPoint::CENTER );
+  mDefaultCamera.SetType( type );
+  mDefaultCamera.SetNearClippingPlane( nearPlane );
+  mDefaultCamera.SetPosition( cameraPosition );
+  return true;
+}
+
+void Scene3dView::AddCamera( CameraActor cameraActor )
+{
+  mCameraActorArray.push_back( cameraActor );
+}
+
+void Scene3dView::AddAnimation( Animation animation )
+{
+  mAnimationArray.push_back( animation );
+}
+
+void Scene3dView::AddShader( Shader shader )
+{
+  mShaderArray.push_back( shader );
+}
+
+Actor Scene3dView::GetRoot()
+{
+  return mRoot;
+}
+
+CameraActor Scene3dView::GetDefaultCamera()
+{
+  return mDefaultCamera;
+}
+
+uint32_t Scene3dView::GetCameraCount()
+{
+  return mCameraActorArray.size();
+}
+
+CameraActor Scene3dView::GetCamera( uint32_t cameraIndex )
+{
+  CameraActor cameraActor;
+  if( cameraIndex < 0 || cameraIndex >= mCameraActorArray.size() )
+  {
+    return cameraActor;
+  }
+  cameraActor = mCameraActorArray[cameraIndex];
+  return cameraActor;
+}
+
+Toolkit::Scene3dView::LightType Scene3dView::GetLightType()
+{
+  return mLightType;
+}
+
+Vector3 Scene3dView::GetLightVector()
+{
+  return mLightVector;
+}
+
+Vector3 Scene3dView::GetLightColor()
+{
+  return mLightColor;
+}
+
+Vector4 Scene3dView::GetIBLScaleFactor()
+{
+  return mIBLScaleFactor;
+}
+
+Texture Scene3dView::GetBRDFTexture()
+{
+  return mBRDFTexture;
+}
+
+Texture Scene3dView::GetSpecularTexture()
+{
+  return mSpecularTexture;
+}
+
+Texture Scene3dView::GetDiffuseTexture()
+{
+  return mDiffuseTexture;
+}
+
+Texture Scene3dView::LoadTexture( const char *imageUrl, bool generateMipmaps )
+{
+  Texture texture;
+
+  Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
+  if( pixelBuffer )
+  {
+    texture = Texture::New( TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
+    PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
+    texture.Upload( pixelData );
+
+    if( generateMipmaps )
+    {
+      texture.GenerateMipmaps();
+    }
+  }
+
+  return texture;
+}
+
+void Scene3dView::OnInitialize()
+{
+  mRoot.SetParentOrigin( ParentOrigin::CENTER );
+  mRoot.SetAnchorPoint( AnchorPoint::CENTER );
+
+  Layer layer = Layer::New();
+  layer.SetBehavior( Layer::LAYER_3D );
+  layer.SetParentOrigin( ParentOrigin::CENTER );
+  layer.SetAnchorPoint( AnchorPoint::CENTER );
+  layer.Add( mRoot );
+
+  Actor self = Self();
+  // Apply some default resizing rules.
+  self.SetParentOrigin( ParentOrigin::CENTER );
+  self.SetAnchorPoint( AnchorPoint::CENTER );
+  self.Add( layer );
+
+  CreateScene();
+}
+
+}//namespace Internal
+
+}//namespace Toolkit
+
+}//namespace Dali
+
diff --git a/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h b/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h
new file mode 100644 (file)
index 0000000..afe95fd
--- /dev/null
@@ -0,0 +1,276 @@
+#ifndef DALI_TOOLKIT_INTERNAL_SCENE3D_VIEW_H\r
+#define DALI_TOOLKIT_INTERNAL_SCENE3D_VIEW_H\r
+\r
+/*\r
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <cstring>\r
+#include <dali/public-api/object/base-object.h>\r
+#include <dali/public-api/rendering/shader.h>\r
+#include <dali/devel-api/adaptor-framework/image-loading.h>\r
+#include <dali/devel-api/adaptor-framework/file-loader.h>\r
+\r
+// INTERNAL INCLUDES\r
+#include <dali-toolkit/public-api/controls/control-impl.h>\r
+#include <dali-toolkit/devel-api/controls/scene3d-view/scene3d-view.h>\r
+#include <dali-toolkit/internal/controls/scene3d-view/gltf-loader.h>\r
+\r
+namespace Dali\r
+{\r
+\r
+namespace Toolkit\r
+{\r
+\r
+class Scene3dView;\r
+\r
+namespace Internal\r
+{\r
+\r
+namespace Gltf\r
+{\r
+\r
+class Loader;\r
+\r
+}\r
+\r
+/**\r
+ * Scene3dView implementation class\r
+ */\r
+class Scene3dView : public Control\r
+{\r
+public:\r
+\r
+  enum CubeType\r
+  {\r
+    CROSS_HORIZONTAL = 0,                 // Cross horizontal style cube map\r
+    ARRAY_HORIZONTAL,                     // array horizontal style cube map\r
+    NONE\r
+  };\r
+\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::Scene3dView\r
+   */\r
+  Scene3dView();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::~Scene3dView\r
+   */\r
+  virtual ~Scene3dView();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::New( const std::string& filePath )\r
+   */\r
+  static Dali::Toolkit::Scene3dView New( const std::string& filePath );\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )\r
+   */\r
+  static Dali::Toolkit::Scene3dView New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor );\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::CreateScene()\r
+   */\r
+  bool CreateScene();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::GetAnimationCount()\r
+   */\r
+  uint32_t GetAnimationCount();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::PlayAnimation()\r
+   */\r
+  bool PlayAnimation( uint32_t index );\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::PlayAnimations()\r
+   */\r
+  bool PlayAnimations();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::SetLight( Toolkit::Scene3dView::LightType type, Vector3 lightVector, Vector3 lightColor )\r
+   */\r
+  bool SetLight( Toolkit::Scene3dView::LightType type, Vector3 lightVector, Vector3 lightColor );\r
+\r
+  /**\r
+   * @brief Set default CameraActor specified in the each scene format specification.\r
+   * Default input values are derived from glTF default camera format.\r
+   * with Dali::Camera::Type = Dali::Camera::LOOK_AT_TARGET,\r
+   * near clipping plane = 0.1,\r
+   * and camera position = Vector3( 0.0, 0.0, 0.0 ).\r
+   */\r
+  bool SetDefaultCamera( const Dali::Camera::Type type = Dali::Camera::LOOK_AT_TARGET, const float nearPlane = 0.1, const Vector3 cameraPosition = Vector3( 0.0, 0.0, 0.0 ) );\r
+\r
+  /**\r
+   * @brief Add CameraActor loaded from scene format file.\r
+   */\r
+  void AddCamera( CameraActor cameraActor );\r
+\r
+  /**\r
+   * @brief Add Animation loaded from scene format file.\r
+   */\r
+  void AddAnimation( Animation animation );\r
+\r
+  /**\r
+   * @brief Add new Shader.\r
+   * Actors can share same Shader if they use same properties.\r
+   * If a property changes in a shader, then the property of all actors that use the shader change.\r
+   */\r
+  void AddShader( Shader shader );\r
+\r
+  /**\r
+   * @brief Get Root Actor.\r
+   */\r
+  Actor GetRoot();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::GetDefaultCamera()\r
+   */\r
+  CameraActor GetDefaultCamera();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::GetCameraCount()\r
+   */\r
+  uint32_t GetCameraCount();\r
+\r
+  /**\r
+   * @copydoc Dali::Toolkit::Scene3dView::GetCamera( uint32_t cameraIndex )\r
+   */\r
+  CameraActor GetCamera( uint32_t cameraIndex );\r
+\r
+  /**\r
+   * @brief Get light type.\r
+   */\r
+  Toolkit::Scene3dView::LightType GetLightType();\r
+\r
+  /**\r
+   * @brief Get light vector.\r
+   * Return light position when light type is LightType::POINT_LIGHT\r
+   * Return light direction when light type is LightType::DIRECTIONAL_LIGHT\r
+   */\r
+  Vector3 GetLightVector();\r
+\r
+  /**\r
+   * @brief Get light color.\r
+   */\r
+  Vector3 GetLightColor();\r
+\r
+  /**\r
+   * @brief Get Scaling factor of IBL.\r
+   */\r
+  Vector4 GetIBLScaleFactor();\r
+\r
+  /**\r
+   * @brief Get BRDF Texture.\r
+   */\r
+  Texture GetBRDFTexture();\r
+\r
+  /**\r
+   * @brief Get diffuse cube map texture.\r
+   */\r
+  Texture GetDiffuseTexture();\r
+\r
+  /**\r
+   * @brief Get specular cube map texture.\r
+   */\r
+  Texture GetSpecularTexture();\r
+\r
+private:\r
+  /**\r
+   * @brief Get Cropped image buffer.\r
+   * For each direction, Offset + faceSize must be width or height or less then them.\r
+   */\r
+  uint8_t* GetCroppedBuffer( uint8_t* sourceBuffer, uint32_t bytesPerPixel, uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset, uint32_t xFaceSize, uint32_t yFaceSize );\r
+\r
+  /**\r
+   * @brief Upload cube map texture.\r
+   */\r
+  void UploadTextureFace( Texture& texture, Devel::PixelBuffer pixelBuffer, uint32_t faceIndex );\r
+\r
+  /**\r
+   * @brief Set diffuse and specular cube map textures.\r
+   */\r
+  void SetCubeMap( const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor = Vector4( 1.0, 1.0, 1.0, 1.0 ) );\r
+\r
+  virtual void OnInitialize();\r
+\r
+\r
+  /**\r
+   * @brief Load 2D texture.\r
+   * @param[in] imageUrl Image URL of the texture.\r
+   * @param[in] generateMipmaps If generateMipmaps is true, then generate mipmap of this texture.\r
+   * @return Texture loaded from imageUrl.\r
+   */\r
+  Texture LoadTexture( const char *imageUrl, bool generateMipmaps );\r
+\r
+private:\r
+  Actor mRoot; // Root actor that contains scene graph\r
+  std::string mFilePath; // Full file path of scene file\r
+\r
+  std::vector<Shader> mShaderArray; // Shader Array to change properties of scene such as lighting.\r
+\r
+  std::vector<CameraActor> mCameraActorArray; // CameraActer array loaded from scene format file.\r
+  CameraActor mDefaultCamera; // Default CameraActor for the empty mCameraActorArray.\r
+\r
+  std::vector<Animation> mAnimationArray; // Animation array loaded from scene format file.\r
+\r
+  Toolkit::Scene3dView::LightType mLightType; // Light type\r
+  Vector3 mLightVector; // Light position when mLightType is LightType::POINT_LIGHT\r
+                        // Light direction when mLightType is LightType::DIRECTIONAL_LIGHT\r
+  Vector3 mLightColor; // Light color\r
+\r
+  Vector4 mIBLScaleFactor; // IBL scaling factor for the IBL rendering\r
+  Texture mBRDFTexture; // BRDF texture for the PBR rendering\r
+  Texture mSpecularTexture; // Specular cube map texture\r
+  Texture mDiffuseTexture; // Diffuse cube map texture\r
+\r
+private:\r
+\r
+  // Undefined copy constructor.\r
+  Scene3dView( const Scene3dView& );\r
+\r
+  // Undefined assignment operator.\r
+  Scene3dView& operator=( const Scene3dView& );\r
+};\r
+\r
+} // namespace Internal\r
+\r
+  // Helpers for public-api forwarding methods\r
+inline const Internal::Scene3dView& GetImpl( const Toolkit::Scene3dView& scene3dView )\r
+{\r
+  DALI_ASSERT_ALWAYS( scene3dView && "Scene3dView handle is empty" );\r
+  const Dali::RefObject& handle = scene3dView.GetImplementation();\r
+\r
+  return static_cast<const Toolkit::Internal::Scene3dView&>( handle );\r
+}\r
+\r
+inline Internal::Scene3dView& GetImpl( Toolkit::Scene3dView& scene3dView )\r
+{\r
+  DALI_ASSERT_ALWAYS( scene3dView && "Scene3dView handle is empty" );\r
+\r
+  Dali::RefObject& handle = scene3dView.GetImplementation();\r
+\r
+  return static_cast<Toolkit::Internal::Scene3dView&>( handle );\r
+}\r
+\r
+}//namespace Toolkit\r
+\r
+}//namespace Dali\r
+\r
+#endif // DALI_TOOLKIT_INTERNAL_SCENE3D_VIEW_H\r
index 64f8251..547df3c 100755 (executable)
@@ -90,6 +90,8 @@ toolkit_src_files = \
    $(toolkit_src_dir)/controls/scrollable/scroll-view/scroll-view-effect-impl.cpp \
    $(toolkit_src_dir)/controls/scrollable/scroll-view/scroll-view-impl.cpp \
    $(toolkit_src_dir)/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp \
+   $(toolkit_src_dir)/controls/scene3d-view/scene3d-view-impl.cpp \
+   $(toolkit_src_dir)/controls/scene3d-view/gltf-loader.cpp \
    $(toolkit_src_dir)/controls/shadow-view/shadow-view-impl.cpp \
    $(toolkit_src_dir)/controls/slider/slider-impl.cpp \
    $(toolkit_src_dir)/controls/super-blur-view/super-blur-view-impl.cpp \
diff --git a/dali-toolkit/styles/images-common/brdfLUT.png b/dali-toolkit/styles/images-common/brdfLUT.png
new file mode 100644 (file)
index 0000000..5f6541b
Binary files /dev/null and b/dali-toolkit/styles/images-common/brdfLUT.png differ