Possible to copy vector point motion from bone influence?

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

Moderators: Víctor Paredes, Belgarath, slowtiger

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

Possible to copy vector point motion from bone influence?

Post by heyvern »

What I mean is, would it be possible to calculate on a bone key frame the position of the points moved by the bones so that this motion could be "copied" as point motion to the vector layer instead of bone movement?

This would be great for doing lip sync switches using bones to manipulate the mouth.

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

I guess you want the points positions to be stored as keys in the Point Motion animation channel. That is tricky, because the updated shape would be distorted immediately by bone influence.

IMO You would need to use a duplicate vector layer with all the points released. The points in the mesh of that duplicate layer would be positioned the same as in the original vector layer. I think that would be feasible.

I think the best solution is a menu script that acts on the currently selected bone layer (and its child layers). It would need to create a duplicate bone layer without the bones, but with the bone animation transformed into point animation.
Last edited by Rasheed on Tue Dec 05, 2006 1:34 pm, edited 1 time in total.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Yes, I don't need the bone motion to be kept anyway.

Actually, if the points were "immediately distorted" by the bones that would be fine. I would just drag that layer out of the bone folder anyway. I would make a duplicate of the vector layer first so I have a "backup" so to speak.

I would be using the bone layer as a switch layer creation tool.

I just wasn't sure if actual point motion is even "recorded" in AS when those points are moved by a bone.

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

heyvern wrote:I just wasn't sure if actual point motion is even "recorded" in AS when those points are moved by a bone.
Well, we just have to find out, don't we?
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

Heyvern, And if you use your tip of point interpolation for switch layers applied to bone layers?
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

Well, the point motion is recorded into keys only relative to the layer. So I needed two layer scripts to pull this off.

You create an original vector layer, which you put into the bone layer, and you create an exact copy of the vector layer, which you can put anywhere you want in the document.

Put this script into the original layer:

Code: Select all

-- org layer script.lua

function LayerScript(moho)

    local mesh = moho:Mesh()
    if ( mesh == nil or mesh:CountPoints() == 0 or moho.frame == 0 ) then
        return
    end
    
    local frame = moho.frame
    
    if ( Pos == nil ) then
        Pos = {}
    end
    
    if (Pos[frame] == nil ) then
        Pos[frame] = {}
        for i=0, mesh:CountPoints() - 1 do
            local pt = mesh:Point(i)
            Pos[frame][i] = pt.fPos
        end
    end
end
And this script into the copy layer:

Code: Select all

-- copy layer script.lua

function LayerScript(moho)

    local mesh = moho:Mesh()
    if ( mesh == nil or mesh:CountPoints() == 0 or moho.frame == 0 ) then
        return
    end
    
    local frame = moho.frame
    
    if ( Pos ~= nil and Pos[frame] ~= nil ) then
        for i=0, mesh:CountPoints() - 1 do
            local pt = mesh:Point(i)
            pt:SetPos( Pos[frame][i], frame )
            pt.fSelected = true
            pt.fAnimPos:AddKey(moho.frame)
        end
        moho:UpdateSelectedChannels()
        mesh:SelectNone()
    end

end
And presto!

It copies the points of one vector layer into another and records all point motion through the global variable Pos. This variable is a table containing all the vectors of all the frames (well, except frame zero) of all the points in the original layer.

The keys are recorded in the copy layer by selecting every point and use the member function UpdateSelectedChannels() of the moho object. After that, the points are deselected.

To run the scripts do the following:
  • make a copy of the original layer
  • turn off all onion skinning
  • go to frame zero
  • embed the org layer script in the original layer
  • embed the copy layer script in the copied layer
  • run the animation
  • go to frame zero
  • remove the layer scripts from the original and copied layers.
Mind you, that this trick only works for a single vector layer. For a multi vector layer layer script, you need to add the layer name to the Pos table, and change the script accordingly. The copy layer script then has to check for a particular layer name, and read the point motion of that layer through the global variable Pos. The problem is that the layer name then needs to be hard coded into the script.

