Support glTF extention: KHR_texture_transform 78/301678/4
authorRichard Huang <r.huang@samsung.com>
Tue, 21 Nov 2023 11:43:42 +0000 (11:43 +0000)
committerRichard Huang <r.huang@samsung.com>
Thu, 23 Nov 2023 10:57:56 +0000 (10:57 +0000)
Change-Id: I54048e0c51c1331ca141d5af6486b9e1350e397a

12 files changed:
automated-tests/resources/TextureTransformMultiTest.bin [new file with mode: 0644]
automated-tests/resources/TextureTransformMultiTest.gltf [new file with mode: 0644]
automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp
automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/internal/loader/gltf2-asset.h
dali-scene3d/internal/loader/gltf2-util.cpp
dali-scene3d/internal/model-components/material-impl.cpp
dali-scene3d/internal/model-components/material-impl.h
dali-scene3d/public-api/loader/material-definition.cpp
dali-scene3d/public-api/loader/material-definition.h
dali-scene3d/public-api/loader/node-definition.cpp

diff --git a/automated-tests/resources/TextureTransformMultiTest.bin b/automated-tests/resources/TextureTransformMultiTest.bin
new file mode 100644 (file)
index 0000000..1dd626e
Binary files /dev/null and b/automated-tests/resources/TextureTransformMultiTest.bin differ
diff --git a/automated-tests/resources/TextureTransformMultiTest.gltf b/automated-tests/resources/TextureTransformMultiTest.gltf
new file mode 100644 (file)
index 0000000..9f37ec0
--- /dev/null
@@ -0,0 +1,3186 @@
+{
+    "asset" : {
+        "copyright" : "Copyright 2020 Analytical Graphics, Inc, CC-BY 4.0 https://creativecommons.org/licenses/by/4.0/ - Model and textures by Ed Mackey.",
+        "generator" : "Khronos glTF Blender I/O v1.2.75",
+        "version" : "2.0"
+    },
+    "extensionsUsed" : [
+        "KHR_texture_transform",
+        "KHR_materials_unlit",
+        "KHR_materials_clearcoat"
+    ],
+    "extensionsRequired" : [
+        "KHR_texture_transform"
+    ],
+    "scene" : 0,
+    "scenes" : [
+        {
+            "name" : "Scene",
+            "nodes" : [
+                0,
+                1,
+                2,
+                3,
+                4,
+                5,
+                6,
+                7,
+                8,
+                9,
+                10,
+                11,
+                12,
+                13,
+                14,
+                15,
+                16,
+                17,
+                18,
+                19,
+                20,
+                21,
+                22,
+                23,
+                24,
+                25,
+                26,
+                27,
+                28
+            ]
+        }
+    ],
+    "nodes" : [
+        {
+            "mesh" : 0,
+            "name" : "BaseColorUV0",
+            "translation" : [
+                0.10000000149011612,
+                0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 1,
+            "name" : "BaseColorUV1",
+            "translation" : [
+                0.3499999940395355,
+                0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 2,
+            "name" : "BaseColorSample",
+            "translation" : [
+                0.6000000238418579,
+                0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 3,
+            "name" : "Background",
+            "translation" : [
+                0,
+                0,
+                -0.02500000037252903
+            ]
+        },
+        {
+            "mesh" : 4,
+            "name" : "Labels"
+        },
+        {
+            "mesh" : 5,
+            "name" : "EmissionUV0",
+            "translation" : [
+                0.10000000149011612,
+                0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 6,
+            "name" : "EmissionUV1",
+            "translation" : [
+                0.3499999940395355,
+                0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 7,
+            "name" : "EmissionSample",
+            "translation" : [
+                0.6000000238418579,
+                0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 8,
+            "name" : "NormalUV0",
+            "translation" : [
+                0.10000000149011612,
+                0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 9,
+            "name" : "NormalUV1",
+            "translation" : [
+                0.3499999940395355,
+                0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 10,
+            "name" : "NormalSample",
+            "translation" : [
+                0.6000000238418579,
+                0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 11,
+            "name" : "MetalRoughUV0",
+            "translation" : [
+                0.10000000149011612,
+                0,
+                0
+            ]
+        },
+        {
+            "mesh" : 12,
+            "name" : "MetalRoughUV1",
+            "translation" : [
+                0.3499999940395355,
+                0,
+                0
+            ]
+        },
+        {
+            "mesh" : 13,
+            "name" : "MetalRoughSample",
+            "translation" : [
+                0.6000000238418579,
+                0,
+                0
+            ]
+        },
+        {
+            "mesh" : 14,
+            "name" : "OcclusionUV0",
+            "translation" : [
+                0.10000000149011612,
+                -0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 15,
+            "name" : "OcclusionUV1",
+            "translation" : [
+                0.3499999940395355,
+                -0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 16,
+            "name" : "OcclusionSample",
+            "translation" : [
+                0.6000000238418579,
+                -0.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 17,
+            "name" : "UnlitUV0",
+            "translation" : [
+                0.10000000149011612,
+                -0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 18,
+            "name" : "UnlitUV1",
+            "translation" : [
+                0.3499999940395355,
+                -0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 19,
+            "name" : "UnlitSample",
+            "translation" : [
+                0.6000000238418579,
+                -0.5,
+                0
+            ]
+        },
+        {
+            "mesh" : 20,
+            "name" : "ClearcoatUV0",
+            "translation" : [
+                0.10000000149011612,
+                -0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 21,
+            "name" : "ClearcoatUV1",
+            "translation" : [
+                0.3499999940395355,
+                -0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 22,
+            "name" : "ClearcoatSample",
+            "translation" : [
+                0.6000000238418579,
+                -0.75,
+                0
+            ]
+        },
+        {
+            "mesh" : 23,
+            "name" : "ClearcoatRoughUV0",
+            "translation" : [
+                0.10000000149011612,
+                -1,
+                0
+            ]
+        },
+        {
+            "mesh" : 24,
+            "name" : "ClearcoatRoughUV1",
+            "translation" : [
+                0.3499999940395355,
+                -1,
+                0
+            ]
+        },
+        {
+            "mesh" : 25,
+            "name" : "ClearcoatRoughSample",
+            "translation" : [
+                0.6000000238418579,
+                -1,
+                0
+            ]
+        },
+        {
+            "mesh" : 26,
+            "name" : "ClearcoatNormalUV0",
+            "translation" : [
+                0.10000000149011612,
+                -1.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 27,
+            "name" : "ClearcoatNormalUV1",
+            "translation" : [
+                0.3499999940395355,
+                -1.25,
+                0
+            ]
+        },
+        {
+            "mesh" : 28,
+            "name" : "ClearcoatNormalSample",
+            "translation" : [
+                0.6000000238418579,
+                -1.25,
+                0
+            ]
+        }
+    ],
+    "materials" : [
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "BaseColorTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 0,
+                    "texCoord" : 0
+                },
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "BaseColorTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 1,
+                    "texCoord" : 1
+                },
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "BaseColorSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "index" : 2,
+                    "texCoord" : 0
+                },
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "doubleSided" : true,
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "BackgroundMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.007408552337437868,
+                    0.07486194372177124,
+                    0.4639684557914734,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "doubleSided" : true,
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "LabelMat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "index" : 3,
+                    "texCoord" : 0
+                },
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                1,
+                1,
+                1
+            ],
+            "emissiveTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 4,
+                "texCoord" : 0
+            },
+            "name" : "EmissionTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0,
+                    0.15000000596046448,
+                    0,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                1,
+                1,
+                1
+            ],
+            "emissiveTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 5,
+                "texCoord" : 1
+            },
+            "name" : "EmissionTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0,
+                    0.15000000596046448,
+                    0,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                1,
+                1,
+                1
+            ],
+            "emissiveTexture" : {
+                "index" : 6,
+                "texCoord" : 0
+            },
+            "name" : "EmissionSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0,
+                    0.15000000596046448,
+                    0,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "NormalTest0Mat",
+            "normalTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 7,
+                "texCoord" : 0
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.10000000149011612
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "NormalTest1Mat",
+            "normalTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 8,
+                "texCoord" : 1
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.10000000149011612
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "NormalSampleMat",
+            "normalTexture" : {
+                "index" : 9,
+                "texCoord" : 0
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 0.10000000149011612
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "MetalRoughTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicRoughnessTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 10,
+                    "texCoord" : 0
+                }
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "MetalRoughTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicRoughnessTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 11,
+                    "texCoord" : 1
+                }
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "MetalRoughSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicRoughnessTexture" : {
+                    "index" : 12,
+                    "texCoord" : 0
+                }
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "OcclusionTest0Mat",
+            "occlusionTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 13,
+                "texCoord" : 0
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "OcclusionTest1Mat",
+            "occlusionTexture" : {
+                "extensions" : {
+                    "KHR_texture_transform" : {
+                        "offset" : [
+                            0.7049999535083774,
+                            0.28500004152502995
+                        ],
+                        "rotation" : 1.5707963705062866,
+                        "scale" : [
+                            0.3499999940395355,
+                            0.3499999940395355
+                        ]
+                    }
+                },
+                "index" : 14,
+                "texCoord" : 1
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "name" : "OcclusionSampleMat",
+            "occlusionTexture" : {
+                "index" : 15,
+                "texCoord" : 0
+            },
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.800000011920929,
+                    0.800000011920929,
+                    0.800000011920929,
+                    1
+                ],
+                "metallicFactor" : 0,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "extensions" : {
+                "KHR_materials_unlit" : {}
+            },
+            "name" : "UnlitTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 16,
+                    "texCoord" : 0
+                }
+            }
+        },
+        {
+            "extensions" : {
+                "KHR_materials_unlit" : {}
+            },
+            "name" : "UnlitTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "extensions" : {
+                        "KHR_texture_transform" : {
+                            "offset" : [
+                                0.7049999535083774,
+                                0.28500004152502995
+                            ],
+                            "rotation" : 1.5707963705062866,
+                            "scale" : [
+                                0.3499999940395355,
+                                0.3499999940395355
+                            ]
+                        }
+                    },
+                    "index" : 17,
+                    "texCoord" : 1
+                }
+            }
+        },
+        {
+            "extensions" : {
+                "KHR_materials_unlit" : {}
+            },
+            "name" : "UnlitSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorTexture" : {
+                    "index" : 18,
+                    "texCoord" : 0
+                }
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 19,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 20,
+                        "texCoord" : 1
+                    }
+                }
+            },
+            "name" : "ClearcoatTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatTexture" : {
+                        "index" : 21,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 1,
+                    "clearcoatRoughnessTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 22,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatRoughTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 1,
+                    "clearcoatRoughnessTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 23,
+                        "texCoord" : 1
+                    }
+                }
+            },
+            "name" : "ClearcoatRoughTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 1,
+                    "clearcoatRoughnessTexture" : {
+                        "index" : 24,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatRoughSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatNormalTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 25,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatNormalTest0Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatNormalTexture" : {
+                        "extensions" : {
+                            "KHR_texture_transform" : {
+                                "offset" : [
+                                    0.7049999535083774,
+                                    0.28500004152502995
+                                ],
+                                "rotation" : 1.5707963705062866,
+                                "scale" : [
+                                    0.3499999940395355,
+                                    0.3499999940395355
+                                ]
+                            }
+                        },
+                        "index" : 26,
+                        "texCoord" : 1
+                    }
+                }
+            },
+            "name" : "ClearcoatNormalTest1Mat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        },
+        {
+            "emissiveFactor" : [
+                0,
+                0,
+                0
+            ],
+            "extensions" : {
+                "KHR_materials_clearcoat" : {
+                    "clearcoatFactor" : 1,
+                    "clearcoatRoughnessFactor" : 0.029999999329447746,
+                    "clearcoatNormalTexture" : {
+                        "index" : 27,
+                        "texCoord" : 0
+                    }
+                }
+            },
+            "name" : "ClearcoatNormalSampleMat",
+            "pbrMetallicRoughness" : {
+                "baseColorFactor" : [
+                    0.0040703266859054565,
+                    0.030168700963258743,
+                    0.16859287023544312,
+                    1
+                ],
+                "metallicFactor" : 1,
+                "roughnessFactor" : 1
+            }
+        }
+    ],
+    "meshes" : [
+        {
+            "name" : "BaseColorUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 0,
+                        "NORMAL" : 1,
+                        "TEXCOORD_0" : 2,
+                        "TEXCOORD_1" : 3
+                    },
+                    "indices" : 4,
+                    "material" : 0
+                }
+            ]
+        },
+        {
+            "name" : "BaseColorUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 5,
+                        "NORMAL" : 6,
+                        "TEXCOORD_0" : 7,
+                        "TEXCOORD_1" : 8
+                    },
+                    "indices" : 4,
+                    "material" : 1
+                }
+            ]
+        },
+        {
+            "name" : "BaseColorSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 9,
+                        "NORMAL" : 10,
+                        "TEXCOORD_0" : 11
+                    },
+                    "indices" : 4,
+                    "material" : 2
+                }
+            ]
+        },
+        {
+            "name" : "BackgroundMesh",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 12,
+                        "NORMAL" : 13
+                    },
+                    "indices" : 4,
+                    "material" : 3
+                }
+            ]
+        },
+        {
+            "name" : "LabelMesh",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 14,
+                        "NORMAL" : 15,
+                        "TEXCOORD_0" : 16
+                    },
+                    "indices" : 17,
+                    "material" : 4
+                }
+            ]
+        },
+        {
+            "name" : "EmissionUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 18,
+                        "NORMAL" : 19,
+                        "TEXCOORD_0" : 20,
+                        "TEXCOORD_1" : 21
+                    },
+                    "indices" : 4,
+                    "material" : 5
+                }
+            ]
+        },
+        {
+            "name" : "EmissionUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 22,
+                        "NORMAL" : 23,
+                        "TEXCOORD_0" : 24,
+                        "TEXCOORD_1" : 25
+                    },
+                    "indices" : 4,
+                    "material" : 6
+                }
+            ]
+        },
+        {
+            "name" : "EmissionSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 26,
+                        "NORMAL" : 27,
+                        "TEXCOORD_0" : 28
+                    },
+                    "indices" : 4,
+                    "material" : 7
+                }
+            ]
+        },
+        {
+            "name" : "NormalUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 29,
+                        "NORMAL" : 30,
+                        "TEXCOORD_0" : 31,
+                        "TEXCOORD_1" : 32
+                    },
+                    "indices" : 4,
+                    "material" : 8
+                }
+            ]
+        },
+        {
+            "name" : "NormalUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 33,
+                        "NORMAL" : 34,
+                        "TEXCOORD_0" : 35,
+                        "TEXCOORD_1" : 36
+                    },
+                    "indices" : 4,
+                    "material" : 9
+                }
+            ]
+        },
+        {
+            "name" : "NormalSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 37,
+                        "NORMAL" : 38,
+                        "TEXCOORD_0" : 39
+                    },
+                    "indices" : 4,
+                    "material" : 10
+                }
+            ]
+        },
+        {
+            "name" : "MetalRoughUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 40,
+                        "NORMAL" : 41,
+                        "TEXCOORD_0" : 42,
+                        "TEXCOORD_1" : 43
+                    },
+                    "indices" : 4,
+                    "material" : 11
+                }
+            ]
+        },
+        {
+            "name" : "MetalRoughUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 44,
+                        "NORMAL" : 45,
+                        "TEXCOORD_0" : 46,
+                        "TEXCOORD_1" : 47
+                    },
+                    "indices" : 4,
+                    "material" : 12
+                }
+            ]
+        },
+        {
+            "name" : "MetalRoughSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 48,
+                        "NORMAL" : 49,
+                        "TEXCOORD_0" : 50
+                    },
+                    "indices" : 4,
+                    "material" : 13
+                }
+            ]
+        },
+        {
+            "name" : "OcclusionUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 51,
+                        "NORMAL" : 52,
+                        "TEXCOORD_0" : 53,
+                        "TEXCOORD_1" : 54
+                    },
+                    "indices" : 4,
+                    "material" : 14
+                }
+            ]
+        },
+        {
+            "name" : "OcclusionUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 55,
+                        "NORMAL" : 56,
+                        "TEXCOORD_0" : 57,
+                        "TEXCOORD_1" : 58
+                    },
+                    "indices" : 4,
+                    "material" : 15
+                }
+            ]
+        },
+        {
+            "name" : "OcclusionSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 59,
+                        "NORMAL" : 60,
+                        "TEXCOORD_0" : 61
+                    },
+                    "indices" : 4,
+                    "material" : 16
+                }
+            ]
+        },
+        {
+            "name" : "UnlitUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 62,
+                        "NORMAL" : 63,
+                        "TEXCOORD_0" : 64,
+                        "TEXCOORD_1" : 65
+                    },
+                    "indices" : 4,
+                    "material" : 17
+                }
+            ]
+        },
+        {
+            "name" : "UnlitUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 66,
+                        "NORMAL" : 67,
+                        "TEXCOORD_0" : 68,
+                        "TEXCOORD_1" : 69
+                    },
+                    "indices" : 4,
+                    "material" : 18
+                }
+            ]
+        },
+        {
+            "name" : "UnlitSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 70,
+                        "NORMAL" : 71,
+                        "TEXCOORD_0" : 72
+                    },
+                    "indices" : 4,
+                    "material" : 19
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 73,
+                        "NORMAL" : 74,
+                        "TEXCOORD_0" : 75,
+                        "TEXCOORD_1" : 76
+                    },
+                    "indices" : 77,
+                    "material" : 20
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 78,
+                        "NORMAL" : 79,
+                        "TEXCOORD_0" : 80,
+                        "TEXCOORD_1" : 81
+                    },
+                    "indices" : 77,
+                    "material" : 21
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 82,
+                        "NORMAL" : 83,
+                        "TEXCOORD_0" : 84
+                    },
+                    "indices" : 77,
+                    "material" : 22
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoarRoughUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 85,
+                        "NORMAL" : 86,
+                        "TEXCOORD_0" : 87,
+                        "TEXCOORD_1" : 88
+                    },
+                    "indices" : 77,
+                    "material" : 23
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatRoughUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 89,
+                        "NORMAL" : 90,
+                        "TEXCOORD_0" : 91,
+                        "TEXCOORD_1" : 92
+                    },
+                    "indices" : 77,
+                    "material" : 24
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatRoughSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 93,
+                        "NORMAL" : 94,
+                        "TEXCOORD_0" : 95
+                    },
+                    "indices" : 77,
+                    "material" : 25
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatNormalUV0",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 96,
+                        "NORMAL" : 97,
+                        "TEXCOORD_0" : 98,
+                        "TEXCOORD_1" : 99
+                    },
+                    "indices" : 4,
+                    "material" : 26
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatNormalUV1",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 100,
+                        "NORMAL" : 101,
+                        "TEXCOORD_0" : 102,
+                        "TEXCOORD_1" : 103
+                    },
+                    "indices" : 4,
+                    "material" : 27
+                }
+            ]
+        },
+        {
+            "name" : "ClearcoatNormalSample",
+            "primitives" : [
+                {
+                    "attributes" : {
+                        "POSITION" : 104,
+                        "NORMAL" : 105,
+                        "TEXCOORD_0" : 106
+                    },
+                    "indices" : 4,
+                    "material" : 28
+                }
+            ]
+        }
+    ],
+    "textures" : [
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 1
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 2
+        },
+        {
+            "source" : 2
+        },
+        {
+            "source" : 2
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 0
+        },
+        {
+            "source" : 3
+        },
+        {
+            "source" : 3
+        },
+        {
+            "source" : 3
+        },
+        {
+            "source" : 2
+        },
+        {
+            "source" : 2
+        },
+        {
+            "source" : 2
+        }
+    ],
+    "images" : [
+        {
+            "mimeType" : "image/png",
+            "name" : "TestMap",
+            "uri" : "TestMap.png"
+        },
+        {
+            "mimeType" : "image/png",
+            "name" : "TTMT_Labels",
+            "uri" : "TTMT_Labels.png"
+        },
+        {
+            "mimeType" : "image/png",
+            "name" : "TestMap_Normal",
+            "uri" : "TestMap_Normal.png"
+        },
+        {
+            "mimeType" : "image/png",
+            "name" : "TestMap",
+            "uri" : "TestMap-1.png"
+        }
+    ],
+    "accessors" : [
+        {
+            "bufferView" : 0,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 1,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 2,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 3,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 4,
+            "componentType" : 5123,
+            "count" : 6,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 5,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 6,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 7,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 8,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 9,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 10,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 11,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 12,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.9999999403953552,
+                1,
+                0
+            ],
+            "min" : [
+                -0.9999999403953552,
+                -1.399999976158142,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 13,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 14,
+            "componentType" : 5126,
+            "count" : 48,
+            "max" : [
+                0.8163908123970032,
+                0.9983971118927002,
+                0
+            ],
+            "min" : [
+                -0.9999999403953552,
+                -1.3177802562713623,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 15,
+            "componentType" : 5126,
+            "count" : 48,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 16,
+            "componentType" : 5126,
+            "count" : 48,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 17,
+            "componentType" : 5123,
+            "count" : 72,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 18,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 19,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 20,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 21,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 22,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 23,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 24,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 25,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 26,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 27,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 28,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 29,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 30,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 31,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 32,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 33,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 34,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 35,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 36,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 37,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 38,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 39,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 40,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 41,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 42,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 43,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 44,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 45,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 46,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 47,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 48,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 49,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 50,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 51,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 52,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 53,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 54,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 55,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 56,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 57,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 58,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 59,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 60,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 61,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 62,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 63,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 64,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 65,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 66,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 67,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 68,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 69,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 70,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 71,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 72,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 73,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.035051580518484116
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266523532569408
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 74,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 75,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 76,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 77,
+            "componentType" : 5123,
+            "count" : 1944,
+            "type" : "SCALAR"
+        },
+        {
+            "bufferView" : 78,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.03505159914493561
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266500249505043
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 79,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 80,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 81,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 82,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.03505159914493561
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266500249505043
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 83,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 84,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 85,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.03505159914493561
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266500249505043
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 86,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 87,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 88,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 89,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.03505159914493561
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266500249505043
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 90,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 91,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 92,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 93,
+            "componentType" : 5126,
+            "count" : 361,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0.03505159914493561
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                -0.014266500249505043
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 94,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 95,
+            "componentType" : 5126,
+            "count" : 361,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 96,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 97,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 98,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 99,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 100,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 101,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 102,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 103,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        },
+        {
+            "bufferView" : 104,
+            "componentType" : 5126,
+            "count" : 4,
+            "max" : [
+                0.10000002384185791,
+                0.10000002384185791,
+                0
+            ],
+            "min" : [
+                -0.10000002384185791,
+                -0.10000002384185791,
+                0
+            ],
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 105,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC3"
+        },
+        {
+            "bufferView" : 106,
+            "componentType" : 5126,
+            "count" : 4,
+            "type" : "VEC2"
+        }
+    ],
+    "bufferViews" : [
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 0
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 48
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 96
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 128
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 12,
+            "byteOffset" : 160
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 172
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 220
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 268
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 300
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 332
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 380
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 428
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 460
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 508
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 576,
+            "byteOffset" : 556
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 576,
+            "byteOffset" : 1132
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 384,
+            "byteOffset" : 1708
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 144,
+            "byteOffset" : 2092
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2236
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2284
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2332
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2364
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2396
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2444
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2492
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2524
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2556
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2604
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2652
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2684
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2732
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2780
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2812
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2844
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 2892
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2940
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 2972
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3004
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3052
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3100
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3132
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3180
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3228
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3260
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3292
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3340
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3388
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3420
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3452
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3500
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3548
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3580
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3628
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3676
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3708
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3740
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3788
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3836
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3868
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3900
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 3948
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 3996
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4028
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4076
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 4124
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 4156
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4188
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4236
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 4284
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 4316
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4348
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 4396
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 4444
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 4476
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 8808
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 13140
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 16028
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 3888,
+            "byteOffset" : 18916
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 22804
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 27136
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 31468
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 34356
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 37244
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 41576
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 45908
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 48796
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 53128
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 57460
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 60348
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 63236
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 67568
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 71900
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 74788
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 77676
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 4332,
+            "byteOffset" : 82008
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 2888,
+            "byteOffset" : 86340
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89228
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89276
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 89324
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 89356
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89388
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89436
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 89484
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 89516
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89548
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 48,
+            "byteOffset" : 89596
+        },
+        {
+            "buffer" : 0,
+            "byteLength" : 32,
+            "byteOffset" : 89644
+        }
+    ],
+    "buffers" : [
+        {
+            "byteLength" : 89676,
+            "uri" : "TextureTransformMultiTest.bin"
+        }
+    ]
+}
index 30ad93f..069941c 100644 (file)
@@ -538,6 +538,7 @@ int UtcDaliGltfLoaderSuccessShort(void)
         "MorphPrimitivesTest",
         "MRendererTest",
         "SimpleSparseAccessor",
