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 


15  i4_linear_allocator *i4_spline_class::p_alloc=0;


16  w32 i4_spline_class::point_refs=0;


17 


18  void 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 


28  void 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 


41  void 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 


64  class i4_1x4_vector


65  {


66  public:


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 


81  class i4_bspline_basis : public i4_4x4_matrix_class


82  {


83  public:


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 


107  void 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 


132  i4_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 


142  void 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 


154  i4_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 


166  i4_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 


209  i4_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 


220  i4_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=(framel3>frame)/(i4_float)(l2>framel3>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 


273  w32 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 


283  void 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 


304  i4_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 

