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 "max_object.hh"


10  #include "file/file.hh"


11  #include "loaders/dir_save.hh"


12  #include "saver_id.hh"


13  #include "debug.hh"


14 


15  #define G3DF_VERSION 3


16 


17  w32 current_anim=0, current_frame=0; // these reference model1


18  m1_poly_object_class *current_model_1=0, *current_model_2=0;


19 


20  i4_grow_heap_class *m1_object_heap=0;


21 


22 


23  i4_bool m1_quad_class::set(w16 a, w16 b, w16 c, w16 d)


24  {


25  // check for degenerate cases


26  if (c==d  b==d  a==d ) { d=0xffff; }


27  else if (b==c  a==c) { c=d; d=0xffff; }


28  else if (a==b) { b=c; c=d; d=0xffff; }


29 


30  g1_quad_class::set(a,b,c,d);


31 


32  return (c!=0xffff);


33  }


34 


35  void m1_quad_class::calc_texture(int reverse,


36  i4_array<g1_vert_class> &verts, w16 vert_off,


37  char *tname)


38  {


39  i4_float


40  tmp_u[4], tmp_v[4],


41  max_val, min_val,


42  scale, translate;


43  int p;


44 


45  strcpy(texture_name, tname);


46 


47  // determine quadgon texture space coordinate system


48  i4_3d_point_class i,j,k;


49 


50  i = verts[vertex_ref[1]+vert_off].v;


51  i = verts[vertex_ref[0]+vert_off].v;


52  i.normalize();


53 


54  j = verts[vertex_ref[num_verts()1]+vert_off].v;


55  j = verts[vertex_ref[0]+vert_off].v;


56  k.cross(i,j);


57  k.normalize();


58 


59  j.cross(k,i);


60 


61  // find quadgon vertex coordinates in texture space


62  for (p=0; p<num_verts(); p++)


63  {


64  tmp_u[p] = verts[vertex_ref[p]+vert_off].v.dot( i );


65  tmp_v[p] = verts[vertex_ref[p]+vert_off].v.dot( j );


66  }


67 


68  // scale u values to fit in interval [0,1]


69  max_val = min_val = tmp_u[0];


70  for (p=1; p<num_verts(); p++)


71  {


72  max_val = (tmp_u[p] > max_val) ? tmp_u[p] : max_val;


73  min_val = (tmp_u[p] < min_val) ? tmp_u[p] : min_val;


74  }


75 


76  texture_scale = max_val  min_val;


77 


78  scale = 1.0/texture_scale;


79  translate = min_val;


80 


81  if (!reverse)


82  for (p=0; p<num_verts(); p++)


83  u[p] = (tmp_u[p]+translate)*scale;


84  else


85  for (p=0; p<num_verts(); p++)


86  u[p] = 1.0  (tmp_u[p]+translate)*scale;


87 


88  // scale v values to fit in interval [0,1]


89  max_val = min_val = tmp_v[0];


90  for (p=1; p<num_verts(); p++)


91  {


92  max_val = (tmp_v[p] > max_val) ? tmp_v[p] : max_val;


93  min_val = (tmp_v[p] < min_val) ? tmp_v[p] : min_val;


94  }


95 


96  scale = 1.0/(max_val  min_val);


97  translate = min_val;


98 


99  for (p=0; p<num_verts(); p++)


100  v[p] = 1.0  (tmp_v[p]+translate)*scale;


101  }


102 


103  void m1_quad_class::set_texture(char *tname)


104  {


105  strcpy(texture_name, tname);


106  }


107 


108  void m1_quad_class::calc_texture_scale(i4_array<g1_vert_class> &verts, w16 vert_off)


109  {


110  i4_float


111  tmp_u[4], tmp_v[4],


112  max_val, min_val,


113  scale, translate;


114  int p;


115 


116  // determine quadgon texture space coordinate system


117  i4_3d_point_class i,j,k;


118 


119  i = verts[vertex_ref[1]+vert_off].v;


120  i = verts[vertex_ref[0]+vert_off].v;


121  i.normalize();


122 


123  j = verts[vertex_ref[num_verts()1]+vert_off].v;


124  j = verts[vertex_ref[0]+vert_off].v;


125  k.cross(i,j);


126  k.normalize();


127 


128  j.cross(k,i);


129 


130  // find quadgon vertex coordinates in texture space


131  for (p=0; p<num_verts(); p++)


132  {


133  tmp_u[p] = verts[vertex_ref[p]+vert_off].v.dot( i );


134  tmp_v[p] = verts[vertex_ref[p]+vert_off].v.dot( j );


135  }


136 


137  // scale u values to fit in interval [0,1]


138  max_val = min_val = tmp_u[0];


139  for (p=1; p<num_verts(); p++)


140  {


141  max_val = (tmp_u[p] > max_val) ? tmp_u[p] : max_val;


142  min_val = (tmp_u[p] < min_val) ? tmp_u[p] : min_val;


143  }


144 


145  texture_scale = max_val  min_val;


146  }


147 


148 


149  void m1_poly_object_class::save_quads(i4_saver_class *fp)


150  {


151  int i,j;


152 


153  fp>mark_section(G1_SECTION_MODEL_QUADS);


154 


155  fp>write_16(quad_a.size());


156  for (i=0; i<quad_a.size(); i++)


157  {


158  for (j=0; j<quad[i].max_verts(); ++j)


159  {


160  fp>write_16(quad_a[i]>vertex_ref[j]);


161  fp>write_float(quad_a[i]>u[j]);


162  fp>write_float(quad_a[i]>v[j]);


163  }


164  fp>write_float(quad_a[i]>texture_scale);


165  fp>write_16(quad_a[i]>flags);


166 


167  fp>write_float(quad_a[i]>normal.x);


168  fp>write_float(quad_a[i]>normal.y);


169  fp>write_float(quad_a[i]>normal.z);


170  }


171  }


