i have a script request! (Poses)

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
synthsin75
Posts: 10271
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Thanks for the input Genete. As long as our scripters are discussing things, I'm optimistic. :wink:
_Trip
Posts: 5
Joined: Thu Jun 05, 2008 3:37 pm
Location: WI
Contact:

Post by _Trip »

Selgin, here is a fixed version of the script - I had the collectgarbage() routine in an area that killed the script.

Code: Select all


--Embed this script into all the vector layers that want to copy poses from frames 1,2,3,4, ..., maxposes
--it must be under a bone type layer and the following ROOT named bones MUST exists:

-- posek (with k form 1 to maxposes)
-- bonelesector

-- Copyright 2008 Genete
-- Released for free.
-- Thanks to Selgin for that great idea.
-- It can be extended for other animated values (curvatures, widths, shape fill colors, shape outline color, etc.)
-- Also weights w[k] can be overweigthed by the pose bone legth. It would allow some sort of variable action weights...
-- Under development...
-- Modififed June 5th, 2008:
-- Tim Fischer:  Added local variables to speed up looping (interpreted languages recalculate every iteration so a variable can be much faster)
--                        Added garbage collection routine to free memory (Auto GC doesn't appear to work).  This fixes hanging, etc

poses = {}

maxposes = 2

bone = {}
boneselector = nil

function LayerScript(moho)
   local w = {}
   local distance
   local posk
   local pos_selector
   local r
   local length

   local k
   local layer = moho.layer
   local frame = moho.frame

   local skel = moho:ParentSkeleton()
   
   if (skel == nil) then
      print ("No parent skeleton found in layer:".. layer:Name())
      return
   end

   local mesh = moho:Mesh()
   
   if (mesh==nil) then
      print ("No mesh found in layer:".. layer:Name())
      return
   end   
   
   if (frame <=maxposes) then
-----------------------------------look for the bones
      for k=1, maxposes do
         bone[k] = nil
         local fc1 = skel:CountBones()-1   -- added to speed up loops
         for i=0, fc1 do
            local bonei = skel:Bone(i)
            local bonek = "pose" .. tostring(k)
            if (bonei:Name() == bonek) then
               bone[k]=bonei
            elseif (bonei:Name() == "boneselector") then
               boneselector=bonei
            end
         end   
         if (bone[k] == nil) then
            print("bone "..k.." is missing")
            return
         end
      end
      if boneselector == nil then
         print("boneselector is missing")
         return
      end
      collectgarbage(maxposes)
---------------------------------
--------------------------------- creates a new array for the layer
      poses[layer]={}
      poses[layer]["points"]={}
      for k=1, maxposes do
         poses[layer]["points"][k]={}
         local fc2 = mesh:CountPoints()-1   -- added to speed up loops
         for i=0, fc2 do
            poses[layer]["points"][k][i]=mesh:Point(i).fAnimPos:GetValue(k) --store all the points/pose/positions
         end
		collectgarbage(fc2)
      end

      return
   end
   
   pos_selector = boneselector.fPos --position of the selector bone.   
   length = boneselector.fLength*boneselector.fAnimScale:GetValue(moho.frame) --current length of the boneselector
   for k=1, maxposes do
      w[k]=0
      posk = bone[k].fPos
      distance = posk - pos_selector
      r = distance:Mag()
      w[k]=weight(r, length)
   end
   
   local wtot=0.0 --total weight
   for k=1, maxposes do
      wtot =wtot +w[k]
   end
   if (wtot == 0.0) then  return  end
   
   local fc3=mesh:CountPoints()-1  -- added to speed up loops
   for i=0, fc3 do --- move the points.
      local pimoved =LM.Vector2:new_local()
      pimoved:Set(0,0)
      for k=1, maxposes do
         pimoved = pimoved + poses[layer]["points"][k][i]*w[k]/wtot
      end
      local pi=mesh:Point(i).fPos:Set(pimoved)
   end
   collectgarbage (fc3)
end


function weight (r, l)
   if (r <= l) then
   local w =r/l-1
      --print(w)
      return w
   else
      return 0.0
   end
end 
Genete - Thanks for the reply and questions. The reason for calcualting the variables *before* the for loop is that in an interpreted language, including VB/VB6, javascript, etc each iteration of the loop *MUST* re-calculate the variable - which can totally kill performance. My recommendations have always been to delclare a variable before the loop and use that as then the calculation only happens once regardless of whether or not there are 1000 iterations. (That would be 999 less calculations to occur).

While a standard calculation isn't such a big deal, the code in question calls a function to "get" the count beffore it subtracts one from it... this can be costly. Since I don't know the code behind of the .count method, I assume the worst (it gets calc'd every time).

So, as a best practices, it is safest to simply declare a variable (minor memory use and gauranteed to be done only once).

As for the garbage collection - open up your task manager (if using windows) and comment out the LAST garbagecollect() function and run AS using any of the above files. Watch the memory grow exponentially until finally the system hangs. Then uncomment the collectgarbage() function and watch as the memory doesn't grow at all.

Indicative of the "auto" garbage collector either not working correctly or the code being done inefficiently for the language.

I played a little bit with redoing the function/splitting it up so that memory was better used for the last for loop - there can be easily 4000 points created every time you move the "Bone" and they never get cleared, so they just add up.

Great script - as I said earlier, I can pinpoint issues with scripts easier than I can create them myself for some reason...
-Tim
_Trip
Posts: 5
Joined: Thu Jun 05, 2008 3:37 pm
Location: WI
Contact:

Post by _Trip »

Genete and all,

One more *very interesting tidbit*. I looked at that PDF as well for scripting the garbage collector, but guess what?

That is not the version of Lua that AS is using... the garbage collector was re-written in a later version (5.1.3??) and isn't called that way any longer.

So maybe with the latest 5.6 update AS scripting is using the latest Lua?

I don't know, but the commands from the PDF would *not* work in AS...

go figure. :roll:
-Tim
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

The reason for calcualting the variables *before* the for loop is that in an interpreted language, including VB/VB6, javascript, etc each iteration of the loop *MUST* re-calculate the variable - which can totally kill performance

Aaaargh! silly interpreted language!!!! I though it was intelligent and only calculate the end of the 'for' loop one time!!!! I learned lua a year ago (if write those scripts can be called "learn") and didn't know that!!!

Regarding to garbage collection I'm running a linux box and don't feel any memory performance improvement. It gets a lot of memory with or without your addition.

Anyway it is a good new to have you here. You can help us (self learned coders) to improve our impulsive scripts :D

-G
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

Hi guys,

This is a great script and a great idea and all, but there's a couple of areas where I feel a little hmm.... limited by it. I'm not a scripter or anything but I wonder if there's any way to make it so that, if need be, point animation can operate within the script. I mean, I often have points during an animation where I realize that I simply need to move a point manually because what I'm getting from the bones is warping the design in such a way that the image and the animation doesn't look right. This script doesn't allow point movement while the script is in play.

Also, I wonder about the affect of bones from parent layers on the points of the vector layers that are under control of this script. You either might get a odd warping or no warping at all, which could also be odd. -I've never tried it, but it seems like plausible issues.

Is there any way to address this in the script?

Thanks,

S
User avatar
synthsin75
Posts: 10271
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Uh, since this script is based on your actions, just add the needed point motion to the action/s. Or am I missing your point?

I think what you're asking for (allowing point motion on top of an action) would require the script to write regular references of the actions to the timeline.

As is, this script doesn't do that (and I'd image that'd take some doing). It seems to work much like meshinstance. All of the information in the actual layer is discarded and replaced by the info from your action.

But only Genete could tell you for sure. :wink:
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I wonder if there's any way to make it so that, if need be, point animation can operate within the script...
I played around with this for just a few minutes. I don't know how it would work exactly. I think you might have to copy frame 0 to an "extra" pose frame. Or grab the point positions from frame 0 and calculate the difference in motion to the other frames with out the pose blending.

The "actual" position of the points on every frame would need to be incorporated equally into the equation for blending the poses. What ever the result of the point motion from poses is, would then be modified by whatever motion is set on the keys by key frames (whether there is a key frame on the frame or not).

The "actual" position of the points (without the poses) is "really" the last pose (the last key frame for the points determines the fPos of the point for later frames). That pose gets extra "influence" when trying to add in point motion to a key frame ON TOP of the blended pose motion.

You wold need a way to get the position of each point with NO pose motion blending added (frame 0) then get the difference of that motion from any hand done point motion on a frame, and add that to the calculation for the pose blending.

It might just be easier to adjust the poses if you need to tweak points. It might be done if I can spend more than 5 minutes goofing with it.
Also, I wonder about the affect of bones from parent layers on the points of the vector layers that are under control of this script. You either might get a odd warping or no warping at all, which could also be odd. -I've never tried it, but it seems like plausible issues.
There is no influence from other bones. Only the pose motion controls the points. All other influence is ignored.

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

Post by heyvern »

Dagnabbit...

Can't make it work. I think it could work... but if the script is sluggish now adding this feature might make it more so.

You would need to subtract the calculated pose motion to get the "unaltered" position of each point on the frame, as if there was no script changing the points position.

This would be the "base" that the script would then "alter" to add the pose motion to. then any point motion added "by hand" would just be "added" to the motion of the poses.

Currently when you try to acquire the fPos of the point on a frame, you get the "altered" value from the script. So this is wrong. If you add that to the points position you get wonky results. You need access to the UNALTERED value FIRST. Then it would work. It's that bit I had trouble with.

The result would be EXACTLY like using point motion on an interpolated switch layer. If you move points on keys on a switch layer that interpolates between layers, you get the motion of that key frame "added" to any interpolation.

Maybe there is an easy way to do this.

I think this is a FANTASTIC suggestion.

-vern
User avatar
synthsin75
Posts: 10271
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

If there were any way to make the script add the actions to the timeline as a normal reference, the point motion addition would already be there. I guess the problem is that this script utilizes the control bone's interpolation instead of the interpolation between action keyframes.

Vern, I think your proposed action assignment by hotkey script would probably be the best solution for this. :wink:
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I almost got it working.

I see this script as a switch layer on steroids. There would be no way to get the kind of key frame "blending" using "linear" interpolation. It's the ability to create new completely different combinations that make this script so fantastic.

-----

What would be cool is being able to access actions without inserting them. Right now actions I think are a bit rough around the edges. They feel as if they are still a fairly new addition due to the lack of much script access.

The perfect solution would be if actions and the keys could be accessed as easily as the main time line keys. then instead of inserting keys in the first frames of the time line you would just use keys from the action.

-vern
User avatar
synthsin75
Posts: 10271
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

The perfect solution would be if actions and the keys could be accessed as easily as the main time line keys. then instead of inserting keys in the first frames of the time line you would just use keys from the action.
What if you made a parse then open file menu script? You'd have to have AS already open, but then you should be able to search the text file for action names and key data, shouldn't you?
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I hate parsing the file format. In AS the script interface does all the heavy lifting for you. Parsing the file format is like "reinventing the wheel". Making a script do what AS already does. You have to figure out where all the information is and translate it line by line from the file. Pain in the arse. I would rather not go down that road.

-vern
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

slice11217 wrote:Hi guys,

This is a great script and a great idea and all, but there's a couple of areas where I feel a little hmm.... limited by it. I'm not a scripter or anything but I wonder if there's any way to make it so that, if need be, point animation can operate within the script. I mean, I often have points during an animation where I realize that I simply need to move a point manually because what I'm getting from the bones is warping the design in such a way that the image and the animation doesn't look right. This script doesn't allow point movement while the script is in play.

Also, I wonder about the affect of bones from parent layers on the points of the vector layers that are under control of this script. You either might get a odd warping or no warping at all, which could also be odd. -I've never tried it, but it seems like plausible issues.

Is there any way to address this in the script?

Thanks,

S
In fact this script is very simple.

First you store a fixed (but can be modified) number of poses in the first frames (they can be stored in the negative frames after fantastic heyvern discovery.
They are like the child vector layers of a switch layer but they are fixed. They have not option to have a animation by the time as far as it hasn't its own time line.
There are two benefits from the usage of switch layers:
1) Visual control of the interpolated pose
2) You can stop at any intermediate pose and / or can combine several poses at the same time.

There is not way to override interpolated point motion unless you could modify the poses along the time line.... Oh! it would be possible to get the poses form the current animated values of some special child vector layers! Even it can be done using a switch layer instead a bone layer to allow easy hide the poses! It would allow avoid the need of store poses in the first frames!
Give me some free time to redo the script and see what happen. :)

BTW, reviewing the script I've found that the line:

Code: Select all

local pi=mesh:Point(i).fPos:Set(pimoved) 
has an unneeded local store of the point in the 'pi' variable. It is never used later. So it can be safely removed to:

Code: Select all

mesh:Point(i).fPos:Set(pimoved) 
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

Genete wrote: First you store a fixed (but can be modified) number of poses in the first frames (they can be stored in the negative frames after fantastic heyvern discovery.
Well see, this is partly what I'm addressing: if I'm animating and I run into a problem (which happens far more frequently than I'd like for it to), and I need a pose that I didn't anticipate then I'm screwed. The script as it stands right now requires that you anticipate everything you're going to need up front. I don't know about anyone else but this is very difficult to do.

I tried the following but it didn't work: using DarthFurby's head turn file with the script applied to it, I went to one of the vector layers. I picked a random point on the timeline and set a keyframe on the point motion. Then I went to another random point on the timeline and set another, making sure that the two poses would be quite different. My hypothesis was that if I set the two keyframes on the point motion and then removed the script from the layer, that the animation would hold. Alas, it did not.
Genete wrote: They are like the child vector layers of a switch layer but they are fixed. They have not option to have a animation by the time as far as it hasn't its own time line.
Child vector layer as also fixed, but less so. While a child vector is selected I can set point motion animation but while it is interpolating from one child to another, I cannot.
Genete wrote: There are two benefits from the usage of switch layers:
1) Visual control of the interpolated pose
2) You can stop at any intermediate pose and / or can combine several poses at the same time.
I've never been able to combine more than two switch child vector layers at any time. Moreover, the only visual control of an interpolated pose that's available is the timing of it, and I'd personally prefer to be able to manipulate the ease the in/out of that manually.

Here's the thing:

The advantage of this script is that you can visually choose whatever pose you need at any given point on the timeline. You can even easily choose gradations of one pose to another and if you set it up right you can go from any pose to any other and choose a interpolation of one pose to the other. This you can't do with a switch layer. You can do this with single frame actions but these can be confusing to set up (I keep going in and out of action mode when setting them up), and also you lose the visual interaction that this script has to its advantage. Actions are plenty easy to use, but not as easy as using this script.

I've personally never been bothered by having to set the start frame at a later point in the timeline anyway since it makes for an easier transition into After Effects if the start frame is on a '00' frame ( 1:00, or 2:00, etc.) Anime Studio's default is to start on frame 0:01 which forces the animator to think in terms of subtracting a frame when transitioning to other software. I could personally care less if the stored frames happened after the 0 frame or before. I'd rather see the frame numbering be a user-defined aspect rather than permanent one. Our current frame 0 could then be a frame '00' or something, perhaps 'XX' or 'ZZ'.

The disadvantage of this script is that once you've set up those poses, that's it! -You can't go in and modify things as you go, you're hardwired in. You have to anticipate what you're going to need up front or suffer the consequences. I'd like to be able to use this script to block in acting, set up head turns, or (and this hasn't been discussed yet) twist the body (which would probably require two poseselector bones), and then go in and modify and finesse what I feel needs to be finessed. In this sense the script is kind of limited.

Also, for head turns it seems you'd need to create a rather vast library of mouth phenomes and eye positions, eyebrow expressions, etc. in every pose -Lots of work! I'm already spending far more time setting up and rigging characters than I am actually animating them. Clients unfortunately are starting to get a little confused into thinking that animating via AS takes longer than drawing it by hand as a result. I end up having to reassure them that the animation is faster, it's the setup that takes a while, and once that's done it doesn't need to be done again.

Anyway, hopefully this makes it a little clearer as to what I'm thinking about. I like the script, I just want more!

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

Post by heyvern »

The disadvantage of this script is that once you've set up those poses, that's it! -You can't go in and modify things as you go, you're hardwired in. You have to anticipate what you're going to need up front or suffer the consequences.
Why? I'm not sure I understand when you say you are "locked in" and can't make changes? The poses are based on named bones, need more poses just increase the "maxpose" variable and add in new poses and bones. If you need to tweak the poses later then, tweak the points on the frame of the pose with onion skin turned on. The only thing that might be a problem is how far ahead do you start the animation so there is rooom to add more poses?
Also, for head turns it seems you'd need to create a rather vast library of mouth phenomes and eye positions, eyebrow expressions, etc. in every pose -Lots of work!
This is the case even if the script had everything you wanted and was perfect. This script doesn't "cause" the extra work. It makes the extra work more usable.

if you create multiple views of a character, that is going to require multiple sets of phonemes. That is the same amount of work. this script is NOT going to change the fact that each "pose" requires a set of phonemes. It never could, it never will. How could it? The phoneme issue is not relevant to this script. You can avoid that by not having phonemes in each pose for a head turn. Don't allow the character to talk WHILE turning. Just use phoneme layers for when the character reaches the final position. that is what I did with switch layer head turns.

I think the phoneme issue could be handled in other ways if needed. Groupings of pose bones for easier selection... just brain storming. Keep in mind this is a brand new idea. No one has really figured out how to set up those bones for something like lip sync.

Try to use what's there now before jumping on the things that aren't perfect. This is an amazing script with lots of potential just as it is right now. If it doesn't work for you right now for everything, scale back what it's used for. Don't use it for body twisting, just use it for simple things.

-vern
Post Reply