Notifications
Clear all

[Closed] bezier curves without bezier curves

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 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 "%
" (getCurrentException()))
  
6 Replies

I get the following error.


[size=3]-- Unknown property: "addNode" in Controller:Position_Script
 
[/size]

What version does this work on?

Stev

oh right, it only works with max 8’s new script controllers

you’d have to put a dependson statement within the script referring to all 4 points by name

Thanks man, I’m going to check it out.

Stev

 eek

General bezier dont exactly exist, thats a quadratic curve – a generalisation through a series of control points which uses the cox-de boor equation. Bezier curves, use the bernstien polynormial, as you have it at the bottom of your fn. And are base on the rule of 2 end knots and 2 tangents. It makes it fast as you dont have to walk the spline. And for b-spline you can also call the same equation again and again on each segment your in.

Quadratic is the order of 1 its the simplist defined curve, bezier is 2, b-spline and non-uniform b-spline is 3 as you have to define a generalization for the cubic polynormial to work it.

Cardinal, Nurbs, and bspline use the same equation, its how you define the vectors for this equation is key. With besier you give it the tangents as there exposed, with cardinal and Nurbs these have to be defined through the generalization. And also special exceptions are needed for the ends of these curves. (the tangent problem)

Pretty slick. I should have paid more attention in math class.

Pretty slick. I should have paid more attention in math class.

haha – don’t think i did

thanky for the additional info eek. makes sense about using the same equation for all segments, i’ll try to implement that when i get the chance!