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

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

Post by heyvern »

That might be easier than some of the other options. Instead of just one set of poses you only pose specific points. Only the points that have a key would be controlled by the "matching" boneselector or pose bone.

I think you can check each point to determine if that point has a key. If it DOESN'T have a key on that pose frame it would be "ignored" by that pose or pose bone. Then ANOTHER pose bone would control that set of points.

The only problem would be if the poses would "blend" nicely. You might not get a smooth blending of all the poses... hmmm.... this is a great idea with so many possibilities... but it is a tough one to figure out.

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

Post by synthsin75 »

I think people keep missing the point of this multiple boneselector idea. If you have a boneselector1 that controls the head poses by pose1bones, then you could have the lipsync boneselector2 only interact with the pose2bones. Then if boneselector1 is the parent of boneselector2, the mouth would be posed along with the head, but still be free to do the lipsync.

Just some thoughts. :wink:
DarthFurby
Posts: 510
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City
Contact:

Post by DarthFurby »

"Selected Point Motion" for pose bones is also another solution for the lipsynch problem. One pose bone could have a mouth phoneme, another an eye blink, and another could have an eyebrow keyed. If you move them to the selector bone at varying distances they could theoretically create all kinds of different expressions with just 3 pose bones on the same mesh! It also cuts down on the number of poses needed while making existing poses a lot more reusable. But I also like the multiple selector option too. Maybe we could have both!
I'm thinking also in a way to avoid the "step" interpolation when you insert a point motion keyframe. I believe that when the script is doing an interpolation it can look for the next (if any) and the previous (must be one at last) point motion keyframe and produce a double interpolation: the one given by the pose bones motion (scripted) and the one given by the two keyframes and add them in a differential way...

But this is other story.
I hope to hear more about this story! If it has a happy ending then I think the names Genete/Selgin/Trip will be in the history books.
User avatar
Barry Baker
Posts: 342
Joined: Fri Aug 27, 2004 6:58 am
Location: UK
Contact:

Post by Barry Baker »

I have been following this thread for a while, and been equally intrigued and baffled by the exchanges. Finally, I had some time, and an excuse, to give it a try. I have been working on a trailer/promo for a second series of "Zorro - Generation Z" and I wanted to see how a head turn would look on Diego, the main character. Here is the result:

http://vimeo.com/1573330

It certainly is a great way of controlling movement, but in the case of this head turn, I have some problems with line widths not working. Basically, the animation takes the line width from the last pose defined rather than from the pose the script is supposed to be referencing. I am using Poses 2.1

Also, although it is very effective in merging different poses to partial degrees, allowing for some very subtle movements, how would one then go about changing expression, or adding lip sync for example? It seems that I can only work within the exact poses I have defined before the start of the animation.
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

Barry Baker wrote: It certainly is a great way of controlling movement, but in the case of this head turn, I have some problems with line widths not working. Basically, the animation takes the line width from the last pose defined rather than from the pose the script is supposed to be referencing. I am using Poses 2.1

Also, although it is very effective in merging different poses to partial degrees, allowing for some very subtle movements, how would one then go about changing expression, or adding lip sync for example? It seems that I can only work within the exact poses I have defined before the start of the animation.
These are EXACTLY the challenges that I've been trying to address! It's why I think that it would be helpful if there was some way that switch layers could be incorporated into the scheme, thereby allowing the use to not only have a head turn but also to have the character talk and act and emote while turning. -Real acting, man!

I've been having issue with the line width thing too, but I'm not using the poses script at the moment. I've been using single-frame actions ala DarthFurby's technique and the line width thing seems to be giving me some serious headache. I don't think the issue is related to the poses script.

I seriously hope that Mike Clifton has been following this thread also. It would be fantastic if this script could be incorporated into a future upgrade of Anime Studio, albeit a more complete variation that allows for switch layers, etc.

S
DarthFurby
Posts: 510
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City
Contact:

Post by DarthFurby »

Genete is probably going to hate me for this, but the solution we are looking for is written here:
Genete wrote:I'm thinking also in a way to avoid the "step" interpolation when you insert a point motion keyframe. I believe that when the script is doing an interpolation it can look for the next (if any) and the previous (must be one at last) point motion keyframe and produce a double interpolation: the one given by the pose bones motion (scripted) and the one given by the two keyframes and add them in a differential way...

