From: seungho Date: Fri, 27 May 2022 10:10:57 +0000 (+0900) Subject: ModelView using scene-loader X-Git-Tag: dali_2.1.32~9^2~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=59d7a437c93f4864515c64d0aa3eacaebd293db6;hp=8ab66eeb0aa2426c25a8eef360d4754fbecfe628 ModelView using scene-loader Change-Id: I4b4c4859f890aedfd01a1ed208fb545484e9486a Signed-off-by: seungho --- diff --git a/automated-tests/resources/animationTest.gltf b/automated-tests/resources/animationTest.gltf new file mode 100644 index 0000000..6c7b12c --- /dev/null +++ b/automated-tests/resources/animationTest.gltf @@ -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 + } + ] +} diff --git a/automated-tests/src/dali-scene-loader/CMakeLists.txt b/automated-tests/src/dali-scene-loader/CMakeLists.txt index 8e700d8..387fb7b 100755 --- a/automated-tests/src/dali-scene-loader/CMakeLists.txt +++ b/automated-tests/src/dali-scene-loader/CMakeLists.txt @@ -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 index 0000000..edc6bc2 --- /dev/null +++ b/automated-tests/src/dali-scene-loader/utc-Dali-ModelView.cpp @@ -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 +#include +#include +#include + +#include + +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(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(Actor::Property::CONNECTED_TO_SCENE)); + + view.Remove(actor); + + DALI_TEST_CHECK(!actor.GetProperty(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(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(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(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(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(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(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(Dali::Actor::Property::SIZE); + DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); + + Vector3 rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); + DALI_TEST_EQUALS(Vector3(1, 1, 1), rootScale, TEST_LOCATION); + + view.FitSize(true); + rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); + DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); + + rootScale = rootActor.GetProperty(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(Dali::Actor::Property::SIZE); + DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); + + Vector3 rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); + DALI_TEST_EQUALS(Vector3(1, 1, 1), rootScale, TEST_LOCATION); + + view.FitSize(true); + rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); + DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); + + rootScale = rootActor.GetProperty(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(Dali::Actor::Property::ANCHOR_POINT); + DALI_TEST_EQUALS(Vector3(0.5, 0.5, 0.5), anchorPoint, TEST_LOCATION); + + view.FitCenter(true); + anchorPoint = rootActor.GetProperty(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 diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Model3dView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Model3dView.cpp index acdf9d7..afe7253 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Model3dView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Model3dView.cpp @@ -24,12 +24,12 @@ 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 index 0000000..0004aac --- /dev/null +++ b/dali-scene-loader/internal/controls/model-view/model-view-impl.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::max(), std::numeric_limits::max(), std::numeric_limits::max()); + pointMax = Vector3(std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::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&& requests) +{ + std::vector 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(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(Toolkit::Control::Property::PADDING); + return Control::GetHeightForWidth(width) + padding.top + padding.bottom; +} + +float ModelView::GetWidthForHeight(float height) +{ + Extents padding; + padding = Self().GetProperty(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 animGroups; + std::vector cameraParameters; + std::vector lights; + + std::vector 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(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 index 0000000..75c062a --- /dev/null +++ b/dali-scene-loader/internal/controls/model-view/model-view-impl.h @@ -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 +#include +#include +#include + +// INTERNAL INCLUDES +#include + +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; + + /** + * @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 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(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(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_SCENE_LOADER_INTERNAL_MODEL_VIEW_H diff --git a/dali-scene-loader/internal/file.list b/dali-scene-loader/internal/file.list index 70d94f3..7987d79 100644 --- a/dali-scene-loader/internal/file.list +++ b/dali-scene-loader/internal/file.list @@ -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 ) diff --git a/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag b/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag index 3c295e3..a55e9c3 100644 --- a/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag +++ b/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag @@ -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 index 0000000..dc0f2aa --- /dev/null +++ b/dali-scene-loader/public-api/controls/model-view/model-view.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(handle); +} + +ModelView::ModelView(Internal::ModelView& implementation) +: Control(implementation) +{ +} + +ModelView::ModelView(Dali::Internal::CustomActor* internal) +: Control(internal) +{ + VerifyCustomActorPointer(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 index 0000000..5a53c40 --- /dev/null +++ b/dali-scene-loader/public-api/controls/model-view/model-view.h @@ -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 + +// EXTERNAL INCLUDES +#include +#include + +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 diff --git a/dali-scene-loader/public-api/environment-definition.h b/dali-scene-loader/public-api/environment-definition.h index 90b0f9e..0fcdee1 100644 --- a/dali-scene-loader/public-api/environment-definition.h +++ b/dali-scene-loader/public-api/environment-definition.h @@ -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; }; diff --git a/dali-scene-loader/public-api/file.list b/dali-scene-loader/public-api/file.list index 488ed7b..dcdc4d3 100644 --- a/dali-scene-loader/public-api/file.list +++ b/dali-scene-loader/public-api/file.list @@ -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 diff --git a/dali-scene-loader/public-api/material-definition.cpp b/dali-scene-loader/public-api/material-definition.cpp index 1766c3f..5838da1 100644 --- a/dali-scene-loader/public-api/material-definition.cpp +++ b/dali-scene-loader/public-api/material-definition.cpp @@ -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 { diff --git a/dali-scene-loader/public-api/node-definition.cpp b/dali-scene-loader/public-api/node-definition.cpp index 7542782..e8dafa8 100644 --- a/dali-scene-loader/public-api/node-definition.cpp +++ b/dali-scene-loader/public-api/node-definition.cpp @@ -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. @@ -22,8 +22,19 @@ 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)) { diff --git a/dali-scene-loader/public-api/node-definition.h b/dali-scene-loader/public-api/node-definition.h index b496cf7..7b70931 100644 --- a/dali-scene-loader/public-api/node-definition.h +++ b/dali-scene-loader/public-api/node-definition.h @@ -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;