Coordinates of the tip of the bone

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Coordinates of the tip of the bone

Post by lehtiniemi »

Any ideas how to calculate the coordinates of the tip of the bone? I'm really bad at vectors...
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Coordinates of the tip of the bone

Post by synthsin75 »

The AS11 add bone tool snaps to the tip of a nearby bone, so you might look there.
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

synthsin75 wrote:The AS11 add bone tool snaps to the tip of a nearby bone, so you might look there.
Ah, of course! Sorry for this newbie question, but where can I access the built-in scripts on mac? I tried in ~/Library folders and Documents/Anime Studio Pro/ -> but couldn't find them... and thank you so much for your help...! Much appreciated!

I'll post a really cool script soon if I get it working!
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Coordinates of the tip of the bone

Post by synthsin75 »

I don't use Mac, but I seem to remember reading something about right-clicking the program and selecting show package or something.
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

synthsin75 wrote:I don't use Mac, but I seem to remember reading something about right-clicking the program and selecting show package or something.
Got it! Thanks! :)
User avatar
hayasidist
Posts: 3519
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Coordinates of the tip of the bone

Post by hayasidist »

Try this...

Code: Select all

	local i
	local vec = LM.Vector2:new_local()
	local tip = LM.Vector2:new_local()
	local angle, scale
	local bone, boneId
	local parent
	local pAngle

	boneId = moho:Skeleton():BoneID(bone)

	vec:Set(bone.fPos)
	angle = bone.fAngle
	length = bone.fLength
	scale = bone.fScale

	parent = bone.fParent
	pAngle = 0
	while parent >= 0 do
		local l = moho:Skeleton():Bone(parent).fAngle
		pAngle = pAngle + moho:Skeleton():Bone(parent).fAngle
		parent = moho:Skeleton():Bone(parent).fParent
	end

	local cum
	i, cum = math.modf ((pAngle + angle)/(2*math.pi))
	cum = cum*2*math.pi

	tip.x = scale * length * math.cos(cum) + vec.x
	tip.y = scale * length * math.sin(cum) + vec.y

this will give "world" coordinates of the tip in the same transform space as the bone -- IOW the vector layer in which the coordinates will be at the tip needs to be a child of the bone layer.
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

hayasidist wrote:Try this...

Code: Select all

	local i
	local vec = LM.Vector2:new_local()
	local tip = LM.Vector2:new_local()
	local angle, scale
	local bone, boneId
	local parent
	local pAngle

	boneId = moho:Skeleton():BoneID(bone)

	vec:Set(bone.fPos)
	angle = bone.fAngle
	length = bone.fLength
	scale = bone.fScale

	parent = bone.fParent
	pAngle = 0
	while parent >= 0 do
		local l = moho:Skeleton():Bone(parent).fAngle
		pAngle = pAngle + moho:Skeleton():Bone(parent).fAngle
		parent = moho:Skeleton():Bone(parent).fParent
	end

	local cum
	i, cum = math.modf ((pAngle + angle)/(2*math.pi))
	cum = cum*2*math.pi

	tip.x = scale * length * math.cos(cum) + vec.x
	tip.y = scale * length * math.sin(cum) + vec.y

this will give "world" coordinates of the tip in the same transform space as the bone -- IOW the vector layer in which the coordinates will be at the tip needs to be a child of the bone layer.
Whoa, thank you so much!!! I'm trying to use the coordinates of the bone to move the same Bone layer accordingly in opposite direction so that the bone tip appears to stay still, but the coordinates don't seem to match precisely. The movement is in the right direction, but doesn't align perfectly.

Should the coordinates match the layer movement of the same bone layer where the bone is or only the children layers of it (like you wrote)? If not, is there a way to transform the coordinates to match the movement of the bone layer itself?

An additional question, is it easy to get the bone base coordinates from your code or is it tip-only?

Thanks greatly for your help, so cool!
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

hayasidist wrote:Try this...

...

this will give "world" coordinates of the tip in the same transform space as the bone -- IOW the vector layer in which the coordinates will be at the tip needs to be a child of the bone layer.
By using your code and mixing it with another example I found, I'm now so far that I can calculate bone base position. I'm starting with base and get tip position later when everything works. I go through the bone chain recursively using your idea and then apply the transformation of each bone to the current bone. This works as long as the layer and its parent layers don't have any transformations. So I still need to transform the current layer somehow to compensate for any transformations that are being applied to it, to make the math with the bones work.

