source: golgotha/src/golg/objs/explode_model.cc

Last change on this file 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: 11.6 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 "objs/explode_model.hh"
10#include "objs/model_id.hh"
11#include "math/pi.hh"
12#include "math/trig.hh"
13#include "math/angle.hh"
14#include "g1_rand.hh"
15#include "resources.hh"
16#include "saver.hh"
17#include "g1_render.hh"
18#include "r1_clip.hh"
19#include "r1_api.hh"
20#include "g1_tint.hh"
21#include "object_definer.hh"
22#include "time/profile.hh"
23#include "map_man.hh"
24#include "map.hh"
25#include "objs/particle_emitter.hh"
26#include "tick_count.hh"
27#include "draw_context.hh"
28
29i4_profile_class pf_exp_model_setup("explode_model setup");
30i4_profile_class pf_exp_model_think("explode_model think");
31i4_profile_class pf_exp_model_draw("explode_model draw");
32
33g1_object_definer<g1_explode_model_class>
34g1_explode_model_def("explode_model");
35
36inline void check_on_map(const i4_3d_vector &v)
37{
38  int vx=i4_f_to_i(v.x), vy=i4_f_to_i(v.y);
39  if (vx<0 || vy<0 || vx>=g1_get_map()->width() || vy>=g1_get_map()->height())
40    i4_error("off map");
41}
42
43
44
45g1_explode_model_class::g1_explode_model_class(g1_object_type id,
46                                               g1_loader_class *fp)
47  : g1_object_class(id,fp)
48{
49  //does not save or load. too complicated and not really necessary
50  vertices = 0;
51  num_vertices = 0;
52
53  faces = 0;
54  num_faces = 0;
55}
56
57void g1_explode_model_class::save(g1_saver_class *fp)
58{
59  g1_object_class::save(fp);
60}
61
62g1_explode_model_class::~g1_explode_model_class()
63{
64  if (vertices)
65    i4_free(vertices);
66 
67  if (faces)
68    i4_free(faces);
69
70
71
72void g1_explode_model_class::grab_model(g1_object_class *o, i4_3d_vector &obj_center)
73{
74  g1_quad_object_class *base_m = o->draw_params.model;
75
76  //face/vertex setup. count all the faces and vertices in base and sub-objects
77   
78  num_faces    = base_m->num_quad;
79  num_vertices = 0;
80
81  obj_center=i4_3d_vector(0,0,0);
82 
83  int i,j;
84  for (i=0; i<base_m->num_quad; i++)
85    num_vertices += base_m->quad[i].num_verts();
86
87  //allocate space
88  faces    = (g1_explode_face_class *)   i4_malloc(sizeof(g1_explode_face_class)   * num_faces,"");
89  vertices = (g1_explode_vertex_class *)i4_malloc(sizeof(g1_explode_vertex_class)*num_vertices,"");
90
91  //copy information. this is ugly, has to use transforms
92  //to get everything into world space, etc.. 
93 
94  i4_transform_class base_transform,mini_transform,spare_transform,*cur_transform;
95
96  //make sure there is a transform ready for the base model
97  o->calc_world_transform(g1_render.frame_ratio, &base_transform);
98
99  cur_transform = &base_transform;     
100 
101  g1_quad_object_class    *m = base_m;
102  g1_explode_face_class   *f = faces;
103  g1_explode_vertex_class *v = vertices;
104 
105  sw32 vertex_count = 0; 
106  sw32 k = 0;
107
108  sw32 total_face_count=0;
109
110 
111  //  while (m)
112  {
113    g1_vert_class *src_verts=m->get_verts(o->draw_params.animation, o->draw_params.frame);
114   
115    for (i=0; i<m->num_quad; i++, f++)
116    {
117      memcpy(f->indices, m->quad[i].vertex_ref, sizeof(f->indices));
118
119      i4_3d_vector center(0,0,0);
120      int tv=f->num_verts();
121      for (j=0; j<tv; j++)
122      {
123        i4_3d_vector t_vert;       
124        cur_transform->transform(src_verts[m->quad[i].vertex_ref[j]].v, t_vert);
125
126        center += t_vert;
127        v[j].v          = t_vert;
128        v[j].s          = m->quad[i].u[j];
129        v[j].t          = m->quad[i].v[j];
130       
131        f->indices[j] = vertex_count++;
132      }
133     
134      center/=(float)tv;                 // center is the average position of verts
135      f->pos = f->l_pos = center;        // set 'position' of face to center location
136      for (j=0; j<tv; j++)               // move points relative to center so they spind about it
137        v[j].v -= center;
138
139      v+=tv;
140     
141      obj_center+=center;
142    }
143
144    if (m->num_quad)
145      obj_center/=(float)m->num_quad;
146  }
147}
148
149void g1_explode_model_class::setup(g1_object_class *source_obj,
150                                   const i4_3d_vector &center,
151                                   g1_explode_params &_params)
152{
153  x=lx=center.x;
154  y=ly=center.y;
155  h=lh=center.z;
156
157  if (x<0 || y<0 || x>=g1_get_map()->width() || y>=g1_get_map()->height())
158    request_remove();
159  else
160  {
161    i4_3d_vector c;
162    grab_model(source_obj, c);
163    params=_params;
164   
165    if (center.x==0)
166    {
167      x=lx=c.x;
168      y=ly=c.y;
169      h=lh=c.z;
170    } 
171
172     
173   
174    int i;
175    for (i=0; i<num_faces; i++)
176    {
177      faces[i].vel = params.initial_vel;
178      faces[i].angular_vel = faces[i].angles = faces[i].l_angles = i4_3d_vector(0,0,0);
179    }
180    occupy_location();
181    request_think();
182  } 
183}
184
185void g1_explode_model_class::think()
186{
187  if (params.stages[params.current_stage].ticks<=0)
188  {
189    params.current_stage++;
190    if (params.current_stage>=params.t_stages)
191    {
192      unoccupy_location();
193      request_remove();
194      return ;
195    }
196  }
197
198  params.stages[params.current_stage].ticks--;
199  float force=params.stages[params.current_stage].force;
200  float air_friction=params.stages[params.current_stage].air_friction;
201  float f;
202  i4_3d_vector d;
203 
204  for (int i=0; i<num_faces; i++)
205  {
206    g1_explode_face_class *face=faces+i;
207
208   
209    if (params.stages[params.current_stage].type==G1_APPLY_SING || i==0)
210    {
211      d=i4_3d_vector(face->pos.x-x, face->pos.y-y, face->pos.z-h);
212      float d_len=d.length();
213      d/=d_len;
214   
215      f=force/(d_len*d_len);
216      d*=f;
217      d.z-=params.gravity;
218    }
219
220    if (params.stages[params.current_stage].type==G1_APPLY_SING || (((g1_tick_counter+i)&31)==0))
221    {
222     
223      float xr=(g1_float_rand(9)-0.5) *0.2;
224      float yr=(g1_float_rand(3)-0.5) *0.2;
225      float zr=(g1_float_rand(4)-0.5) *0.2;
226
227
228
229      faces[i].angular_vel.x = xr;
230      faces[i].angular_vel.y = yr;
231      faces[i].angular_vel.z = zr;
232    }
233   
234
235    face->vel *= air_friction;
236    face->vel += d;
237    face->l_pos = face->pos;
238
239    i4_3d_vector ray=face->vel;
240   
241    g1_object_class *hit;
242//     if (g1_get_map()->check_non_player_collision(0xff, face->pos, ray, hit))
243//       face->vel.z *=-0.5;      // not accurate, but who cares :)
244 
245    face->pos += ray;
246   
247    face->l_angles = face->angles;
248    face->angles += face->angular_vel;   
249    i4_normalize_angle(face->angles.x);
250    i4_normalize_angle(face->angles.y);
251    i4_normalize_angle(face->angles.z);
252  }
253  request_think();
254}
255
256
257i4_profile_class pf_exp_model_draw_transform("explode_model_draw::transform");
258i4_profile_class pf_exp_model_draw_get_ambient("explode_model_draw::get_ambient");
259
260r1_texture_ref g1_burnt_texture("solid_black");
261
262void fast_transform(i4_transform_class *t, const i4_3d_vector &src, r1_3d_point_class &dst);
263
264void g1_explode_model_class::draw(g1_draw_context_class *context)
265{
266  pf_exp_model_draw.start();
267
268  pf_exp_model_draw_transform.start();
269
270  i4_transform_class out,face_trans; 
271
272  int i,j,k;
273
274  i4_float scale_x = g1_render.scale_x;
275  i4_float scale_y = g1_render.scale_y;   
276 
277  r1_vert t_vertices[2048];
278  r1_vert clip_buf_1[64];
279  r1_vert clip_buf_2[64];
280
281  g1_explode_vertex_class *src_v = vertices;
282  r1_vert *v                     = t_vertices;
283
284  w8 ANDCODE = 0xFF;
285  w8 ORCODE  = 0;   
286
287  g1_explode_face_class *f = faces; 
288
289  w8 vertex_count = 0;
290
291 
292 
293  g1_render.r_api->use_texture(g1_burnt_texture.get(), 0, 0);
294
295 
296  for (i=0; i<num_faces; i++,f++)
297  {
298    i4_3d_vector interp_rot;
299
300    interp_rot.x = i4_interpolate_angle(f->l_angles.x, f->angles.x, g1_render.frame_ratio);
301    interp_rot.y = i4_interpolate_angle(f->l_angles.y, f->angles.y, g1_render.frame_ratio);
302    interp_rot.z = i4_interpolate_angle(f->l_angles.z, f->angles.z, g1_render.frame_ratio);
303 
304    face_trans.rotate_x_y_z(interp_rot.x,interp_rot.y,interp_rot.z,i4_T);
305
306    face_trans.t.interpolate(f->l_pos, f->pos, g1_render.frame_ratio);
307   
308    out.multiply(*context->transform,face_trans);
309     
310    w8 face_and = 0xFF;   
311    g1_explode_vertex_class *src_face_v = src_v;
312    r1_vert *face_v                     = v;
313
314    int tv=faces[i].num_verts();
315    for (j=0; j<tv; j++,src_v++,v++)
316    {
317      fast_transform(&out, src_v->v, v->v);
318
319      v->v.x *= scale_x;
320      v->v.y *= scale_y;
321     
322      w8 code = r1_calc_outcode(v);
323      ANDCODE &= code;
324      ORCODE  |= code;
325     
326      face_and &= code;
327     
328      if (!code)
329      {
330        //valid point
331        i4_float ooz = 1.f / v->v.z;
332     
333        v->px = v->v.x * ooz * g1_render.center_x + g1_render.center_x;
334        v->py = v->v.y * ooz * g1_render.center_y + g1_render.center_y;
335        v->w  = ooz;
336      }
337    }
338   
339    if (face_and==0)
340    {
341      for (j=0; j<tv; j++,src_face_v++,face_v++,vertex_count++)
342      {
343        face_v->r = 0;
344        face_v->g = 0;
345        face_v->b = 0;
346        face_v->a = 1.0;
347        face_v->s = 0;
348        face_v->t = 0;
349      }
350    }
351    else
352      vertex_count += tv;
353  }
354
355  pf_exp_model_draw_transform.stop();
356
357  if (ANDCODE)
358  {
359    pf_exp_model_draw.stop();
360    return;
361  }
362
363  f = faces;
364
365  for (i=0; i<num_faces; i++, f++)
366  {
367    int tv=f->num_verts();
368
369    if (ORCODE==0)
370    {
371      float nearest_w = 0;
372
373      for (j=0; j<tv; j++)
374      {
375        r1_vert *temp_vert = &t_vertices[f->indices[j]];
376       
377        float ooz = temp_vert->w;
378       
379        if (ooz > nearest_w)
380          nearest_w=ooz;
381      }
382       
383      g1_render.r_api->render_poly(tv, t_vertices+f->indices[0]);
384    }
385    else
386    {
387      sw32 num_poly_verts = tv;
388       
389      r1_vert temp_buf_1[64];
390      r1_vert temp_buf_2[64];
391      r1_vert *clipped_poly;
392       
393      clipped_poly = g1_render.r_api->clip_poly(&num_poly_verts,
394                                         t_vertices,
395                                         (w16 *)f->indices,
396                                         temp_buf_1,
397                                         temp_buf_2,
398                                         R1_CLIP_NO_CALC_OUTCODE);
399       
400      if (clipped_poly && num_poly_verts>=3)     
401      {
402        float nearest_w = 0;
403
404        r1_vert *temp_vert = clipped_poly;
405
406        for (j=0; j<num_poly_verts; j++, temp_vert++)
407        {       
408          i4_float ooz = 1 / temp_vert->v.z;
409
410          temp_vert->w  = ooz;
411          temp_vert->px = temp_vert->v.x * ooz * g1_render.center_x + g1_render.center_x;
412          temp_vert->py = temp_vert->v.y * ooz * g1_render.center_y + g1_render.center_y;
413 
414          if (ooz > nearest_w)
415            nearest_w=ooz;                           
416        }                 
417         
418
419        g1_render.r_api->render_poly(num_poly_verts,clipped_poly);
420      }
421    }
422  }
423 
424
425  pf_exp_model_draw.stop();
426
427
428g1_explode_params::g1_explode_params()
429{
430  stages[0].setup(1,0.01, G1_APPLY_WHOLE);  // apply force for 2 ticks
431  stages[1].setup(3, 0,    G1_APPLY_WHOLE);  // wait 20 ticks with no force to watch results
432  stages[2].setup(2, 1.0, G1_APPLY_SING);  // wait 20 ticks with no force to watch results
433  stages[3].setup(10, 0,  G1_APPLY_SING);  // wait 20 ticks with no force to watch results
434  t_stages=4;
435  current_stage=0;
436  gravity=0.02;
437  initial_vel=i4_3d_vector(0,0,0);
438
Note: See TracBrowser for help on using the repository browser.