But this is other story.
It may sound like confusing computer babble to some of you, but it's enough for now that Genete understands the challenges(and synthsin75 noticed the issue immediately), and can hopefully work out a solution at some point. Should that happen, I will make TWO videos to show what new features and abilities this opens up and put to rest some concerns(Hi Barry, slice11217): 1) A Video Tutorial to set up a simple rotatable head model(including a lipsynch or two), and 2) A Presentation Video for animators looking to persuade studio executives into adopting an Anime Studio based workflow. For the latter I will be using a much more sophisticated model to impress the crowd, most likely a refined version of the design I did for Chucky's mascot thread. The other advantage of this 2nd video(and accompanying project file) is that Mike can use it to help court investors and distributors should he ever decide to start his own company as opposed to relying on corporations who may not quite "get" it, and maybe even hire people like Genete and Vern for developer support.

I make these videos because Genete will have invented the greatest 2d animation production tool of the modern era: 2d models that move and behave as if they were animated frame by frame, but with the ease of use of 3d models. While children will be able to play with these 2d digital "barbie" dolls, the real benefactor would be the animation industry since it would mean lightning fast turnover on the most difficult, expensive and time consuming phase of production: Character animation. Not the cutout style we're used to seeing from Flash, but fluid traditional Disney quality animation using versatile mannequins that can be posed any way we want, an advantage that 3d based productions have long enjoyed, except now WE would have the advantage because unlike 3d, Genete's "2.5D" pose bone model would be fast and easy to build, while allowing us to use designs that could never have been built in 3d.

Genete, am I an arrogant jerk or am I being honest? Both might be true, but EVERYONE's feedback is valid, right down to the beginner that just signed up on the board. This means there are bound to be disagreements, even amongst friends, and if cooler heads prevail, open discussion, the true mark of a healthy forum. Although we disagreed, I witnessed what happened when you were struck by "inspiration." The other day I saw a disfigured man in a wheelchair cry out "If you give respect, you get it back, big time." Perhaps that is a lesson I have not learned. If you want revenge, perfect the script, fulfill the balance of my feature requests, and I will pay the price by making those videos.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

Hi people. I'm just writing this post to tell you that I'm in the process to set up a new computer (PC based). It would take some time to make all the things working properly again (I bought it without any operating system) so please be patience with me.

I'll read and understand your post (and other interesting ones in other threads) and would reply properly. But now I'm so "occupied" :)

From the first read I only can say thanks for your encouragement. You know that I need it to do things ;)

Back in a short time...

-G
chucky
Posts: 4650
Joined: Sun Jan 28, 2007 4:24 am

Post by chucky »

Barry, I saw your neo mickey and I thought it was sublime. The afx twin was cute too :)
I understand the reservations about the mickey thing, but I think your animation surpassed the old mouse context and I was surprised that there was any link, pity it was a Disney commission otherwise you could just change the character's face a little and call it a frikn badger, for all I care.
Great stuff.
I liked flush too, reminded me of the old 101 dalmatians style.

Oh yeah! How's that computer coming Genete? :roll: we miss you. :cry:
User avatar
Barry Baker
Posts: 342
Joined: Fri Aug 27, 2004 6:58 am
Location: UK
Contact:

Post by Barry Baker »

Chucky, thanks for your appreciation. To be honest, I can understand the objection to messing with Mickey; in fact it was John Lasseter himself who pulled the plug on the project for this very reason. But it was a shame they didn't see beyond that to what could be done with the concept, by simply changing the lead character - maybe to a badger, as you suggest.

I haven't credited the Flush ad on my Vimeo page, but it was designed by me in the style of Sylvain Chomet, who also directed it (in an executive fashion from Edinburgh)

As for the Poses script, I hope this gets developed further. It really has the potential to be an amazing tool if a way could be found to add acting into the mix, maybe by using switch layers, as slice11217 (catchy name, slice!) suggested.
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

Hey -has this script been forgotten?
User avatar
Víctor Paredes
Site Admin
Posts: 5815
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

I just used the script yesterday to make this spaceship:
Image
I have the anme file on share your work, here
PocketGoat
Posts: 45
Joined: Mon Jun 11, 2007 9:02 am

Post by PocketGoat »

I could be wrong, but wouldn't it be possible to use pose morphing together with any other sort of animation if you calculated the morphs in terms of their difference from a neutral pose, rather than as absolute values?
So frame one is a neutral pose, the point position difference in frame 2, 3, etc from the neutral pose point position is stored, and then that difference is added onto a current frame's point positions, rather than overriding everything else. Point position = current position + pose morphing difference rather than point position = pose morphing position.
I tried to modify the script myself, but I'm not familiar with lua or anime studio scripts so it was slow going.
I'm I missing something, or would this work?
PocketGoat
Posts: 45
Joined: Mon Jun 11, 2007 9:02 am

