2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Math/spline.cpp $
17 * Revision 1.4 2002/06/17 06:33:09 relnev
18 * ryan's struct patch for gcc 2.95
20 * Revision 1.3 2002/06/09 04:41:22 relnev
21 * added copyright header
23 * Revision 1.2 2002/05/03 13:34:33 theoddone33
26 * Revision 1.1.1.1 2002/05/03 03:28:09 root
30 * 3 7/08/99 10:53a Dave
31 * New multiplayer interpolation scheme. Not 100% done yet, but still
32 * better than the old way.
34 * 2 7/06/99 4:24p Dave
35 * Mid-level checkin. Starting on some potentially cool multiplayer
45 #include "alphacolors.h"
48 // -------------------------------------------------------------------------------------------------
49 // SPLINE DEFINES/VARS
53 // -------------------------------------------------------------------------------------------------
57 // integer factorial. =o
64 for(idx=1; idx<=n; idx++){
72 bez_spline::bez_spline()
77 for(idx=0; idx<MAX_BEZ_PTS; idx++){
78 pts[idx] = vmd_zero_vector;
84 bez_spline::bez_spline(int _num_pts, vector *_pts[MAX_BEZ_PTS])
86 bez_set_points(_num_pts, _pts);
90 void bez_spline::bez_set_points(int _num_pts, vector *_pts[MAX_BEZ_PTS])
96 for(idx=0; idx<_num_pts; idx++){
97 SDL_assert(_pts[idx] != NULL);
98 if(_pts[idx] != NULL){
99 pts[idx] = *_pts[idx];
105 #define COMB(_n, _k) ( (float)bez_fact(_n) / (float)(bez_fact(_k) * bez_fact(_n - _k)) )
106 float bez_spline::BEZ(int k, int n, float u)
108 float a = (float)COMB(n, k);
109 float b = (float)pow(u, (float)k);
110 float c = (float)pow(1.0f - u, (float)(n - k));
115 // get a point on the curve
116 void bez_spline::bez_get_point(vector *out, float u)
121 SDL_assert(out != NULL);
130 for(idx=0; idx<num_pts; idx++){
132 bez_val = BEZ(idx, num_pts-1, u);
135 out->xyz.x += pts[idx].xyz.x * bez_val;
138 out->xyz.y += pts[idx].xyz.y * bez_val;
141 out->xyz.z += pts[idx].xyz.z * bez_val;
146 void bez_spline::bez_render(int divs, color *c)
157 inc = 1.0f / (float)divs;
160 gr_set_color_fast(c);
162 // draw that many divisions
163 bez_get_point(&pt, 0.0f);
164 g3_rotate_vertex(&a, &pt);
165 for(idx=1; idx<=divs; idx++){
167 bez_get_point(&pt, (float)idx * inc);
168 g3_rotate_vertex(&b, &pt);
171 g3_draw_line(&a, &b);
177 // draw the control points
178 gr_set_color_fast(&Color_bright_green);
179 for(idx=0; idx<num_pts; idx++){
180 g3_draw_sphere_ez(&pts[idx], 0.75f);
185 // --------------------------------------------------------------------------
189 herm_spline::herm_spline()
194 for(idx=0; idx<MAX_HERM_PTS; idx++){
195 pts[idx] = vmd_zero_vector;
196 d_pts[idx] = vmd_zero_vector;
202 herm_spline::herm_spline(int _num_pts, vector *_pts[MAX_HERM_PTS], vector *_d_pts[MAX_HERM_PTS])
204 herm_set_points(_num_pts, _pts, _d_pts);
208 void herm_spline::herm_set_points(int _num_pts, vector *_pts[MAX_HERM_PTS], vector *_d_pts[MAX_HERM_PTS])
214 for(idx=0; idx<_num_pts; idx++){
215 SDL_assert(_pts[idx] != NULL);
216 if(_pts[idx] != NULL){
217 pts[idx] = *_pts[idx];
219 SDL_assert(_d_pts[idx] != NULL);
220 if(_d_pts[idx] != NULL){
221 d_pts[idx] = *_d_pts[idx];
226 // get a point on the hermite curve.
227 void herm_spline::herm_get_point(vector *out, float u, int k)
229 float a = ( (2.0f * u * u * u) - (3.0f * u * u) + 1 );
230 float b = ( (-2.0f * u * u * u) + (3.0f * u * u) );
231 float c = ( (u * u * u) - (2.0f * u * u) + u );
232 float d = ( (u * u * u) - (u * u) );
235 vm_vec_copy_scale(&va, &pts[k], a);
238 vm_vec_copy_scale(&vb, &pts[k+1], b);
241 vm_vec_copy_scale(&vc, &d_pts[k], c);
244 vm_vec_copy_scale(&vd, &d_pts[k+1], d);
246 vm_vec_add(out, &va, &vb);
247 vm_vec_add2(out, &vc);
248 vm_vec_add2(out, &vd);
251 // the derivative of a point on the hermite curve
252 void herm_spline::herm_get_deriv(vector *deriv, float u, int k)
254 float a = ( (6.0f * u * u) - (6.0f * u) );
255 float b = ( (-6.0f * u * u) + (6.0f * u) );
256 float c = ( (3.0f * u * u) - (4.0f * u) + 1 );
257 float d = ( (3.0f * u * u) - (2.0f * u) );
260 vm_vec_copy_scale(&va, &pts[k], a);
263 vm_vec_copy_scale(&vb, &pts[k+1], b);
266 vm_vec_copy_scale(&vc, &d_pts[k], c);
269 vm_vec_copy_scale(&vd, &d_pts[k+1], d);
271 vm_vec_add(deriv, &va, &vb);
272 vm_vec_add2(deriv, &vc);
273 vm_vec_add2(deriv, &vd);
277 void herm_spline::herm_render(int divs, color *clc)
281 float inc = 1.0f / (float)divs;
287 gr_set_color_fast(clc);
289 // render each section
290 for(idx=0; idx<num_pts-1; idx++){
292 herm_get_point(&pt, 0.0f, idx);
293 g3_rotate_vertex(&a, &pt);
296 herm_get_deriv(&d_pt, 0.0f, idx);
297 vm_vec_add2(&d_pt, &pt);
298 g3_rotate_vertex(&c, &d_pt);
299 g3_draw_line(&a, &c);
301 for(s_idx=1; s_idx<divs * 2; s_idx++){
303 herm_get_point(&pt, (float)s_idx * inc, idx);
305 // 2nd point on the line
306 g3_rotate_vertex(&b, &pt);
309 g3_draw_line(&a, &b);
311 // draw the deriv line
312 herm_get_deriv(&d_pt, (float)s_idx * inc, idx);
313 vm_vec_add2(&d_pt, &pt);
314 g3_rotate_vertex(&c, &d_pt);
315 g3_draw_line(&b, &c);
322 // draw the control points
323 gr_set_color_fast(&Color_bright_green);
324 for(idx=0; idx<num_pts; idx++){
325 g3_draw_sphere_ez(&pts[idx], 0.75f);