172 


173  void m1_poly_object_class::save_texture_names(i4_saver_class *fp)


174  {


175  fp>mark_section(G1_SECTION_MODEL_TEXTURE_NAMES);


176 


177  fp>write_16(quad_a.size());


178  for (int i=0; i<quad_a.size(); i++)


179  {


180  w16 len=strlen(quad_a[i]>texture_name);


181  fp>write_16(len);


182  fp>write(quad_a[i]>texture_name, len);


183  }


184  }


185 


186 


187  void m1_poly_object_class::save_vert_animations(i4_saver_class *fp)


188  {


189  int i,j;


190 


191  fp>mark_section(G1_SECTION_MODEL_VERT_ANIMATION);


192 


193  fp>write_16(num_vertex);


194 


195  fp>write_16(anim_a.size());


196  for (i=0; i<anim_a.size(); i++)


197  {


198  fp>write_counted_str(*anim_a[i]>animation_name);


199 


200  fp>write_16(anim_a[i]>vertex_a.size() / num_vertex);


201 


202  for (j=0; j<anim_a[i]>vertex_a.size(); j++)


203  {


204  g1_vert_class *v=&anim_a[i]>vertex_a[j];


205 


206  fp>write_float(v>v.x);


207  fp>write_float(v>v.y);


208  fp>write_float(v>v.z);


209 


210  fp>write_float(v>normal.y);


211  fp>write_float(v>normal.z);


212  fp>write_float(v>normal.z);


213  }


214  }


215  }


216 


217  void m1_poly_object_class::save_mount_points(i4_saver_class *fp)


218  {


219  int i,j;


220 


221  fp>mark_section("GMOD Mounts");


222 


223  fp>write_16(mount_a.size());


224  for (i=0; i<mount_a.size(); i++)


225  {


226  fp>write_counted_str(*mount_a[i]>name);


227 


228  fp>write_float(mount_a[i]>offset.x);


229  fp>write_float(mount_a[i]>offset.y);


230  fp>write_float(mount_a[i]>offset.z);


231  }


232  }


233 


234  void m1_poly_object_class::calc_quad_normal(i4_array<g1_vert_class> &v,


235  m1_quad_class &q)


236  {


237  // find the surface normal used in lighting


238  i4_3d_point_class p[4];


239 


240  for (int i=0; i<q.num_verts(); i++)


241  p[i]=v[q.vertex_ref[i]].v;


242 


243  p[1] = p[0];


244  p[2] = p[0];


245 


246  if (q.num_verts()==3)


247  q.normal.cross(p[1], p[2]);


248  else


249  {


250  i4_3d_vector normal1, normal2;


251 


252  p[3] = p[0];


253  normal1.cross(p[1], p[2]);


254  normal2.cross(p[2], p[3]);


255 


256  if (normal1.length()>normal2.length())


257  q.normal = normal1;


258  else


259  q.normal = normal2;


260  }


261 


262  if (q.normal.x==0 && q.normal.y==0 && q.normal.z==0)


263  q.normal=i4_3d_vector(0,0,1);


264  else


265  q.normal.normalize();


266  }


267 


268  void m1_poly_object_class::calc_vert_normals()


269  {


270  for (int a=0; a<anim_a.size(); a++)


271  {


272  // calculate normal for each face


273  for (w32 i=0; i<quad_a.size(); i++)


274  calc_quad_normal(anim_a[a]>vertex_a, *quad_a[i]);


275 


276  for (w32 v=0; v<num_vertex; v++)


277  {


278  w32 t=0;


279  i4_3d_vector sum=i4_3d_vector(0,0,0);


280 


281  for (w32 j=0; j<quad_a.size(); j++)


282  {


283  if (quad_a[j]>vertex_ref[0]==v 


284  quad_a[j]>vertex_ref[1]==v 


285  quad_a[j]>vertex_ref[2]==v 


286  quad_a[j]>vertex_ref[3]==v)


287  {


288  t++;


289  sum+=quad_a[j]>normal;


290  }


291  }


292 


293  if (sum.x!=0  sum.y!=0  sum.z!=0)


294  sum.normalize();


295  else


296  sum.set(0,0,1);


297  anim_a[a]>vertex_a[v].normal=sum;


298  }


299  }


300  }


301 


302 


303  void m1_poly_object_class::save(i4_saver_class *fp)


304  {


305  int i,j;


306  calc_vert_normals();


307 


308  dbg("saving textures...");


309  save_texture_names(fp);


310  dbg("saving quads...");


311  save_quads(fp);


312  dbg("saving verts...");


313  save_vert_animations(fp);


314  dbg("saving mount points...");


315  save_mount_points(fp);


316  dbg("done.\n");


317  }


318 


319  void m1_poly_object_class::cleanup()


320  {


321  w32 i;


322 


323  dbg("Zapping quads...");


324  for (i=0; i<quad_a.size(); i++)


325  delete quad_a[i];


326 


327  dbg("Zapping verts...");


328  for (i=0; i<anim_a.size(); i++)


329  delete anim_a[i];


330 


331  dbg("Final clearing...");


332  quad_a.clear();


333  anim_a.clear();


334 


335  dbg("Cleanup Done.\n");


336  }


337 