So, I think it is best if you have several layers to transform, do one at a time, so you end up with copies of your original layers. However, for some reason it crashed Moho each time I changed layers. So restart Moho for each layer you want to transform and save liberally.

BTW Here is your movie redone with my scripts:

Image
click on image to watch video on YouTube

Here is the Moho file (without the sound): lips_copy.moho.zip
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

HOLY COW!!!!

I LOVE YOU MAN! I want to send you candy and flowers and... wash your car... and... and...

<gasp> <thunk>

I passed out there for a minute. I can't believe you did this so fast. I have been wanting this for ages and never thought to post it.

THIS IS EXACTLY WHAT I NEEDED!

The process is very fast. And it makes keys on every frame which is actually kind of freaking cool! I have all those keys to pick from if I need to.

This is kick arse! I am jumping up and down! I can use this to do SO MUCH with switch layers for lip sync... whatever.

THANK YOU RASHEED!

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

I told you in another thread I was full of brilliant ideas. The only problem in this case was I had to test my scripts before I could release them. The scripts were essentially written in 5 minutes once I had the right idea.

Anyway, glad to have helped you, Vern!
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I was just thinking that there are a LOT of people who do point animation in AS who don't like to use the bones.

This could be a good way for them to get bone motion into the point animation. It really opens up the options.

You could do rough motion with bones, tweak with points, then combine them both into point motion, and continue tweaking either with bones or points etc.

What would be the possiblilty of creating a menu script for this? Instead of using a layer script, use a menu script like the copy bones script?

You would go to a key frame of a bone layer, select the mesh at that point and "Copy Points", go to the copied layer and "Paste Points".

This would eliminate LUA having to "know" which layer had what points etc. You would be ON the layer, no need for running through a list.

-vern
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

Can it be somewhat different?
  • if there is not yet a copy of the currently selected vector layer, then :
    • make a copy of the current vector layer above the selected vector layer
    • name it after the selected layer, with " (copy)" attached to the layer name
  • else :
    • clear all keys in the point motion animation channel in the copied layer
  • find the frames in the parent layer which have keys in the bone animation channels
  • in the found frames, put keys in the point motion animation channel of the copied layer, based on the points positions in the selected layer
The net effect would be that a layer controlled through its parent layer's bone animation is copied into a layer with point animation. If it is possible, I could even add an option to release all points in the copied layer, so the parent bone layer has no effect on it, and you can tweak the points even more, without being bothered by the influence of bones.

I will start on this tomorrow and it will take probably considerably more time, because I have never written a menu script before. It will be good experience for the scripting tutorial I'm writing right now (see here). This tutorial isn't extensive enough to publish, but you can have a look at it).
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

Rasheed wrote:Can it be somewhat different?
  • if there is not yet a copy of the currently selected vector layer, then :
    • make a copy of the current vector layer above the selected vector layer
    • name it after the selected layer, with " (copy)" attached to the layer name
  • else :
    • clear all keys in the point motion animation channel in the copied layer
  • find the frames in the parent layer which have keys in the bone animation channels
  • in the found frames, put keys in the point motion animation channel of the copied layer, based on the points positions in the selected layer
Forget about this, I tried another version of the "org script layer.lua" (see below). It now only puts keys in those frames of the copied layer if there is a key in the parent bone layer of the original vector layer.

See here what the result is:

Image

The purple rectangle is the one controlled by the bone in Layer 2. The brown rectangle is "Layer 1 copy".

This means if you want to transform bone animation into points animation, you will need to fill every frame with a key. If you do not, the inbetweens of the copied layer will be different from those in the layer that is controlled by bones.

____

Here is the test code I used to investigate this. It uses a separate function FindHasKeys to keep the main function readable.
DO NOT USE THE SCRIPT BELOW, BECAUSE ITS METHOD IS FLAWED!!!

Code: Select all

-- org layer script2.lua
--
-- in combination with the copy layer script, this script will only put keys
-- in the frames of the copied layer if this layer's parent layer has bones in
-- these frames
--
-- Note that this method is flawed, because bone animation is something else
-- than points animation. Each key in the copied layer has to be present,
-- otherwise the points animation will deviate from the bone animation.
--
-- So, DO NOT USE THIS SCRIPT!!!

