source: golgotha/src/golg/g1_render.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: 40.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 "controller.hh"
10#include "map.hh"
11#include "window/win_evt.hh"
12#include "time/profile.hh"
13#include "menu/menu.hh"
14#include "menu/textitem.hh"
15#include "window/style.hh"
16#include "time/time.hh"
17#include "resources.hh"
18#include "input.hh"
19#include "mess_id.hh"
20#include "sound_man.hh"
21#include "g1_speed.hh"
22#include "remove_man.hh"
23#include "image/color.hh"
24#include "light.hh"
25#include "statistics.hh"
26#include "r1_api.hh"
27#include "r1_clip.hh"
28#include "math/random.hh"
29#include "math/pi.hh"
30#include "math/angle.hh"
31#include "math/trig.hh"
32#include "g1_render.hh"
33#include "tile.hh"
34#include "g1_tint.hh"
35#include "time/profile.hh"
36#include "g1_texture_id.hh"
37#include "g1_tint.hh"
38#include "objs/map_piece.hh"
39#include "objs/stank.hh"
40#include "lisp/lisp.hh"
41#include "map_vert.hh"
42#include "loaders/load.hh"
43#include "r1_font.hh"
44
45static i4_profile_class pf_render_object_transform("::render_object (transform)"),
46  pf_render_object_light("::render_object (light)"),
47  pf_render_object_pack("::render_object (project/pack)"),
48  pf_render_sprite("g1_render::render_sprite"),
49  pf_render_draw_outline("g1_render::draw_outline"),
50  pf_post_draw_quads("g1_render::post_draw_quads"),
51  pf_add_translucent_trail("g1_render::add_trans_trail"),
52  pf_draw_building("g1_render::draw_building");
53 
54
55
56const  sw32                    max_post_draw_quads = 1024;
57static g1_post_draw_quad_class g1_post_draw_quads[max_post_draw_quads];
58static sw32                    g1_num_post_draw_quads = 0;
59
60const  sw32                    max_post_draw_verts = max_post_draw_quads*4;
61static r1_vert                 g1_post_draw_verts[max_post_draw_verts];
62static sw32                    g1_num_post_draw_verts = 0;
63
64struct g1_post_draw_sprite_struct
65{
66  r1_texture_handle tex;
67  float z;
68  float s1, t1, s2, t2;
69  float x1,y1,x2,y2;
70 
71} g1_post_draw_sprites[G1_MAX_SPRITES];
72int g1_t_post_draw_sprites=0;
73
74
75 
76g1_render_class g1_render;
77
78//this is used for the damage/blackening effect of hurt vehicles
79
80static w8 charred_array[8] =
81{
82  8|1|128|4|32|2|64,
83  8|1|128|4|32|2,
84  8|1|128|4|32,
85  8|1|128|4,
86  8|1|128,
87  8|1,
88  8,
89  0
90};
91
92i4_bool g1_render_class::main_draw=i4_F;
93
94i4_float g1_render_class::scale_x,
95         g1_render_class::scale_y,
96         g1_render_class::ooscale_x,
97         g1_render_class::ooscale_y,
98         g1_render_class::center_x,
99         g1_render_class::center_y;
100
101sw8      g1_render_class::render_damage_level = -1;
102
103r1_render_api_class *g1_render_class::r_api;
104
105
106float g1_render_class::calculate_frame_ratio()
107{
108  if (g1_map_is_loaded())
109  {
110    i4_time_class now;
111    if (g1_resources.paused)
112      frame_ratio=1.0;
113    else
114      frame_ratio=1.0+now.milli_diff(g1_get_map()->tick_time)*G1_HZ/1000.0;
115 
116    if (frame_ratio>1)
117      frame_ratio=1;
118  }
119  else frame_ratio=0;
120 
121  return frame_ratio;
122}
123
124// this is the default function for handling tinted polygons
125g1_quad_class *g1_tint_modify_function(g1_quad_class *in,
126                                       g1_player_type player)
127{
128  g1_render.r_api->set_color_tint(g1_player_tint_handles[player]);
129  return in;
130}
131
132void g1_get_ambient_function(i4_transform_class *object_to_world,
133                             i4_float &ar, i4_float &ag, i4_float &ab)
134{
135  g1_get_map()->get_illumination_light(object_to_world->t.x,
136                                         object_to_world->t.y, ar,ag,ab);
137}
138
139
140
141void fast_transform(i4_transform_class *t,const i4_3d_vector &src, r1_3d_point_class &dst)
142{
143#ifndef WIN32
144  dst.x = t->x.x*src.x + t->y.x*src.y + t->z.x*src.z + t->t.x;
145  dst.y = t->x.y*src.x + t->y.y*src.y + t->z.y*src.z + t->t.y;
146  dst.z = t->x.z*src.x + t->y.z*src.y + t->z.z*src.z + t->t.z;
147#else
148  _asm
149  {
150    mov     eax, t
151    mov     ecx, src
152    mov     edx, dst
153
154    //optimized transformation: 34 cycles               
155    //compute t->x.x*src.x, t->x.y*src.x, t->x.z*src.x
156    fld dword ptr  [ecx+0]     ;starts & ends on cycle 0
157    fmul dword ptr [eax+0]     ;starts on cycle 1       
158    fld dword ptr  [ecx+0]     ;starts & ends on cycle 2
159    fmul dword ptr [eax+4]     ;starts on cycle 3       
160    fld dword ptr  [ecx+0]     ;starts & ends on cycle 4
161    fmul dword ptr [eax+8]     ;starts on cycle 5   
162   
163    //compute t->y.x*src.y, t->y.y*src.y, t->y.z*src.y
164    fld dword ptr  [ecx+4]     ;starts & ends on cycle 6
165    fmul dword ptr [eax+12]    ;starts on cycle 7     
166    fld dword ptr  [ecx+4]     ;starts & ends on cycle 8
167    fmul dword ptr [eax+16]    ;starts on cycle 9       
168    fld dword ptr  [ecx+4]     ;starts & ends on cycle 10
169    fmul dword ptr [eax+20]    ;starts on cycle 11 
170   
171    //st0           st1           st2           st3           st4           st5
172    //t->y.z*src.y  t->y.y*src.y  t->y.x*src.y  t->x.z*src.x  t->x.y*src.x  t->x.x*src.x
173   
174    fxch           st(2)       ;no cost             
175    //st0           st1           st2           st3           st4           st5
176    //t->y.x*src.y  t->y.y*src.y  t->y.z*src.y  t->x.z*src.x  t->x.y*src.x  t->x.x*src.x
177
178    faddp          st(5),st(0) ;starts on cycle 12 
179    //st0           st1           st2           st3           st4
180    //t->y.y*src.y  t->y.z*src.y  t->x.z*src.x  t->x.y*src.x  t->x.x*src.x+
181    //                                                        t->y.x*src.y
182
183    faddp          st(3),st(0) ;starts on cycle 13 
184    //st0           st1           st2           st3
185    //t->y.z*src.y  t->x.z*src.x  t->x.y*src.x+ t->x.x*src.x+
186    //                            t->y.y*src.y  t->y.x*src.y
187
188    faddp          st(1),st(0) ;starts on cycle 14
189    //st0           st1           st2
190    //t->x.z*src.x+ t->x.y*src.x+ t->x.x*src.x+
191    //t->y.z*src.y  t->y.y*src.y  t->y.x*src.y
192
193    //compute t->z.x*src.z, t->z.y*src.z, t->z.z*src.z
194    fld dword ptr  [ecx+8]     ;starts & ends on cycle 15
195    fmul dword ptr [eax+24]    ;starts on cycle 16     
196    fld dword ptr  [ecx+8]     ;starts & ends on cycle 17
197    fmul dword ptr [eax+28]    ;starts on cycle 18       
198    fld dword ptr  [ecx+8]     ;starts & ends on cycle 19
199    fmul dword ptr [eax+32]    ;starts on cycle 20       
200   
201    //st0           st1           st2           st3           st4           st5
202    //t->z.z*src.z  t->z.y*src.z  t->z.x*src.z  t->x.z*src.x+ t->x.y*src.x+ t->x.x*src.x+
203    //                                          t->y.z*src.y  t->y.y*src.y  t->y.x*src.y
204    fxch           st(2)       ;no cost                 
205   
206    faddp          st(5),st(0) ;starts on cycle 21       
207    //st0           st1           st2           st3           st4
208    //t->z.y*src.z  t->z.z*src.z  t->x.z*src.x+ t->x.y*src.x+ t->x.x*src.x+
209    //                            t->y.z*src.y  t->y.y*src.y  t->y.x*src.y+
210    //                                                        t->z.x*src.z
211   
212    faddp          st(3),st(0) ;starts on cycle 22       
213   
214    //st0           st1           st2           st3
215    //t->z.z*src.z  t->x.z*src.x+ t->x.y*src.x+ t->x.x*src.x+
216    //              t->y.z*src.y  t->y.y*src.y+ t->y.x*src.y+
217    //                            t->z.y*src.z  t->z.x*src.z   
218   
219    faddp          st(1),st(0) ;starts on cycle 23       
220    //st0           st1           st2
221    //t->x.z*src.x+ t->x.y*src.x+ t->x.x*src.x+
222    //t->y.z*src.y+ t->y.y*src.y+ t->y.x*src.y+
223    //t->z.z*src.z  t->z.y*src.z  t->z.x*src.z
224
225    fxch           st(2)       ;no cost                 
226    //st0            st1           st2
227    //t->x.x*src.x+  t->x.y*src.x+ t->x.z*src.x+
228    //t->y.x*src.y+  t->y.y*src.y+ t->y.z*src.y+
229    //t->z.x*src.z   t->z.y*src.z  t->z.z*src.z
230   
231    fadd dword ptr [eax+36]    ;starts on cycle 24       
232    fxch           st(1)       ;starts on cycle 25       
233   
234    //st0            st1           st2
235    //t->x.y*src.x+  dest_x        t->x.z*src.x+
236    //t->y.y*src.y+                t->y.z*src.y+
237    //t->z.y*src.z                 t->z.z*src.z
238   
239    fadd dword ptr [eax+40]    ;starts on cycle 26       
240    fxch           st(2)       ;no cost                 
241   
242    //st0            st1    st2
243    //t->x.z*src.x+  dest_x dest_y
244    //t->y.z*src.y+         
245    //t->z.z*src.z
246    fadd dword ptr [eax+44]    ;starts on cycle 27       
247    fxch           st(1)       ;no cost
248   
249    //st0     st1    st2
250    //dest_x  dest_z dest_y
251   
252    fstp dword ptr [edx+0]     ;starts on cycle 28, ends on cycle 29
253    fstp dword ptr [edx+8]     ;starts on cycle 30, ends on cycle 31
254    fstp dword ptr [edx+4]     ;starts on cycle 32, ends on cycle 33 
255  }
256#endif
257}
258
259
260void g1_render_class::uninstall_font()
261{
262  if (rendered_font)
263  {
264    delete rendered_font;
265    rendered_font=0;
266  }
267
268
269}
270
271void g1_render_class::install_font()
272{
273  uninstall_font();
274  i4_image_class *im=i4_load_image("bitmaps/golg_font_18.tga");
275  if (im)
276  {
277    rendered_font=new r1_font_class(r_api, im);   
278    delete im;
279  }
280}
281
282void g1_render_class::render_object(g1_quad_object_class *obj,
283                                    i4_transform_class *object_to_view,
284                                    i4_transform_class *object_to_world,
285                                    i4_float texture_scale,                     
286                                    int player_num,
287                                    sw32 current_frame,
288                                    g1_screen_box *bound_box,
289                                    w32 option_flags)
290{
291  g1_stat_counter.increment(g1_statistics_counter_class::OBJECTS);
292
293 
294  int i,j,k,num_vertices;
295  r1_vert t_vertices[512];
296  int src_quad[4];
297  i4_transform_class view_transform;
298 
299  num_vertices            = obj->num_vertex;
300  r1_vert *v              = t_vertices;
301  g1_vert_class *src_vert = obj->get_verts(0, current_frame);
302   
303  w8 ANDCODE = 0xFF;
304  w8 ORCODE  = 0;
305
306  g1_vert_class *src_v=src_vert;
307 
308  pf_render_object_transform.start();
309
310  //get this vector before we warp the transform
311  i4_3d_vector cam_in_object_space;
312  object_to_view->inverse_transform(i4_3d_vector(0,0,0),cam_in_object_space);
313
314 
315  view_transform.x.x = object_to_view->x.x * scale_x;
316  view_transform.x.y = object_to_view->x.y * scale_y;
317  view_transform.x.z = object_to_view->x.z;
318  view_transform.y.x = object_to_view->y.x * scale_x;
319  view_transform.y.y = object_to_view->y.y * scale_y;
320  view_transform.y.z = object_to_view->y.z;
321  view_transform.z.x = object_to_view->z.x * scale_x;
322  view_transform.z.y = object_to_view->z.y * scale_y;
323  view_transform.z.z = object_to_view->z.z;
324  view_transform.t.x = object_to_view->t.x * scale_x;
325  view_transform.t.y = object_to_view->t.y * scale_y;
326  view_transform.t.z = object_to_view->t.z;
327 
328  for (i=0; i<num_vertices; i++, src_v++, v++)
329  {
330    fast_transform(&view_transform,src_v->v,v->v);
331
332    //v->v.x *= scale_x; //this is accomplished by the above matrix multiplies
333    //v->v.y *= scale_y;
334
335    w8 code = r1_calc_outcode(v);
336    ANDCODE &= code;
337    ORCODE  |= code;
338    if (!code)
339    {
340      //valid point
341      i4_float ooz = r1_ooz(v->v.z);
342     
343      v->px = v->v.x * ooz * center_x + center_x;
344      v->py = v->v.y * ooz * center_y + center_y;
345
346
347      v->w  = ooz;
348    }
349  }
350
351  pf_render_object_transform.stop();
352
353  if (ANDCODE)
354    return;
355
356  pf_render_object_light.start();
357
358  //IMPORTANT
359  //we need this transform to do lighting
360  if (object_to_world)
361  {
362    //worldspace light vector
363    i4_3d_vector light = g1_lights.direction;
364    i4_3d_vector t_light;
365
366    // get the ambient contribution from the map at the object's center point
367    i4_float ar,ag,ab;
368    get_ambient(object_to_world, ar,ag,ab);
369
370    float dir_int=g1_lights.directional_intensity;
371   
372    //transform light into object space for lighting
373    object_to_world->inverse_transform_3x3(light,t_light);
374
375    src_vert = obj->get_verts(0,current_frame);
376    v        = t_vertices;
377
378
379    for (i=0; i<num_vertices; i++, src_vert, v++)
380    {
381      //      i4_float reflected_intensity = 1.0;
382
383      i4_float dot=-src_vert[i].normal.dot(t_light);
384      i4_float reflected_intensity = g1_lights.directional_intensity * dot;
385
386
387      if (reflected_intensity<0)
388        reflected_intensity=0;
389     
390      v->r = reflected_intensity * dir_int + ar;  if (v->r>1.0) v->r=1.0;
391      v->g = reflected_intensity * dir_int + ag;  if (v->g>1.0) v->g=1.0;
392      v->b = reflected_intensity * dir_int + ab;  if (v->b>1.0) v->b=1.0;
393      v->a = 1.0;
394    }
395  }
396  else
397  {
398    v = t_vertices;   
399    for (i=0; i<num_vertices; i++, v++)
400    {
401      v->r = v->g = v->b = 1.f;//g1_lights.ambient_intensity;
402      v->a = 1.0;
403    }
404  }
405
406 
407  if (render_damage_level != -1)
408  {
409    //set their lighting values to 1
410    v = t_vertices;   
411    for (i=0; i<num_vertices; i++, v++)
412      if ((1<<(i&7)) & charred_array[render_damage_level])
413        v->r = v->g = v->b = 0;
414  }
415 
416  pf_render_object_light.stop();     
417
418  pf_render_object_pack.start();
419  g1_quad_class *q_ptr = obj->quad, *q;
420  for (i=0; i<obj->num_quad; i++, q_ptr++)
421  {
422    sw32 num_poly_verts = q_ptr->num_verts();
423
424    i4_3d_vector cam_to_pt = src_vert[q_ptr->vertex_ref[0]].v;
425    cam_to_pt -= cam_in_object_space;
426
427    float dot = cam_to_pt.dot(q_ptr->normal);
428
429    if (dot<0)
430    {
431      if (g1_tint!=G1_TINT_OFF && g1_hurt_tint==0)
432      {
433        if ((q_ptr->get_flags(g1_quad_class::TINT)||(g1_tint==G1_TINT_ALL))
434            && player_num!=-1)
435          q=tint_modify(q_ptr, player_num);
436        else
437        {
438          r_api->set_color_tint(0);
439          q=q_ptr;
440        }
441      }
442      else q=q_ptr;
443         
444      // copy in the texture coordinates     
445      for (j=0; j<num_poly_verts; j++)     
446      {
447        int ref=q->vertex_ref[j];
448        src_quad[j]=ref;
449 
450        v = &t_vertices[ref];
451        v->s = q->u[j];
452        v->t = q->v[j];
453      }
454     
455
456      if (ORCODE==0)
457      {
458        float nearest_w = 0;
459       
460        if (bound_box)
461        {         
462          for (j=0; j<num_poly_verts; j++)
463          {       
464            r1_vert *temp_vert = &t_vertices[q->vertex_ref[j]];
465           
466            float ooz = temp_vert->w;
467           
468            if (ooz > nearest_w)
469              nearest_w=ooz;
470             
471            if (temp_vert->px < bound_box->x1) bound_box->x1 = temp_vert->px;
472            if (temp_vert->px > bound_box->x2) bound_box->x2 = temp_vert->px;
473
474            if (temp_vert->py < bound_box->y1) bound_box->y1 = temp_vert->py;
475            if (temp_vert->py > bound_box->y2) bound_box->y2 = temp_vert->py;
476
477            if (temp_vert->v.z > bound_box->z2) bound_box->z2 = temp_vert->v.z;
478
479            if (temp_vert->v.z < bound_box->z1)
480            {
481              bound_box->z1 = temp_vert->v.z;
482              bound_box->w  = ooz;
483            }                           
484          }
485        }
486        else
487        {
488          for (j=0; j<num_poly_verts; j++)
489          {       
490            r1_vert *temp_vert = &t_vertices[q->vertex_ref[j]];
491           
492            float ooz = temp_vert->w;           
493           
494            if (ooz > nearest_w)
495              nearest_w=ooz;                         
496          }
497        }
498       
499        i4_float twidth = nearest_w * q->texture_scale * texture_scale * center_x * 2;
500
501        r_api->use_texture(q->material_ref, i4_f_to_i(twidth), current_frame);
502
503        g1_stat_counter.increment(g1_statistics_counter_class::OBJECT_POLYS);
504        g1_stat_counter.increment(g1_statistics_counter_class::TOTAL_POLYS);
505        r_api->render_poly(num_poly_verts,t_vertices,q->vertex_ref);
506      }
507      else
508      {
509        r1_vert temp_buf_1[64];
510        r1_vert temp_buf_2[64];
511        r1_vert *clipped_poly;
512       
513        clipped_poly = r_api->clip_poly(&num_poly_verts,
514                                         t_vertices,
515                                         q->vertex_ref,
516                                         temp_buf_1,
517                                         temp_buf_2,
518                                         R1_CLIP_NO_CALC_OUTCODE
519                                         );
520       
521
522        if (clipped_poly && num_poly_verts>=3)     
523        {
524          float nearest_w = 0;
525
526          if (!bound_box)
527          {                 
528            r1_vert *temp_vert = clipped_poly;
529
530            for (j=0; j<num_poly_verts; j++, temp_vert++)
531            {       
532              i4_float ooz = r1_ooz(temp_vert->v.z);
533
534              temp_vert->w  = ooz;
535              temp_vert->px = temp_vert->v.x * ooz * center_x + center_x;
536              temp_vert->py = temp_vert->v.y * ooz * center_y + center_y;
537 
538              if (ooz > nearest_w)
539                nearest_w=ooz;                           
540            }                 
541          }
542          else
543          {         
544            r1_vert *temp_vert = clipped_poly;
545
546            for (j=0; j<num_poly_verts; j++,temp_vert++)
547            {           
548              float ooz = r1_ooz(temp_vert->v.z);
549
550              temp_vert->w  = ooz;
551              temp_vert->px = temp_vert->v.x * ooz * center_x + center_x;
552              temp_vert->py = temp_vert->v.y * ooz * center_y + center_y;
553
554              if (ooz > nearest_w)
555                nearest_w=ooz;
556               
557              if (temp_vert->px < bound_box->x1) bound_box->x1 = temp_vert->px;
558              if (temp_vert->px > bound_box->x2) bound_box->x2 = temp_vert->px;
559
560              if (temp_vert->py < bound_box->y1) bound_box->y1 = temp_vert->py;
561              if (temp_vert->py > bound_box->y2) bound_box->y2 = temp_vert->py;
562
563              if (temp_vert->v.z > bound_box->z2) bound_box->z2 = temp_vert->v.z;
564
565              if (temp_vert->v.z < bound_box->z1)
566              {
567                bound_box->z1 = temp_vert->v.z;
568                bound_box->w = ooz;
569              }
570            }                 
571          }
572       
573          i4_float twidth = nearest_w * q->texture_scale * texture_scale * center_x * 2;
574          r_api->use_texture(q->material_ref, i4_f_to_i(twidth), current_frame);
575          r_api->render_poly(num_poly_verts,clipped_poly);
576
577          g1_stat_counter.increment(g1_statistics_counter_class::OBJECT_POLYS);
578          g1_stat_counter.increment(g1_statistics_counter_class::TOTAL_POLYS);
579        }
580      }
581    }
582  }
583
584  if (g1_tint!=G1_TINT_OFF && g1_hurt_tint==0)
585    r_api->set_color_tint(0);
586 
587  pf_render_object_pack.stop();
588}
589
590void g1_render_class::render_object_polys(g1_quad_object_class *obj,
591                                          i4_transform_class *object_to_view,
592                                          sw32 current_frame)
593{
594  int i,j,k,num_vertices;
595  r1_vert t_vertices[512];
596  int src_quad[4];
597  i4_transform_class view_transform;
598 
599  num_vertices            = obj->num_vertex;
600  r1_vert *v              = t_vertices;
601  g1_vert_class *src_vert = obj->get_verts(0, current_frame);
602   
603  w8 ANDCODE = 0xFF;
604  w8 ORCODE  = 0;
605
606  g1_vert_class *src_v=src_vert;
607 
608  pf_render_object_transform.start();
609
610  view_transform.x.x = object_to_view->x.x * scale_x;
611  view_transform.x.y = object_to_view->x.y * scale_y;
612  view_transform.x.z = object_to_view->x.z;
613  view_transform.y.x = object_to_view->y.x * scale_x;
614  view_transform.y.y = object_to_view->y.y * scale_y;
615  view_transform.y.z = object_to_view->y.z;
616  view_transform.z.x = object_to_view->z.x * scale_x;
617  view_transform.z.y = object_to_view->z.y * scale_y;
618  view_transform.z.z = object_to_view->z.z;
619  view_transform.t.x = object_to_view->t.x * scale_x;
620  view_transform.t.y = object_to_view->t.y * scale_y;
621  view_transform.t.z = object_to_view->t.z;
622 
623  i4_float adjuster = -0.01f;
624
625  for (i=0; i<num_vertices; i++, src_v++, v++)
626  {
627    fast_transform(&view_transform,src_v->v,v->v);
628
629    //v->v.x *= scale_x; //this is accomplished by the above matrix multiplies
630    //v->v.y *= scale_y;
631
632    w8 code = r1_calc_outcode(v);
633    ANDCODE &= code;
634    ORCODE  |= code;
635    if (!code)
636    {
637      //valid point
638      i4_float ooz = r1_ooz(v->v.z);
639      i4_float ooz_adjusted = r1_ooz(v->v.z + adjuster);
640
641      v->px = v->v.x * ooz * center_x + center_x;
642      v->py = v->v.y * ooz * center_y + center_y;
643
644      v->w  = ooz_adjusted;
645
646      v->a = v->r = v->g = v->b = 1.f;
647    }
648  }
649
650  pf_render_object_transform.stop();
651
652  if (ANDCODE)
653    return;
654
655  pf_render_object_pack.start();
656 
657  g1_quad_class *q_ptr = obj->quad;
658 
659  for (i=0; i<obj->num_quad; i++, q_ptr++)
660  {
661    sw32 num_poly_verts = q_ptr->num_verts();
662
663    if (ORCODE==0)
664    {
665      r_api->render_poly(num_poly_verts,t_vertices,q_ptr->vertex_ref);
666    }
667    else
668    {
669      r1_vert temp_buf_1[64];
670      r1_vert temp_buf_2[64];
671      r1_vert *clipped_poly;
672
673      clipped_poly = r_api->clip_poly(&num_poly_verts,
674                                      t_vertices,
675                                      q_ptr->vertex_ref,
676                                      temp_buf_1,
677                                      temp_buf_2,
678                                      R1_CLIP_NO_CALC_OUTCODE
679                                      );
680
681      if (clipped_poly && num_poly_verts>=3)
682      {
683        r1_vert *temp_vert = clipped_poly;
684
685        for (j=0; j<num_poly_verts; j++, temp_vert++)
686        {
687          float ooz = r1_ooz(temp_vert->v.z);
688          float ooz_adjusted = r1_ooz(temp_vert->v.z + adjuster);
689         
690          temp_vert->px = temp_vert->v.x * ooz * center_x + center_x;
691          temp_vert->py = temp_vert->v.y * ooz * center_y + center_y;
692
693          temp_vert->w  = ooz_adjusted;
694        }
695
696        r_api->render_poly(num_poly_verts,clipped_poly);
697      }
698    }
699  }
700
701  pf_render_object_pack.stop();
702}
703
704void g1_render_class::render_3d_line(const i4_3d_point_class &p1,
705                                     const i4_3d_point_class &p2,
706                                     i4_color color1,
707                                     i4_color color2,
708                                     i4_transform_class *t,
709                                     i4_bool draw_in_front_of_everything)
710{
711  r1_vert v[2];
712
713  project_point(p1, v[0], t);
714  project_point(p2, v[1], t);
715
716  if (draw_in_front_of_everything)
717  {
718    v[0].v.z=g1_near_z_range();
719    v[1].v.z=g1_near_z_range();
720   
721    float ooz = r1_ooz(g1_near_z_range());
722   
723    v[0].w = ooz;
724    v[1].w = ooz;
725  }
726 
727  v[0].r=g1_table_0_255_to_0_1[(color1&0xff0000)>>16];
728  v[0].g=g1_table_0_255_to_0_1[(color1&0xff00)>>8];
729  v[0].b=g1_table_0_255_to_0_1[(color1&0xff)>>0];
730
731  v[1].r=g1_table_0_255_to_0_1[(color2&0xff0000)>>16];
732  v[1].g=g1_table_0_255_to_0_1[(color2&0xff00)>>8];
733  v[1].b=g1_table_0_255_to_0_1[(color2&0xff)>>0];
734   
735  r_api->set_shading_mode(R1_COLORED_SHADING);
736  r_api->set_alpha_mode(R1_ALPHA_DISABLED);
737  r_api->disable_texture();
738
739  r1_clip_render_lines(1, v, center_x, center_y, r_api);
740  r_api->set_constant_color(0xffffff);
741}
742
743void g1_draw_vert_line(float x, float y1, float y2, r1_vert *v)
744{
745  r1_vert *v1=v, *v2=v+1;
746  v1->px=x;   v2->px=x;
747  v1->py=y1;  v2->py=y2;
748  g1_render.r_api->render_lines(1, v);
749}
750
751
752
753
754void g1_draw_horz_line(float y, float x1, float x2, r1_vert *v)
755
756{
757  r1_vert *v1=v, *v2=v+1;
758  v1->py=y;   v2->py=y; 
759  v1->px=x1;  v2->px=x2;
760  g1_render.r_api->render_lines(1, v);
761}
762
763void g1_render_class::draw_outline(g1_screen_box *box, g1_object_class *for_who)
764{
765  pf_render_draw_outline.start();
766  r1_vert line_points[3];
767
768  sw32 width  = (sw32)(center_x*2);
769  sw32 height = (sw32)(center_y*2);
770
771  //dunno whats up w/these.. looks like the box is ending up outside the viewport somehow
772 
773  sw32 box_x1 = i4_f_to_i(box->x1);
774  sw32 box_y1 = i4_f_to_i(box->y1);
775  sw32 box_x2 = i4_f_to_i(box->x2);
776  sw32 box_y2 = i4_f_to_i(box->y2);
777 
778  box_x1++;
779  box_y1++;
780  box_x2--;
781  box_y2--;
782
783  if (box_x1 < 0 || box_y1 < 0 || box_x2<0 || box_y2<0)
784  {
785    pf_render_draw_outline.stop();
786    return;
787  }
788
789  if (box_x2 > width || box_x1>width || box_y2 > height || box_y1 > height)
790  {
791    pf_render_draw_outline.stop();
792    return;
793  }
794
795  r_api->disable_texture();
796
797  i4_float depth   = box->z1;
798  i4_float oodepth = box->w;
799
800  line_points[0].v.z = depth;
801  line_points[0].w   = oodepth;
802  line_points[1].v.z = depth;
803  line_points[1].w   = oodepth;
804  line_points[2].v.z = depth;
805  line_points[2].w   = oodepth;
806 
807  line_points[0].r   = 0.25f;
808  line_points[0].g   = 0.25f;
809  line_points[0].b   = 0.f;
810  line_points[1].r   = 1.0f;
811  line_points[1].g   = 1.0f;
812  line_points[1].b   = 0.f;
813  line_points[2].r   = 0.25f;
814  line_points[2].g   = 0.25f;
815
816  line_points[2].b   = 0.f;
817
818  //dunno whats up w/these.. looks like the box is ending up outside the viewport somehow
819  box->x1 += 1;
820  box->y1 += 1;
821
822
823
824  float width_adjust  = (box_x2 - box_x1)/6;
825  float height_adjust = (box_y2 - box_y1)/6;
826
827
828
829  line_points[0].px = box_x1;
830  line_points[0].py = box_y1 + height_adjust; 
831
832
833
834  line_points[1].px = box_x1;
835  line_points[1].py = box_y1;
836 
837  line_points[2].px = box_x1 + width_adjust;
838  line_points[2].py = box_y1;
839 
840  r_api->render_lines(2,line_points);
841
842  g1_map_piece_class *mp;
843  if (for_who && (box_x1+6<=box_x2) && box_y1>=5)
844  {
845    mp=g1_map_piece_class::cast(for_who);
846    if (mp && mp->health>0)
847    {
848      float percent=mp->health/(float)mp->defaults->health;
849     
850      //protect against invalid health values
851      if (percent > 1.f) percent = 1.f;
852      if (percent < 0.f) percent = 0.f;
853
854      i4_color c;
855 
856      if (percent<=0.25)
857        c=0xff0000;           // red
858      if (percent<=0.5)
859        c=0xffff00;           // yellow
860      else
861        c=0x00ff00;           // green
862
863      r_api->clear_area(box_x1, box_y1-5, box_x2, box_y1-2, 0, box->z1+0.01);
864
865      int box_w=(box_x2-1)-(box_x1+1);
866      r_api->clear_area(box_x1+1, box_y1-4, box_x1+1+(int)(box_w*percent), box_y1-3, c, box->z1);
867    }
868  }
869
870
871  line_points[0].px = box_x2 - width_adjust;
872  line_points[0].py = box_y1;
873
874  line_points[1].px = box_x2;
875  line_points[1].py = box_y1;
876 
877  line_points[2].px = box_x2;
878  line_points[2].py = box_y1 + height_adjust;
879 
880  r_api->render_lines(2,line_points);
881
882  line_points[0].px = box_x2;
883  line_points[0].py = box_y2 - height_adjust;
884
885  line_points[1].px = box_x2;
886  line_points[1].py = box_y2;
887 
888  line_points[2].px = box_x2 - width_adjust;
889  line_points[2].py = box_y2;
890 
891  r_api->render_lines(2,line_points);
892 
893  line_points[0].px = box_x1 + width_adjust;
894  line_points[0].py = box_y2;
895
896  line_points[1].px = box_x1;
897  line_points[1].py = box_y2;
898 
899  line_points[2].px = box_x1;
900  line_points[2].py = box_y2 - height_adjust;
901 
902  r_api->render_lines(2,line_points);
903
904  pf_render_draw_outline.stop();
905}
906
907int g1_sprite_depth_compare(const void *a, const void *b)
908{
909  if (((g1_post_draw_sprite_struct *)a)->z<((g1_post_draw_sprite_struct *)b)->z)
910    return -1;
911  else if (((g1_post_draw_sprite_struct *)a)->z>((g1_post_draw_sprite_struct *)b)->z)
912    return 1;
913  else
914    return 0;
915   
916}
917
918sw32 g1_render_class::add_post_draw_vert(r1_vert &a)
919{
920  g1_post_draw_verts[g1_num_post_draw_verts] = a;
921  g1_num_post_draw_verts++;
922   
923  return (g1_num_post_draw_verts-1);
924}
925
926sw32 g1_render_class::add_post_draw_quad(g1_post_draw_quad_class &q)
927{
928  g1_post_draw_quads[g1_num_post_draw_quads] = q;
929  g1_num_post_draw_quads++;
930   
931  return (g1_num_post_draw_quads-1);
932}
933
934
935void g1_render_class::post_draw_quads()
936{
937  int i,j;
938     
939  if (g1_num_post_draw_quads)
940  {
941
942    pf_post_draw_quads.start();
943
944
945    r1_vert temp_buf_1[8];
946    r1_vert temp_buf_2[8];
947
948    r_api->disable_texture();
949    r_api->set_alpha_mode(R1_ALPHA_LINEAR);
950    //    r_api->set_shading_mode(R1_COLORED_SHADING); 
951    //    r_api->set_write_mode(R1_COMPARE_W | R1_WRITE_COLOR);
952
953    int t = g1_num_post_draw_quads;
954
955    for (i=0; i<t; i++)
956    {
957      g1_post_draw_quad_class *q = &g1_post_draw_quads[i];
958
959      sw32 num_poly_verts = (q->vert_ref[3]==0xFFFF) ? (3) : (4);
960         
961      r1_vert *clipped_poly = r_api->clip_poly(&num_poly_verts,
962                                               g1_post_draw_verts,
963                                               q->vert_ref,
964                                               temp_buf_1,
965                                               temp_buf_2,
966                                               0);
967         
968      if (clipped_poly && num_poly_verts>=3)
969      {
970        for (j=0; j<num_poly_verts; j++)
971        {       
972          float ooz = r1_ooz(clipped_poly[j].v.z);           
973           
974          clipped_poly[j].px = clipped_poly[j].v.x * ooz * center_x + center_x;
975          clipped_poly[j].py = clipped_poly[j].v.y * ooz * center_y + center_y;
976          clipped_poly[j].w  = ooz;                 
977        }         
978        r_api->render_poly(num_poly_verts,clipped_poly);
979      }   
980    }
981
982    r_api->set_alpha_mode(R1_ALPHA_DISABLED);
983    g1_num_post_draw_quads = 0;
984    g1_num_post_draw_verts = 0; 
985
986    pf_post_draw_quads.stop();
987
988  }
989 
990  qsort(g1_post_draw_sprites, g1_t_post_draw_sprites, sizeof(g1_post_draw_sprite_struct),
991        g1_sprite_depth_compare);
992
993  for (i=0; i<g1_t_post_draw_sprites; i++)
994  {
995    g1_post_draw_sprite_struct *s=g1_post_draw_sprites + i;
996    r1_clip_render_textured_rect(s->x1,s->y1,s->x2,s->y2, s->z,
997                                 1.0,
998                                 i4_f_to_i(g1_render.center_x*2),
999                                 i4_f_to_i(g1_render.center_y*2),
1000                                 s->tex, 0, g1_render.r_api, s->s1, s->t1, s->s2, s->t2);
1001    g1_stat_counter.increment(g1_statistics_counter_class::SPRITES);
1002  }
1003 
1004  g1_t_post_draw_sprites=0;
1005
1006}
1007
1008void g1_render_class::clip_render_quad(g1_quad_class *q,
1009                                       r1_vert *verts,
1010                                       i4_transform_class *t,
1011                                       int current_frame)
1012{
1013  int i;
1014  i4_3d_vector p;
1015
1016  w8 ANDCODE = 0xFF;
1017  w8 ORCODE  = 0;
1018
1019
1020  for (i=0; i<4; i++)
1021  {
1022    int vref=q->vertex_ref[i];
1023
1024    r1_3d_point_class *v=&verts[vref].v;
1025
1026    p=i4_3d_vector(v->x, v->y, v->z);
1027
1028    i4_3d_vector &temp_v = (i4_3d_vector &)verts[vref].v;
1029    t->transform(p, temp_v);
1030
1031    verts[vref].v.x *= scale_x;
1032    verts[vref].v.y *= scale_y;
1033
1034   
1035    w8 code = r1_calc_outcode(verts+vref);
1036    ANDCODE &= code;
1037  }
1038
1039  if (ANDCODE) return ;
1040 
1041  sw32 num_poly_verts = 4;
1042  r1_vert temp_buf_1[32];
1043  r1_vert temp_buf_2[32];
1044
1045
1046  r1_vert *clipped_poly = r_api->clip_poly(&num_poly_verts,
1047                                           verts,
1048                                           q->vertex_ref,
1049                                           temp_buf_1,
1050                                           temp_buf_2,
1051                                           R1_CLIP_NO_CALC_OUTCODE);
1052 
1053
1054  if (clipped_poly && num_poly_verts>=3)     
1055  {
1056    float nearest_w = 0;
1057
1058    int j;
1059    for (j=0; j<num_poly_verts; j++)
1060    {       
1061      float ooz = r1_ooz(clipped_poly[j].v.z);
1062      if (ooz > nearest_w)
1063        nearest_w=ooz;
1064             
1065      clipped_poly[j].px = clipped_poly[j].v.x * ooz * center_x + center_x;
1066      clipped_poly[j].py = clipped_poly[j].v.y * ooz * center_y + center_y;
1067      clipped_poly[j].w  = ooz;                 
1068    }
1069       
1070    if (q->material_ref)
1071    {
1072      i4_float twidth = nearest_w * q->texture_scale * center_x * 2;
1073      r_api->use_texture(q->material_ref, i4_f_to_i(twidth), current_frame);
1074    }
1075
1076    r_api->render_poly(num_poly_verts, clipped_poly);
1077  }
1078}
1079
1080
1081void g1_render_class::add_translucent_trail(i4_transform_class *t,
1082                                            i4_3d_point_class *spots, int t_spots,
1083                                            float start_width, float end_width,
1084                                            float start_alpha, float end_alpha,
1085                                            w32 sc, w32 ec)
1086 
1087{
1088  if (t_spots<2) return;
1089
1090  pf_add_translucent_trail.start();
1091
1092  //make sure there's enough space in our arrays
1093  if ((t_spots+1)*3 > (max_post_draw_verts - g1_num_post_draw_verts))
1094  {
1095    //i4_warning("g1_render::no space for tail vertices");
1096    pf_add_translucent_trail.stop();
1097    return; 
1098  }
1099
1100  if ((t_spots*2)   > (max_post_draw_quads - g1_num_post_draw_quads))
1101  {
1102    //i4_warning("g1_render::no space for tail polys");
1103    pf_add_translucent_trail.stop();
1104    return;
1105  }
1106
1107  i4_float start_r=g1_table_0_255_to_0_1[((sc>>16)&0xff)];
1108  i4_float start_g=g1_table_0_255_to_0_1[((sc>>8)&0xff)];
1109  i4_float start_b=g1_table_0_255_to_0_1[((sc>>0)&0xff)];
1110
1111  i4_float end_r=g1_table_0_255_to_0_1[((ec>>16)&0xff)];
1112  i4_float end_g=g1_table_0_255_to_0_1[((ec>>8)&0xff)];
1113  i4_float end_b=g1_table_0_255_to_0_1[((ec>>0)&0xff)];
1114
1115  int i;
1116  i4_3d_point_class proj[256];
1117  i4_3d_point_class *p = proj; 
1118
1119  for (i=0; i<t_spots; i++, p++)
1120    t->transform(spots[i], *p);
1121 
1122  float width      = start_width;
1123  float width_step = (end_width-start_width)/(t_spots-1);
1124  float next_width = start_width;
1125
1126  float alpha_step = (end_alpha-start_alpha)/(t_spots-1);
1127  float r_step     = (end_r-start_r)/(t_spots-1);
1128  float g_step     = (end_g-start_g)/(t_spots-1);
1129  float b_step     = (end_b-start_b)/(t_spots-1);
1130
1131  i4_2d_vector perp0( -(proj[1].y-proj[0].y),  proj[1].x-proj[0].x);
1132
1133  if (perp0.x==0 && perp0.y==0)
1134    perp0.x=1;
1135  else   
1136    perp0.normalize();
1137   
1138  float &ooxscale = scale_x;//ooscale_x;
1139  float &ooyscale = scale_y;//ooscale_y;
1140
1141  int sv = g1_num_post_draw_verts;
1142
1143  i4_float r = start_r;
1144  i4_float g = start_g;
1145  i4_float b = start_b;
1146  i4_float edge_alpha = 0.1;
1147
1148  add_smoke_vert((proj[0].x + perp0.x * width) * ooxscale,
1149                 (proj[0].y + perp0.y * width) * ooyscale,
1150                 proj[0].z, r,g,b, edge_alpha);
1151
1152  add_smoke_vert((proj[0].x) * ooxscale,
1153                 (proj[0].y) * ooyscale,
1154                 proj[0].z, r,g,b, start_alpha);
1155
1156
1157  add_smoke_vert((proj[0].x - perp0.x * width) * ooxscale,
1158                 (proj[0].y - perp0.y * width) * ooyscale,
1159                 proj[0].z, r,g,b, edge_alpha);
1160
1161
1162  for (i=1; i<t_spots; i++)
1163  {
1164    next_width  += width_step;   
1165    r           += r_step;
1166    g           += g_step;
1167    b           += b_step;   
1168    start_alpha += alpha_step;
1169
1170    i4_2d_vector perp_last, perp_next, perp;
1171     
1172    perp_last.x =-(proj[i].y-proj[i-1].y);
1173    perp_last.y = (proj[i].x-proj[i-1].x);
1174   
1175    if (perp_last.x==0 && perp_last.y==0)
1176      perp_last.x=1;
1177    else
1178      perp_last.normalize();
1179
1180    if (i==t_spots-1)
1181      perp=perp_last;
1182    else
1183    {
1184      perp_next.x =-(proj[i+1].y-proj[i].y);
1185      perp_next.y = (proj[i+1].x-proj[i].x);
1186     
1187      if (perp_next.x==0 && perp_next.y==0)
1188        perp_next.x=1;
1189      else
1190        perp_next.normalize();
1191
1192      perp.x=perp_last.x + perp_next.x;
1193      perp.y=perp_last.y + perp_next.y;
1194
1195      if (perp.x==0 && perp.y==0)
1196        perp.x=1;
1197      else
1198        perp.normalize();     
1199    }
1200 
1201    add_smoke_vert((proj[i].x + perp.x * next_width) * ooxscale,
1202                   (proj[i].y + perp.y * next_width) * ooyscale,
1203                   proj[i].z, r,g,b, edge_alpha);
1204
1205    add_smoke_vert((proj[i].x) * ooxscale,
1206                   (proj[i].y) * ooyscale,
1207                   proj[i].z, r,g,b, start_alpha);
1208
1209    add_smoke_vert((proj[i].x - perp.x * next_width) * ooxscale,
1210                   (proj[i].y - perp.y * next_width) * ooyscale,
1211                   proj[i].z, r,g,b, edge_alpha);
1212                 
1213    g1_post_draw_quad_class q1(sv+ i*3,
1214                               sv + i*3+1,
1215                               sv + i*3-2,
1216                               sv + i*3-3);
1217    add_post_draw_quad(q1);
1218
1219    g1_post_draw_quad_class q2(sv +i*3+1,
1220                            sv + i*3+2,
1221                            sv + i*3-1,
1222                            sv + i*3-2);
1223    add_post_draw_quad(q2);
1224  }
1225
1226  pf_add_translucent_trail.stop();
1227}
1228
1229
1230inline g1_map_vertex_class *g1vmin(g1_map_vertex_class *v1,
1231                                   g1_map_vertex_class *v2)
1232{
1233  if (v1->height<v2->height)
1234    return v1;
1235  else return v2;
1236}
1237
1238
1239i4_bool g1_render_class::project_point(const i4_3d_point_class &p,
1240                                       r1_vert &v,
1241                                       i4_transform_class *transform)
1242{
1243  i4_3d_vector &temp_v = (i4_3d_vector &)v.v;
1244  transform->transform(p,temp_v);
1245  v.v.x *= scale_x;
1246  v.v.y *= scale_y;
1247
1248  if (v.v.z>0.001)
1249  {
1250    float ooz = r1_ooz(v.v.z);
1251   
1252    v.px = v.v.x * ooz * center_x + center_x;
1253    v.py = v.v.y * ooz * center_y + center_y;
1254
1255    v.w = ooz;
1256
1257    return i4_T;
1258  } else return i4_F;
1259}
1260
1261
1262void g1_render_class::draw_rectangle(int sx1, int sy1, int sx2, int sy2, i4_color col,
1263                                     i4_draw_context_class &context)
1264{
1265  sw32 x1,y1,x2,y2;
1266  if (sx1<sx2) { x1=sx1; x2=sx2; } else { x1=sx2; x2=sx1; }
1267  if (sy1<sy2) { y1=sy1; y2=sy2; } else { y1=sy2; y2=sy1; }
1268
1269  r_api->set_shading_mode(R1_SHADE_DISABLED);
1270
1271  r1_clip_clear_area(x1,y1,x2,y1, col, 0.01, context, r_api);
1272  r1_clip_clear_area(x2,y1,x2,y2, col, 0.01, context, r_api);
1273  r1_clip_clear_area(x1,y2,x2,y2, col, 0.01, context, r_api);
1274  r1_clip_clear_area(x1,y1,x1,y2, col, 0.01, context, r_api);
1275}
1276
1277
1278#define V0 0,1
1279#define V1 1,1
1280#define V2 1,0
1281#define V3 0,0
1282
1283void g1_setup_tri_texture_coords(r1_vert *tri1, r1_vert *tri2,
1284                                 int cell_rotation, int cell_is_mirrored)
1285{
1286  float u[4]={0,1,1,0};
1287  float v[4]={1,1,0,0};
1288 
1289  int dir=cell_is_mirrored ? 1 : 3, on=cell_rotation;
1290
1291  tri1[0].s=u[on];
1292  tri1[0].t=v[on]; 
1293  on=(on+dir)&3;
1294
1295  tri1[1].s=u[on];
1296  tri1[1].t=v[on]; 
1297  on=(on+dir)&3;
1298
1299  tri1[2].s=u[on];
1300  tri1[2].t=v[on];
1301
1302
1303  on=cell_rotation;
1304
1305  tri2[0].s=u[on];
1306  tri2[0].t=v[on];
1307  on=(on+dir+dir)&3;
1308
1309  tri2[1].s=u[on];
1310  tri2[1].t=v[on];
1311  on=(on+dir)&3;
1312
1313  tri2[2].s=u[on];
1314  tri2[2].t=v[on];
1315}
1316
1317
1318
1319
1320void g1_render_class::render_sprite(const i4_3d_vector &p,
1321                                    r1_texture_handle tex,
1322                                    float sprite_width, float sprite_height,
1323                                    float s1, float t1, float s2, float t2)
1324{
1325 
1326  if (p.z >= r1_near_clip_z)
1327  {
1328    if (g1_t_post_draw_sprites<G1_MAX_SPRITES)
1329    {
1330      g1_post_draw_sprite_struct *s=g1_post_draw_sprites + g1_t_post_draw_sprites;
1331     
1332      float ooz = r1_ooz(p.z);
1333     
1334      i4_float xs = g1_render.center_x * ooz * g1_render.scale_x;
1335      i4_float ys = g1_render.center_y * ooz * g1_render.scale_y;
1336
1337      float cx=g1_render.center_x + p.x*xs;
1338      float cy=g1_render.center_y + p.y*ys;
1339      float w=sprite_width * g1_render.center_x * ooz;
1340      float h=sprite_height * g1_render.center_x * ooz;
1341     
1342      s->x1=cx-w/2; s->y1=cy-h/2;
1343      s->x2=cx+w/2; s->y2=cy+h/2;
1344   
1345      s->z=p.z;     
1346      s->tex=tex;
1347      s->s1=s1;      s->t1=t1;      s->s2=s2;      s->t2=t2;
1348
1349      g1_t_post_draw_sprites++;
1350    }   
1351  }
1352}
1353
1354
1355void g1_render_class::render_near_sprite(float px, float py,
1356                                         r1_texture_handle tex,
1357                                         float sprite_width, float sprite_height,
1358                                         float s1, float t1, float s2, float t2)
1359{
1360  if (g1_t_post_draw_sprites<G1_MAX_SPRITES)
1361  {
1362    g1_post_draw_sprite_struct *s=g1_post_draw_sprites + g1_t_post_draw_sprites;
1363    s->x1=px-sprite_width/2; s->y1=py-sprite_height/2;
1364    s->x2=px+sprite_width/2; s->y2=py+sprite_height/2;
1365   
1366    s->z=r1_near_clip_z;     
1367    s->tex=tex;
1368    s->s1=s1;      s->t1=t1;      s->s2=s2;      s->t2=t2;
1369
1370    g1_t_post_draw_sprites++;
1371  }   
1372}
1373
Note: See TracBrowser for help on using the repository browser.