Thanks! Got it to work now, here's the resulting script: viewtopic.php?f=12&t=29029
My biggest mistake, however was that I went through the fMovedMatrix recursively. You only need to read the fMovedMatrix from the first parent. That matrix includes all the transformations that its parents cause. When I went through the whole skeleton recursively, this resulted that the earlier the parent, the more times its effect would be applied to the last bone.
Coordinates of the tip of the bone
Moderators: Víctor Paredes, Belgarath, slowtiger
-
- Posts: 107
- Joined: Mon Jan 14, 2013 3:18 pm
-
- Posts: 107
- Joined: Mon Jan 14, 2013 3:18 pm
Re: Coordinates of the tip of the bone
Oh, I came up way the most simple way to calculate this!
Basing on that you can get the transformation effect of the whole parent skeleton to the current bone by transforming the current bone with fMovedMatrix of the parent bone, you can think like this: the tip of the current bone is basically the base of the next child bone. Even if there is no child bone, the current bone still has fMovedMatrix which you can apply to the current bone coordinates. This will give you the base of the imaginary child bone. This way you have the tip coordinates of the current bone.
So instead of doing
, to get the tip coordinates just do
Basing on that you can get the transformation effect of the whole parent skeleton to the current bone by transforming the current bone with fMovedMatrix of the parent bone, you can think like this: the tip of the current bone is basically the base of the next child bone. Even if there is no child bone, the current bone still has fMovedMatrix which you can apply to the current bone coordinates. This will give you the base of the imaginary child bone. This way you have the tip coordinates of the current bone.
So instead of doing
Code: Select all
skel:Bone(current bone parent).fMovedMatrix:Transform(current bone fPos)
Code: Select all
skel:Bone(current bone).fMovedMatrix:Transform(current bone fPos)
- hayasidist
- Posts: 3523
- Joined: Wed Feb 16, 2011 8:12 pm
- Location: Kent, England
Re: Coordinates of the tip of the bone
That sounded so simple and straightforward - so I gave it a go ... but I'm getting different results from the "longhand" (seems to be right) and your shorter approach (can't get it to give the right answer!?)
I've made glaring errors in 2 lines of code before, and doubtless I will again -- but I just don't see what's fundamentally different between the above and your
Code: Select all
vec:Set(bone.fPos)
bone.fMovedMatrix:Transform(vec)
print (vec.x, vec.y) -- not consistent with observed tip position?
skel:Bone(current bone).fMovedMatrix:Transform(current bone fPos)
-
- Posts: 107
- Joined: Mon Jan 14, 2013 3:18 pm
Re: Coordinates of the tip of the bone
I can't tell... it looks the same. You must also remember to take the layer transform into account.hayasidist wrote:That sounded so simple and straightforward - so I gave it a go ... but I'm getting different results from the "longhand" (seems to be right) and your shorter approach (can't get it to give the right answer!?)I've made glaring errors in 2 lines of code before, and doubtless I will again -- but I just don't see what's fundamentally different between the above and yourCode: Select all
vec:Set(bone.fPos) bone.fMovedMatrix:Transform(vec) print (vec.x, vec.y) -- not consistent with observed tip position?
skel:Bone(current bone).fMovedMatrix:Transform(current bone fPos)
Code: Select all
local m= LM.Matrix:new_local()
moho.layer:GetLayerTransform(frame,m, nil) -- bypass camera transformations by passing nil as document object
Code: Select all
-- Calculates bone position and returns the coordinates within the current layer
function JL_walk_tool:CalculateBonePosition(moho, bone, trackBoneBase, frame)
local skel
skel = moho:Skeleton()
if (skel == nil) then return end
local i
local vec = LM.Vector2:new_local()
local boneId
local parent
local curFrame = moho.layer:CurFrame()
-- Save current frame
if not (frame == curFrame) then
moho:SetCurFrame(frame)
end
boneId = moho:Skeleton():BoneID(bone)
vec:Set(bone.fPos)
parent = bone.fParent
-- Apply parent transformation to the current bone. This seems to include all the transformations caused by the following parents so
-- you only need to read it from the first parent.
-- If user wants to track bone tip, this can be calculated by applying CURRENT bone transformation to the
-- current position instead, returning the child bone base coordinate (which equals current bone tip)
if (parent >= 0) then
-- Calculate base or tip coordinates?
if (trackBoneBase) then
skel:Bone(parent).fMovedMatrix:Transform(vec)
else
bone.fMovedMatrix:Transform(vec)
end
end
-- Lastly, apply transformations by the current layer
local m= LM.Matrix:new_local()
moho.layer:GetLayerTransform(frame,m, nil) -- bypass camera transformations by passing nil as document object
m:Transform(vec)
-- Move back to current original frame
if not (frame == curFrame) then
moho:SetCurFrame(curFrame)
end
return vec
end
- hayasidist
- Posts: 3523
- Joined: Wed Feb 16, 2011 8:12 pm
- Location: Kent, England
Re: Coordinates of the tip of the bone
sorry - I can't make it work. It's close but ...
I took your routine and hardwired a call to it
I took your routine and hardwired a call to it
Code: Select all
Print ("Bone", bone:Name(), "Base x, y", bone.fPos.x, bone.fPos.y, "angle/length/scale", bone.fAngle, bone.fLength, bone.fScale) -- confirms correct bone
vec = CalculateBonePosition (moho, bone, false, moho.frame)
Print ("Returned vec is", vec.x, vec.y) -- does not match the bone tip as observed by placing a vector shape inside or outside the bone group at the bone tip
-
- Posts: 107
- Joined: Mon Jan 14, 2013 3:18 pm
Re: Coordinates of the tip of the bone
Ah, but sorry I'm not using my function to get absolute coordinates. I'm only calculating movement in the local Bone layer, so I haven't tried absolute coordinates and how they match. But you should get absolute coordinates by changing the transform matrix at the end to:hayasidist wrote:sorry - I can't make it work. It's close but ...
I took your routine and hardwired a call to itCode: Select all
Print ("Bone", bone:Name(), "Base x, y", bone.fPos.x, bone.fPos.y, "angle/length/scale", bone.fAngle, bone.fLength, bone.fScale) -- confirms correct bone vec = CalculateBonePosition (moho, bone, false, moho.frame) Print ("Returned vec is", vec.x, vec.y) -- does not match the bone tip as observed by placing a vector shape inside or outside the bone group at the bone tip
Code: Select all
moho.layer:GetFullTransform(frame,m, moho.document)
I also assume that fPos is all the bone movement the parent bone can contain and it doesn't exclude something that fAnimPos contains. I don't think so. But if you are calculating coordinates at frame 0, then you have to use fRestMatrix instead of fMovedMatrix, I think.