KhronosGroup / KhronosGroup/glTF-Sample-Assets

Asset with skinned mesh not at root, and various transforms

Open
#263 8 comments 1 reaction 0 assignees View on GitHub

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

Image

(here, showing both the x- and the y-translation)

The right way of displaying it is this:

Image

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.