+        "TextureTransformMultiTest",
         "AnimatedCube",
         /**
          * For the Avocado glTF file and its Assets
@@ -944,3 +945,48 @@ int UtcDaliGltfLoaderQuantizedMesh(void)
 
   END_TEST;
 }
+
+int UtcDaliGltfLoaderTextureTransform(void)
+{
+  Context ctx;
+
+  auto& resources = ctx.resources;
+
+  /**
+   * For the Avocado glTF file and its Assets
+   * Donated by Microsoft for glTF testing
+   * Take from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Avocado/glTF-Quantized
+   */
+  ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AvocadoQuantized.gltf", ctx.loadResult);
+
+  auto& scene = ctx.scene;
+  DALI_TEST_EQUAL(1u, scene.GetRoots().size());
+  DALI_TEST_EQUAL(1u, scene.GetNodeCount());
+
+  TestApplication app;
+
+  Customization::Choices choices;
+  for(auto iRoot : scene.GetRoots())
+  {
+    auto resourceRefs = resources.CreateRefCounter();
+    scene.CountResourceRefs(iRoot, choices, resourceRefs);
+    resources.mReferenceCounts = std::move(resourceRefs);
+    resources.CountEnvironmentReferences();
+    resources.LoadResources(ctx.pathProvider);
+  }
+
+  auto& materials = resources.mMaterials;
+  DALI_TEST_EQUAL(1u, materials.size());
+
+  auto  iMaterial = materials.begin();
+  auto& md        = iMaterial->first;
+
+  DALI_TEST_EQUAL(3u, md.mTextureStages.size());
+
+  Matrix3 textureTransformGroundTruth(0.000238f, 0.0f, 0.0f, 0.0f, 0.000242f, 0.0f, 0.00678f, 0.002982f, 1.0f);
+  DALI_TEST_EQUALS(md.mTextureStages[0].mTexture.mTransform, textureTransformGroundTruth, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(md.mTextureStages[1].mTexture.mTransform, textureTransformGroundTruth, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(md.mTextureStages[2].mTexture.mTransform, textureTransformGroundTruth, 0.01f, TEST_LOCATION);
+
+  END_TEST;
+}
index e3bc2d2..38eb937 100644 (file)
@@ -265,6 +265,13 @@ int UtcDaliMaterialCheckUniform(void)
   DALI_TEST_EQUALS(FaceCullingMode::BACK, renderer.GetProperty<FaceCullingMode::Type>(Dali::Renderer::Property::FACE_CULLING_MODE), TEST_LOCATION);
   DALI_TEST_EQUALS(DepthTestMode::ON, renderer.GetProperty<DepthTestMode::Type>(Dali::Renderer::Property::DEPTH_TEST_MODE), TEST_LOCATION);
 
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uBaseColorTextureTransformAvailable")), TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uNormalTextureTransformAvailable")), TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uNormalRoughnessTextureTransformAvailable")), TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uMetalRoughnessTextureTransformAvailable")), TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uOcclusionTextureTransformAvailable")), TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, renderer.GetProperty<float>(renderer.GetPropertyIndex("uEmissiveTextureTransformAvailable")), TEST_LOCATION);
+
   END_TEST;
 }
 
