Deparenting Bones from Scale Hierarchy but keeping rotation/position relations

does this whole menu on blender have any effect to how the bone system works:
image

I need to be able to scale a bone and not have it scale the its children. If its not possible then I need to figure out a ratio system and recursively iterate over the bone hierarchy each time.

bone.scale(x,y,z,false) could be used, but its cumulative effect throws me off…
in this example:https://www.babylonjs-playground.com/#1BZJVJ#117

it does not just keep scaling the arm down or up when the slider is set to a value other then 1, why is that?
Any input?

https://www.babylonjs-playground.com/#1BZJVJ#125

So it does do what I thought it should if you turn off the animation, I guess that means if an animation is running it always sets the scale to 1 or something prior to the registerBeforeRender which then scales the bones? Explaining why it does not just inflate or explode like in #125

Pinging @gryff or @JCPalmer

It affects the output matrices, yes. I have not tried it, but turning off inherit scale in all the child bones might do as you wish.

yeah it works, but unfortunately the effects are cumulative… is there a way to make scale none cumulative?
setScale is none cumulative but has no argument to skip children.

Would a change to the bone scale function like this fix that? I would have to account for if the scale is of the bone was positive or negative on any of the axes though as well to set them to a -1 instead of 1.

I might be way off on this though… not really sure if it would be the local mat or the scale mat that I would want to reset to 1.

Also I am not proposing this as a change to the engine, but rather a function I will rebuild to serve my use case.

public scale(x: number, y: number, z: number, scaleChildren = false, noneCumulative = false): void {
    var locMat = this.getLocalMatrix();

    // Apply new scaling on top of current local matrix
    var scaleMat = Bone._tmpMats[0];
   
   if(noneCumulative){
        scaleMat[0]=1
        scaleMat[5]=1
        scaleMat[10]=1
    }

    Matrix.ScalingToRef(x, y, z, scaleMat);
    scaleMat.multiplyToRef(locMat, locMat);

    // Invert scaling matrix and apply the inverse to all children
    scaleMat.invert();

    for (var child of this.children) {
        var cm = child.getLocalMatrix();
        cm.multiplyToRef(scaleMat, cm);
        cm.multiplyAtIndex(12, x);
        cm.multiplyAtIndex(13, y);
        cm.multiplyAtIndex(14, z);

        child._markAsDirtyAndDecompose();
    }

    this._markAsDirtyAndDecompose();

    if (scaleChildren) {
        for (var child of this.children) {
            child.scale(x, y, z, scaleChildren);
        }
    }
}

@Deltakosh : Don’t think I can help DK. I have forgotten anything I ever learned about matrices ! :upside_down_face:

cheers, gryff :slight_smile:

1 Like

Maybe I’m not understanding the issue correctly but if you want to set every bone to (1, 1, 1), you can jsut go through all bones and force the scale to it

Or is it just for a specific bone? Then you need to cancel it in all children

yeah I was hoping for a way to make bone.scale act like bone.setScale as a direct scale not a cumulative one, I might have found a solution though.

YEah the problem is that bone structure is a hierarchy

My solution was to use scale, but store the last value set on the scale of the bone and then divide a 1,1,1 vector by the last scale set to get a “revert” scale. Apply the revert scale with bone.scale(revert.x,revert.y,revert.z,false) then
bone.scale(newScale.x,newScale.y,newScale.z,false)

its kinda hacky but it works :slight_smile:

1 Like