Aearon
04-01-2006, 07:32 AM
well, since talked to eek and mark about this stuff a while ago... i had to give it a shot myself now that i had some time ;)
this is a simple function that takes 4 helpers as input, and creates a point that is constrained to the bezier curve defined by these for helpers
note that this only works with exactly 4 points (a special case of a bezier curve which is faster to calculate than a general bezier), 4 points is what makes sense for spine setups as well as probably for curvy limbs my opinion.
here's (http://astronomy.swin.edu.au/%7Epbourke/curves/bezier/) where i got the formula from (contain's c++ code that can easily be translated into maxscript or a max expression)
hope this helps anyone out there!
to test it, select 4 objects and run the script
it's very fast already, but if anyone has an idea how to speed up the script controller itself, i'm all ears
fn
createBezierPoint
points -- array of 4 objects to define the curve (1 and 4 are the control points, 2 and 3 are control handles)
u: -- position of the point along the curve (value range 0 to 1), this can either be a float value or a float subanim
=
(
try
(
if points.count != 4 then throw ("need 4 points, got " + points.count as string)
local theP = point centerMarker:true axisTriped:false cross:false box:false size:0 constantScreenSize:false drawOnTop:false
local cnt = position_script()
theP.pos.controller = cnt
for i=1 to 4 do
(
if not isValidNode points[i] then throw ("point " + i as string + " not a valid node")
cnt.addNode ("p" + i as string) points[i]
)
case (classof u) of (
float: cnt.addConstant "mu" u
subAnim: if classof u.value == float then cnt.addTarget "mu" u else throw ("u subAnim value needs to be a float")
default: throw ("invalid value for 'u', need either float or float subanim, got " + (classof u) as string)
)
cnt.setExpression \
"p1 = p1.transform[4]
p2 = p2.transform[4]
p3 = p3.transform[4]
p4 = p4.transform[4]
mum1 = 1 - mu
mum13 = mum1^3
mu3 = mu^3
(mum13*p1 + 3*mu*mum1^2*p2 + 3*mu^2*mum1*p3 + mu3*p4)"
return theP
)catch(throw())
)
try(for i=0.0 to 1.0 by 0.1 do createBezierPoint (selection as array) u:i)catch(format "%\n" (getCurrentException()))
this is a simple function that takes 4 helpers as input, and creates a point that is constrained to the bezier curve defined by these for helpers
note that this only works with exactly 4 points (a special case of a bezier curve which is faster to calculate than a general bezier), 4 points is what makes sense for spine setups as well as probably for curvy limbs my opinion.
here's (http://astronomy.swin.edu.au/%7Epbourke/curves/bezier/) where i got the formula from (contain's c++ code that can easily be translated into maxscript or a max expression)
hope this helps anyone out there!
to test it, select 4 objects and run the script
it's very fast already, but if anyone has an idea how to speed up the script controller itself, i'm all ears
fn
createBezierPoint
points -- array of 4 objects to define the curve (1 and 4 are the control points, 2 and 3 are control handles)
u: -- position of the point along the curve (value range 0 to 1), this can either be a float value or a float subanim
=
(
try
(
if points.count != 4 then throw ("need 4 points, got " + points.count as string)
local theP = point centerMarker:true axisTriped:false cross:false box:false size:0 constantScreenSize:false drawOnTop:false
local cnt = position_script()
theP.pos.controller = cnt
for i=1 to 4 do
(
if not isValidNode points[i] then throw ("point " + i as string + " not a valid node")
cnt.addNode ("p" + i as string) points[i]
)
case (classof u) of (
float: cnt.addConstant "mu" u
subAnim: if classof u.value == float then cnt.addTarget "mu" u else throw ("u subAnim value needs to be a float")
default: throw ("invalid value for 'u', need either float or float subanim, got " + (classof u) as string)
)
cnt.setExpression \
"p1 = p1.transform[4]
p2 = p2.transform[4]
p3 = p3.transform[4]
p4 = p4.transform[4]
mum1 = 1 - mu
mum13 = mum1^3
mu3 = mu^3
(mum13*p1 + 3*mu*mum1^2*p2 + 3*mu^2*mum1*p3 + mu3*p4)"
return theP
)catch(throw())
)
try(for i=0.0 to 1.0 by 0.1 do createBezierPoint (selection as array) u:i)catch(format "%\n" (getCurrentException()))