Post by PocketGoat »

I've managed to rough something out and it does seem to work. It's late where I am so I'll probably call it quits and finish it tomorrow. There's a problem where if you stay on the same frame and move the view the shape expands because the script is refreshing using the new values, but if you change frames it cuts it out. I'm sure some scripting guru can fix it, or I'll figure something out tomorrow.
So yes, using this script you can deform the shape with non-pose bones or use point animation, or anything else you normally would as well as the pose bones.
Enjoy.

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.)
-- (curvature done!)
-- 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

--Genete 2008 july, 27th
---I've added some testing to speed up the positioning on the poses. You can edit the poses freely staying at its own frame but 
---if you modify a pose then you have to go to frame 0 to store the modifications on the pose array. Frame 0 is slow!!!
---Now the pose bone legth has influence on the final weight of the poses. So you can control the interpolated pose with the poses lengths.
---Added the Curvature channel. Now the curvature is stored and is interpolated between poses. It produces automatically a keyframe on each frame
---There is NO WAY to solve this because the curvature channel has not a fCurvature variable to set like the one for the points.
---Added the functionality of an external variable: GE_ToggleKeyframePoses.Status
---You have to run the ge_toggle_keyframe_poses.lua script by the menu or button script to modify the variable Status form false (default value)
---to True and viceversa. When this variable is set to true the inrterpolated point motion is stored in a keyframe. This is useful to 
---store all the animation in its own keyframes and be able to remove the embedde scripts. Also useful when used on single frames to key all the 
---point motions for all layers where the script is embedded.
---Added the ability to avoid interpolate or set again an existing keyframe. This allows the user to insert a keyframe in any moment of the
---interpolation and manually modify the interpolated values. This solves the situation where the interpolated poses produces a bad value
---difficult to solve by modifying the poses thenselves.

---Added interpolation for style shape fill and line color. I've tried Line Widht but it seems not to work.

--PocketGoat 2009, 15th May.
--Added ability to use other types of animation in conjunction with poses. 

poses = {}

maxposes = 4

bone = {}
boneselector = nil

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

   local k,i,l
   local layer = moho.layer
   local frame = moho.frame
   local pimoved =LM.Vector2:new_local()
   local pi

   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 and frame > 0) then return end
   if (frame <= maxposes or boneselector == nil) then
-----------------------------------look for the bones
      for k=2, 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
---------------------------------
--------------------------------- creates a new array for the layer
      poses[layer]={}
      poses[layer]["points"]={} -- this is the array for the point motion
      for k=1, maxposes do
         poses[layer]["points"][k]={}
         local fc2 = mesh:CountPoints()-1   -- added to speed up loops
		 if k == 1 then
			for i=0, fc2 do
				poses[layer]["points"][k][i]=mesh:Point(i).fAnimPos:GetValue(k) --store all the points/pose/positions for neutral layer 1
			end
		 else
			for i=0, fc2 do
				poses[layer]["points"][k][i]=mesh:Point(i).fAnimPos:GetValue(k) - poses[layer]["points"][1][i] --store point differences for other layers
			end
		 end
         collectgarbage(fc2)
      end
      poses[layer]["curvature"]={} -- this is the array for the curvatures
      for k=2, maxposes do
         poses[layer]["curvature"][k]={}
         local fc3 = mesh:CountCurves()-1
         for i=0, fc3 do
            poses[layer]["curvature"][k][i]={}
            local curvei = mesh:Curve(i)
            local fc4 = curvei:CountPoints()-1
            for l=0, fc4 do
               poses[layer]["curvature"][k][i][l]=curvei:GetCurvature(l,k)--store all the point of curves/pose /curvature
            end
            collectgarbage(fc4)
         end
         collectgarbage(fc3)
      end
      poses[layer]["fillcolor"]={}
      poses[layer]["linecolor"]={}
      poses[layer]["linewidth"]={}
      for k=2, maxposes do
         poses[layer]["fillcolor"][k]={}
         poses[layer]["linecolor"][k]={}
         poses[layer]["linewidth"][k]={}
         
         local fc5=mesh:CountShapes()-1
         for i=0, fc5 do
            local shapei=mesh:Shape(i)
            poses[layer]["fillcolor"][k][i]=shapei.fMyStyle.fFillCol:GetValue(k)
            poses[layer]["linecolor"][k][i]=shapei.fMyStyle.fLineCol:GetValue(k)
            poses[layer]["linewidth"][k][i]=shapei.fMyStyle.fLineWidth
         end
      end
      
      return
   end -- end of frame < maxposes or boneselector == nil
   
   pos_selector = boneselector.fPos --position of the selector bone.   
