ModelView using scene-loader 30/275630/48
authorseungho <sbsh.baek@samsung.com>
Fri, 27 May 2022 10:10:57 +0000 (19:10 +0900)
committerseungho <sbsh.baek@samsung.com>
Mon, 18 Jul 2022 01:03:26 +0000 (10:03 +0900)
Change-Id: I4b4c4859f890aedfd01a1ed208fb545484e9486a
Signed-off-by: seungho <sbsh.baek@samsung.com>
15 files changed:
automated-tests/resources/animationTest.gltf [new file with mode: 0644]
automated-tests/src/dali-scene-loader/CMakeLists.txt
automated-tests/src/dali-scene-loader/utc-Dali-ModelView.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-Model3dView.cpp
dali-scene-loader/internal/controls/model-view/model-view-impl.cpp [new file with mode: 0644]
dali-scene-loader/internal/controls/model-view/model-view-impl.h [new file with mode: 0644]
dali-scene-loader/internal/file.list
dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene-loader/public-api/controls/model-view/model-view.cpp [new file with mode: 0644]
dali-scene-loader/public-api/controls/model-view/model-view.h [new file with mode: 0644]
dali-scene-loader/public-api/environment-definition.h
dali-scene-loader/public-api/file.list
dali-scene-loader/public-api/material-definition.cpp
dali-scene-loader/public-api/node-definition.cpp
dali-scene-loader/public-api/node-definition.h

