FS2_Open
Open source remastering of the Freespace 2 engine
spline.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "globalincs/alphacolors.h"
13 #include "graphics/2d.h"
14 #include "math/spline.h"
15 #include "render/3d.h"
16 
17 
18 
19 // -------------------------------------------------------------------------------------------------
20 // SPLINE DEFINES/VARS
21 //
22 
23 
24 // -------------------------------------------------------------------------------------------------
25 // SPLINE FUNCTIONS
26 //
27 
28 static float bez_fact_lookup[13] = {
29  1.0f, // 0!
30  1.0f, // 1!
31  2.0f, // 2!
32  6.0f, // 3!
33  24.0f, // 4!
34  120.0f, // 5!
35  720.0f, // 6!
36  5040.0f, // 7!
37  40320.0f, // 8!
38  362880.0f, // 9!
39  3628800.0f, // 10!
40  39916800.0f, // 11!
41  479001600.0f, // 12!
42 };
43 
44 // Limited Factorial
45 static float bez_fact(int n)
46 {
47  Assert((n >= 0) && (n <= 12));
48 
49  return bez_fact_lookup[n];
50 }
51 
52 // bez constructor
54 {
55  int idx;
56 
57  // zero all points
58  for(idx=0; idx<MAX_BEZ_PTS; idx++){
60  }
61  num_pts = 0;
62 }
63 
64 // bez constructor
66 {
67  bez_set_points(_num_pts, _pts);
68 }
69 
70 // set control points
71 void bez_spline::bez_set_points(int _num_pts, vec3d *_pts[MAX_BEZ_PTS])
72 {
73  int idx;
74 
75  // store the points
76  num_pts = _num_pts;
77  for(idx=0; idx<_num_pts; idx++){
78  Assert(_pts[idx] != NULL);
79  if(_pts[idx] != NULL){
80  pts[idx] = *_pts[idx];
81  }
82  }
83 }
84 
85 // blend function
86 #define COMB(_n, _k) (bez_fact(_n) / (bez_fact(_k) * bez_fact(_n - _k)))
87 float bez_spline::BEZ(int k, int n, float u)
88 {
89  float a = (float)COMB(n, k);
90  float b = (float)pow(u, (float)k);
91  float c = (float)pow(1.0f - u, (float)(n - k));
92 
93  return a * b * c;
94 }
95 
96 // get a point on the curve
98 {
99  int idx;
100  float bez_val;
101 
102  Assert(out != NULL);
103  if(out == NULL){
104  return;
105  }
106 
107  // calc
108  out->xyz.x = 0.0f;
109  out->xyz.y = 0.0f;
110  out->xyz.z = 0.0f;
111  for(idx=0; idx<num_pts; idx++){
112  // bez val
113  bez_val = BEZ(idx, num_pts-1, u);
114 
115  // x component
116  out->xyz.x += pts[idx].xyz.x * bez_val;
117 
118  // y component
119  out->xyz.y += pts[idx].xyz.y * bez_val;
120 
121  // z component
122  out->xyz.z += pts[idx].xyz.z * bez_val;
123  }
124 }
125 
126 // render a bezier
128 {
129  float inc;
130  int idx;
131  vertex a, b;
132  vec3d pt;
133 
134  // bleh
135  if(divs <= 0){
136  return;
137  }
138  inc = 1.0f / (float)divs;
139 
140  // draw in red
142 
143  // draw that many divisions
144  bez_get_point(&pt, 0.0f);
145  g3_rotate_vertex(&a, &pt);
146  for(idx=1; idx<=divs; idx++){
147  // second point
148  bez_get_point(&pt, (float)idx * inc);
149  g3_rotate_vertex(&b, &pt);
150 
151  // draw the line
152  g3_draw_line(&a, &b);
153 
154  // store b
155  a = b;
156  }
157 
158  // draw the control points
160  for(idx=0; idx<num_pts; idx++){
161  g3_draw_sphere_ez(&pts[idx], 0.75f);
162  }
163 }
164 
165 
166 // --------------------------------------------------------------------------
167 // HERMITE splines
168 
169 // constructor
171 {
172  int idx;
173 
174  // zero all points
175  for(idx=0; idx<MAX_HERM_PTS; idx++){
178  }
179  num_pts = 0;
180 }
181 
182 // constructor
183 herm_spline::herm_spline(int _num_pts, vec3d *_pts[MAX_HERM_PTS], vec3d *_d_pts[MAX_HERM_PTS])
184 {
185  herm_set_points(_num_pts, _pts, _d_pts);
186 }
187 
188 // set the points
189 void herm_spline::herm_set_points(int _num_pts, vec3d *_pts[MAX_HERM_PTS], vec3d *_d_pts[MAX_HERM_PTS])
190 {
191  int idx;
192 
193  // store the points
194  num_pts = _num_pts;
195  for(idx=0; idx<_num_pts; idx++){
196  Assert(_pts[idx] != NULL);
197  if(_pts[idx] != NULL){
198  pts[idx] = *_pts[idx];
199  }
200  Assert(_d_pts[idx] != NULL);
201  if(_d_pts[idx] != NULL){
202  d_pts[idx] = *_d_pts[idx];
203  }
204  }
205 }
206 
207 // get a point on the hermite curve.
208 void herm_spline::herm_get_point(vec3d *out, float u, int k)
209 {
210  float a = ( (2.0f * u * u * u) - (3.0f * u * u) + 1 );
211  float b = ( (-2.0f * u * u * u) + (3.0f * u * u) );
212  float c = ( (u * u * u) - (2.0f * u * u) + u );
213  float d = ( (u * u * u) - (u * u) );
214 
215  vec3d va;
216  vm_vec_copy_scale(&va, &pts[k], a);
217 
218  vec3d vb;
219  vm_vec_copy_scale(&vb, &pts[k+1], b);
220 
221  vec3d vc;
222  vm_vec_copy_scale(&vc, &d_pts[k], c);
223 
224  vec3d vd;
225  vm_vec_copy_scale(&vd, &d_pts[k+1], d);
226 
227  vm_vec_add(out, &va, &vb);
228  vm_vec_add2(out, &vc);
229  vm_vec_add2(out, &vd);
230 }
231 
232 // the derivative of a point on the hermite curve
233 void herm_spline::herm_get_deriv(vec3d *deriv, float u, int k)
234 {
235  float a = ( (6.0f * u * u) - (6.0f * u) );
236  float b = ( (-6.0f * u * u) + (6.0f * u) );
237  float c = ( (3.0f * u * u) - (4.0f * u) + 1 );
238  float d = ( (3.0f * u * u) - (2.0f * u) );
239 
240  vec3d va;
241  vm_vec_copy_scale(&va, &pts[k], a);
242 
243  vec3d vb;
244  vm_vec_copy_scale(&vb, &pts[k+1], b);
245 
246  vec3d vc;
247  vm_vec_copy_scale(&vc, &d_pts[k], c);
248 
249  vec3d vd;
250  vm_vec_copy_scale(&vd, &d_pts[k+1], d);
251 
252  vm_vec_add(deriv, &va, &vb);
253  vm_vec_add2(deriv, &vc);
254  vm_vec_add2(deriv, &vd);
255 }
256 
257 // render a bezier
258 void herm_spline::herm_render(int divs, color *clc)
259 {
260  int idx;
261  int s_idx;
262  float inc = 1.0f / (float)divs;
263 
264  vertex a, b, c;
265  vec3d pt, d_pt;
266 
267  // draw in red
268  gr_set_color_fast(clc);
269 
270  // render each section
271  for(idx=0; idx<num_pts-1; idx++){
272  // render this piece
273  herm_get_point(&pt, 0.0f, idx);
274  g3_rotate_vertex(&a, &pt);
275 
276  // draw the deriv
277  herm_get_deriv(&d_pt, 0.0f, idx);
278  vm_vec_add2(&d_pt, &pt);
279  g3_rotate_vertex(&c, &d_pt);
280  g3_draw_line(&a, &c);
281 
282  for(s_idx=1; s_idx<divs * 2; s_idx++){
283  // second point
284  herm_get_point(&pt, (float)s_idx * inc, idx);
285 
286  // 2nd point on the line
287  g3_rotate_vertex(&b, &pt);
288 
289  // draw the line
290  g3_draw_line(&a, &b);
291 
292  // draw the deriv line
293  herm_get_deriv(&d_pt, (float)s_idx * inc, idx);
294  vm_vec_add2(&d_pt, &pt);
295  g3_rotate_vertex(&c, &d_pt);
296  g3_draw_line(&b, &c);
297 
298  // store b
299  a = b;
300  }
301  }
302 
303  // draw the control points
305  for(idx=0; idx<num_pts; idx++){
306  g3_draw_sphere_ez(&pts[idx], 0.75f);
307  }
308 }
void herm_render(int divs, color *c)
Definition: spline.cpp:258
void bez_set_points(int _num_pts, vec3d *_pts[MAX_BEZ_PTS])
Definition: spline.cpp:71
void herm_set_points(int _num_pts, vec3d *_pts[MAX_HERM_PTS], vec3d *_d_pts[MAX_HERM_PTS])
Definition: spline.cpp:189
float BEZ(int k, int n, float u)
Definition: spline.cpp:87
Assert(pm!=NULL)
Definition: pstypes.h:88
int num_pts
Definition: spline.h:57
Definition: 2d.h:95
struct vec3d::@225::@227 xyz
GLclampf f
Definition: Glext.h:7097
enum_h * u
Definition: lua.cpp:12649
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
int g3_draw_line(vertex *p0, vertex *p1)
Definition: 3ddraw.cpp:112
int num_pts
Definition: spline.h:31
#define MAX_BEZ_PTS
Definition: spline.h:25
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
void herm_get_point(vec3d *out, float u, int k)
Definition: spline.cpp:208
color Color_bright_green
Definition: alphacolors.cpp:31
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
void bez_get_point(vec3d *out, float u)
Definition: spline.cpp:97
vec3d pts[MAX_HERM_PTS]
Definition: spline.h:55
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
void herm_get_deriv(vec3d *deriv, float u, int k)
Definition: spline.cpp:233
void bez_render(int divs, color *c)
Definition: spline.cpp:127
int idx
Definition: multiui.cpp:761
GLclampd n
Definition: Glext.h:7286
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
Definition: vecmat.cpp:257
vec3d d_pts[MAX_HERM_PTS]
Definition: spline.h:56
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
vec3d pts[MAX_BEZ_PTS]
Definition: spline.h:30
#define MAX_HERM_PTS
Definition: spline.h:52
bez_spline()
Definition: spline.cpp:53
int g3_draw_sphere_ez(const vec3d *pnt, float rad)
Definition: 3ddraw.cpp:498
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
const GLubyte * c
Definition: Glext.h:8376
#define COMB(_n, _k)
Definition: spline.cpp:86