index db3c146..a77b5fa 100644 (file)
@@ -40,26 +40,42 @@ uniform lowp float uDielectricSpecular;
 #ifdef THREE_TEX
 #ifdef BASECOLOR_TEX
 uniform sampler2D sAlbedoAlpha;
+uniform float uBaseColorTextureTransformAvailable;
+uniform mat3 uBaseColorTextureTransform;
 #endif // BASECOLOR_TEX
 #ifdef METALLIC_ROUGHNESS_TEX
 uniform sampler2D sMetalRoughness;
+uniform float uMetalRoughnessTextureTransformAvailable;
+uniform mat3 uMetalRoughnessTextureTransform;
 #endif // METALLIC_ROUGHNESS_TEX
 #ifdef NORMAL_TEX
 uniform sampler2D sNormal;
+uniform float uNormalTextureTransformAvailable;
+uniform mat3 uNormalTextureTransform;
 uniform float uNormalScale;
 #endif // NORMAL_TEX
 #else // THREE_TEX
 uniform sampler2D sAlbedoMetal;
+uniform float uBaseColorTextureTransformAvailable;
+uniform mat3 uBaseColorTextureTransform;
 uniform sampler2D sNormalRoughness;
+uniform float uNormalRoughnessTextureTransformAvailable;
+uniform mat3 uNormalRoughnessTextureTransform;
 #endif
 