diff --git a/automated-tests/resources/animationTest.gltf b/automated-tests/resources/animationTest.gltf
new file mode 100644 (file)
index 0000000..6c7b12c
--- /dev/null
@@ -0,0 +1,1419 @@
+{
+    "accessors" : [
+        {
+            "bufferView" : 0,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 1,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 2,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 3,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 4,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 5,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 6,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 7,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 8,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 9,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 10,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 11,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 12,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 13,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 14,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 15,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 16,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 17,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 18,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 19,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 20,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 21,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 22,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 23,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 24,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 25,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 26,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 27,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 28,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 29,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 30,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 31,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 32,
+            "componentType" : 5126,
+            "count" : 24,
+            "max" : [
+                1,
+                1,
+                1
+            ],
+            "min" : [
+                -1,
+                -1,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 33,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 34,
+            "componentType" : 5126,
+            "count" : 24,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 35,
+            "componentType" : 5121,
+            "count" : 36,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 36,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                1,
+                0,
+                1
+            ],
+            "min" : [
+                -1,
+                0,
+                -1
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 37,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 38,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 39,
+            "componentType" : 5121,
+            "count" : 6,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 40,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.6666666666666667
+            ],
+            "min" : [
+                0.041666666666666664
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 41,
+            "componentType" : 5126,
+            "count" : 5,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 42,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.6666666666666667
+            ],
+            "min" : [
+                0.041666666666666664
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 43,
+            "componentType" : 5126,
+            "count" : 15,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 44,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.6666666666666667
+            ],
+            "min" : [
+                0.041666666666666664
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 45,
+            "componentType" : 5126,
+            "count" : 15,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 46,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.7083333333333333
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 47,
+            "componentType" : 5126,
+            "count" : 5,
+            "type" : "VEC4"
+        },
+        {
+            "bufferView" : 48,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.7083333333333333
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 49,
+            "componentType" : 5126,
+            "count" : 15,
+            "type" : "VEC4"
+        },
+        {
+            "bufferView" : 50,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.7083333333333333
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 51,
+            "componentType" : 5126,
+            "count" : 5,
+            "type" : "VEC4"
+        },
+        {
+            "bufferView" : 52,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.7083333333333333
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 53,
+            "componentType" : 5126,
+            "count" : 5,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 54,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.6666666666666667
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 55,
+            "componentType" : 5126,
+            "count" : 15,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 56,
+            "componentType" : 5126,
+            "count" : 5,
+            "max" : [
+                1.6666666666666667
+            ],
+            "min" : [
+                0
+            ],
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 57,
+            "componentType" : 5126,
+            "count" : 5,
+            "type" : "VEC3"
+        }
+    ],
+    "animations" : [
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 0,
+                        "path" : "scale"
+                    }
+                }
+            ],
+            "name" : "Step Scale",
+            "samplers" : [
+                {
+                    "input" : 40,
+                    "interpolation" : "STEP",
+                    "output" : 41
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 3,
+                        "path" : "scale"
+                    }
+                }
+            ],
+            "name" : "Linear Scale",
+            "samplers" : [
+                {
+                    "input" : 40,
+                    "interpolation" : "LINEAR",
+                    "output" : 41
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 4,
+                        "path" : "scale"
+                    }
+                }
+            ],
+            "name" : "CubicSpline Scale",
+            "samplers" : [
+                {
+                    "input" : 44,
+                    "interpolation" : "CUBICSPLINE",
+                    "output" : 45
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 5,
+                        "path" : "rotation"
+                    }
+                }
+            ],
+            "name" : "Step Rotation",
+            "samplers" : [
+                {
+                    "input" : 46,
+                    "interpolation" : "STEP",
+                    "output" : 47
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 6,
+                        "path" : "rotation"
+                    }
+                }
+            ],
+            "name" : "CubicSpline Rotation",
+            "samplers" : [
+                {
+                    "input" : 48,
+                    "interpolation" : "CUBICSPLINE",
+                    "output" : 49
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 7,
+                        "path" : "rotation"
+                    }
+                }
+            ],
+            "name" : "Linear Rotation",
+            "samplers" : [
+                {
+                    "input" : 50,
+                    "interpolation" : "LINEAR",
+                    "output" : 51
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 8,
+                        "path" : "translation"
+                    }
+                }
+            ],
+            "name" : "Step Translation",
+            "samplers" : [
+                {
+                    "input" : 52,
+                    "interpolation" : "STEP",
+                    "output" : 53
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 9,
+                        "path" : "translation"
+                    }
+                }
+            ],
+            "name" : "CubicSpline Translation",
+            "samplers" : [
+                {
+                    "input" : 54,
+                    "interpolation" : "CUBICSPLINE",
+                    "output" : 55
+                }
+            ]
+        },
+        {
+            "channels" : [
+                {
+                    "sampler" : 0,
+                    "target" : {
+                        "node" : 10,
+                        "path" : "translation"
+                    }
+                }
+            ],
+            "name" : "Linear Translation",
+            "samplers" : [
+                {
+                    "input" : 56,
+                    "interpolation" : "LINEAR",
+                    "output" : 57
+                }
+            ]
+        }
+    ],
+    "asset" : {
+        "generator" : "Khronos Blender glTF 2.0 I/O",
+        "version" : "2.0"
+    },
+    "bufferViews" : [
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 0
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 288
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 576
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 768
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 804
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 1092
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 1380
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 1572
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 1608
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 1896
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 2184
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 2376
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 2412
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 2700
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 2988
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 3180
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 3216
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 3504
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 3792
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 3984
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 4020
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 4308
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 4596
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 4788
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 4824
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 5112
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 5400
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 5592
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 5628
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 5916
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 6204
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 6396
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 6432
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 288,
+            "byteOffset" : 6720
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 192,
+            "byteOffset" : 7008
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 36,
+            "byteOffset" : 7200
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 7236
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 7284
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 7332
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 6,
+            "byteOffset" : 7364
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 7372
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 60,
+            "byteOffset" : 7392
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 7452
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 180,
+            "byteOffset" : 7472
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 7652
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 180,
+            "byteOffset" : 7672
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 7852
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 80,
+            "byteOffset" : 7872
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 7952
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 240,
+            "byteOffset" : 7972
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 8212
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 80,
+            "byteOffset" : 8232
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 8312
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 60,
+            "byteOffset" : 8332
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 8392
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 180,
+            "byteOffset" : 8412
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 20,
+            "byteOffset" : 8592
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 60,
+            "byteOffset" : 8612
+        }
+    ],
+    "buffers" : [
+        {
+            "byteLength" : 8672,
+            "uri" : "interpolation.bin"
+        }
+    ],
+    "extensions" : {},
+    "images" : [
+        {
+            "mimeType" : "image/jpeg",
+            "name" : "l.jpg",
+            "uri" : "l.jpg"
+        }
+    ],
+    "materials" : [
+        {
+            "name" : "Material",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.001",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.002",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.007",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.006",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.008",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.004",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.005",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.003",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        },
+        {
+            "name" : "Material.009",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "index" : 0,
+                    "texCoord" : 0
+                },
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.5
+            }
+        }
+    ],
+    "meshes" : [
+        {
+            "name" : "Cube",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 1,
+                        "POSITION" : 0,
+                        "TEXCOORD_0" : 2
+                    },
+                    "material" : 0
+                }
+            ]
+        },
+        {
+            "name" : "Cube.001",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 5,
+                        "POSITION" : 4,
+                        "TEXCOORD_0" : 6
+                    },
+                    "material" : 1
+                }
+            ]
+        },
+        {
+            "name" : "Cube.002",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 9,
+                        "POSITION" : 8,
+                        "TEXCOORD_0" : 10
+                    },
+                    "material" : 2
+                }
+            ]
+        },
+        {
+            "name" : "Cube.003",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 13,
+                        "POSITION" : 12,
+                        "TEXCOORD_0" : 14
+                    },
+                    "material" : 3
+                }
+            ]
+        },
+        {
+            "name" : "Cube.004",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 17,
+                        "POSITION" : 16,
+                        "TEXCOORD_0" : 18
+                    },
+                    "material" : 4
+                }
+            ]
+        },
+        {
+            "name" : "Cube.005",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 21,
+                        "POSITION" : 20,
+                        "TEXCOORD_0" : 22
+                    },
+                    "material" : 5
+                }
+            ]
+        },
+        {
+            "name" : "Cube.006",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 25,
+                        "POSITION" : 24,
+                        "TEXCOORD_0" : 26
+                    },
+                    "material" : 6
+                }
+            ]
+        },
+        {
+            "name" : "Cube.008",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 29,
+                        "POSITION" : 28,
+                        "TEXCOORD_0" : 30
+                    },
+                    "material" : 7
+                }
+            ]
+        },
+        {
+            "name" : "Cube.009",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 33,
+                        "POSITION" : 32,
+                        "TEXCOORD_0" : 34
+                    },
+                    "material" : 8
+                }
+            ]
+        },
+        {
+            "name" : "Plane.001",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "NORMAL" : 37,
+                        "POSITION" : 36,
+                        "TEXCOORD_0" : 38
+                    },
+                    "material" : 9
+                }
+            ]
+        }
+    ],
+    "nodes" : [
+        {
+            "name" : "Cube"
+        },
+        {
+            "name" : "Light",
+            "rotation" : [
+                0.16907575726509094,
+                0.7558802962303162,
+                -0.27217137813568115,
+                0.570947527885437
+            ],
+            "scale" : [
+                1,
+                1,
+                0.9999999403953552
+            ],
+            "translation" : [
+                0.18540644645690918,
+                5.903861999511719,
+                8.732584953308105
+            ]
+        },
+        {
+            "name" : "Camera",
+            "rotation" : [
+                0.6819981932640076,
+                0,
+                0,
+                0.7313538193702698
+            ],
+            "scale" : [
+                1,
+                0.39365354180336,
+                1
+            ],
+            "translation" : [
+                0.31374117732048035,
+                4.958309173583984,
+                29.236623764038086
+            ]
+        },
+        {
+            "name" : "Cube.001",
+            "translation" : [
+                -3.2963297367095947,
+                0,
+                6.461143493652344e-05
+            ]
+        },
+        {
+            "name" : "Cube.002",
+            "translation" : [
+                3.3401193618774414,
+                0,
+                0.008944988250732422
+            ]
+        },
+        {
+            "name" : "Cube.003",
+            "translation" : [
+                0,
+                3.356412410736084,
+                0
+            ]
+        },
+        {
+            "name" : "Cube.004",
+            "rotation" : [
+                0,
+                0,
+                -0.006683696992695332,
+                0.9999777674674988
+            ],
+            "translation" : [
+                3.33506178855896,
+                3.356412410736084,
+                0
+            ]
+        },
+        {
+            "name" : "Cube.005",
+            "rotation" : [
+                0,
+                0,
+                -0.03925982117652893,
+                0.9992290735244751
+            ],
+            "scale" : [
+                0.9999999403953552,
+                0.9999999403953552,
+                1
+            ],
+            "translation" : [
+                -3.311399221420288,
+                3.356412410736084,
+                0
+            ]
+        },
+        {
+            "name" : "Cube.006",
+            "translation" : [
+                0,
+                6.665226459503174,
+                0
+            ]
+        },
+        {
+            "name" : "Cube.008",
+            "translation" : [
+                3.3051798343658447,
+                6.734194278717041,
+                0
+            ]
+        },
+        {
+            "name" : "Cube.009",
+            "translation" : [
+                -3.2975807189941406,
+                6.958913326263428,
+                0
+            ]
+        },
+        {
+            "name" : "Plane",
+            "rotation" : [
+                0.7071068286895752,
+                0,
+                0,
+                0.7071068286895752
+            ],
+            "scale" : [
+                4.218648433685303,
+                1,
+                0.3652837574481964
+            ],
+            "translation" : [
+                0,
+                -1.7941787242889404,
+                1.0036747455596924
+            ]
+        }
+    ],
+    "scene" : 0,
+    "scenes" : [
+        {
+            "name" : "Scene",
+            "nodes" : [
+                0,
+                1,
+                2,
+                3,
+                4,
+                5,
+                6,
+                7,
+                8,
+                9,
+                10,
+                11
+            ]
+        }
+    ],
+    "textures" : [
+        {
+            "source" : 0
+        }
+    ]
+}
index 8e700d8..387fb7b 100755 (executable)
@@ -16,6 +16,7 @@ SET(TC_SOURCES
   utc-Dali-FacialAnimation.cpp
   utc-Dali-Gltf2Loader.cpp
   utc-Dali-KtxLoader.cpp
+  utc-Dali-ModelView.cpp
   utc-Dali-MatrixStack.cpp
   utc-Dali-MeshDefinition.cpp
   utc-Dali-NodeDefinition.cpp
diff --git a/automated-tests/src/dali-scene-loader/utc-Dali-ModelView.cpp b/automated-tests/src/dali-scene-loader/utc-Dali-ModelView.cpp
new file mode 100644 (file)
index 0000000..edc6bc2
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2022 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 <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene-loader/public-api/controls/model-view/model-view.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_view_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_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";
+const char* TEST_GLTF_TRIANGLE_FILE_NAME       = TEST_RESOURCE_DIR "/AnimatedTriangle.gltf";
+const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf";
+const char* TEST_DLI_FILE_NAME                 = TEST_RESOURCE_DIR "/arc.dli";
+/**
+ * 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) 2022 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_irradiance.ktx";
+const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx";
+} // namespace
+
+// Negative test case for a method
+int UtcDaliModelViewUninitialized(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliModelViewUninitialized");
+
+  Scene3D::ModelView view;
+
+  try
+  {
+    // New() must be called to create a ModelView or it wont be valid.
+    Actor a = Actor::New();
+    view.Add(a);
+    DALI_TEST_CHECK(false);
+  }
+  catch(Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT(e);
+    DALI_TEST_CHECK(!view);
+  }
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelViewNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliModelViewNew");
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  DALI_TEST_CHECK(view);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelViewDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliModelViewDownCast");
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  BaseHandle         handle(view);
+
+  Scene3D::ModelView modelView = Scene3D::ModelView::DownCast(handle);
+  DALI_TEST_CHECK(view);
+  DALI_TEST_CHECK(modelView);
+  DALI_TEST_CHECK(modelView == view);
+  END_TEST;
+}
+
+int UtcDaliModelViewTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("ModelView");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  Scene3D::ModelView modelView = Scene3D::ModelView::DownCast(handle);
+  DALI_TEST_CHECK(modelView);
+
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelViewAddRemove(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliModelViewAddRemove");
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  DALI_TEST_CHECK(view);
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK(!actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+  view.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  view.SetProperty(Actor::Property::SIZE, application.GetScene().GetSize());
+  view.Add(actor);
+  application.GetScene().Add(view);
+
+  DALI_TEST_CHECK(actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+  view.Remove(actor);
+
+  DALI_TEST_CHECK(!actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+  END_TEST;
+}
+
+int UtcDaliModelViewCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  DALI_TEST_CHECK(view);
+
+  Scene3D::ModelView copy(view);
+  DALI_TEST_CHECK(view == copy);
+
+  Scene3D::ModelView assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == view);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  DALI_TEST_EQUALS(1, view.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  view.SetProperty(Actor::Property::SENSITIVE, false);
+  DALI_TEST_CHECK(false == view.GetProperty<bool>(Actor::Property::SENSITIVE));
+
+  Scene3D::ModelView moved = std::move(view);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(false == moved.GetProperty<bool>(Actor::Property::SENSITIVE));
+  DALI_TEST_CHECK(!view);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  DALI_TEST_EQUALS(1, view.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  view.SetProperty(Actor::Property::SENSITIVE, false);
+  DALI_TEST_CHECK(false == view.GetProperty<bool>(Actor::Property::SENSITIVE));
+
+  Scene3D::ModelView moved;
+  moved = std::move(view);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(false == moved.GetProperty<bool>(Actor::Property::SENSITIVE));
+  DALI_TEST_CHECK(!view);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewOnScene01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  uint32_t modelCount = view.GetModelRoot().GetChildCount();
+  DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewOnScene02(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_DLI_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  uint32_t modelCount = view.GetModelRoot().GetChildCount();
+  DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION);
+
+  Actor   rootActor = view.GetModelRoot();
+  Vector3 rootSize  = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  DALI_TEST_EQUALS(Vector3(2, 2, 1), rootSize, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewOnSizeSet(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector2 size(200.0f, 300.0f);
+  view.SetProperty(Actor::Property::SIZE, size);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(view.GetCurrentProperty<Vector2>(Actor::Property::SIZE), size, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewGetNaturalSize(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  Vector3 naturalSize = view.GetNaturalSize();
+
+  DALI_TEST_EQUALS(Vector3(2, 2, 2), naturalSize, TEST_LOCATION);
+
+  Actor root = view.GetModelRoot();
+  DALI_TEST_CHECK(root);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewSetImageBasedLightSource01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor meshActor = view.FindChildByName("AnimatedCube");
+  DALI_TEST_CHECK(meshActor);
+
+  Renderer renderer = meshActor.GetRendererAt(0u);
+  DALI_TEST_CHECK(renderer);
+
+  TextureSet textureSet = renderer.GetTextures();
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+
+  Texture diffuseTexture  = textureSet.GetTexture(5u);
+  Texture specularTexture = textureSet.GetTexture(6u);
+
+  view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+
+  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
+  Texture newSpecularTexture = textureSet.GetTexture(6u);
+
+  DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION);
+  DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewSetImageBasedLightSource02(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor meshActor = view.FindChildByName("AnimatedCube");
+  DALI_TEST_CHECK(meshActor);
+
+  Renderer renderer = meshActor.GetRendererAt(0u);
+  DALI_TEST_CHECK(renderer);
+
+  TextureSet textureSet = renderer.GetTextures();
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+
+  Texture diffuseTexture  = textureSet.GetTexture(5u);
+  Texture specularTexture = textureSet.GetTexture(6u);
+
+  view.SetImageBasedLightSource("", "");
+
+  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
+  Texture newSpecularTexture = textureSet.GetTexture(6u);
+
+  DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
+  DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewSetImageBasedLightSource03(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor meshActor = view.FindChildByName("AnimatedCube");
+  DALI_TEST_CHECK(meshActor);
+
+  Renderer renderer = meshActor.GetRendererAt(0u);
+  DALI_TEST_CHECK(renderer);
+
+  TextureSet textureSet = renderer.GetTextures();
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+
+  Texture diffuseTexture  = textureSet.GetTexture(5u);
+  Texture specularTexture = textureSet.GetTexture(6u);
+
+  view.SetImageBasedLightSource("dummy.ktx", "dummy.ktx");
+
+  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
+  Texture newSpecularTexture = textureSet.GetTexture(6u);
+
+  DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
+  DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewFitSize01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor   rootActor = view.GetModelRoot();
+  Vector3 rootSize  = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION);
+
+  Vector3 rootScale = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SCALE);
+  DALI_TEST_EQUALS(Vector3(1, 1, 1), rootScale, TEST_LOCATION);
+
+  view.FitSize(true);
+  rootSize = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION);
+
+  rootScale = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SCALE);
+  DALI_TEST_EQUALS(Vector3(25, 25, 25), rootScale, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewFitSize02(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector2(0, 0));
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Actor   rootActor = view.GetModelRoot();
+  Vector3 rootSize  = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION);
+
+  Vector3 rootScale = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SCALE);
+  DALI_TEST_EQUALS(Vector3(1, 1, 1), rootScale, TEST_LOCATION);
+
+  view.FitSize(true);
+  rootSize = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION);
+
+  rootScale = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SCALE);
+  DALI_TEST_EQUALS(Vector3(1, 1, 1), rootScale, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewFitCenter(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_TRIANGLE_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize = view.GetNaturalSize();
+  DALI_TEST_EQUALS(Vector3(1, 1, 0), naturalSize, TEST_LOCATION);
+
+  Actor   rootActor   = view.GetModelRoot();
+  Vector3 anchorPoint = rootActor.GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
+  DALI_TEST_EQUALS(Vector3(0.5, 0.5, 0.5), anchorPoint, TEST_LOCATION);
+
+  view.FitCenter(true);
+  anchorPoint = rootActor.GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
+  DALI_TEST_EQUALS(Vector3(1.0, 1.0, 0.5), anchorPoint, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewAnimation01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  uint32_t animationCount = view.GetAnimationCount();
+  DALI_TEST_EQUALS(1, animationCount, TEST_LOCATION);
+
+  Animation animationByIndex = view.GetAnimation(0u);
+  DALI_TEST_CHECK(animationByIndex);
+
+  Animation animationByName = view.GetAnimation("animation_AnimatedCube");
+  DALI_TEST_CHECK(animationByName);
+  DALI_TEST_EQUALS(animationByIndex, animationByName, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelViewAnimation02(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME);
+  view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+
+  application.GetScene().Add(view);
+
+  application.SendNotification();
+  application.Render();
+
+  uint32_t animationCount = view.GetAnimationCount();
+  DALI_TEST_EQUALS(9, animationCount, TEST_LOCATION);
+
+  Animation animation1 = view.GetAnimation("Step Scale");
+  DALI_TEST_CHECK(animation1);
+  DALI_TEST_EQUALS(1.66667f, animation1.GetDuration(), 0.001f, TEST_LOCATION);
+
+  Animation animation2 = view.GetAnimation("CubicSpline Scale");
+  DALI_TEST_CHECK(animation2);
+  DALI_TEST_EQUALS(1.66667f, animation2.GetDuration(), 0.001f, TEST_LOCATION);
+
+  DALI_TEST_NOT_EQUALS(animation1, animation2, 0.0f, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
index acdf9d7..afe7253 100644 (file)
 using namespace Dali;
 using namespace Dali::Toolkit;
 
-void model_view_startup(void)
+void model3d_view_startup(void)
 {
   test_return_value = TET_UNDEF;
 }
 
-void model_view_cleanup(void)
+void model3d_view_cleanup(void)
 {
   test_return_value = TET_PASS;
 }
@@ -42,7 +42,7 @@ const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/";
 } // namespace
 
 // Negative test case for a method
-int UtcDaliModelViewUninitialized(void)
+int UtcDaliModel3dViewUninitialized(void)
 {
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliModel3dViewUninitialized");
@@ -66,7 +66,7 @@ int UtcDaliModelViewUninitialized(void)
 }
 
 // Positive test case for a method
-int UtcDaliModelViewNew(void)
+int UtcDaliModel3dViewNew(void)
 {
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliModel3dViewNew");
@@ -80,7 +80,7 @@ int UtcDaliModelViewNew(void)
 }
 
 // Positive test case for a method
-int UtcDaliModelViewDownCast(void)
+int UtcDaliModel3dViewDownCast(void)
 {
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliModelViewDownCast");
@@ -96,7 +96,7 @@ int UtcDaliModelViewDownCast(void)
 }
 
 // Positive test case for a method
-int UtcDaliModelViewPropertyNames(void)
+int UtcDaliModel3dViewPropertyNames(void)
 {
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliModel3dViewPropertyNames");
@@ -126,7 +126,7 @@ int UtcDaliModelViewPropertyNames(void)
 }
 
 // Positive test case for a method
-int UtcDaliModelViewAddRemove(void)
+int UtcDaliModel3dViewAddRemove(void)
 {
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliModel3dViewAddRemove");
@@ -150,7 +150,7 @@ int UtcDaliModelViewAddRemove(void)
   END_TEST;
 }
 
-int UtcDaliModelCopyAndAssignment(void)
+int UtcDaliModel3dViewCopyAndAssignment(void)
 {
   ToolkitTestApplication application;
 
@@ -169,7 +169,7 @@ int UtcDaliModelCopyAndAssignment(void)
   END_TEST;
 }
 
-int UtcDaliModelMoveConstructor(void)
+int UtcDaliModel3dViewMoveConstructor(void)
 {
   ToolkitTestApplication application;
 
@@ -187,7 +187,7 @@ int UtcDaliModelMoveConstructor(void)
   END_TEST;
 }
 
-int UtcDaliModelMoveAssignment(void)
+int UtcDaliModel3dViewMoveAssignment(void)
 {
   ToolkitTestApplication application;
 
@@ -206,7 +206,7 @@ int UtcDaliModelMoveAssignment(void)
   END_TEST;
 }
 
-int UtcDaliModelTypeRegistry(void)
+int UtcDaliModel3dViewTypeRegistry(void)
 {
   ToolkitTestApplication application;
 
@@ -225,7 +225,7 @@ int UtcDaliModelTypeRegistry(void)
   END_TEST;
 }
 
-int UtcDaliModelOnSizeSet(void)
+int UtcDaliModel3dViewOnSizeSet(void)
 {
   ToolkitTestApplication application;
 
diff --git a/dali-scene-loader/internal/controls/model-view/model-view-impl.cpp b/dali-scene-loader/internal/controls/model-view/model-view-impl.cpp
new file mode 100644 (file)
index 0000000..0004aac
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2022 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 "model-view-impl.h"
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <filesystem>
+
+// INTERNAL INCLUDES
+#include <dali-scene-loader/public-api/animation-definition.h>
+#include <dali-scene-loader/public-api/camera-parameters.h>
+#include <dali-scene-loader/public-api/dli-loader.h>
+#include <dali-scene-loader/public-api/gltf2-loader.h>
+#include <dali-scene-loader/public-api/light-parameters.h>
+#include <dali-scene-loader/public-api/load-result.h>
+#include <dali-scene-loader/public-api/node-definition.h>
+#include <dali-scene-loader/public-api/scene-definition.h>
+#include <dali-scene-loader/public-api/shader-definition-factory.h>
+#include <dali-scene-loader/public-api/controls/model-view/model-view.h>
+
+using namespace Dali;
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+BaseHandle Create()
+{
+  return Scene3D::ModelView::New(std::string());
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelView, Toolkit::Control, Create);
+DALI_TYPE_REGISTRATION_END()
+
+static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE  = 2u;
+static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
+
+static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
+
+static constexpr std::string_view KTX_EXTENSION  = ".ktx";
+static constexpr std::string_view OBJ_EXTENSION  = ".obj";
+static constexpr std::string_view GLTF_EXTENSION = ".gltf";
+static constexpr std::string_view DLI_EXTENSION  = ".dli";
+
+struct BoundingVolume
+{
+  void Init()
+  {
+    pointMin = Vector3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
+    pointMax = Vector3(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
+  }
+
+  void ConsiderNewPointInVolume(const Vector3& position)
+  {
+    pointMin.x = std::min(position.x, pointMin.x);
+    pointMin.y = std::min(position.y, pointMin.y);
+    pointMin.z = std::min(position.z, pointMin.z);
+
+    pointMax.x = std::max(position.x, pointMax.x);
+    pointMax.y = std::max(position.y, pointMax.y);
+    pointMax.z = std::max(position.z, pointMax.z);
+  }
+
+  Vector3 CalculateSize()
+  {
+    return pointMax - pointMin;
+  }
+
+  Vector3 CalculatePivot()
+  {
+    Vector3 pivot = pointMin / (pointMin - pointMax);
+    for(uint32_t i = 0; i < 3; ++i)
+    {
+      // To avoid divid by zero
+      if(pointMin[i] == pointMax[i])
+      {
+        pivot[i] = 0.5f;
+      }
+    }
+    return pivot;
+  }
+
+  Vector3 pointMin;
+  Vector3 pointMax;
+};
+
+Texture LoadCubeMap(const std::string& cubeMapPath)
+{
+  std::filesystem::path modelPath(cubeMapPath);
+  std::string           extension = modelPath.extension();
+  std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+
+  Texture cubeTexture;
+  if(extension == KTX_EXTENSION)
+  {
+    SceneLoader::CubeData cubeData;
+    if(SceneLoader::LoadCubeMapData(cubeMapPath, cubeData))
+    {
+      cubeTexture = cubeData.CreateTexture();
+    }
+    else
+    {
+      DALI_LOG_ERROR("Fail to load cube map, %s\n", cubeMapPath.c_str());
+    }
+  }
+
+  return cubeTexture;
+}
+
+void ConfigureBlendShapeShaders(
+  SceneLoader::ResourceBundle& resources, const SceneLoader::SceneDefinition& scene, Actor root, std::vector<SceneLoader::BlendshapeShaderConfigurationRequest>&& requests)
+{
+  std::vector<std::string> errors;
+  auto                     onError = [&errors](const std::string& msg) { errors.push_back(msg); };
+  if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
+  {
+    SceneLoader::ExceptionFlinger flinger(ASSERT_LOCATION);
+    for(auto& msg : errors)
+    {
+      flinger << msg << '\n';
+    }
+  }
+}
+
+void AddModelTreeToAABB(BoundingVolume& AABB, const SceneLoader::SceneDefinition& scene, const Dali::SceneLoader::Customization::Choices& choices, Dali::SceneLoader::Index iNode, Dali::SceneLoader::NodeDefinition::CreateParams& nodeParams, Matrix parentMatrix)
+{
+  static constexpr uint32_t BOX_POINT_COUNT             = 8;
+  static uint32_t           BBIndex[BOX_POINT_COUNT][3] = {{0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1}};
+
+  Matrix nodeMatrix;
+  const SceneLoader::NodeDefinition* node        = scene.GetNode(iNode);
+  Matrix                             localMatrix = node->GetLocalSpace();
+  Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix);
+
+  Vector3 volume[2];
+  if(node->GetExtents(nodeParams.mResources, volume[0], volume[1]))
+  {
+    for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i)
+    {
+      Vector4 position       = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f);
+      Vector4 objectPosition = nodeMatrix * position;
+      objectPosition /= objectPosition.w;
+
+      AABB.ConsiderNewPointInVolume(Vector3(objectPosition));
+    }
+  }
+
+  if(node->mCustomization)
+  {
+    if(!node->mChildren.empty())
+    {
+      auto                     choice = choices.Get(node->mCustomization->mTag);
+      Dali::SceneLoader::Index i      = std::min(choice != Dali::SceneLoader::Customization::NONE ? choice : 0, static_cast<Dali::SceneLoader::Index>(node->mChildren.size() - 1));
+
+      AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix);
+    }
+  }
+  else
+  {
+    for(auto i : node->mChildren)
+    {
+      AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix);
+    }
+  }
+}
+
+} // anonymous namespace
+
+ModelView::ModelView(const std::string& modelPath, const std::string& resourcePath)
+: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
+  mModelPath(modelPath),
+  mResourcePath(resourcePath),
+  mModelLayer(),
+  mModelRoot(),
+  mNaturalSize(Vector3::ZERO),
+  mModelPivot(AnchorPoint::CENTER),
+  mIblScaleFactor(1.0f),
+  mFitSize(false),
+  mFitCenter(false)
+{
+}
+
+ModelView::~ModelView()
+{
+}
+
+Dali::Scene3D::ModelView ModelView::New(const std::string& modelPath, const std::string& resourcePath)
+{
+  ModelView* impl = new ModelView(modelPath, resourcePath);
+
+  Dali::Scene3D::ModelView handle = Dali::Scene3D::ModelView(*impl);
+
+  // Second-phase init of the implementation
+  // This can only be done after the CustomActor connection has been made...
+  impl->Initialize();
+
+  return handle;
+}
+
+const Actor ModelView::GetModelRoot()
+{
+  return mModelRoot;
+}
+
+void ModelView::FitSize(bool fit)
+{
+  mFitSize = fit;
+  ScaleModel();
+}
+
+void ModelView::FitCenter(bool fit)
+{
+  mFitCenter = fit;
+  FitModelPosition();
+}
+
+void ModelView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor)
+{
+  Texture diffuseTexture = LoadCubeMap(diffuse);
+  if(diffuseTexture)
+  {
+    Texture specularTexture = LoadCubeMap(specular);
+    if(specularTexture)
+    {
+      mDiffuseTexture  = diffuseTexture;
+      mSpecularTexture = specularTexture;
+      mIblScaleFactor  = scaleFactor;
+
+      SetImageBasedLight(mModelRoot);
+    }
+  }
+}
+
+uint32_t ModelView::GetAnimationCount()
+{
+  return mAnimations.size();
+}
+
+Dali::Animation ModelView::GetAnimation(uint32_t index)
+{
+  Dali::Animation animation;
+  if(mAnimations.size() > index)
+  {
+    animation = mAnimations[index].second;
+  }
+  return animation;
+}
+
+Dali::Animation ModelView::GetAnimation(const std::string& name)
+{
+  Dali::Animation animation;
+  if(!name.empty())
+  {
+    for(auto&& animationData : mAnimations)
+    {
+      if(animationData.first == name)
+      {
+        animation = animationData.second;
+        break;
+      }
+    }
+  }
+  return animation;
+}
+
+///////////////////////////////////////////////////////////
+//
+// Private methods
+//
+
+void ModelView::OnSceneConnection(int depth)
+{
+  if(!mModelRoot)
+  {
+    LoadModel();
+  }
+
+  Control::OnSceneConnection(depth);
+}
+
+void ModelView::OnInitialize()
+{
+  Actor self  = Self();
+  mModelLayer = Layer::New();
+  mModelLayer.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
+  mModelLayer.SetProperty(Layer::Property::DEPTH_TEST, true);
+  mModelLayer.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  mModelLayer.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  mModelLayer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT,
+                              Dimension::ALL_DIMENSIONS);
+
+  // Models in glTF and dli are defined as right hand coordinate system.
+  // DALi uses left hand coordinate system. Scaling negative is for change winding order.
+  mModelLayer.SetProperty(Dali::Actor::Property::SCALE_Y, -1.0f);
+  self.Add(mModelLayer);
+}
+
+Vector3 ModelView::GetNaturalSize()
+{
+  if(!mModelRoot)
+  {
+    LoadModel();
+  }
+
+  return mNaturalSize;
+}
+
+float ModelView::GetHeightForWidth(float width)
+{
+  Extents padding;
+  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+  return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
+}
+
+float ModelView::GetWidthForHeight(float height)
+{
+  Extents padding;
+  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+  return Control::GetWidthForHeight(height) + padding.start + padding.end;
+}
+
+void ModelView::OnRelayout(const Vector2& size, RelayoutContainer& container)
+{
+  Control::OnRelayout(size, container);
+  ScaleModel();
+}
+
+void ModelView::LoadModel()
+{
+  std::filesystem::path modelPath(mModelPath);
+  if(mResourcePath.empty())
+  {
+    mResourcePath = std::string(modelPath.parent_path()) + "/";
+  }
+  std::string extension = modelPath.extension();
+  std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+
+  SceneLoader::ResourceBundle::PathProvider pathProvider = [&](SceneLoader::ResourceType::Value type) {
+    return mResourcePath;
+  };
+
+  SceneLoader::ResourceBundle                        resources;
+  SceneLoader::SceneDefinition                       scene;
+  std::vector<SceneLoader::AnimationGroupDefinition> animGroups;
+  std::vector<SceneLoader::CameraParameters>         cameraParameters;
+  std::vector<SceneLoader::LightParameters>          lights;
+
+  std::vector<Dali::SceneLoader::AnimationDefinition> animations;
+  animations.clear();
+
+  SceneLoader::LoadResult output{resources, scene, animations, animGroups, cameraParameters, lights};
+
+  if(extension == DLI_EXTENSION)
+  {
+    SceneLoader::DliLoader              loader;
+    SceneLoader::DliLoader::InputParams input{
+      pathProvider(SceneLoader::ResourceType::Mesh),
+      nullptr,
+      {},
+      {},
+      nullptr,
+      {}};
+    SceneLoader::DliLoader::LoadParams loadParams{input, output};
+    if(!loader.LoadScene(mModelPath, loadParams))
+    {
+      SceneLoader::ExceptionFlinger(ASSERT_LOCATION) << "Failed to load scene from '" << mModelPath << "': " << loader.GetParseError();
+    }
+  }
+  else if(extension == GLTF_EXTENSION)
+  {
+    SceneLoader::ShaderDefinitionFactory sdf;
+    sdf.SetResources(resources);
+    SceneLoader::LoadGltfScene(mModelPath, sdf, output);
+
+    resources.mEnvironmentMaps.push_back({});
+  }
+  else
+  {
+    DALI_LOG_ERROR("Unsupported model type.\n");
+  }
+
+  SceneLoader::Transforms                   xforms{SceneLoader::MatrixStack{}, SceneLoader::ViewProjection{}};
+  SceneLoader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
+  SceneLoader::Customization::Choices       choices;
+
+  mModelRoot = Actor::New();
+
+  BoundingVolume AABB;
+  for(auto iRoot : scene.GetRoots())
+  {
+    auto resourceRefs = resources.CreateRefCounter();
+    scene.CountResourceRefs(iRoot, choices, resourceRefs);
+    resources.CountEnvironmentReferences(resourceRefs);
+
+    resources.LoadResources(resourceRefs, pathProvider);
+
+    // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction.
+    // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling.
+    for(auto&& env : resources.mEnvironmentMaps)
+    {
+      env.first.mYDirection = Y_DIRECTION;
+    }
+
+    if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
+    {
+      scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
+      scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
+      ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
+
+      scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+
+      mModelRoot.Add(actor);
+    }
+
+    AddModelTreeToAABB(AABB, scene, choices, iRoot, nodeParams, Matrix::IDENTITY);
+  }
+
+  if(!animations.empty())
+  {
+    auto getActor = [&](const std::string& name) {
+      return mModelRoot.FindChildByName(name);
+    };
+
+    mAnimations.clear();
+    for(auto&& animation : animations)
+    {
+      Dali::Animation anim = animation.ReAnimate(getActor);
+
+      mAnimations.push_back({animation.mName, anim});
+    }
+  }
+
+  SetImageBasedLight(mModelRoot);
+
+  mNaturalSize = AABB.CalculateSize();
+  mModelPivot = AABB.CalculatePivot();
+  mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
+
+  FitModelPosition();
+  ScaleModel();
+
+  mModelLayer.Add(mModelRoot);
+}
+
+void ModelView::ScaleModel()
+{
+  if(mModelRoot)
+  {
+    if(mFitSize)
+    {
+      Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+      if(size.x > 0.0f && size.y > 0.0f)
+      {
+        float scaleFactor = MAXFLOAT;
+        scaleFactor       = std::min(size.x / mNaturalSize.x, scaleFactor);
+        scaleFactor       = std::min(size.y / mNaturalSize.y, scaleFactor);
+        mModelRoot.SetProperty(Dali::Actor::Property::SCALE, scaleFactor);
+      }
+      else
+      {
+        DALI_LOG_ERROR("ModelView size is wrong.");
+      }
+    }
+    else
+    {
+      mModelRoot.SetProperty(Dali::Actor::Property::SCALE, 1.0f);
+    }
+  }
+}
+
+void ModelView::FitModelPosition()
+{
+  if(mModelRoot)
+  {
+    if(mFitCenter)
+    {
+      // Loaded model pivot is not the model center.
+      mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+      mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
+    }
+    else
+    {
+      mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+      mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    }
+  }
+}
+
+void ModelView::SetImageBasedLight(Actor node)
+{
+  if(!mDiffuseTexture || !mSpecularTexture || !node)
+  {
+    return;
+  }
+
+  uint32_t rendererCount = node.GetRendererCount();
+  if(rendererCount)
+  {
+    node.RegisterProperty(SceneLoader::NodeDefinition::GetIblScaleFactorUniformName().data(), mIblScaleFactor);
+  }
+
+  for(uint32_t i = 0; i < rendererCount; ++i)
+  {
+    Dali::Renderer renderer = node.GetRendererAt(i);
+    if(renderer)
+    {
+      Dali::TextureSet textures = renderer.GetTextures();
+      if(textures)
+      {
+        uint32_t textureCount = textures.GetTextureCount();
+        // EnvMap requires at least 2 texture, diffuse and specular
+        if(textureCount > 2u)
+        {
+          textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, mDiffuseTexture);
+          textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, mSpecularTexture);
+        }
+      }
+    }
+  }
+
+  uint32_t childrenCount = node.GetChildCount();
+  for(uint32_t i = 0; i < childrenCount; ++i)
+  {
+    SetImageBasedLight(node.GetChildAt(i));
+  }
+}
+
+} // namespace Internal
+} // namespace Scene3D
+} // namespace Dali
diff --git a/dali-scene-loader/internal/controls/model-view/model-view-impl.h b/dali-scene-loader/internal/controls/model-view/model-view-impl.h
new file mode 100644 (file)
index 0000000..75c062a
--- /dev/null
@@ -0,0 +1,187 @@
+#ifndef DALI_SCENE_LOADER_INTERNAL_MODEL_VIEW_H
+#define DALI_SCENE_LOADER_INTERNAL_MODEL_VIEW_H
+
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/rendering/texture.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene-loader/public-api/controls/model-view/model-view.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+class ModelView;
+
+namespace Internal
+{
+/**
+ * @brief Impl class for ModelView.
+ */
+class ModelView : public Dali::Toolkit::Internal::Control
+{
+public:
+  using AnimationData = std::pair<std::string, Dali::Animation>;
+
+  /**
+   * @brief Creates a new ModelView.
+   *
+   * @return A public handle to the newly allocated ModelView.
+   */
+  static Dali::Scene3D::ModelView New(const std::string& modelPath, const std::string& resourcePath);
+
+  /**
+   * @copydoc ModelView::GetModelRoot()
+   */
+  const Actor GetModelRoot();
+
+  /**
+   * @copydoc ModelView::FitModel()
+   */
+  void FitSize(bool fit);
+
+  /**
+   * @copydoc ModelView::FitCenter()
+   */
+  void FitCenter(bool fit);
+
+  /**
+   * @copydoc ModelView::SetImageBasedLightSource()
+   */
+  void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor);
+
+  /**
+   * @copydoc ModelView::GetAnimationCount()
+   */
+  uint32_t GetAnimationCount();
+
+  /**
+   * @copydoc ModelView::GetAnimation()
+   */
+  Dali::Animation GetAnimation(uint32_t index);
+
+  /**
+   * @copydoc ModelView::GetAnimation()
+   */
+  Dali::Animation GetAnimation(const std::string& name);
+
+protected:
+  /**
+   * @brief Constructs a new ModelView.
+   */
+  ModelView(const std::string& modelPath, const std::string& resourcePath);
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ModelView();
+
+private:
+  /**
+   * @copydoc CustomActorImpl::OnSceneConnection()
+   */
+  void OnSceneConnection(int depth) override;
+
+  /**
+   * @copydoc Toolkit::Control::OnInitialize()
+   */
+  void OnInitialize() override;
+
+  /**
+   * @copydoc Toolkit::Control::GetNaturalSize
+   */
+  Vector3 GetNaturalSize() override;
+
+  /**
+   * @copydoc Toolkit::Control::GetHeightForWidth()
+   */
+  float GetHeightForWidth(float width) override;
+
+  /**
+   * @copydoc Toolkit::Control::GetWidthForHeight()
+   */
+  float GetWidthForHeight(float height) override;
+
+  /**
+   * @copydoc Toolkit::Control::OnRelayout()
+   */
+  void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
+
+  /**
+   * @brief Loads a model from file
+   */
+  void LoadModel();
+
+  /**
+   * @brief Scales the model to fit the control or to return to original size.
+   */
+  void ScaleModel();
+
+  /**
+   * @brief Changes model anchor point to set the model at center or returns to the original model pivot.
+   */
+  void FitModelPosition();
+
+  /**
+   * @brief Changes IBL information of the input node.
+   */
+  void SetImageBasedLight(Actor node);
+
+private:
+  std::string                  mModelPath;
+  std::string                  mResourcePath;
+  Dali::Layer                  mModelLayer;
+  Dali::Actor                  mModelRoot;
+  std::vector<AnimationData>   mAnimations;
+
+  Dali::Texture    mSpecularTexture;
+  Dali::Texture    mDiffuseTexture;
+  Vector3          mNaturalSize;
+  Vector3          mModelPivot;
+  float            mIblScaleFactor;
+  bool             mFitSize;
+  bool             mFitCenter;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Dali::Scene3D::Internal::ModelView& GetImpl(Dali::Scene3D::ModelView& obj)
+{
+  DALI_ASSERT_ALWAYS(obj);
+  Dali::RefObject& handle = obj.GetImplementation();
+  return static_cast<Dali::Scene3D::Internal::ModelView&>(handle);
+}
+
+inline const Dali::Scene3D::Internal::ModelView& GetImpl(const Dali::Scene3D::ModelView& obj)
+{
+  DALI_ASSERT_ALWAYS(obj);
+  const Dali::RefObject& handle = obj.GetImplementation();
+  return static_cast<const Dali::Scene3D::Internal::ModelView&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_SCENE_LOADER_INTERNAL_MODEL_VIEW_H
index 70d94f3..7987d79 100644 (file)
@@ -5,4 +5,5 @@ set(scene_loader_src_files ${scene_loader_src_files}
        ${scene_loader_internal_dir}/hash.cpp
        ${scene_loader_internal_dir}/json-reader.cpp
        ${scene_loader_internal_dir}/json-util.cpp
+       ${scene_loader_internal_dir}/controls/model-view/model-view-impl.cpp
 )
index 3c295e3..a55e9c3 100644 (file)
@@ -64,10 +64,11 @@ uniform vec3 uEmissiveFactor;
 #endif
 
 //// For IBL
+uniform sampler2D sbrdfLUT;
 uniform samplerCube sDiffuseEnvSampler;
 uniform samplerCube sSpecularEnvSampler;
-uniform sampler2D sbrdfLUT;
 uniform float uIblIntensity;
+uniform vec3 uYDirection;
 
 // For Alpha Mode.
 uniform lowp float uOpaque;
@@ -201,8 +202,8 @@ void main()
   mediump vec3 reflection = -normalize(reflect(v, n));
 
   lowp vec3 color = vec3(0.0);
-  lowp vec3 diffuseLight = linear(texture(sDiffuseEnvSampler, n).rgb);
-  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection).rgb);
+  lowp vec3 diffuseLight = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
+  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
   // retrieve a scale and bias to F0. See [1], Figure 3
   lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
 
