source: golgotha/src/i4/math/spline.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 6.2 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "math/spline.hh"
10#include "memory/lalloc.hh"
11#include "math/matrix.hh"
12#include "error/error.hh"
13#include "file/file.hh"
14
15i4_linear_allocator *i4_spline_class::p_alloc=0;
16w32 i4_spline_class::point_refs=0;
17
18void i4_spline_class::move(i4_float x_add, i4_float y_add, i4_float z_add)
19{
20  for (point *p=points; p; p=p->next) 
21  {
22    p->x+=x_add;
23    p->y+=y_add;
24    p->z+=z_add;
25  }
26}
27
28void i4_spline_class::save(i4_file_class *fp)
29{
30  fp->write_32(t_points);
31  for (point *p=points; p; p=p->next)
32  {
33    fp->write_32(p->frame);
34    fp->write_8(p->selected);
35    fp->write_float(p->x);
36    fp->write_float(p->y);
37    fp->write_float(p->z);
38  }
39}
40
41void i4_spline_class::load(i4_file_class *fp)
42{
43  cleanup();
44  t_points=fp->read_32();
45  point *last=0;
46
47  for (w32 i=0; i<t_points; i++)
48  {
49    point *p=(point *)p_alloc->alloc();
50    p->frame=fp->read_32();
51    p->selected=fp->read_8();
52    p->x=fp->read_float();
53    p->y=fp->read_float();
54    p->z=fp->read_float();
55    p->next=0;
56
57    if (last)
58      last->next=p;
59    else points=p;
60    last=p;
61  }
62}
63
64class i4_1x4_vector
65{
66public:
67  i4_float x,y,z,t;
68  i4_1x4_vector() { ; }
69  i4_1x4_vector(i4_float x, i4_float y, i4_float z, i4_float t) : x(x), y(y), z(z), t(t) { ; }
70  i4_float dot(const i4_1x4_vector &b) { return b.x*x + b.y*y + b.z*z + b.t*t; }
71  i4_1x4_vector& operator*=(i4_float b)
72  {
73    x *= b;
74    y *= b;
75    z *= b;
76    t *= b;
77    return *this;
78  }
79};
80
81class i4_bspline_basis : public i4_4x4_matrix_class
82{
83public:
84  i4_bspline_basis()
85  {
86    sw16 b[16]= { -1,3,-3,1,3,-6,3,0,-3,0,3,0,1,4,1,0};
87    for (w32 i=0; i<16; i++)
88      elt[i]=(i4_float)b[i];   
89  }
90
91  void transform(i4_1x4_vector &b, i4_1x4_vector &result)
92  {
93    i4_float vx,vy,vz,vt;
94    vx=b.x;
95    vy=b.y;
96    vz=b.z;
97    vt=b.t;
98         
99    result.x = vx*elt[0] + vy*elt[1] + vz*elt[2] + vt*elt[3];
100    result.y = vx*elt[4] + vy*elt[5] + vz*elt[6] + vt*elt[7];
101    result.z = vx*elt[8] + vy*elt[9] + vz*elt[10] + vt*elt[11];
102    result.t = vx*elt[12] + vy*elt[13] + vz*elt[14] + vt*elt[15];
103  }
104 
105};
106
107void i4_spline_class::delete_selected()
108{
109  point *p,*last=0;
110  for (p=points; p; )
111  {
112    if (p->selected)
113    {
114      if (last)
115        last->next=p->next;
116      else points=p->next;
117      point *q=p;
118      p=p->next;
119
120      p_alloc->free(q);
121
122      t_points--;
123    }
124    else
125    {     
126      last=p;
127      p=p->next;
128    }
129  }
130}
131
132i4_spline_class::i4_spline_class()
133{
134  if (!p_alloc)
135    p_alloc=new i4_linear_allocator(sizeof(point), 512, 512, "spline point allocator");
136
137  point_refs++;
138  points=0;
139  t_points=0;
140}
141
142void i4_spline_class::cleanup()
143{
144  while (points)
145  {
146    point *q=points;
147    points=points->next;
148
149    t_points--;
150    p_alloc->free(q);
151  }
152}
153
154i4_spline_class::~i4_spline_class()
155{
156  cleanup();
157
158  point_refs--;
159  if (point_refs==0)
160  {
161    delete p_alloc;
162    p_alloc=0;
163  }
164}
165
166i4_spline_class::point *i4_spline_class::add_control_point(i4_float x,
167                                                           i4_float y,
168                                                           i4_float z,
169                                                           w32 frame)
170{
171  point *p=points,*last=0;
172  while (p && p->frame<=frame)
173  {
174    last=p;
175    p=p->next;
176  }
177
178  if (last && last->frame==frame)      // you can't add two different points at the same time
179  {
180    last->x=x;
181    last->y=y;
182    last->z=z;
183    return last;
184  }
185
186
187  point *n=(point *)p_alloc->alloc();
188  n->x=x;
189  n->y=y;
190  n->z=z;
191  n->frame=frame;
192  n->selected=i4_F;
193
194  if (last)
195  {
196    n->next=last->next;
197    last->next=n;
198  }
199  else
200  {
201    n->next=points;
202    points=n;
203  } 
204  t_points++;
205
206  return n;
207}
208
209i4_spline_class::point *i4_spline_class::get_control_point(w32 p)
210{
211  point *q=points;
212  while (p && q)
213  {
214    p--;
215    q=q->next;
216  }
217  return q;
218}
219
220i4_bool i4_spline_class::get_point(w32 frame, i4_float &x, i4_float &y, i4_float &z)
221{
222  if (!points || points->frame>frame)
223    return i4_F;
224 
225  if (!points->next)
226  {
227    x=points->x;
228    y=points->y;
229    z=points->z;
230    return i4_T;
231  }
232
233  point *l1=points, *l2=points, *l3=points, *l4=points;
234  while (l4->next && l2->frame<=frame)
235  {
236    l4=l3;
237    l3=l2;
238    l2=l1;
239    if (l1->next)
240      l1=l1->next;
241  }
242
243  i4_bspline_basis b;
244  i4_float u;
245
246  if (l2->frame==l3->frame)
247    u=0;
248  else
249    u=(frame-l3->frame)/(i4_float)(l2->frame-l3->frame);
250
251  i4_1x4_vector px=i4_1x4_vector(l4->x, l3->x, l2->x, l1->x),rx;
252  i4_1x4_vector py=i4_1x4_vector(l4->y, l3->y, l2->y, l1->y),ry;
253  i4_1x4_vector pz=i4_1x4_vector(l4->z, l3->z, l2->z, l1->z),rz;
254 
255  i4_1x4_vector u_vector=i4_1x4_vector(u*u*u, u*u, u, 1);
256
257  b.transform(px,rx); 
258  b.transform(py,ry); 
259  b.transform(pz,rz); 
260 
261  rx*=1/6.0;
262  ry*=1/6.0;
263  rz*=1/6.0;
264
265  x=u_vector.dot(rx);
266  y=u_vector.dot(ry);
267  z=u_vector.dot(rz);
268
269  return i4_T;
270}
271
272
273w32 i4_spline_class::last_frame()
274{
275  if (!points) return 0;
276  point *p;
277
278  for (p=points; p->next; p=p->next);
279  return p->frame;
280}
281
282
283void i4_spline_class::insert_control_points()
284{
285  for (point *p=points; p; p=p->next)
286  {
287    if (p->selected && p->next && p->next->frame>p->frame+1)
288    {
289      point *n=(point *)p_alloc->alloc();
290      n->x=(p->x + p->next->x)/2.0;
291      n->y=(p->y + p->next->y)/2.0;
292      n->z=(p->z + p->next->z)/2.0;
293
294      n->frame=(p->frame + p->next->frame)/2;
295      n->selected=i4_F;
296      n->next=p->next;
297      p->next=n;
298      p=p->next;
299      t_points++;
300    }
301  }
302}
303
304i4_spline_class::point *i4_spline_class::get_control_point_previous_to_frame(w32 frame)
305{
306  point *p=points;
307  for (; p && p->frame<frame; p=p->next);
308  return p;
309}
310
311
Note: See TracBrowser for help on using the repository browser.