+
+
 #ifdef OCCLUSION
 uniform sampler2D sOcclusion;
+uniform float uOcclusionTextureTransformAvailable;
+uniform mat3 uOcclusionTextureTransform;
 uniform float uOcclusionStrength;
 #endif
 
 #ifdef EMISSIVE_TEXTURE
 uniform sampler2D sEmissive;
+uniform float uEmissiveTextureTransformAvailable;
+uniform mat3 uEmissiveTextureTransform;
 #endif
 uniform vec3 uEmissiveFactor;
 
@@ -127,6 +143,11 @@ vec3 linear(vec3 color)
   return pow(color, vec3(2.2));
 }
 
+vec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform)
+{
+    return vec2(textureTransform * vec3(texCoord, 1.0));
+}
+
 void main()
 {
   // Metallic and Roughness material properties are packed together
@@ -142,29 +163,34 @@ void main()
 #ifdef THREE_TEX
   // The albedo may be defined from a base texture or a flat color
 #ifdef BASECOLOR_TEX
-  lowp vec4 baseColor = texture(sAlbedoAlpha, vUV);
+  mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
+  lowp vec4 baseColor = texture(sAlbedoAlpha, baseColorTexCoords);
   baseColor = vColor * vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
 #else // BASECOLOR_TEX
   lowp vec4 baseColor = vColor * uColorFactor;
 #endif // BASECOLOR_TEX
 
 #ifdef METALLIC_ROUGHNESS_TEX
-  lowp vec4 metrou = texture(sMetalRoughness, vUV);
+  mediump vec2 metalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uMetalRoughnessTextureTransform), uMetalRoughnessTextureTransformAvailable);
+  lowp vec4 metrou = texture(sMetalRoughness, metalRoughnessTexCoords);
   metallic = metrou.METALLIC * metallic;
   perceptualRoughness = metrou.ROUGHNESS * perceptualRoughness;
 #endif // METALLIC_ROUGHNESS_TEX
 
 #ifdef NORMAL_TEX