diff --git a/dali-scene-loader/public-api/controls/model-view/model-view.cpp b/dali-scene-loader/public-api/controls/model-view/model-view.cpp
new file mode 100644 (file)
index 0000000..dc0f2aa
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2022 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-scene-loader/public-api/controls/model-view/model-view.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene-loader/internal/controls/model-view/model-view-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+ModelView::ModelView()
+{
+}
+
+ModelView::ModelView(const ModelView& modelView) = default;
+
+ModelView::ModelView(ModelView&& rhs) = default;
+
+ModelView& ModelView::operator=(const ModelView& modelView) = default;
+
+ModelView& ModelView::operator=(ModelView&& rhs) = default;
+
+ModelView::~ModelView()
+{
+}
+
+ModelView ModelView::New(const std::string& modelPath, const std::string& resourcePath)
+{
+  return Internal::ModelView::New(modelPath, resourcePath);
+}
+
+ModelView ModelView::DownCast(BaseHandle handle)
+{
+  return Control::DownCast<ModelView, Internal::ModelView>(handle);
+}
+
+ModelView::ModelView(Internal::ModelView& implementation)
+: Control(implementation)
+{
+}
+
+ModelView::ModelView(Dali::Internal::CustomActor* internal)
+: Control(internal)
+{
+  VerifyCustomActorPointer<Internal::ModelView>(internal);
+}
+
+const Actor ModelView::GetModelRoot()
+{
+  return GetImpl(*this).GetModelRoot();
+}
+
+void ModelView::FitSize(bool fit)
+{
+  GetImpl(*this).FitSize(fit);
+}
+
+void ModelView::FitCenter(bool fit)
+{
+  GetImpl(*this).FitCenter(fit);
+}
+
+void ModelView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor)
+{
+  GetImpl(*this).SetImageBasedLightSource(diffuse, specular, scaleFactor);
+}
+
+uint32_t ModelView::GetAnimationCount()
+{
+  return GetImpl(*this).GetAnimationCount();
+}
+
+Dali::Animation ModelView::GetAnimation(uint32_t index)
+{
+  return GetImpl(*this).GetAnimation(index);
+}
+
+Dali::Animation ModelView::GetAnimation(const std::string& name)
+{
+  return GetImpl(*this).GetAnimation(name);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
diff --git a/dali-scene-loader/public-api/controls/model-view/model-view.h b/dali-scene-loader/public-api/controls/model-view/model-view.h
new file mode 100644 (file)
index 0000000..5a53c40
--- /dev/null
@@ -0,0 +1,214 @@
+#ifndef DALI_SCENE_LOADER_MODEL_VIEW_H
+#define DALI_SCENE_LOADER_MODEL_VIEW_H
+
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-scene-loader/public-api/api.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal DALI_INTERNAL
+{
+class ModelView;
+}
+
+/**
+ * @addtogroup dali_toolkit_controls_model_view
+ * @{
+ */
+
+/**
+ * @brief ModelView is a control to show 3D model objects.
+ * ModelView supports to load glTF 2.0 and DLI models for the input format
+ * and also supports Physically Based Rendering with Image Based Lighting.
+ *
+ * The Animations defined in the glTF or DLI models are also loaded and can be retrieved by using GetAnimation() method.
+ * The number of animation is also retrieved by GetAnimationCount() method.
+ *
+ * By default, The loaded model has it's own position and size which are defined in vertex buffer regardless of the Control size.
+ * The model can be resized and repositioned to fit to the ModelView Control with FitSize() and FitCenter() methods.
+ *
+ * @code
+ *
+ * ModelView modelView = ModelView::New(modelUrl);
+ * modelView.SetProperty(Dali::Actor::Property::SIZE, Vector2(width, height));
+ * modelView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ * modelView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ * modelView.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
+ * modelView.FitSize(true);
+ * modelView.FitCenter(true);
+ * window.Add(modelView);
+ * uint32_t animationCount = modelView.GetAnimationCount();
+ * Dali::Animation animation = modelView.GetAnimation(0);
+ * animation.Play();
+ *
+ * @endcode
+ */
+class DALI_SCENE_LOADER_API ModelView : public Dali::Toolkit::Control
+{
+public:
+  /**
+   * @brief Create an initialized ModelView.
+   * @param[in] modelPath model file path.(e.g., glTF, and DLI).
+   * @param[in] resourcePath resource file path that includes binary, image etc.
+   * @note If resourcePath is empty, the parent directory path of modelPath is used for resource path.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static ModelView New(const std::string& modelPath, const std::string& resourcePath = std::string());
+
+  /**
+   * @brief Creates an uninitialized ModelView.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   */
+  ModelView();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~ModelView();
+
+  /**
+   * @brief Copy constructor.
+   * @param[in] modelView Handle to an object
+   */
+  ModelView(const ModelView& modelView);
+
+  /**
+   * @brief Move constructor
+   *
+   * @param[in] rhs A reference to the moved handle
+   */
+  ModelView(ModelView&& rhs);
+
+  /**
+   * @brief Assignment operator.
+   * @param[in] modelView Handle to an object
+   * @return reference to this
+   */
+  ModelView& operator=(const ModelView& modelView);
+
+  /**
+   * @brief Move assignment
+   *
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  ModelView& operator=(ModelView&& rhs);
+
+  /**
+   * @brief Downcasts an Object handle to ModelView.
+   *
+   * If handle points to a ModelView, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @param[in] handle Handle to an object
+   * @return Handle to a ModelView or an uninitialized handle
+   */
+  static ModelView DownCast(BaseHandle handle);
+
+  /**
+   * @brief Retrieves model root Actor.
+   * @return Root Actor of the model.
+   */
+  const Actor GetModelRoot();
+
+  /**
+   * @brief Fits the model to the Control size.
+   * @param[in] fit true to fit model size to control.
+   * @note This method makes model fit to the Control size by keeping original model ratio.
+   * It means If model size is (2, 2, 2) and ModelView size is (10, 8), then the model become looks (8, 8, 8).
+   * If ModelView Size x or y is 0, this method don't work anything.
+   * If ModelView Size z is 0, this method considers only x and y values of ModelView Size.
+   */
+  void FitSize(bool fit);
+
+  /**
+   * @brief Moves the model to the center of control.
+   * @param[in] fit true to fit model to center of control.
+   * @note This method doesn't changes size of model.
+   */
+  void FitCenter(bool fit);
+
+  /**
+   * @brief Changes Image Based Light as the input textures.
+   * @param[in] diffuse cube map that can be used as a diffuse IBL source.
+   * @param[in] specular cube map that can be used as a specular IBL source.
+   * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
+   */
+  void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor = 1.0f);
+
+  /**
+   * @brief Gets number of animations those loaded from model file.
+   * @return The number of loaded animations.
+   * @note This method should be called after Model load finished.
+   */
+  uint32_t GetAnimationCount();
+
+  /**
+   * @brief Gets animation at the index.
+   * @param[in] index Index of animation to be retrieved.
+   * @return Animation at the index.
+   * @note This method should be called after Model load finished.
+   */
+  Dali::Animation GetAnimation(uint32_t index);
+
+  /**
+   * @brief Retrieves animation with the given name.
+   * @param[in] name string name of animation to be retrieved.
+   * @return Animation that has the given name.
+   * @note This method should be called after Model load finished.
+   */
+  Dali::Animation GetAnimation(const std::string& name);
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Toolkit::Internal implementation.
+   *
+   * @param[in] implementation The Control implementation
+   */
+  DALI_INTERNAL ModelView(Internal::ModelView& implementation);
+
+  /**
+   * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
+   *
+   * @param[in] internal A pointer to the internal CustomActor
+   */
+  DALI_INTERNAL ModelView(Dali::Internal::CustomActor* internal);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE_LOADER_MODEL_VIEW_H
index 90b0f9e..0fcdee1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_SCENE_LOADER_ENVIRONMENT_DEFINITION_H
 #define DALI_SCENE_LOADER_ENVIRONMENT_DEFINITION_H
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -82,6 +82,7 @@ public: // DATA
   std::string mDiffuseMapPath;
   std::string mSpecularMapPath;
   Quaternion  mCubeOrientation = Quaternion::IDENTITY;
+  Vector3     mYDirection      = Vector3::ONE;
   float       mIblIntensity    = 1.0f;
   bool        mUseBrdfTexture  = false;
 };