--   length = boneselector.fLength*boneselector.fAnimScale:GetValue(moho.frame) --current length of the boneselector
   length = boneselector.fLength*boneselector.fScale --current length of the boneselector

-- Calculate the distance form the boneselector to all the pose bones and calculate its "weight" influence
   for k=2, maxposes do
      w[k]=0
      posk = bone[k].fPos
      distance = posk - pos_selector
      r = distance:Mag()
      w[k]=weight(r, length)*bone[k].fScale --***THE SCALE OF THE POSE BONE CREATE INFLUENCE ON THE POSE!***
   end
   
   local wtot=0.0 --total weight initially = 0.0
   for k=2, maxposes do
      wtot =wtot +w[k]
   end
   if (wtot == 0.0) then  return  end
   for k=2, maxposes do
      w[k]=w[k]/wtot -- normalize the weights.
   end
   
---------------------------------------------POINT MOTION
   local fc3=mesh:CountPoints()-1  -- added to speed up loops
   for i=0, fc3 do --- move the points.
      pimoved:Set(mesh:Point(i).fPos)
      pi= mesh:Point(i)
      ---if (pi.fAnimPos:HasKey(frame)) then break end -- if there is a keyframe then don't overrride it. Not needed anymore. 
      for k=2, maxposes do
         pimoved = pimoved + (poses[layer]["points"][k][i]*w[k])/2
      end
      if(GE_ToggleKeyframePoses.Status==false) then
         mesh:Point(i).fPos:Set(pimoved) --move the point
      else
         pi.fAnimPos.value=pimoved -- move the point
         pi.fAnimPos:StoreValue()--this produces a keyframe and stores its valule
         moho.document:SetDirty()
      end
   end
---------------------------------------------END POINT MOTION    
---------------------------------------------CURVATURE
   fc3 = mesh:CountCurves()-1
   for i=0, fc3 do
      local curvei = mesh:Curve(i)
      local fc4 = curvei:CountPoints()-1
      for l=0, fc4 do
         local currentcurvature = 0.0
         for k=2, maxposes do
            currentcurvature=currentcurvature + poses[layer]["curvature"][k][i][l]*w[k]
            curvei:SetCurvature(l,currentcurvature,frame)
         end
      end
   end

---------------------------------------------END CURVATURE
---------------------------------------------STYLE

   fc3 = mesh:CountShapes()-1
   for i=0, fc3 do
      local shapei = mesh:Shape(i)
         local currentfillcol = LM.ColorVector:new_local()
         local currentlinecol = LM.ColorVector:new_local()
         local currentlinewidth = 0.0
         currentfillcol:Set(0.0,0.0,0.0)
         currentlinecol:Set(0.0,0.0,0.0)
         for k=2, maxposes do
            currentfillcol=currentfillcol+poses[layer]["fillcolor"][k][i]*w[k]
            currentlinecol=currentlinecol+poses[layer]["linecolor"][k][i]*w[k]
            currentlinewidth=currentlinewidth+poses[layer]["linewidth"][k][i]*w[k]
            --if(shapei.fMyStyle.fDefineFillCol) then
             shapei.fMyStyle.fFillCol:SetValue(frame,currentfillcol) --end
            --if(shapei.fMyStyle.fDefineLinecol) then 
            shapei.fMyStyle.fLineCol:SetValue(frame,currentlinecol) --end
            --if(shapei.fMyStyle.fDefineLineWidth) then 
            shapei.fMyStyle.fLineWidth=currentlinewidth --end
         end
   end
--------------------------------------------- END STYLE


   collectgarbage (fc3)

end ---FUNCTION END


function weight (r, l)
   if (r <= l) then
   local w =1-r/l
      return w
   else
      return 0.0
   end
end 
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I think your concept is valid... the bigger problem is performance. The extra calculations required to find the "offset" values might just add to the performance hit. This is a real performance hog dealing with all of those points and calculations.

I haven't played around with this script that much.

-vern
PocketGoat
Posts: 45
Joined: Mon Jun 11, 2007 9:02 am

Post by PocketGoat »

I can't really say, I was only playing around with Genete's simple example. Frame 0 is rather slow when the script is turned on, but there was no lag on any other frame. I'll try a more complicated test tomorrow and see how bad of a performance hit we're talking.
Post Reply