--- /dev/null
+{
+ "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
+ }
+ ]
+}
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
--- /dev/null
+/*
+ * 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
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;
}
} // namespace
// Negative test case for a method
-int UtcDaliModelViewUninitialized(void)
+int UtcDaliModel3dViewUninitialized(void)
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliModel3dViewUninitialized");
}
// Positive test case for a method
-int UtcDaliModelViewNew(void)
+int UtcDaliModel3dViewNew(void)
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliModel3dViewNew");
}
// Positive test case for a method
-int UtcDaliModelViewDownCast(void)
+int UtcDaliModel3dViewDownCast(void)
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliModelViewDownCast");
}
// Positive test case for a method
-int UtcDaliModelViewPropertyNames(void)
+int UtcDaliModel3dViewPropertyNames(void)
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliModel3dViewPropertyNames");
}
// Positive test case for a method
-int UtcDaliModelViewAddRemove(void)
+int UtcDaliModel3dViewAddRemove(void)
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliModel3dViewAddRemove");
END_TEST;
}
-int UtcDaliModelCopyAndAssignment(void)
+int UtcDaliModel3dViewCopyAndAssignment(void)
{
ToolkitTestApplication application;
END_TEST;
}
-int UtcDaliModelMoveConstructor(void)
+int UtcDaliModel3dViewMoveConstructor(void)
{
ToolkitTestApplication application;
END_TEST;
}
-int UtcDaliModelMoveAssignment(void)
+int UtcDaliModel3dViewMoveAssignment(void)
{
ToolkitTestApplication application;
END_TEST;
}
-int UtcDaliModelTypeRegistry(void)
+int UtcDaliModel3dViewTypeRegistry(void)
{
ToolkitTestApplication application;
END_TEST;
}
-int UtcDaliModelOnSizeSet(void)
+int UtcDaliModel3dViewOnSizeSet(void)
{
ToolkitTestApplication application;
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
${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
)
#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;
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);
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
#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.
std::string mDiffuseMapPath;
std::string mSpecularMapPath;
Quaternion mCubeOrientation = Quaternion::IDENTITY;
+ Vector3 mYDirection = Vector3::ONE;
float mIblIntensity = 1.0f;
bool mUseBrdfTexture = false;
};
${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
${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
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);
textureSet.SetSampler(n, specularSampler);
++n;
}
-
- // If pre-computed brdf texture is defined, set the texture.
- if(envTextures.mBrdf)
- {
- textureSet.SetTexture(n, envTextures.mBrdf);
- }
}
else
{
/*
- * 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);
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);
}
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))
{
#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.
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;
*/
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;
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;