following a curved path
Monkey Forums/Monkey Programming/following a curved path
| ||
hi guys ive figured out how to get an image too follow path with straight lines but im after creating a path that is curved or even spiralled.Am i right in thinking i need to figure out bezier curves for this and if so does anyone know of somme easy to follow tutorials. what im after ultimately is for a particle emitter where i can make the spawn point of the emitter follow the curved path.Any pointers would be most welcome |
| ||
Cant you make a curve from a number of straight lines? |
| ||
Yeah but it looks kinda jerky.that was something I tried but doesn't quite look good enuogh |
| ||
The 2 functions I use for Beizer curves:Class P2 Field X,Y End Function BezierArrayQuadratic:P2[](p1:P2,p2:P2,p3:P2,segments) Local i Local result := New List<P2>() For Local i := 0 Until segments Local t := Float(i) / segments Local a := Pow((1.0 - t), 2.0) Local b := 2.0 * t * (1.0 - t) Local c := Pow(t, 2.0) Local x := a * p1.X + b * p2.X + c * p3.X Local y := a * p1.Y + b * p2.Y + c * p3.Y result.AddLast(New P2(x,y)) End Return result.ToArray() End Function BezierArrayCubic:P2[](p1:P2,p2:P2,p3:P2,p4:P2,segments) Local i Local result := New List<P2>() For Local i := 0 Until segments Local t := Float(i) / segments Local a := Pow((1.0 - t), 3.0) Local b := 3.0 * t * Pow((1.0 - t), 2.0) Local c := 3.0 * Pow(t, 2.0) * (1.0 - t) Local d := Pow(t, 3.0) Local x := a * p1.X + b * p2.X + c * p3.X + d * p4.X Local y := a * p1.Y + b * p2.Y + c * p3.Y + d * p4.Y result.AddLast(New P2(x,y)) End Return result.ToArray() End And then you could use the following to move between the values: Global stLinear := New stLinearCl() Class SimpleTween Method Do:Float(value:Float) Abstract Method Do:Float(fromvalue:Float, tovalue:Float, ratio:Float) Return Do(ratio)*(tovalue-fromvalue)+fromvalue End Method ToString:String() Abstract End Class stLinearCl Extends SimpleTween Method ToString:String() Return "linear" End Method Do:Float(value:Float) Final Return value End End Class stSinCl Extends SimpleTween Field frequency:Float Method ToString:String() Return "sin" End Method Do:Float(value:Float) Final Return Sin(value*360*frequency) End End |
| ||
Cheers looks complex but I will study this after work tonight |
| ||
For the most part you'll want to use bezier or other spline to define the curved path but to convert it to straight lines for actual usage. Not only is it faster to work with the straight lines but splines don't allow you to easily do things like find a point at a certain distance along the path. Erik's code above looks like it spits out a straight line approximation of the bezier with a given number of segments. This may work fine for you but if you need to balance numbers of points with accuracy in the approximation then you might want to do something that continues or stops creating segments based on a measurement of the midpoint error. |
| ||
You can parameterise a Bezier. I did this in the past for my old HyperCurve screensaver. You plot your basic curve as a series of points, then for the portion of the curve nearest one of the points, you take that point and the two adjacent points, and generate four control points for a cubic curve. Then you can use a parameter from 0-1 to generate any point along the curve. I don't remember the details but the C++ code looks like this, maybe it gives an idea of what I was doing: |
| ||
The first part of this might be helpful. It explains the ideas / math behind parametrizing bezier curves... |
| ||
thanks for all the feed back guys.lots of good info there.I wrote a test program using erics BezierArrayQuadratic function and got it working really easy.I plan to slightly modified it to save it to an array instead of list and i can use this to figure out where the spawn point should be over the life of the emitter.Well thats my theory anyway,no doubt i will hit a few probs along the way.On holiday next week so should have a working version in my editor by then.cheers |