I'm imagining to fix this I'd have to use GetFullTransformation and use the Transform method on the bone itself. However, when I do this, it causes unwanted movement and breaks the location.

How can I apply the full transformation brought by the current layer scale, rotation and all parent layer transformations?

The full transformation code that doesn't work is commented in the example below:

Code: Select all

function JL_compensate_bone_movement:CalculateBonePosition(moho, bone)
	local skel

	skel = moho:Skeleton()

	if (skel == nil) then return end

	local i
	local vec = LM.Vector2:new_local()
	local boneId
	local parent

	boneId = moho:Skeleton():BoneID(bone)


    local curFrame = moho.layer:CurFrame()

    -- local m= LM.Matrix:new_local()
    -- moho.layer:GetLayerTransform(curFrame,m,moho.document)

	vec:Set(bone.fPos)

	parent = bone.fParent

	while parent >= 0 do

		skel:Bone(parent).fMovedMatrix:Transform(vec)

        parent = moho:Skeleton():Bone(parent).fParent
   end

   -- m:Transform(vec)

   return vec

end
User avatar
hayasidist
Posts: 3519
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Coordinates of the tip of the bone

Post by hayasidist »

this is why I said what I said about frames of reference.

where in the hierarchy is the layer in which you want to use the calculated coordinates?

e.g.
Bone <-- calculate here
>vector
Group
>vector <-- use here?

fPos as stored is not changed when the layer / camera transforms change
but the place on the screen where you'll find fPos does change
so if you have different transforms in the Bone and Group layers in the above example then the same fPos in the two vector layers will be in different places on the screen
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

hayasidist wrote:this is why I said what I said about frames of reference.

where in the hierarchy is the layer in which you want to use the calculated coordinates?

e.g.
Bone <-- calculate here
>vector
Group
>vector <-- use here?

fPos as stored is not changed when the layer / camera transforms change
but the place on the screen where you'll find fPos does change
so if you have different transforms in the Bone and Group layers in the above example then the same fPos in the two vector layers will be in different places on the screen
Yea you did warn me. :)

This is my structure:
Bone layer <--- calculate movement of selected bone here, apply same movement to layer here

I could imagine the structure being like this in a complicated character rig:
Group layer
--Group layer
--Bone layer <-- movement is still being calculated and applied on the same layer: from bone movement to layer movement

For what it's worth, I also dug up an old post by LM related to a different matter, it says like this:
The way to move the parent without moving the children would be to transform the children's position into world coordinates (using the inverse of the parent's fRestMatrix), move the parent, and then transform the children bones from world coordinates back to the parent's coordinates using the new fRestMatrix.
Maybe this can also give hints about the transform (that I don't understand).

Regarding to fPos, it doesn't seem to change when the parent bone is moving the bone, either. This is really weird to me. It only changes when the bone is translated directly but not when the parent is moving it as a part of the skeleton. This makes sense in that the skeleton calculates everything based on bone automations, but it seems to make reading and calculating the bone position unnecessary complicated. Same with fAnimPos.
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Coordinates of the tip of the bone

Post by synthsin75 »

lehtiniemi wrote:Regarding to fPos, it doesn't seem to change when the parent bone is moving the bone, either. This is really weird to me. It only changes when the bone is translated directly but not when the parent is moving it as a part of the skeleton. This makes sense in that the skeleton calculates everything based on bone automations, but it seems to make reading and calculating the bone position unnecessary complicated. Same with fAnimPos.
A bone's position is always relative to its parent bone (or layer if unparented). So moving/rotating a parent bone will not change the position of its child. A bone's parent is the 0,0 of its coordinate system and those coordinates move with the parent, which moves the child. But the child bone doesn't move in the parent bone coordinates unless you directly move that child.
User avatar
hayasidist
Posts: 3519
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Coordinates of the tip of the bone

Post by hayasidist »

lehtiniemi wrote: I'm trying to use the coordinates of the bone to move the same Bone layer accordingly in opposite direction so that the bone tip appears to stay still
ok so you want to translate the bone layer? (and not move the camera?) and it's all in just the x/y plane?

a couple of initial observations:
> the layer transform matrix will change because you'll be translating the layer. Seems at first sight to be a bit of a catch-22 - you need the transform to get a "screen" position; but you use that to move the layer and so that'll change the transform matrix... hmmm...
> the bone will (likely) move in an arc and the layer will move in a straight line, so the toe will start and end in the right place but won't be right part way through its movement-- so this will need layer keys more frequently than bone keys.
lehtiniemi
Posts: 107
Joined: Mon Jan 14, 2013 3:18 pm

Re: Coordinates of the tip of the bone

Post by lehtiniemi »

hayasidist wrote:
lehtiniemi wrote: I'm trying to use the coordinates of the bone to move the same Bone layer accordingly in opposite direction so that the bone tip appears to stay still
ok so you want to translate the bone layer? (and not move the camera?) and it's all in just the x/y plane?
This is correct. Well, it would be a plus if the script worked even if the camera is animated with pan/zoom. But for starters, we can say that moving camera doesn't need to work. I can always move the camera after the script has been used. And it's all x/y, yes. :)
hayasidist wrote: a couple of initial observations:
> the layer transform matrix will change because you'll be translating the layer. Seems at first sight to be a bit of a catch-22 - you need the transform to get a "screen" position; but you use that to move the layer and so that'll change the transform matrix... hmmm...
> the bone will (likely) move in an arc and the layer will move in a straight line, so the toe will start and end in the right place but won't be right part way through its movement-- so this will need layer keys more frequently than bone keys.
I wrote this into my code - now the script goes through the transformations and writes the changes into an array. It then goes through the array again, this time applying the transformations from the precalculated values.

