Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting Bone Inverses #391

Open
aliascc opened this issue Nov 29, 2022 · 1 comment
Open

Setting Bone Inverses #391

aliascc opened this issue Nov 29, 2022 · 1 comment

Comments

@aliascc
Copy link

aliascc commented Nov 29, 2022

Hi,

I'm trying to add the inverse bind matrices to the skeleton but I am having the following problems (btw, I'm not an expect in JS. I'm trying to build some interactive 3D examples in Jupyter notebooks that use animations and this is the last step. Loading directly from GLTF sadly is not an option):

The Skeleton Model doesn't have the option to add it to it. I tried modifying the three-class-config to the following (adding boneInverses: new Types.ArrayBuffer('float32', [null, 16], {nullable: true}),):

Skeleton: {
        relativePath: './objects/Skeleton',
        properties: {
            bones: new Types.ThreeTypeArray('Bone'),
            boneInverses: new Types.ArrayBuffer('float32', [null, 16], {nullable: true}),
        },
        constructorArgs: ['bones', 'boneInverses'],
    },
  1. When creating an instance, I get a flat array instead of a 2D array (i.e. if I send 3 matrices4x4 I would expect a dimension of [3,16] but I get [48] which causes problems in the init function of the Skeleton.
    a. Any way to force the dimensions to be respected as stated in the three-class-config?
    b. Would it be ok to create a Skeleton.js next to Skeleton_autogen.js and extend constructThreeObject ? So I make sure to send the correct 2D array? Would this cause any issues?

  2. Even getting around problem 1 (which I tried and seemed to be working), I get an issue when I try to bind the Skeleton to the SkinnedMeshModel here:

    assignSkeleton(obj, key, value) {
        if (value) {
            obj.bind(value);
            obj.scale.multiplyScalar(1);
        }
    }

Calling the bind function for the SkinnedMesh expects the skeleton and bindMatrix but only the skeleton gets send:

bind( skeleton, bindMatrix ) {

		this.skeleton = skeleton;

		if ( bindMatrix === undefined ) {
			this.updateMatrixWorld( true );

			this.skeleton.calculateInverses();

			bindMatrix = this.matrixWorld;

		}

As it expects bindMatrix to be defined and it is not, it will override the inverse bind matrices by calling this.skeleton.calculateInverses() function

I haven't been able to get around this issue, as I don't want to break the current behavior. I've thought of maybe setting a boolean before assigning the skeleton using a different function but I don't really understand how the calls are made to JS, because a function I tried to set always got called after the assignment.

@vidartf
Copy link
Member

vidartf commented Feb 17, 2023

Hi,

Thanks for taking the time to write a detailed issue, and sorry for not replying to it sooner. Here are some comments that I hope are helpful:

  • First of all: why do you need to add this inverse matrix? Can it not be deterministically calculated from the bones? Or is it about it being quick to load?

  • b. Would it be ok to create a Skeleton.js next to Skeleton_autogen.js and extend constructThreeObject ? So I make sure to send the correct 2D array? Would this cause any issues?

    Making an override might be your best option here, as it is quite complex logic for the inverse.

  • Regarding the type declaration in the config: Do whatever gets the autogenerated version to a state that is as useful for overriding as possible. Ideally, you would have an InitializedThreeType (since if you don't specify it, three will calculate it for you), wrapping a ThreeTypeArray (since it is a regular JS array of BufferArrays on the three side), wrapping a Matrix4 type. I do not think the typing system allows such a combination currently, but your override might be able to reuse bits from those three.

  • You can also consider overriding syncToThreeObj, or having assignSkeleton for both bones and boneInverses, and then passing both props to bind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants