i have a script request! (Poses)

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

Moderators: Fahim, Distinct Sun, Víctor Paredes, erey, Belgarath, slowtiger

i have a script request! (Poses)

Postby Víctor Paredes » Fri Feb 01, 2008 12:56 am

sorry, i have a script idea and maybe you (genete, heyvern, are you there?) can write it, or at least tell me that it's a stupid request.

well, it's hard to explain for me, so i did two swf examples
with a simple shape Here
and with a simple smile Here

it's similar what you do using actions. you draw a face (or whatever), create some single frame actions in which you move the points to get different face poses. and after create the poses you put this actions across the timeline as references or copies.

but my idea is without the use of actions. imagine you could assign one bone for each pose and move a master bone around. so according to the distance of the master bone from the poses bones, the face were changing.

in the swf files you can see four bones and the poses their represent.

i think it would be really cool if something like this could be done, you could control turning heads with just one bone and with much more flexibility in the animation.

what do you think?

_________________________
i don´t know how it could be done, but my idea (as a code ignorant) is to draw the character, insert it into a bone layer, duplicate the vector layer several times and make on each one the different poses. then, using a script similar to the 3d stuff done by genete and heyvern, create bones for each point of each pose layer.
Last edited by Víctor Paredes on Sat Feb 02, 2008 2:49 pm, edited 1 time in total.
User avatar
Víctor Paredes
 
Posts: 4814
Joined: Wed Jan 26, 2005 12:18 am
Location: Ireland

Postby Genete » Fri Feb 01, 2008 1:09 am

yes.

who? :roll:
User avatar
Genete
 
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Postby heyvern » Fri Feb 01, 2008 8:52 am

I know enough about the scripting now in AS after many mistakes and wrong assumptions to be pretty confident this COULD be done. However it would be freaking hard I think.

First off it would have to use actions or possibly a switch layer. The actions or switch would not actually be used directly, they would just be a place to "store" the point motion poses. Then the script would use the bone position to somehow average the position of the effected points and "copy" the new point position to the main time line.

Another BETTER idea (I'm brainstorming. This helps) would be to use bone only actions. This is much better but requires more set up for the character.

Imagine you only use bones to create the poses for the character NO POINT MOTION AT ALL and save those poses as actions. The posing bone when moved would only have to average the position of the bones in the actions (instead of all the points). The reason this would be better is that you wouldn't need keys for all the points or bones. Just the moving bone. The motion of that bone wouldn't add a key for the other bones just move them around based on proximity to a pose.

I am already working on something like this. A way to constrain one bone to multiple bones so the values are averaged. Just that by itself is half the battle.

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

Postby Genete » Fri Feb 01, 2008 12:43 pm

I think it is possible but not in a full flexible way (any number of poses). The number of poses would be fixed. If not the script would be so complicated. Also the bone naming must be manual.

It could be possible to create a embeded script for vector layers that looks for four (four or what ever number of poses is set) special named bones and for one special one which will be the "pose" selector.
Calculate the distance from the selector one to the rest of bones wouldn't be so difficult. The pose result would be the average of the inverse of the distance from each pose. More close the pose selector to the pose bone is more similar to that pose will be the points movement result.

The rest is a question of calculate the points position dinamically based on point position at predefined keyframes:

frame 1: pose 1
frame 2: pose 2
and so on.

You would waste the first frames of the animation in benefit of the stored poses.

Each vector layer should run its own embedded script. As well as the vector layers share the parent skeleton they read all the same pose selector bone relative position.

The vector layers wouldn't produce any keyframe by the embedded script only the bones would produce.

Any the points of the vector layer that has activated the embedded script cannot be moved by any bone or by hand. The script would override that movement.

I'll try it. Don't promise any result but try it yes. :D

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

Postby Genete » Fri Feb 01, 2008 4:39 pm

"The proof is in the pudding" ;)

http://www.darthfurby.com/genete/Scripting/poses.zip

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

-- pose1
-- pose2
-- pose3
-- pose4
-- bonelesector

-- Copyright 2008 Genete
-- Released for free.
-- Thanks to Selgin for that great idea.
---
function LayerScript(moho)
   if (moho.frame ==0) then
      return -- it works only for other frames beyond frame 0
   end

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

   local bone1 = nil
   local bone2 = nil
   local bone3 = nil
   local bone4 = nil
   local boneselector = nil

   for i=0, skel:CountBones() -1 do
      local bone = skel:Bone(i)
      if (bone:Name() == "pose1") then
         bone1=bone
      end
      if (bone:Name() == "pose2") then
         bone2=bone
      end
      if (bone:Name() == "pose3") then
         bone3=bone
      end
      if (bone:Name() == "pose4") then
         bone4=bone
      end
      if (bone:Name() == "boneselector") then
         boneselector=bone
      end
   end

   if(bone1==nil) then
       print ("return1")
       return
     end
   if(bone2==nil) then
      print ("return2")
      return
    end
   if(bone3==nil) then
      print ("return3")
      return
   end
   if(bone4==nil) then
       print ("return4")
       return
   end
   if(boneselector==nil) then
       print ("return s")
      return
   end
   
   -- Calculate the average of distances.
   local w1=0 --weights
   local w2=0
   local w3=0
   local w4=0
   local distance1 = LM.Vector2:new_local() --distances
   local distance2 = LM.Vector2:new_local()
   local distance3 = LM.Vector2:new_local()
   local distance4 = LM.Vector2:new_local()
   local pos1 = bone1.fPos -- positions
   local pos2 = bone2.fPos
   local pos3 = bone3.fPos
   local pos4 = bone4.fPos
   local pos_selector = boneselector.fPos --position of the selector bone.
   distance1=pos1-pos_selector
   distance2=pos2-pos_selector
   distance3=pos3-pos_selector
   distance4=pos4-pos_selector
   
   if (distance1:Mag() == 0) then
      w1 = 1.0
      w2 = 0.0
      w3 = 0.0
      w4 = 0.0
   elseif (distance2:Mag() == 0) then
      w1 = 0.0
      w2 = 1.0
      w3 = 0.0
      w4 = 0.0
   elseif (distance3:Mag() == 0) then
      w1 = 0.0
      w2 = 0.0
      w3 = 1.0
      w4 = 0.0
   elseif (distance4:Mag() == 0) then
      w1 = 0.0
      w2 = 0.0
      w3 = 0.0
      w4 = 1.0
   else
      w1 = 1/distance1:Mag()
      w2 = 1/distance2:Mag()
      w3 = 1/distance3:Mag()
      w4 = 1/distance4:Mag()
   end
   
   local w = w1+w2+w3+w4
   if (w == 0.0) then return end

   for i=0, mesh:CountPoints()-1 do
      local p=mesh:Point(i)
      local posp1=p.fAnimPos:GetValue(1)
      local posp2=p.fAnimPos:GetValue(2)
      local posp3=p.fAnimPos:GetValue(3)
      local posp4=p.fAnimPos:GetValue(4)
      local pmoved = (posp1*w1+posp2*w2+posp3*w3+posp4*w4)/w
      p.fPos:Set(pmoved)
   end
end
User avatar
Genete
 
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Postby Víctor Paredes » Fri Feb 01, 2008 5:22 pm

genete, i love you!!! the script is awesome and you are so fast.
it's the best dessert i could have (i just finished my lunch).


:oops: just one question, is there a way to have more than four poses?
User avatar
Víctor Paredes
 
Posts: 4814
Joined: Wed Jan 26, 2005 12:18 am
Location: Ireland

Postby Genete » Fri Feb 01, 2008 5:53 pm

For sure,
how many do you want? :wink:

The problem is that if the number of poses is unknown the script should look for bones names and try to match if it is like:

pose + n

where 'n' is any number (any frame). It would lead into a endless loop.

OK, let's limit the maximum number of poses. Then the script would do the same but for a limited quantity: (number of bones) * (maximum number of poses).
I think it would slow down a lot the script.
Anyway I'm working on it. :wink:
So how many poses do you need?
Remember that the bones must exists and the name would be set manually to "bone" + "n" where n is from 1 to maximum number of poses.

This script can be extended to curvatures, shapes properties and everything that is in the vector layer. I can do it if you want but let me have free time and enough motivation. :/

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

Postby Víctor Paredes » Fri Feb 01, 2008 7:04 pm

could the script read how many pose bones are there? and then, define how many vector poses are?
i think, you could have many expressions, mouth movements, lipsync, etc.

can you use all the animated values of a vector layer? :shock:
if so, this script will take AS to other level (maybe i'm exaggerating :oops: ).
User avatar
Víctor Paredes
 
Posts: 4814
Joined: Wed Jan 26, 2005 12:18 am
Location: Ireland

Postby Genete » Fri Feb 01, 2008 8:36 pm

This is the desired script:

Just change the variable: maxposes and all will work.
Regarding to the other animatable features it can be done. Let me work a little on them and you'll get all them working.

Best
-G

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 deveopment...


function LayerScript(moho)

-------------------------------
   local maxposes = 4
-------------------------------

   if (moho.frame ==0) then
      return -- it works only for other frames beyond frame 0
   end

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

   local bone= {}
   local w = {}
   local distance = {}
   local boneselector = nil
   
   for k=1, maxposes do
      bone[k] = nil
      for i=0, skel:CountBones() -1 do
         local bonei = skel:Bone(i)
         local bonek = "pose" .. tostring(k)
         if (bonei:Name() == bonek) then
            bone[k]=bonei
            break
         end
      end   
      if (bone[k] == nil) then
         print("bone "..k.." is missing")
         return
      end
   end
   for i=0, skel:CountBones() -1 do
      local bonei = skel:Bone(i)
      if (bonei:Name() == "boneselector") then
         boneselector=bonei
      end
   end
   if boneselector == nil then
      print("boneselector is missing")
      return
   end
   
   -- Calculate the average of distances.
   local pos_selector = boneselector.fPos --position of the selector bone.   
   
   for k=1, maxposes do --- check whether there is exacly a distence == 0.0
      w[k]=0
      local posk = bone[k].fPos
      distance[k] = posk - pos_selector
      if (distance[k]:Mag() == 0.0) then
         for r=1, maxposes do
            w[r]=0
         end
         w[k]=1
      else
         w[k]=1.0/distance[k]:Mag()
      end
   end
   
   local wtot=0.0 --total weight
   for k=1, maxposes do
      wtot =wtot +w[k]
   end
   if (wtot == 0.0) then return end

   for i=0, mesh:CountPoints()-1 do --- move the points.
      local pi=mesh:Point(i)
      local pimoved =LM.Vector2:new_local()
      pimoved:Set(0,0)
      for k=1, maxposes do
      local pospik=pi.fAnimPos:GetValue(k)
         pimoved = pimoved + pospik*w[k]/wtot
      end
      pi.fPos:Set(pimoved)
   end
end
User avatar
Genete
 
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Postby Genete » Fri Feb 01, 2008 9:03 pm

selgin wrote:could the script read how many pose bones are there? and then, define how many vector poses are?
i think, you could have many expressions, mouth movements, lipsync, etc.

can you use all the animated values of a vector layer? :shock:
if so, this script will take AS to other level (maybe i'm exaggerating :oops: ).


You define the vector poses at the 1 to maxposes first frames. Then setting the bonenames and the value maxposes at the script you have all that you need.
In this way it is simplified so much and more poses can be achieved in a reasonable way.

I see several interesting things:

1) As well as points positions (or vector layers animatable features) depends on distance of the boneselector to all the pose bones, and depends to all the poses at the same time it is very interesting how you can modify the behaviour depending on bone poses position. It is more flexible than actions because with actions you have always the same interpolation. Action A to Action B. With this script you can go from pose A to pose B passing by pose C if the bones are properly placed.
2) You can move the pose form one frame to other easily!!!. If you do it with actions you need to move all the actions keyframes from all the sublayers because it is stored on each different layer. With this script the keyframes are only set in one layer (the bone layer) so you can easily move the pose position and all the subfolders would follow.
3) You always have poses references. If one pose is changed (you make a change at one of the 1 to maxposes frames) it is spreaded to all the animation immediately. Like actions do.
4) Interpolation between 1 frame actions depends on the action keyframe iteself at frame 1. Now with this script interpolation depends on bone translation interpolation!!!! It can be ease in- out or step.... :)


My head is boiling....

I fell like you, this is a big step for Anime Studio.
More ideas will come. When they are mature I'll update the script.
Please feed back.
-G
User avatar
Genete
 
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Postby Víctor Paredes » Fri Feb 01, 2008 10:10 pm

it works wonderfully, thanks for the addition of poses. if the rest of animated channels can be added, i think soon we will say goodbye to actions.

do you know what is great too? you can move the pose bones during the animation, so you can re-configure the poses order.

i'll do (meanwhile nobody looks me here, because i'm working) a character with several expressions, to show the rest of the forum members what a wonderful script genete has wrote.
User avatar
Víctor Paredes
 
Posts: 4814
Joined: Wed Jan 26, 2005 12:18 am
Location: Ireland

Postby Genete » Sat Feb 02, 2008 12:44 am

I'm working on it.

Width has a problem. I don't know how to read it at a desired frame. I think that interface function is not given.

The rest will come later.
-G
User avatar
Genete
 
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Postby DarthFurby » Sat Feb 02, 2008 1:51 am

WOW!!! I just looked at the file. Genete you have done many amazing things on this forum, but this is by far the greatest. This is the answer to the 2.5D model I've been looking for! Also thanks to Selgin for coming up with the idea. If this works as well as I think, then something really big is about to happen here. I will also be building a model based on this script. Very very excited.
User avatar
DarthFurby
 
Posts: 509
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City

Postby Genete » Sat Feb 02, 2008 1:58 am

Hey Darth!
I'm working on the rest of animatable values.
It would take a bit and have not solution for point width.

Tomorrow I'll continue. Now I'm so tired.

BTW: Again thanks for your infinite generosity. :D

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

Postby DK » Sat Feb 02, 2008 4:50 am

Holy Cow...Like Daz Puppeteer but for AS :) Great suggestion Selgin and amazing work Genete!!!!! The potential for this incredible! I did not know this thread was even happening till now. Sometimes I log onto the Forum and accidentally close the browser down too early and miss all fresh posts from the day before. Darn annoying but I will be watching this one closely.
Congratulations Genete!

D.K
User avatar
DK
 
Posts: 2336
Joined: Mon Aug 09, 2004 6:06 am
Location: Australia

Next

Return to Scripting

Who is online

Users browsing this forum: No registered users and 0 guests