2 * $Logfile: /Freespace2/code/Math/spline.cpp $
9 * Revision 1.1 2002/05/03 03:28:09 root
13 * 3 7/08/99 10:53a Dave
14 * New multiplayer interpolation scheme. Not 100% done yet, but still
15 * better than the old way.
17 * 2 7/06/99 4:24p Dave
18 * Mid-level checkin. Starting on some potentially cool multiplayer
28 #include "alphacolors.h"
31 // -------------------------------------------------------------------------------------------------
32 // SPLINE DEFINES/VARS
36 // -------------------------------------------------------------------------------------------------
40 // integer factorial. =o
47 for(idx=1; idx<=n; idx++){
55 bez_spline::bez_spline()
60 for(idx=0; idx<MAX_BEZ_PTS; idx++){
61 pts[idx] = vmd_zero_vector;
67 bez_spline::bez_spline(int _num_pts, vector *_pts[MAX_BEZ_PTS])
69 bez_set_points(_num_pts, _pts);
73 void bez_spline::bez_set_points(int _num_pts, vector *_pts[MAX_BEZ_PTS])
79 for(idx=0; idx<_num_pts; idx++){
80 Assert(_pts[idx] != NULL);
81 if(_pts[idx] != NULL){
82 pts[idx] = *_pts[idx];
88 #define COMB(_n, _k) ( (float)bez_fact(_n) / (float)(bez_fact(_k) * bez_fact(_n - _k)) )
89 float bez_spline::BEZ(int k, int n, float u)
91 float a = (float)COMB(n, k);
92 float b = (float)pow(u, (float)k);
93 float c = (float)pow(1.0f - u, (float)(n - k));
98 // get a point on the curve
99 void bez_spline::bez_get_point(vector *out, float u)
113 for(idx=0; idx<num_pts; idx++){
115 bez_val = BEZ(idx, num_pts-1, u);
118 out->x += pts[idx].x * bez_val;
121 out->y += pts[idx].y * bez_val;
124 out->z += pts[idx].z * bez_val;
129 void bez_spline::bez_render(int divs, color *c)
140 inc = 1.0f / (float)divs;
143 gr_set_color_fast(c);
145 // draw that many divisions
146 bez_get_point(&pt, 0.0f);
147 g3_rotate_vertex(&a, &pt);
148 for(idx=1; idx<=divs; idx++){
150 bez_get_point(&pt, (float)idx * inc);
151 g3_rotate_vertex(&b, &pt);
154 g3_draw_line(&a, &b);
160 // draw the control points
161 gr_set_color_fast(&Color_bright_green);
162 for(idx=0; idx<num_pts; idx++){
163 g3_draw_sphere_ez(&pts[idx], 0.75f);
168 // --------------------------------------------------------------------------
172 herm_spline::herm_spline()
177 for(idx=0; idx<MAX_HERM_PTS; idx++){
178 pts[idx] = vmd_zero_vector;
179 d_pts[idx] = vmd_zero_vector;
185 herm_spline::herm_spline(int _num_pts, vector *_pts[MAX_HERM_PTS], vector *_d_pts[MAX_HERM_PTS])
187 herm_set_points(_num_pts, _pts, _d_pts);
191 void herm_spline::herm_set_points(int _num_pts, vector *_pts[MAX_HERM_PTS], vector *_d_pts[MAX_HERM_PTS])
197 for(idx=0; idx<_num_pts; idx++){
198 Assert(_pts[idx] != NULL);
199 if(_pts[idx] != NULL){
200 pts[idx] = *_pts[idx];
202 Assert(_d_pts[idx] != NULL);
203 if(_d_pts[idx] != NULL){
204 d_pts[idx] = *_d_pts[idx];
209 // get a point on the hermite curve.
210 void herm_spline::herm_get_point(vector *out, float u, int k)
212 float a = ( (2.0f * u * u * u) - (3.0f * u * u) + 1 );
213 float b = ( (-2.0f * u * u * u) + (3.0f * u * u) );
214 float c = ( (u * u * u) - (2.0f * u * u) + u );
215 float d = ( (u * u * u) - (u * u) );
218 vm_vec_copy_scale(&va, &pts[k], a);
221 vm_vec_copy_scale(&vb, &pts[k+1], b);
224 vm_vec_copy_scale(&vc, &d_pts[k], c);
227 vm_vec_copy_scale(&vd, &d_pts[k+1], d);
229 vm_vec_add(out, &va, &vb);
230 vm_vec_add2(out, &vc);
231 vm_vec_add2(out, &vd);
234 // the derivative of a point on the hermite curve
235 void herm_spline::herm_get_deriv(vector *deriv, float u, int k)
237 float a = ( (6.0f * u * u) - (6.0f * u) );
238 float b = ( (-6.0f * u * u) + (6.0f * u) );
239 float c = ( (3.0f * u * u) - (4.0f * u) + 1 );
240 float d = ( (3.0f * u * u) - (2.0f * u) );
243 vm_vec_copy_scale(&va, &pts[k], a);
246 vm_vec_copy_scale(&vb, &pts[k+1], b);
249 vm_vec_copy_scale(&vc, &d_pts[k], c);
252 vm_vec_copy_scale(&vd, &d_pts[k+1], d);
254 vm_vec_add(deriv, &va, &vb);
255 vm_vec_add2(deriv, &vc);
256 vm_vec_add2(deriv, &vd);
260 void herm_spline::herm_render(int divs, color *clc)
264 float inc = 1.0f / (float)divs;
270 gr_set_color_fast(clc);
272 // render each section
273 for(idx=0; idx<num_pts-1; idx++){
275 herm_get_point(&pt, 0.0f, idx);
276 g3_rotate_vertex(&a, &pt);
279 herm_get_deriv(&d_pt, 0.0f, idx);
280 vm_vec_add2(&d_pt, &pt);
281 g3_rotate_vertex(&c, &d_pt);
282 g3_draw_line(&a, &c);
284 for(s_idx=1; s_idx<divs * 2; s_idx++){
286 herm_get_point(&pt, (float)s_idx * inc, idx);
288 // 2nd point on the line
289 g3_rotate_vertex(&b, &pt);
292 g3_draw_line(&a, &b);
294 // draw the deriv line
295 herm_get_deriv(&d_pt, (float)s_idx * inc, idx);
296 vm_vec_add2(&d_pt, &pt);
297 g3_rotate_vertex(&c, &d_pt);
298 g3_draw_line(&b, &c);
305 // draw the control points
306 gr_set_color_fast(&Color_bright_green);
307 for(idx=0; idx<num_pts; idx++){
308 g3_draw_sphere_ez(&pts[idx], 0.75f);