source: golgotha/src/max_plugin/max_object.cc @ 484

Last change on this file since 484 was 80, checked in by Sam Hocevar, 14 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: 8.1 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 "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
17w32 current_anim=0, current_frame=0;       // these reference model1
18m1_poly_object_class *current_model_1=0, *current_model_2=0;
19
20i4_grow_heap_class *m1_object_heap=0;
21
22
23i4_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
35void 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
103void m1_quad_class::set_texture(char *tname)
104{
105  strcpy(texture_name, tname);
106}
107
108void 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
149void 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
173void 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
187void 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
217void 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
234void 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
268void 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
303void 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
319void 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
Note: See TracBrowser for help on using the repository browser.