I'm trying to wrap my head around this. On which level should I try to perform the calculations? As I understand, if I have the following:
Group layer
..Bone layer
....Bone at the end of the skeleton (like toe tip)

Does the transformation go something like this:
Camera transforms-> Group layer transforms -> Bone layer transforms -> Bones before the tip bone transform -> Toe tip bone

And to be able to figure out how much the bone moves on screen, I'll have to reverse engineer the whole chain? Or does GetFullTransformation return me the transformation of that full chain? So, is the following correct: if I figure out the local movement of the toe tip bone withing the bone layer and apply moho.layer:GetFullTransformation (how do I use this matrix on a vector? Transform()? Multiply?), do I get the amount of what the bone really moves on screen (comparable to fAnimPos)? Does GetFullTransformation return EVERYTHING that happens, like Bone layer scaling, rotation, group layer rotation? If camera movement makes this even more complicated, we can skip that for now.

Basically I need to calculate the offset of the selected bone movement, move the same Bone layer by the offset amount. And somehow make this so that this all can be contained and parent transformations are taken into account.

I know this is really complicated, I'm just trying to understand the transformation orders properly. Also, you've been helping me out really much - if you can help me solve this, I'm more than happy to give a small donation for your help! Just pm me in that case. The tool I'm building will be really useful and I'll share it here as well if I ever get it to work. The only missing part is to capture the bone offset.

Thanks again for your help, so much!
User avatar
hayasidist
Posts: 3519
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Coordinates of the tip of the bone

Post by hayasidist »

I'm pretty sure that FullTransform includes camera and all the effects of motion etc on all relevant layers. (http://aslua.com/index.php?show=method& ... orm&id=537)

to back the camera out I have successfully used:

Code: Select all

		m:Invert()
		moho.document:GetCameraMatrix(moho.frame, cam)
		m:Multiply(cam)
		m:Invert()
How I've used this in the past: m:Transform(vec) will work with the local camera settings to give an appropraitely transformed vec; but I've also found times when I needed to include z as in m:Transform(ved3d) and then project the resulting 3d vector onto the x/y plane.

There is a "right" sequence of transforms -- I can't find it right now... I **think** its z rotation before x/y rotation before translate .. but I can't be sure about where shear and scale fit in

with bones in the timeline it's also important to manage the fMovedMatrix via M_Skeleton:UpdateBoneMatrix(id) (see http://aslua.com/index.php?show=method& ... rix&id=885)


hope that's another centimetre forward!
User avatar
hayasidist
Posts: 3519
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Coordinates of the tip of the bone

Post by hayasidist »

Duh!
glimpse of the blindingly obvious.

I think you don't need any transforms other than the fMovedMatrix if it's all in the same layer and the camera doesn't move!!

vec0 = layerXY(at 0) + boneXY (at 0)

calculate bone tip as in my first post on that subject; then

layerNewXY = vec0 - tip

==

and with a bit of work you can get a plausible tracking with layer motion keyframes just at bone keyframes if you use and tweak Bezier interpolation.
Post Reply