-  n = texture(sNormal, vUV).rgb;
+  mediump vec2 normalTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalTextureTransform), uNormalTextureTransformAvailable);
+  n = texture(sNormal, normalTexCoords).rgb;
   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
 #endif // NORMAL_TEX
 #else // THREE_TEX
-  vec4 albedoMetal = texture(sAlbedoMetal, vUV);
+  mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
+  vec4 albedoMetal = texture(sAlbedoMetal, baseColorTexCoords);
   lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
 
   metallic = albedoMetal.METALLIC * metallic;
 
-  vec4 normalRoughness = texture(sNormalRoughness, vUV);
+  mediump vec2 normalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalRoughnessTextureTransform), uNormalRoughnessTextureTransformAvailable);
+  vec4 normalRoughness = texture(sNormalRoughness, normalRoughnessTexCoords);
   perceptualRoughness = normalRoughness.ROUGHNESS * perceptualRoughness;
 
   n = normalRoughness.rgb;
@@ -290,12 +316,14 @@ void main()
   }
 
 #ifdef OCCLUSION
-  lowp float ao = texture(sOcclusion, vUV).r;
+  mediump vec2 occlusionTexCoords = mix(vUV, computeTextureTransform(vUV, uOcclusionTextureTransform), uOcclusionTextureTransformAvailable);
+  lowp float ao = texture(sOcclusion, occlusionTexCoords).r;
   color = mix(color, color * ao, uOcclusionStrength);
 #endif // OCCLUSION
 
 #ifdef EMISSIVE_TEXTURE