function LayerScript(moho)

    local frame = moho.frame
    local mesh = moho:Mesh()
    local layer = moho.layer
    local parent = layer:Parent()

    if ( mesh == nil or mesh:CountPoints() == 0 or parent == nil
         or moho.frame == 0 ) then
        return
    end
    
    hasKey = FindHasKey(moho, parent)
    if ( hasKey == nil ) then
            return
    end
    
    if ( not hasKey[frame] ) then
        return
    end

    if ( Pos == nil ) then
        Pos = {}
    end
    
    if (Pos[frame] == nil ) then
        Pos[frame] = {}
        for i=0, mesh:CountPoints() - 1 do
            local pt = mesh:Point(i)
            Pos[frame][i] = pt.fPos
        end
    end
end

function FindHasKey(moho, parent)

    local prevLayer = moho.layer
    moho:SetSelLayer(parent)
    local boneCount = moho:CountBones()
    if ( boneCount == 0 ) then
        moho:SetSelLayer(prevLayer)
        return  nil
    end
    local skel = moho:Skeleton()
    local endFrame = moho.document:EndFrame()

    local hasKey = {}
    for b = 0, boneCount - 1 do
    
        local bone = skel:Bone(b)
        local bAnimPos = bone.fAnimPos
        local cAnimPos = bAnimPos:CountKeys()
        local bAnimAngle = bone.fAnimAngle
        local cAnimAngle = bAnimAngle:CountKeys()
        local bAnimScale = bone.fAnimScale
        local cAnimScale = bAnimScale:CountKeys()
        local bIKLock = bone.fIKLock
        local cIKLock = bIKLock:CountKeys()
        local frame = 1
        while ( ( cAnimPos > 0 or cAnimAngle > 0 or cAnimScale > 0
            or cIKLock > 0 ) and frame <= endFrame ) do
            if ( bAnimPos:HasKey(frame) ) then
                hasKey[frame] = true
                cAnimPos = cAnimPos - 1
            end
            if ( bAnimAngle:HasKey(frame) ) then
                hasKey[frame] = true
                cAnimAngle = cAnimAngle - 1
            end
            if ( bAnimScale:HasKey(frame) ) then
                hasKey[frame] = true
                cAnimScale = cAnimScale - 1
            end
            if ( bIKLock:HasKey(frame) ) then
                hasKey[frame] = true
                cIKLock = cIKLock - 1
            end
            frame = frame + 1
        end
    end
    moho:SetSelLayer(prevLayer)
    return hasKey
end
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

Vern, if you need to include every key in the point animation, is it then still as useful to you? Dealing with so many keys is perhaps not worth the effort, unless you put them into an action.
User avatar
bupaje
Posts: 1175
Joined: Fri Nov 12, 2004 5:44 pm
Location: California
Contact:

Post by bupaje »

What!?!? Is this an answer to this old suggestion???

http://www.lostmarble.com/forum/viewtopic.php?t=3991

If so OOOO AAAHH. I have homework to do when I get home but going to play with that this weekend if so.
[url=http://burtabreu.animationblogspot.com:2gityfdw]My AnimationBlogSpot[/url:2gityfdw]
User avatar
artfx
Posts: 213
Joined: Sat Nov 11, 2006 10:52 pm
Location: Hollywood
Contact:

Post by artfx »

All this happened TODAY?!

You guys are amazing!
----
Terrence Walker
Studio ArtFX
LEARN HOW TO Make YOur Own Animated Film!
Get Video Training to Show You How!
User avatar
Rasheed
Posts: 2008
Joined: Tue May 17, 2005 8:30 am
Location: The Netherlands

Post by Rasheed »

While layer translation cannot be captured with this method, everything that has to do with point motion inside a layer can be copied reliably, as long as you do one vector layer at a time, and restart AS (or Moho) for the next layer.

This is a bug and I will not fix this, because I want to write a menu script, that will automatically create a copy of a layer with the points motion in it.

BTW, here is a SWF file I exported from a Moho file I treated this way.

Test2.swf
(source: Test2.moho.zip)
Post Reply