source: golgotha/src/golg/obj3d.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 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: 9.9 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 <string.h>
10#include "obj3d.hh"
11#include "loaders/dir_load.hh"
12#include "checksum/checksum.hh"
13#include "string/str_checksum.hh"
14#include "saver_id.hh"
15#include "time/profile.hh"
16
17#ifdef i4_NEW_CHECK
18#undef new
19#endif
20
21void g1_quad_object_class::scale(i4_float value)
22{
23  for (int j=0; j<num_animations; j++)
24  {
25    g1_vert_class *p=animation[j].vertex;
26    for (int i=0; i<animation[j].num_frames; i++)
27    {
28      g1_vert_class *p=get_verts(j,i);
29      for (int k=0; k<num_vertex; k++)
30        p[k].v*=value;
31    }
32  }
33   
34  for (w32 a=0; a<num_quad; a++)
35    quad[a].texture_scale *= value;
36
37  for (w32 m=0; m<num_mounts; m++)
38    mount[m] *= value;
39
40  extent *= value;
41}
42
43void g1_quad_object_class::translate(i4_float xadd, i4_float yadd, i4_float zadd)
44{
45  for (int j=0; j<num_animations; j++)
46  {
47    g1_vert_class *p=animation[j].vertex;
48
49    for (int i=0; i<animation[j].num_frames; i++)
50    {
51      g1_vert_class *p=get_verts(j,i);
52      for (int k=0; k<num_vertex; k++)
53        p[k].v += i4_3d_point_class(xadd, yadd, zadd);
54    }     
55  }
56}
57
58void g1_quad_object_class::calc_extents()
59{
60  int i,j,k;
61
62  i4_float minx, maxx, miny, maxy, minz, maxz;
63
64  extent=0.0;
65
66  minx=miny=minz=9999;
67  maxx=maxy=maxz=-9999;
68 
69  for(i=0;i<num_animations;i++)
70  {
71    for(j=0;j<animation[i].num_frames;j++)
72    {
73      for(k=j*num_vertex;k<(j*num_vertex)+num_vertex;k++)
74      {
75        if(animation[i].vertex[k].v.length()>extent) extent=animation[i].vertex[k].v.length();
76        if(animation[i].vertex[k].v.x < minx) minx=animation[i].vertex[k].v.x;
77        if(animation[i].vertex[k].v.y < miny) miny=animation[i].vertex[k].v.y;
78        if(animation[i].vertex[k].v.z < minz) minz=animation[i].vertex[k].v.z;
79        if(animation[i].vertex[k].v.x > maxx) maxx=animation[i].vertex[k].v.x;
80        if(animation[i].vertex[k].v.y > maxy) maxy=animation[i].vertex[k].v.y;
81        if(animation[i].vertex[k].v.z > maxz) maxz=animation[i].vertex[k].v.z;
82      }
83    }
84  }
85}
86
87void g1_quad_object_class::update(i4_float time)
88{
89  for (int i=0; i<num_special; i++)
90  {
91    g1_texture_animation *t = &special[i];
92    g1_quad_class *q = &quad[t->quad_number];
93    int max_frames = t->max_frames;
94
95    if (max_frames==0)
96    {
97      // panning
98
99      i4_float fr, du,dv;
100     
101      fr = time*t->speed;
102      fr -= i4_float(int(fr));
103      du = t->du*fr;
104      dv = t->dv*fr;
105
106      for (int n=0; n<q->num_verts(); n++)
107      {
108        q->u[n] = t->u[n] + du;
109        q->v[n] = t->v[n] + dv;
110      }
111    }
112    else
113    {
114      // animation
115      int frame = int(time*t->speed)%max_frames;
116
117      int x = frame%t->frames_x;
118      int y = frame/t->frames_x;
119
120      for (int n=0; n<q->num_verts(); n++)
121      {
122        q->u[n] = t->u[n] + t->du*x;
123        q->v[n] = t->v[n] + t->dv*y;
124      }
125    }
126  }
127}
128
129i4_bool g1_quad_object_class::intersect(const i4_3d_vector &point,
130                                        const i4_3d_vector &ray,
131                                        int anim, int frame,
132                                        i4_float *intersect_t,
133                                        int *hit_poly,
134                                        i4_3d_vector *normal)
135{
136  g1_vert_class *verts = get_verts(anim, frame);
137  g1_quad_class *q = quad;
138  i4_bool hit = i4_F;
139  i4_float new_t = 1.0;
140
141  for (int i=0; i<num_quad; i++, q++)
142  {
143    if (q->normal.dot(ray)>=0)
144      // wrong direction, next quad
145      continue;
146
147    // find intersection point in polygon's plane
148    i4_float d = q->normal.dot(verts[q->vertex_ref[0]].v);
149    i4_float num = d - q->normal.dot(point);
150    i4_float den = q->normal.dot(ray);
151    i4_float t = num/den;
152   
153    if (t<0)
154      // behind the observer, next
155      continue;
156
157    if (t>=new_t)
158      // check if new intersection is closer than previous ones
159      continue;
160
161    // project point into plane
162    int j, u,v;
163    i4_3d_vector new_ray(ray);
164    new_ray *= t;
165    i4_3d_vector new_point(point);
166    new_point += new_ray;
167
168    // determine orthogonal plane for 2D point in polygon test
169    i4_3d_vector abs_normal;
170
171    abs_normal.set(fabs(q->normal.x), fabs(q->normal.y), fabs(q->normal.z));
172
173    if (abs_normal.x>abs_normal.y && abs_normal.x>abs_normal.z)
174    {
175      // test in yz plane
176      u = 1; v = 2;
177    }
178    else if (abs_normal.y>abs_normal.x && abs_normal.y>abs_normal.z)
179    {
180      // test in zx plane
181      u = 2; v = 0;
182    }
183    else
184    {
185      // test in xy plane
186      u = 0; v = 1;
187    }
188
189    // count first axis crossings of polygon to determine whether point in polygon
190    i4_float
191      dx1, dy1,
192      dx2 = verts[q->vertex_ref[0]].v[u] - new_point[u],
193      dy2 = verts[q->vertex_ref[0]].v[v] - new_point[v];
194
195    int
196      x_sign1, y_sign1,
197      x_sign2 = dx2>0,
198      y_sign2 = dy2>0;
199
200    int inside=0;
201
202    for (j=q->num_verts()-1; j>=0; j--)
203    {
204      dx1 = verts[q->vertex_ref[j]].v[u] - new_point[u];
205      dy1 = verts[q->vertex_ref[j]].v[v] - new_point[v];
206      x_sign1 = dx1>0;
207      y_sign1 = dy1>0;
208      if (y_sign1 != y_sign2)
209      {
210        // crosses x-axis
211        if (x_sign1 != x_sign2)
212        {
213          // check if crossing point is positive ((slope2>slope1) ^ (y2>y1))
214          if ((dx2*dy1 > dx1*dy2) ^ (dy2>dy1))
215            inside = !inside;
216        }
217        else if (x_sign1)
218          // crosses +x-axis
219          inside = !inside;
220        y_sign2 = y_sign1;
221      }
222      x_sign2 = x_sign1;
223      dx2 = dx1;
224      dy2 = dy1;
225    }
226
227    if (inside)
228    {
229      // update current intersection
230      new_t = t;
231      if (hit_poly) *hit_poly=i;
232      if (normal) *normal=q->normal;
233      hit = i4_T;
234    }
235  }
236  if (intersect_t) *intersect_t=new_t;
237  return hit;
238}
239
240i4_bool g1_quad_object_class::get_mount_point(char *name, i4_3d_vector& vect) const
241{
242  w32 id = i4_check_sum32(name, strlen(name));
243
244  for (int i=0; i<num_mounts; i++)
245    if (mount_id[i] == id)
246    {
247      vect = mount[i];
248      return i4_T;
249    }
250  return i4_F;
251}
252
253
254static i4_profile_class pf_load_tnames("models:load_tname");
255static i4_profile_class pf_load_quads("models:load_quads");
256static i4_profile_class pf_load_verts("models:load_verts");
257static i4_profile_class pf_load_mounts("models:load_mounts");
258static i4_profile_class pf_load_tanim("models:load_tanim");
259
260
261
262g1_quad_object_class *g1_base_object_loader_class::load(i4_loader_class *fp)
263{
264  int i,j,k;
265 
266  if (!fp)
267    return 0;
268
269  if (!fp->goto_section(G1_SECTION_MODEL_TEXTURE_NAMES))
270    return 0;
271
272  obj=allocate_object();
273
274  pf_load_tnames.start();
275  w16 quads=fp->read_16();
276  set_num_quads(quads);
277
278  char name[256];
279  for (i=0; i<quads; i++)
280  {   
281    w16 len = fp->read_16();
282    fp->read(name, len);
283    name[len]=0;
284    store_texture_name(i, name);
285  } 
286  pf_load_tnames.stop();
287
288  if (!fp->goto_section(G1_SECTION_MODEL_QUADS))
289    return 0;
290
291  pf_load_quads.start();
292  fp->read_16();                // repeat of num quads (why?)
293  for (i=0; i<quads; i++)
294  {
295    w16 ref[4];
296    i4_float u[4],v[4], scale;
297    i4_3d_vector normal;
298    w32 flags;
299
300    for (j=0; j<4; ++j)
301    {
302      ref[j]=fp->read_16();
303      u[j]=fp->read_float();
304      v[j]=fp->read_float();
305    }
306
307    scale=fp->read_float();
308    flags=fp->read_16();
309
310    normal.x=fp->read_float();
311    normal.y=fp->read_float();
312    normal.z=fp->read_float();     
313
314    create_quad(i, 4, ref, flags);
315    store_texture_params(i, scale, u, v);
316    store_quad_normal(i, normal);
317  }
318  pf_load_quads.stop();
319
320  if (!fp->goto_section(G1_SECTION_MODEL_VERT_ANIMATION))
321    return 0;
322 
323  pf_load_verts.start();
324  w16 nv=fp->read_16();  // number of vertexes in object
325  w16 na=fp->read_16();  // number of animations
326
327  set_num_vertex(nv);
328  set_num_animations(na);
329
330  for (i=0; i<na; i++)
331  {
332    int len=fp->read_16();
333    fp->read(name, len);
334    name[len]=0;
335
336    w16 frames = fp->read_16();
337
338    create_animation(i, name, frames);
339
340    for (j=0; j<frames; j++)
341    {
342      for (k=0; k<nv; k++)
343      {
344        i4_3d_vector v,n;
345
346        v.x=fp->read_float();
347        v.y=fp->read_float();
348        v.z=fp->read_float();
349
350        n.x=fp->read_float();
351        n.y=fp->read_float();
352        n.z=fp->read_float();
353
354        create_vertex(i,j,k,v);
355        store_vertex_normal(i,j,k,n);
356      }
357    }
358  } 
359  pf_load_verts.stop();
360
361  // optional mount points
362  if (fp->goto_section("GMOD Mounts"))
363  {
364    pf_load_mounts.start();
365 
366    w16 mounts = fp->read_16();
367    set_num_mount_points(mounts);
368   
369    for (i=0; i<mounts; i++)
370    {
371      i4_3d_vector v;
372     
373      int len=fp->read_16();
374      fp->read(name, len);
375      name[len]=0;
376
377      v.x = fp->read_float();
378      v.y = fp->read_float();
379      v.z = fp->read_float();
380     
381      create_mount_point(i,name,v);
382    }
383    pf_load_mounts.stop();
384 
385  }
386
387  // optional mount points
388  if (fp->goto_section("GMOD Texture Animations"))
389  {
390    pf_load_tanim.start();
391    w16 anims = fp->read_16();
392    set_num_texture_animations(anims);
393   
394    for (i=0; i<anims; i++)
395    {
396      w16 q;
397      w8 maxf, frx;
398      i4_float sp,du,dv;
399     
400      fp->read_format("211fff",&q,&maxf,&frx,&sp,&du,&dv);
401     
402      if (maxf>0)
403        create_texture_animation(i,q,maxf,frx,du,dv,sp);
404      else
405        create_texture_pan(i,q,du,dv,sp);
406    }
407    pf_load_tanim.stop();
408  }
409
410  finish_object();
411
412  return obj;
413}
414
415
Note: See TracBrowser for help on using the repository browser.