Splines or curves
BlitzMax Forums/BlitzMax Programming/Splines or curves
| ||
You have two points, two normals, and an interpolation value between them. If the interpolation value is 0, the result is the first point and normal. If the interpolation value is 1, the result is the second point and normal. How do you calculate a curved path between the two points, so that the function can return a value for any interpolation? For example, if I got the values for interpolations of 0.0, 0.2, 0.4, 0.6, 0.8, and 1.0, and created a line from one to the next, it would form a curved path with 5 segments. Function Curve( point0:TVec3, normal0:TVec3, point1:TVec3, normal1:TVec3, interpolation:Float, resultpoint:TVec3, resultnormal:TVec3 ) EndFunction |
| ||
So in principle I think the problem is pretty easy, but to do it efficiently might not be. Consider the function, f(t) = at^3 + bt^2 + ct + d where a,b,c,d are 3-vectors. Then essentially the problem that you've posed is to solve the equations, f(0) = point0 f'(0) = tangent0 f(1) = point1 f'(1) = tangent1 where I've used tangent0 and tangent1 as opposed to normal0 and normal1 since these do not generate a unique line. Thus, you must simply solve two cubic equations and two quadratic. The former are going to be (as functions go) quite computationally intensive, but if you're not doing too many it should be OK. |
| ||
Cubic splines [pdf] are something I've been learning recently, in my quest to deal with network lag prediction, and they're very simple. (Applying them to physical movement/timing is the part that's holding me back.) You can just replace the For/Next loop (For t# = 0.0 To 1.0 Step 0.1) with your interpolation value to get any point along the curve (eg. t# = 0.5 is halfway). Here's an animated visualisation -- use mouse, plus -/+ to select the point to be moved. This Blitz3D code shows how to 'chain' splines to form smooth sequences -- the first two points in the second spline are derived from the last two points in the first. Lastly, some alternative splines that may be of interest: Java demos Java code |
| ||
Ah what I said before was totally wrong, you don't need to solve a cubic just a few linear equations. You have, d = point0 c = tangent 0 (from the first two equations) a+b+tangent0+point0 = point1 3a+2b+tangent0 = tangent1. These two equations can be easily solved to give the equation that you need efficiently. |
| ||
Thanks, here is my 3D version:Type TSpline Field A:Float, B:Float, C:Float, D:Float Field E:Float, F:Float, G:Float, H:Float Field I:Float, J:Float, K:Float, L:Float Method Init(p0:TVec3,n0:TVec3,p1:TVec3,n1:TVec3,mag:Float=1) Local x0:Float, y0:Float, z0:Float, x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float, x3:Float, y3:Float, z3:Float x0=p0.x y0=p0.y z0=p0.z x1=n0.x*mag+p0.x y1=n0.y*mag+p0.y z1=n0.z*mag+p0.z x2=n1.x*mag+p1.x y2=n1.y*mag+p1.y z2=n1.z*mag+p1.z x3=p1.x y3=p1.y z3=p1.z ' x coefficients... A = x3 - (3.0 * x2) + (3.0 * x1) - x0 B = (3.0 * x2) - (6.0 * x1) + (3.0 * x0) C = (3.0 * x1) - (3.0 * x0) D = x0 ' y coefficients... E = y3 - (3.0 * y2) + (3.0 * y1) - y0 F = (3.0 * y2) - (6.0 * y1) + (3.0 * y0) G = (3.0 * y1) - (3.0 * y0) H = y0 ' z coefficients... I = z3 - (3.0 * z2) + (3.0 * z1) - z0 J = (3.0 * z2) - (6.0 * z1) + (3.0 * z0) K = (3.0 * z1) - (3.0 * z0) L = z0 EndMethod Method Interpolate(t:Float,v:TVec3) v.x = Float((A * (t ^ 3.0)) + (B * (t ^ 2.0)) + (C * t) + D) v.y = Float((E * (t ^ 3.0)) + (F * (t ^ 2.0)) + (G * t) + H) v.z = Float((I * (t ^ 3.0)) + (J * (t ^ 2.0)) + (K * t) + L) EndMethod EndType |