-  lowp vec3 emissive = linear(texture(sEmissive, vUV).rgb) * uEmissiveFactor;
+  mediump vec2 emissiveTexCoords = mix(vUV, computeTextureTransform(vUV, uEmissiveTextureTransform), uEmissiveTextureTransformAvailable);
+  lowp vec3 emissive = linear(texture(sEmissive, emissiveTexCoords).rgb) * uEmissiveFactor;
 #else
   lowp vec3 emissive = uEmissiveFactor;
 #endif // EMISSIVE_TEXTURE
index e90cf38..16c7cd8 100644 (file)
@@ -20,7 +20,9 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/common/map-wrapper.h>
 #include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/matrix3.h>
 #include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector4.h>
 #include <cstdint>
 #include <memory>
@@ -375,6 +377,39 @@ struct Texture
   Ref<Sampler> mSampler;
 };
 
+struct TextureTransform
+{
+  float         mRotation = 0.0f;
+  Dali::Vector2 mUvOffset = Dali::Vector2::ZERO;
+  Dali::Vector2 mUvScale  = Dali::Vector2::ONE;
+  uint32_t      mTexCoord = 0u;
+
+  operator bool() const
+  {
+    return !Dali::EqualsZero(mRotation) || mUvOffset != Dali::Vector2::ZERO || mUvScale != Dali::Vector2::ONE || mTexCoord != 0u;
+  }
+
+  const Dali::Matrix3 GetTransform() const
+  {
+    // See: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform
+    Dali::Matrix3 translation = Dali::Matrix3(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, mUvOffset.x, mUvOffset.y, 1.0f);
+    Dali::Matrix3 rotation    = Dali::Matrix3(cos(-mRotation), sin(-mRotation), 0.0f, -sin(-mRotation), cos(-mRotation), 0.0f, 0.0f, 0.0f, 1.0f);
+    Dali::Matrix3 scale       = Dali::Matrix3(mUvScale.x, 0.0f, 0.0f, 0.0f, mUvScale.y, 0.0f, 0.0f, 0.0f, 1.0f);
+
+    return translation * rotation * scale;
+  }
+};
+
+struct TextureExtensions
+{
+  TextureTransform mTextureTransform;
+
+  operator bool() const
+  {
+    return mTextureTransform;
+  }
+};
+
 struct TextureInfo
 {
   Ref<gltf2::Texture> mTexture;
@@ -382,9 +417,11 @@ struct TextureInfo
   float               mScale    = 1.f;
   float               mStrength = 1.f;
 
+  TextureExtensions mTextureExtensions;
+
   operator bool() const
   {
-    return !!mTexture;
+    return mTexture;
   }
 };
 
index c4e492f..7979786 100644 (file)
@@ -49,12 +49,12 @@ static const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
   Geometry::TRIANGLE_FAN}; //...because Dali swaps the last two.
 
 static const Dali::Scripting::StringEnum EXTENSION_STRING_TABLE[] =
-{
-  {"NONE", gltf2::ExtensionFlags::NONE},
-  {"KHR_mesh_quantization", gltf2::ExtensionFlags::KHR_MESH_QUANTIZATION},
-  {"KHR_texture_transform", gltf2::ExtensionFlags::KHR_TEXTURE_TRANSFORM},
-  {"KHR_materials_ior", gltf2::ExtensionFlags::KHR_MATERIALS_IOR},
-  {"KHR_materials_specular", gltf2::ExtensionFlags::KHR_MATERIALS_SPECULAR},
+  {
+    {"NONE", gltf2::ExtensionFlags::NONE},
+    {"KHR_mesh_quantization", gltf2::ExtensionFlags::KHR_MESH_QUANTIZATION},
+    {"KHR_texture_transform", gltf2::ExtensionFlags::KHR_TEXTURE_TRANSFORM},
+    {"KHR_materials_ior", gltf2::ExtensionFlags::KHR_MATERIALS_IOR},
+    {"KHR_materials_specular", gltf2::ExtensionFlags::KHR_MATERIALS_SPECULAR},
 };
 static const unsigned int EXTENSION_STRING_TABLE_COUNT = sizeof(EXTENSION_STRING_TABLE) / sizeof(EXTENSION_STRING_TABLE[0]);
 
@@ -173,13 +173,31 @@ const json::Reader<gltf2::Texture>& GetTextureReader()
   return TEXURE_READER;
 }
 
+const json::Reader<gltf2::TextureTransform>& GetTextureTransformReader()
+{
+  static const auto TEXURE_TRANSFORM_READER = std::move(json::Reader<gltf2::TextureTransform>()
+                                                          .Register(*json::MakeProperty("rotation", json::Read::Number<float>, &gltf2::TextureTransform::mRotation))
+                                                          .Register(*json::MakeProperty("offset", gltf2::ReadDaliVector<Vector2>, &gltf2::TextureTransform::mUvOffset))
+                                                          .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector2>, &gltf2::TextureTransform::mUvScale))
+                                                          .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureTransform::mTexCoord)));
+  return TEXURE_TRANSFORM_READER;
+}
+
+const json::Reader<gltf2::TextureExtensions>& GetTextureExtensionsReader()
+{
+  static const auto TEXTURE_EXTENSION_READER = std::move(json::Reader<gltf2::TextureExtensions>()
+                                                           .Register(*json::MakeProperty("KHR_texture_transform", json::ObjectReader<gltf2::TextureTransform>::Read, &gltf2::TextureExtensions::mTextureTransform)));
+  return TEXTURE_EXTENSION_READER;
+}
+
 const json::Reader<gltf2::TextureInfo>& GetTextureInfoReader()
 {
   static const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
                                                      .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
                                                      .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
                                                      .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
-                                                     .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength)));
+                                                     .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength))
+                                                     .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::TextureExtensions>::Read, &gltf2::TextureInfo::mTextureExtensions)));
   return TEXURE_INFO_READER;
 }
 
