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
Víctor Paredes
Site Admin
Posts: 5646
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

i have a script request! (Poses)

Post by Víctor Paredes »

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.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

yes.

who? :roll:
User avatar
heyvern
Posts: 7035
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

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
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

"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
Víctor Paredes
Site Admin
Posts: 5646
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

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?
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
Víctor Paredes
Site Admin
Posts: 5646
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

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: ).
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
Víctor Paredes
Site Admin
Posts: 5646
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

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.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
DarthFurby
Posts: 510
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City
Contact:

Post by DarthFurby »

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.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

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
DK
Posts: 2849
Joined: Mon Aug 09, 2004 6:06 am
Location: Australia

Post by DK »

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
Post Reply