index 488ed7b..dcdc4d3 100644 (file)
@@ -15,6 +15,7 @@ set(scene_loader_src_files ${scene_loader_src_files}
        ${scene_loader_public_api_dir}/material-definition.cpp
        ${scene_loader_public_api_dir}/matrix-stack.cpp
        ${scene_loader_public_api_dir}/mesh-definition.cpp
+       ${scene_loader_public_api_dir}/controls/model-view/model-view.cpp
        ${scene_loader_public_api_dir}/node-definition.cpp
        ${scene_loader_public_api_dir}/parse-renderer-state.cpp
        ${scene_loader_public_api_dir}/renderer-state.cpp
@@ -26,4 +27,4 @@ set(scene_loader_src_files ${scene_loader_src_files}
        ${scene_loader_public_api_dir}/string-callback.cpp
        ${scene_loader_public_api_dir}/utils.cpp
        ${scene_loader_public_api_dir}/view-projection.cpp
-)
+)
\ No newline at end of file
index 1766c3f..5838da1 100644 (file)
@@ -262,6 +262,13 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ
   if(mEnvironmentIdx < environments.size())
   {
     auto& envTextures = environments[mEnvironmentIdx].second;
+    // If pre-computed brdf texture is defined, set the texture.
+    if(envTextures.mBrdf)
+    {
+      textureSet.SetTexture(n, envTextures.mBrdf);
+      ++n;
+    }
+
     if(envTextures.mDiffuse)
     {
       textureSet.SetTexture(n, envTextures.mDiffuse);
@@ -278,12 +285,6 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ
       textureSet.SetSampler(n, specularSampler);
       ++n;
     }
-
-    // If pre-computed brdf texture is defined, set the texture.
-    if(envTextures.mBrdf)
-    {
-      textureSet.SetTexture(n, envTextures.mBrdf);
-    }
   }
   else
   {
index 7542782..e8dafa8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
 
 namespace Dali
 {
+namespace
+{
+constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
+constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
+}
+
 namespace SceneLoader
 {
+bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
+{
+  return false;
+}
+
 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
 {
   receiver.Register(ResourceType::Shader, mShaderIdx);
@@ -89,6 +100,50 @@ Matrix NodeDefinition::GetLocalSpace() const
   return localSpace;
 }
 
+std::string_view NodeDefinition::GetIblScaleFactorUniformName()
+{
+  return IBL_INTENSITY_STRING;
+}
+
+std::string_view NodeDefinition::GetIblYDirectionUniformName()
+{
+  return IBL_Y_DIRECTION;
+}
+
+bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
+{
+  if(mRenderable)
+  {
+    if(!mRenderable->GetExtents(resources, min, max))
+    {
+      // If the renderable node don't have mesh accessor, use size to compute extents.
+      min = -mSize / 2.0f;
+      max = mSize / 2.0f;
+    }
+    return true;
+  }
+  return false;
+}
+
+bool ModelNode::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
+{
+  auto& mesh = resources.mMeshes[mMeshIdx];
+  uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
+  uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
+  if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
+  {
+    min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
+    max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
+    if(minSize == 3u)
+    {
+      min.z = mesh.first.mPositions.mBlob.mMin[2];
+      max.z = mesh.first.mPositions.mBlob.mMax[2];
+    }
+    return true;
+  }
+  return false;
+}
+
 void ModelNode::RegisterResources(IResourceReceiver& receiver) const
 {
   Renderable::RegisterResources(receiver);
@@ -167,10 +222,11 @@ void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParam
   }
 
   Index envIdx = matDef.mEnvironmentIdx;
-  actor.RegisterProperty("uIblIntensity", resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
+  actor.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
+  actor.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
 
-  float opaque = 0.0f;
-  float mask = 0.0f;
+  float opaque      = 0.0f;
+  float mask        = 0.0f;
   float alphaCutoff = matDef.GetAlphaCutoff();
   if(!MaskMatch(matDef.mFlags, MaterialDefinition::TRANSPARENCY))
   {
index b496cf7..7b70931 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_SCENE_LOADER_NODE_DEFINITION_H_
 #define DALI_SCENE_LOADER_NODE_DEFINITION_H_
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -162,6 +162,7 @@ public: // TYPES
   public: // METHODS
     virtual ~Renderable() = default;
 
+    virtual bool GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const;
     virtual void RegisterResources(IResourceReceiver& receiver) const;
     virtual void ReflectResources(IResourceReflector& reflector);
     virtual void OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const;
@@ -217,8 +218,35 @@ public: // METHODS
    */
   Actor CreateActor(CreateParams& params) const;
 
+  /**
+   * @brief Gets local space matrix of this node
+   * @return Matrix of local space.
+   */
   Matrix GetLocalSpace() const;
 
+  /**
+   * @brief Retrieves minimum and maximum position of this node in local space.
+   * @param[in] resources ResourceBundle that contains mesh information of this node.
+   * @param[out] min Minimum position of the mesh of this node.
+   * @param[out] max Maximum position of the mesh of this node.
+   * @return true If the node has mesh.
+   */
+  bool GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const;
+
+  /**
+   * @brief Retrieves Scale Factor uniform name.
+   * This uniform name can be used to change scale factor for ibl.
+   * @return std::string_view of the scale factor uniform name.
+   */
+  static std::string_view GetIblScaleFactorUniformName();
+
+  /**
+   * @brief Retrieves ibl Ydirection uniform name.
+   * This uniform name can be used to flip y direction of ibl in shader.
+   * @return std::string_view of the YDirection uniform name.
+   */
+  static std::string_view GetIblYDirectionUniformName();
+
 public: // DATA
   static const std::string ORIGINAL_MATRIX_PROPERTY_NAME;
 
@@ -248,6 +276,7 @@ public: // DATA
   Index   mMaterialIdx = INVALID_INDEX;
 
 public: // METHODS
+  bool GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const override;
   void RegisterResources(IResourceReceiver& receiver) const override;
   void ReflectResources(IResourceReflector& reflector) override;
   void OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const override;