@@ -588,18 +606,23 @@ TextureDefinition ConvertTextureInfo(const gltf2::TextureInfo& textureInfo, Conv
       std::vector<uint8_t> dataBuffer;
       dataBuffer.resize(textureInfo.mTexture->mSource->mBufferView->mByteLength);
       stream.read(reinterpret_cast<char*>(dataBuffer.data()), static_cast<std::streamsize>(static_cast<size_t>(textureInfo.mTexture->mSource->mBufferView->mByteLength)));
-      return TextureDefinition{std::move(dataBuffer), ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
+      return TextureDefinition{std::move(dataBuffer), ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode, textureInfo.mTextureExtensions.mTextureTransform.GetTransform()};
     }
     return TextureDefinition();
   }
   else
   {
-    return TextureDefinition{uri, ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
+    return TextureDefinition{uri, ConvertSampler(textureInfo.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode, textureInfo.mTextureExtensions.mTextureTransform.GetTransform()};
   }
 }
 
 void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, gltf2::TextureInfo textureInfo, const Dali::Scene3D::Loader::ImageMetadata& metaData, ConversionContext& context)
 {
+  // Overrides the textureInfo texCoord value if KHR_texture_transform extension is supported and texCoord value is supplied.
+  if(textureInfo.mTextureExtensions && textureInfo.mTexCoord != textureInfo.mTextureExtensions.mTextureTransform.mTexCoord && textureInfo.mTextureExtensions.mTextureTransform.mTexCoord != 0u)
+  {
+    textureInfo.mTexCoord = textureInfo.mTextureExtensions.mTextureTransform.mTexCoord;
+  }
   materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(textureInfo, context, metaData)});
   materialDefinition.mFlags |= semantic;
 }
@@ -767,19 +790,20 @@ MeshDefinition::Accessor ConvertMeshPrimitiveAccessor(const gltf2::Accessor& acc
 
   return MeshDefinition::Accessor{
     std::move(MeshDefinition::Blob{bufferViewOffset + accessor.mByteOffset,
-          accessor.GetBytesLength(),
-          static_cast<uint16_t>(bufferViewStride),
-          static_cast<uint16_t>(accessor.GetElementSizeBytes()),
-          accessor.mMin,
-          accessor.mMax}),
-      std::move(sparseBlob),
-      accessor.mBufferView ? accessor.mBufferView->mBuffer.GetIndex() : 0,
-      accessor.mNormalized};
+                                   accessor.GetBytesLength(),
+                                   static_cast<uint16_t>(bufferViewStride),
+                                   static_cast<uint16_t>(accessor.GetElementSizeBytes()),
+                                   accessor.mMin,
+                                   accessor.mMax}),
+    std::move(sparseBlob),
+    accessor.mBufferView ? accessor.mBufferView->mBuffer.GetIndex() : 0,
+    accessor.mNormalized};
 }
 
 MeshDefinition::Accessor* GetAccessorFromAttribute(gltf2::Attribute::HashType attributeHash,
-                                                   MeshDefinition& meshDefinition,
-                                                   bool& needNormals, bool& needTangents)
+                                                   MeshDefinition&            meshDefinition,
+                                                   bool&                      needNormals,
+                                                   bool&                      needTangents)
 {
   MeshDefinition::Accessor* accessorDest{nullptr};
 
@@ -841,10 +865,10 @@ MeshDefinition::Accessor* GetAccessorFromAttribute(gltf2::Attribute::HashType at
   return accessorDest;
 }
 
-void SetFlagsFromComponentType(const gltf2::Accessor& accessor,
+void SetFlagsFromComponentType(const gltf2::Accessor&     accessor,
                                gltf2::Attribute::HashType attributeHash,
-                               MeshDefinition& meshDefinition,
-                               bool isQuantized)
+                               MeshDefinition&            meshDefinition,
+                               bool                       isQuantized)
 {
   switch(gltf2::Attribute::TypeFromHash(attributeHash))
   {
@@ -1554,6 +1578,8 @@ void SetObjectReaders()
   json::SetObjectReader(GetImageReader());
   json::SetObjectReader(GetSamplerReader());
   json::SetObjectReader(GetTextureReader());
+  json::SetObjectReader(GetTextureTransformReader());
+  json::SetObjectReader(GetTextureExtensionsReader());
   json::SetObjectReader(GetTextureInfoReader());
   json::SetObjectReader(GetMaterialPbrReader());
   json::SetObjectReader(GetMaterialSpecularReader());
index 69a1a53..0e58ce5 100644 (file)
@@ -679,6 +679,14 @@ void Material::SetRendererUniform(Dali::Renderer renderer)
   renderer.RegisterProperty("uSpecularFactor", mTextureInformations[TextureIndex::SPECULAR].mFactor.x);
   renderer.RegisterProperty("uSpecularColorFactor", Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor));
 
+  // No requirement to use texture transform for runtime generated models.
+  renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uNormalTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 0.0f);
+
   float opaque = mIsOpaque ? 1.0f : 0.0f;
   float mask   = mIsMask ? 1.0f : 0.0f;
   renderer.RegisterProperty("uOpaque", opaque);
@@ -752,8 +760,7 @@ void Material::NotifyObserver()
     mObserverNotifying = false;
 
     // Resolve observer queue during notify
-    mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e)
-                                    { return !e.second; }),
+    mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e) { return !e.second; }),
                      mObservers.end());
   }
 }
index fe45dee..a41b8b5 100644 (file)
@@ -73,6 +73,7 @@ public:
     uint32_t                            mLoadingTaskId{0u};
     uint32_t                            mSemantic;
     Scene3D::Loader::ShaderOption::Type mShaderOptionType;
+    Matrix3                             mTransform{Scene3D::Loader::TextureDefinition::DEFAULT_TRANSFORM};
   };
 
   using TextureInformationContainer = std::vector<TextureInformation>;
