- Editado
Bone's local scale isn't local
Hi,
I'm using the latest C runtime. I'm trying to apply a scaling to a bone, which scales the image attached to the bone in a fixed way. In other words as the bone rotates the image itself just rotates without changing aspect ratio. So I tried changing the scaleX on the bone, which the documentation says is a local scale. However that didn't work, as the scaling applies in screen space not local to the bone, so as the bone rotates, the aspect ratio of the image changes. Am I misunderstanding something or is that a bug?
Cheers
Tony
Update: It's looking more like a bug now, as it works as expected on another image which doesn't use IK but does use a mesh.
Bone scaleX
is local, it is always in the direction the bone is pointing, as rendered in the editor.
Note that RegionAttachment scaleX
is always relative to the attachment, not the bone.
The editor uses the Spine Runtimes, so bone scale is definitely local scale. It could still be a bug, but it's not likely. Did you try what you are doing by changing bone local scaleX in the editor? The result should be the same as doing it at runtime via code.
Maybe you can post screenshots?
Thanks for replying. The weird thing is that it works fine in the editor using the Scale tool and scaling the root bone. I updated the C source from github a few hours ago just to make sure I was up to date.
I've attached a screenshot of the problem. I'm doing the same thing to the left leg as the right. However the (screen) right leg gets longer because it is rotated to the right. The IK constraint on it subsequently makes it bend.
scaleX
is in the direction the bone is pointing, so changing it will always make the bone longer or shorter. I think you just need to adjust scaleY, which is perpendicular to the direction the bone is pointing (unless there is shear or scale from a parent bone involved).
Apologies, I have been using scaleY all along, I just copied it down wrongly from from my code in my first post. As you can see, it works for the left leg. However scaleY doesn't work on the leg when it is rotated. It appears to be always in screen space, because if I rotate the leg down, the scale gradually becomes perpendicular to the bone.
You should see the same behavior in the editor. If you don't, it's a bug and we'd need the project file and images to debug further.
Note that if you use nonuniform scale on the parent bone when using 2 bone IK, the IK solution when the target is out of range may not rotate the bones so they both point straight to the target. This is because with nonuniform scale, pointing the bones straight can make the bones shorter than when they are bent. IK rotates the bones so the child tip is closest to the target. So, in your example where the leg is straight using IK, when you change scaleX or scaleY on the parent, it may cause the leg to bend.
To workaround this, you can make a new bone that is a sibling to the child bone, attach your images to the new bone, and scale it instead of the parent IK bone.
What's the best way to send you the project file and images?
Sorry, I should have mentioned: contact@esotericsoftware.com
Thanks for all your help so far. I was just about to email, but then I figured out what's going wrong. The issue is that the scale change is inherited in screen space. The scaling that I'm doing in the animation is actually done on the hips and that change is inherited all the way down the leg. As the hips get wider the left leg scales properly, but the right leg inherits the scale as screen space horizontal scaling rather than scaling local to the bone. What I expected to happen is that the scaling is inherited as a bone scale instead of a screen space scale.
I could work round this by un-checking inherit scale in the UI and doing the inheritance myself, but I need to be able to use IK constraints on the leg, so that's not an option (as it is greyed out in the UI). Even if I add an extra bone in before the leg to break the scale inheritance, the leg itself can still bend so I have the same issue between the upper and lower leg when it is bent.
What do you suggest I do?
Instead of parenting the upper leg bone to the hip, you can use a transform constraint and not constrain the scale, but only translation and rotation. Also make sure you set the constraint to local
.
Doing it this way you will be able to use an IK Constraint as well.
Thanks for your help on the move! I think I get what you're saying. However the problem is not the inheritance between the upper leg and the hip (which I could also break using another bone), but the upper leg to the lower leg. As they are both part of the IK constraint, I don't have the option of not inheriting the upper leg's scale change to the lower leg.
I edited the post a little and added a screenshot to clear things up.
Also, if you scale the root bone all bones will be affected, instead you could scale the hip bone, or another bone higher up the hierarchy than the leg bones, this would prevent any unwanted scaling on the legs.
Thanks for that, but I'm afraid that still doesn't look like a solution. My problem is that I want to do a local scale on both the upper AND the lower leg (The rest of the skeleton isn't an issue). However, as soon as I scale the upper leg, the scaling is inherited by the lower leg. That would be OK except the inheritance happens in screen space, but I want it to happen locally to the bone so when the lower leg is bent the leg doesn't change from getting fatter to getting longer.
Does that make sense?
It makes sense, I'll see if I can come up with something Creating an extra set of "shadow" bones might do the trick.
Thanks! Would it be a lot of work to allow IK constraints without inheriting scale (even if it were just done programatically from my code)? If inherit scale were turned off, the IK could work exactly as it does now, and that would be fine for my purposes.
Ok, I've set up a small project you can check out.
Try selecting L_bone1, L_bone2, L_bone1_attach, L_bone2_attach, and scale each bone locally on the X axis. Doing this should give you what you're after at runtime.
Note that the project was created with Spine 3.7.07-beta but the same setup will work in non-beta.
Regarding your other runtime question, this is something Nate or Mario will be better suited to answer.
Thanks for that, that looks like that will work! I'll wait and see if Nate or Mario say if there's a programatic option that doesn't involve doubling up bones and constraints before implementing.
tony escribióThe issue is that the scale change is inherited in screen space.
No, scale is always applied along the scaled bone's local axes. It only appears to use world axes because your hip bone is rotated to match the world axes.
The scaling that I'm doing in the animation is actually done on the hips and that change is inherited all the way down the leg. As the hips get wider the left leg scales properly, but the right leg inherits the scale as screen space horizontal scaling rather than scaling local to the bone. What I expected to happen is that the scaling is inherited as a bone scale instead of a screen space scale.
Scale is applied to child bones in the direction of the scaled bones axes. Open spineboy and scale the root bone on one axis. The whole skeleton is squashed. Imagine if scale worked like you want, scaling the root bone would cause spineboy to get weirdly stretched, but not in any useful way.
Scale used to work as you would like (solely to simplify the math and edge cases skewing scale brings), but it was much less powerful and meant skew was not possible.
Even if I add an extra bone in before the leg to break the scale inheritance, the leg itself can still bend so I have the same issue between the upper and lower leg when it is bent.
If you scale the hip and the legs inherit that scale, it will not work like you want. The direction the legs are scaled comes from the direction of the hip bone. As the leg bones rotate, they will change size.
Shiu's project adds a child to each IK bone so inherit scale can be disabled, then attachments go on that child. This is reasonable. I don't think the transform constraints to keep the legs in place are necessary. If you have attachments on the hip you need to scale, you can use the same approach and add a child bone with disable inherit scale.
Thanks for the clarification. That all makes sense. Thanks everyone for all your help!