Math help - vector angles and x y postions

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

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Math help - vector angles and x y postions

Post by heyvern »

Here's the scoop...

I'm revisiting my "aim bone" script. I made some improvements but I'm still stuck at one spot. I'm so close to fixing this I can taste it... and if it tastes delicious...

Here's how it works -

One bone "aims" at another bone. That works. You drag the target, the aiming bone follows it and scales down (not up) to maintain the aim and angle. Works great for easy foreshortening of limbs.

Here's the tricky part. I want to key frame the ability to turn of or "freeze" the scaling of the aiming bone. I've got that working by using scaling on the target bone. If the target bone is scaled above 1 then it stops scaling the aim bone. Below or equal to 1 it scales the aim bone for foreshortening of a limb.

For instance you drag the "forearm" target and the arm points towards the viewer. The forearm gets shorter to create the illusion. NOW you don't want the forearm to scale any more because you want to swing it from that angle maintaining a "circular" rotation. Can't do this by dragging the target. It's a linear motion.

Here's where I need the math help. The aim bone is aiming based on the magnitude or length of the vector of two points; its origin or base is the first point and the base of the target bone is the second point.

Works great. Now if I turn off the scaling of the aim bone (rotation only as the target bone moves), I need to use the angle and LENGTH or scale of the AIM bone to "force" or "freeze" the location of the target bone to the tip of the aim bone.

So you turn off the "scaling" on one frame and drag the target. The aim bone now only rotates and does not scale but its angle is still controlled by the target bone. When you turn scaling back on I need to make sure that during that movement of the target bone its location doesn't go past the end of the aim bone so there is no "jump" in the animation.

The aim and target bones have... "odd" parenting. With an arm set up the forearm is a child of the bicep target. The forearm and bicep targets are children of the shoulder or the "top" of that whole chain.

--------------------

My goal is to make sure that when dragging the target with "scaling" turned off for the aimer bone, the target bone can still be dragged but its position does not exceed the length of the aimer bone. It should never go past the tip of that bone but still can be dragged to change the angle. The aiming still works the same but now the target is constrained to the aim bone.

Then... when the scaling for this is turned back on that target bone is in the exact position to continue animating for the next key frame without causing an abrupt change in scaling of the aim bone.

This will work if I can just figure out how to "reverse" the "aiming" process in a sort of backwards way... in reverse sort of.

Here is the layer script code I have for aiming an "aimer" bone at a "target" bone. Just name two bones exactly the same, one has an ".aim" extension, the other has a ".trg" extension.

Code: Select all

function LayerScript(moho)

    local layer = moho.layer
    if ( not layer:IsBoneType() ) then
        return
    end
    local skel = moho:Skeleton()
    local boneCount = skel:CountBones()
    if ( boneCount == 0) then
        return
    end
    
    aimGrps = {} -- list of bone pairs for "pointing"

    for b = 0, boneCount - 1 do
        local bone = skel:Bone(b)
        local boneName = skel:Bone(b):Name()
        local Baimer = string.find(boneName, '.aim') -- bone that points to the target
        local Btarget = string.find(boneName, '.trg') -- target of the pointer bone
        
        if ( Baimer or Btarget ) then
            local name = string.sub(boneName, 1, -5)
            if (aimGrps[name] == nil) then
                aimGrps[name] = {}
            end
            if (Baimer) then
                aimGrps[name].Bp = bone
            end
            if (Btarget) then
                aimGrps[name].Bt = bone
            end
        end
    end    

    if (moho.frame > 0) then
        if (aimGrps ~= nil) then
            for b in aimGrps do
                local aimer = aimGrps[b].Bp -- aiming bone
                local target = aimGrps[b].Bt -- matching target bone
                local inverseAIM = LM.Matrix:new_local()

                local offset = LM.Vector2:new_local()
                offset.x = target.fPos.x
                offset.y = target.fPos.y
                
                local TRGBoneP = skel:Bone(target.fParent)
                if ( TRGBoneP ~= nil) then
                    TRGBoneP.fMovedMatrix:Transform(offset)
                end

                -- this is where the "magic" starts.

                local boneVec = LM.Vector2:new_local()
                local Bonelength = aimer.fLength
                boneVec = boneVec + offset
 
                inverseAIM:Set(aimer.fMovedMatrix)
                inverseAIM:Invert()
                inverseAIM:Transform(boneVec)
                inverseAIM:Transform(offset)

                --local dL = boneVec:Mag()
                local bscale = offset:Mag() / Bonelength
                local angle = aimer.fAngle
                angle = angle + math.atan2(boneVec.y, boneVec.x)
                while angle > 2 * math.pi do
                        angle = angle - 2 * math.pi
                end
                while angle < 0 do
                        angle = angle + 2 * math.pi
                end
                -- this is where the magic ends--
                --------------------------

                -- here's where the "magic" angle and scale values
                -- are applied to the aimer bones
                -- I need to somehow use all this "in reverse"
                -- to determine a position for the target bone
                -- when scaling is turned off.

                if (bscale <= 1.0) then
                    aimer.fScale = bscale
                end

                aimer.fAngle = angle
                
            end
            moho:Skeleton():UpdateBoneMatrix()
        end
    end
end
-vern
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

A simple diagram would help you and me :)
-G
Post Reply