KhronosGroup / KhronosGroup/glTF-Sample-Assets
Asset with skinned mesh not at root, and various transforms
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.1k
- Forks
- 108
- Avg merge
- 9h 39m
- Merged PRs (30d)
- 4
Description
(@emackey @lexaknyazev as discussed during the call)
There should be a test asset with a skinned mesh node that is not the root node, and where the skinned mesh node or its parent contain some transform. The goal of that would be to verify that viewers do not apply these transforms, because neither the parent transform nor the local transform should affect the skinned mesh.
I took the existing SimpleSkin example, and added the respective nodes:
- The skinned mesh node has a parent with a translation of (1,0,0)
- The skinned mesh node itself has a translation of (0,1,0)
I also added some "floor" (a unit square) to make it visually obvious when a viewer displays the wrong thing.
The wrong way of displaying it would be
(here, showing both the x- and the y-translation)
The right way of displaying it is this:
The warnings that are generated by the validator are
NODE_SKINNED_MESH_NON_ROOT: Node with a skinned mesh is not root. Parent transforms will not affect a skinned mesh. /nodes/1
NODE_SKINNED_MESH_LOCAL_TRANSFORMS: Local transforms will not affect a skinned mesh. /nodes/1
as expected.
(I checked it in https://gltf-viewer.donmccurdy.com/ and https://sandbox.babylonjs.com/ , and they both display it correctly)
The embedded version of the asset is shown here:
{
"accessors" : [ {
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 24,
"type" : "SCALAR",
"max" : [ 9 ],
"min" : [ 0 ]
}, {
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 10,
"type" : "VEC3",
"max" : [ 0.5, 2.0, 0.0 ],
"min" : [ -0.5, 0.0, 0.0 ]
}, {
"bufferView" : 1,
"byteOffset" : 160,
"componentType" : 5123,
"count" : 10,
"type" : "VEC4",
"max" : [ 0, 1, 0, 0 ],
"min" : [ 0, 0, 0, 0 ]
}, {
"bufferView" : 1,
"byteOffset" : 320,
"componentType" : 5126,
"count" : 10,
"type" : "VEC4",
"max" : [ 1.0, 1.0, 0.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0, 0.0 ]
}, {
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 6,
"type" : "SCALAR",
"max" : [ 3 ],
"min" : [ 0 ]
}, {
"bufferView" : 3,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 4,
"type" : "VEC3",
"max" : [ 0.5, 0.0, 0.5 ],
"min" : [ -0.5, 0.0, -0.5 ]
}, {
"bufferView" : 3,
"byteOffset" : 48,
"componentType" : 5126,
"count" : 4,
"type" : "VEC3",
"max" : [ 0.0, -1.0, 0.0 ],
"min" : [ 0.0, -1.0, 0.0 ]
}, {
"bufferView" : 4,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 12,
"type" : "SCALAR",
"max" : [ 5.5 ],
"min" : [ 0.0 ]
}, {
"bufferView" : 4,
"byteOffset" : 48,
"componentType" : 5126,
"count" : 12,
"type" : "VEC4",
"max" : [ 0.0, 0.0, 0.707, 1.0 ],
"min" : [ 0.0, 0.0, -0.707, 0.707 ]
}, {
"bufferView" : 5,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 2,
"type" : "MAT4",
"max" : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ],
"min" : [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 1.0 ]
} ],
"animations" : [ {
"channels" : [ {
"sampler" : 0,
"target" : {
"node" : 3,
"path" : "rotation"
}
} ],
"samplers" : [ {
"input" : 7,
"interpolation" : "LINEAR",
"output" : 8
} ]
} ],
"asset" : {
"generator" : "JglTF from https://github.com/javagl/JglTF",
"version" : "2.0"
},
"buffers" : [ {
"uri" : "data:application/gltf-buffer;base64,AAABAAMAAAADAAIAAgADAAUAAgAFAAQABAAFAAcABAAHAAYABgAHAAkABgAJAAgAAAAAvwAAAAAAAAAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAC/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAAL8AAIA/AAAAAAAAAAAAAAA/AACAPwAAAAAAAAAAAAAAvwAAwD8AAAAAAAAAAAAAAD8AAMA/AAAAAAAAAAAAAAC/AAAAQAAAAAAAAAAAAAAAPwAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAEA/AACAPgAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAAD8AAAA/AAAAAAAAAAAAAIA+AABAPwAAAAAAAAAAAACAPgAAQD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAABAAIAAQADAAIAAAAAvwAAAAAAAAC/AAAAPwAAAAAAAAC/AAAAvwAAAAAAAAA/AAAAPwAAAAAAAAA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAD8AAIA/AADAPwAAAEAAACBAAABAQAAAYEAAAIBAAACQQAAAoEAAALBAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAPT9ND/0/TQ/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAPT9NL/0/TQ/AAAAAAAAAAD0/TS/9P00PwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8=",
"byteLength" : 1004
} ],
"bufferViews" : [ {
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 48,
"target" : 34963
}, {
"buffer" : 0,
"byteOffset" : 48,
"byteLength" : 480,
"byteStride" : 16,
"target" : 34962
}, {
"buffer" : 0,
"byteOffset" : 528,
"byteLength" : 12,
"target" : 34963
}, {
"buffer" : 0,
"byteOffset" : 540,
"byteLength" : 96,
"byteStride" : 12,
"target" : 34962
}, {
"buffer" : 0,
"byteOffset" : 636,
"byteLength" : 240
}, {
"buffer" : 0,
"byteOffset" : 876,
"byteLength" : 128
} ],
"materials" : [ {
"pbrMetallicRoughness" : {
"baseColorFactor" : [ 0.0, 0.5, 0.0, 1.0 ],
"metallicFactor" : 0.0,
"roughnessFactor" : 1.0
},
"doubleSided" : true
}, {
"pbrMetallicRoughness" : {
"baseColorFactor" : [ 0.0, 0.0, 1.0, 1.0 ],
"metallicFactor" : 0.0,
"roughnessFactor" : 1.0
},
"doubleSided" : true
} ],
"meshes" : [ {
"primitives" : [ {
"attributes" : {
"POSITION" : 1,
"JOINTS_0" : 2,
"WEIGHTS_0" : 3
},
"indices" : 0,
"material" : 0,
"mode" : 4
} ]
}, {
"primitives" : [ {
"attributes" : {
"POSITION" : 5,
"NORMAL" : 6
},
"indices" : 4,
"material" : 1,
"mode" : 4
} ]
} ],
"nodes" : [ {
"children" : [ 1 ],
"translation" : [ 1.0, 0.0, 0.0 ]
}, {
"skin" : 0,
"mesh" : 0,
"translation" : [ 0.0, 1.0, 0.0 ]
}, {
"children" : [ 3 ]
}, {
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ],
"translation" : [ 0.0, 1.0, 0.0 ]
}, {
"mesh" : 1
} ],
"scene" : 0,
"scenes" : [ {
"nodes" : [ 0, 2, 4 ]
} ],
"skins" : [ {
"inverseBindMatrices" : 9,
"joints" : [ 2, 3 ]
} ]
}
If this is considered to be a suitable test asset, I'll create a PR.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing the embedded asset with the existing SimpleSkin example, then inspect the repository's conventions for sample assets. Verify the non-root skinned mesh and its parent and local translations produce the stated validator warnings and correct viewer behavior; done means the asset is ready for a PR.
Written by the indexing model from the issue text.
Assessment
- Domain
- content, testing
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100