@@ -278,10 +279,10 @@ private:
 
 private:
   // Delete copy & move operator
-  Material(const Material&)                = delete;
-  Material(Material&&)                     = delete;
+  Material(const Material&) = delete;
+  Material(Material&&)      = delete;
   Material& operator=(const Material& rhs) = delete;
-  Material& operator=(Material&& rhs)      = delete;
+  Material& operator=(Material&& rhs) = delete;
 
 private:
   ObserverContainer mObservers{}; ///< List of observers who need to be notified after some properties are changed.
index 0d3cb20..2e6ef5f 100644 (file)
@@ -33,6 +33,8 @@ namespace Scene3D
 {
 namespace Loader
 {
+const Matrix3 TextureDefinition::DEFAULT_TRANSFORM = Matrix3(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
+
 namespace
 {
 constexpr SamplerFlags::Type FILTER_MODES_FROM_DALI[]{
@@ -152,27 +154,30 @@ Sampler SamplerFlags::MakeSampler(Type flags)
   return sampler;
 }
 
-TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode)
+TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform)
 : mImageUri(imageUri),
   mSamplerFlags(samplerFlags),
   mMinImageDimensions(minImageDimensions),
-  mSamplingMode(samplingMode)
+  mSamplingMode(samplingMode),
+  mTransform(transform)
 {
 }
 
-TextureDefinition::TextureDefinition(std::string&& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode)
+TextureDefinition::TextureDefinition(std::string&& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform)
 : mImageUri(std::move(imageUri)),
   mSamplerFlags(samplerFlags),
   mMinImageDimensions(minImageDimensions),
-  mSamplingMode(samplingMode)
+  mSamplingMode(samplingMode),
+  mTransform(transform)
 {
 }
 
-TextureDefinition::TextureDefinition(std::vector<uint8_t>&& textureBuffer, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode)
+TextureDefinition::TextureDefinition(std::vector<uint8_t>&& textureBuffer, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform)
 : mImageUri(),
   mSamplerFlags(samplerFlags),
   mMinImageDimensions(minImageDimensions),
   mSamplingMode(samplingMode),
+  mTransform(transform),
   mTextureBuffer(std::move(textureBuffer))
 {
 }
index 43dabc1..a995d69 100644 (file)
@@ -111,16 +111,19 @@ struct DALI_SCENE3D_API SamplerFlags
  */
 struct DALI_SCENE3D_API TextureDefinition
 {
+  static const Matrix3 DEFAULT_TRANSFORM;
+
   std::string          mImageUri; // When the texture is loaded from embedded resources, this URI is used as a data stream.
   std::string          mDirectoryPath;
   SamplerFlags::Type   mSamplerFlags;
   ImageDimensions      mMinImageDimensions;
   SamplingMode::Type   mSamplingMode;
+  Matrix3              mTransform{DEFAULT_TRANSFORM}; // Texture transform
   std::vector<uint8_t> mTextureBuffer;
 
-  TextureDefinition(const std::string& imageUri = "", SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR);
-  TextureDefinition(std::string&& imageUri, SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR);
-  TextureDefinition(std::vector<uint8_t>&& textureBuffer, SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR);
+  TextureDefinition(const std::string& imageUri = "", SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR, Matrix3 transform = DEFAULT_TRANSFORM);
+  TextureDefinition(std::string&& imageUri, SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR, Matrix3 transform = DEFAULT_TRANSFORM);
+  TextureDefinition(std::vector<uint8_t>&& textureBuffer, SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR, Matrix3 transform = DEFAULT_TRANSFORM);
 };
 
 /**
index 56e63af..218969b 100644 (file)
@@ -350,6 +350,66 @@ void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinit
     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
   }
 
+  renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uNormalTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 0.0f);
+  renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 0.0f);
+
+  auto iTexture   = matDef.mTextureStages.begin();
+  auto checkStage = [&](uint32_t flags) {
+    return iTexture != matDef.mTextureStages.end() && MaskMatch(iTexture->mSemantic, flags);
+  };
+
+  if(checkStage(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC))
+  {
+    renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uBaseColorTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+
+    if(checkStage(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
+    {
+      renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 1.0f);
+      renderer.RegisterProperty("uNormalRoughnessTextureTransform", iTexture->mTexture.mTransform);
+      ++iTexture;
+    }
+  }
+  else if(checkStage(MaterialDefinition::ALBEDO))
+  {
+    renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uBaseColorTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+  }
+
+  if(checkStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+  {
+    renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uMetalRoughnessTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+  }
+
+  if(checkStage(MaterialDefinition::NORMAL))
+  {
+    renderer.RegisterProperty("uNormalTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uNormalTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+  }
+
+  if(checkStage(MaterialDefinition::OCCLUSION))
+  {
+    renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uOcclusionTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+  }
+
+  if(checkStage(MaterialDefinition::EMISSIVE))
+  {
+    renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 1.0f);
+    renderer.RegisterProperty("uEmissiveTextureTransform", iTexture->mTexture.mTransform);
+    ++iTexture;
+  }
+
   float opaque      = matDef.mIsOpaque ? 1.0f : 0.0f;
   float mask        = matDef.mIsMask ? 1.0f : 0.0f;
   float alphaCutoff = matDef.GetAlphaCutoff();
@@ -378,9 +438,10 @@ void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinit
       Internal::Material::TextureInformation textureInformation;
       if(matDef.CheckTextures(SEMANTICS[i]))
       {
-        textureInformation.mTexture = textures.GetTexture(textureIndex + textureIndexOffset);
-        textureInformation.mSampler = textures.GetSampler(textureIndex + textureIndexOffset);
-        textureInformation.mUrl     = matDef.mTextureStages[textureIndex].mTexture.mDirectoryPath + matDef.mTextureStages[textureIndex].mTexture.mImageUri;
+        textureInformation.mTexture   = textures.GetTexture(textureIndex + textureIndexOffset);
+        textureInformation.mSampler   = textures.GetSampler(textureIndex + textureIndexOffset);
+        textureInformation.mUrl       = matDef.mTextureStages[textureIndex].mTexture.mDirectoryPath + matDef.mTextureStages[textureIndex].mTexture.mImageUri;
+        textureInformation.mTransform = matDef.mTextureStages[textureIndex].mTexture.mTransform;
         textureIndex++;
       }
       textureInformation.mFactor = GetTextureFactor(matDef, SEMANTICS[i]);