source: golgotha/src/golg/map_lod.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: 21.8 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 "map.hh"
10#include "map_man.hh"
11#include "map_vert.hh"
12#include "map_cell.hh"
13#include "div_table.cc"
14#include "camera.hh"
15#include "r1_api.hh"
16#include "tmanage.hh"
17#include "r1_clip.hh"
18#include "g1_render.hh"
19#include "tile.hh"
20#include "controller.hh"
21#include "statistics.hh"
22#include "lisp/li_class.hh"
23#include "resources.hh"
24#include "time/profile.hh"
25#include "light.hh"
26
27static i4_profile_class pf_map_fast("map_fast"),
28  pf_calc_map_lod("calc_map_lod"),
29  pf_gather_objects("gather_objects"),
30  pf_draw_tri("draw_tri");
31
32
33i4_image_class *render_map_section(int x1, int y1, int x2, int y2, int im_w, int im_h);
34
35inline float fmin(float a, float b) { return (a<b)?a:b; }
36inline float fmax(float a, float b) { return (a>b)?a:b; }
37
38class texture_context
39{
40public:
41  i4_float x1,y1;                                 // offset in the map
42  i4_float sx, sy;                                // scale factors to get [0,1] texture coords.
43  r1_texture_handle texture;                      // texture to use
44};
45
46class lod_node
47{
48public:
49  w16 x1,y1,x2,y2;                                // bounding box for this LOD node
50  i4_float z1,z2;
51  i4_float metric;                                // metric for determining LOD "importance"
52  lod_node *child[2];                             // orthogonal BSP children
53  w8 texture_context;                             // which texture context to use or 0 for 1x1
54
55  w8 flags;
56  enum
57  {
58    CLIPPED    = 1<<0,                            // this node is completely out of the view
59    IN_VIEW    = 1<<1,                            //                         in the view
60    CLIP_FLAGS = CLIPPED | IN_VIEW,
61    V_SPLIT    = 1<<2,                            // node split vertically
62  };
63
64  lod_node(w16 x1,w16 y1,w16 x2,w16 y2, i4_float metric=0)
65    : x1(x1), y1(y1), x2(x2), y2(y2), metric(metric)
66  {
67    child[0] = 0;
68    child[1] = 0;
69  }
70};
71
72class g1_lod_context_class
73{
74public:
75  // texture contexts for the large subdivided texture used to cover the whole map
76  texture_context map_texture[5];
77  int num_context, last_context;
78
79  // LOD tree
80  lod_node *root;
81
82  // breadth first ordering of the lod_nodes
83  lod_node *queue[150*100*2];
84  int num_queued, front;
85 
86  // lod_nodes submitted for drawing
87  lod_node *quad[150*100];
88  int num_quads;
89
90  // current controller
91  g1_object_controller_class *cont;
92  i4_3d_vector pos;
93
94  g1_lod_context_class() : root(0) {}
95
96  void init_lod()
97  // make LOD tree
98  {
99    if (root)
100      delete_lod_tree(root);
101
102    num_context=0;
103    make_lod_node(&root,0,0,0,g1_get_map()->width(),g1_get_map()->height());
104
105    for (int i=1; i<=num_context; i++)
106    {
107      int x1,y1,x2,y2;
108
109      x1 = i4_f_to_i(map_texture[i].x1);
110      y1 = i4_f_to_i(map_texture[i].y1);
111      x2 = x1 + i4_f_to_i(1.0/map_texture[i].sx + 0.5);
112      y2 = y1 + i4_f_to_i(1.0/map_texture[i].sy + 0.5);
113      i4_image_class *im = render_map_section(x1,y1,x2,y2, 256,256);
114      map_texture[i].texture = g1_render.r_api->get_tmanager()->register_image(im);
115      delete im;
116    }
117  }
118
119  void uninit_lod()
120  {
121    delete_lod_tree(root);
122  }
123
124  void use_controller(g1_object_controller_class *_cont) { cont = _cont; }
125
126  int test_clip(lod_node *p)
127  // test bounding region of lod_node against the view frustrum
128  {
129    const i4_float MAX_FLY_HEIGHT=3.0;
130    int clip = cont->test_clip(i4_3d_vector(p->x1,p->y1,p->z1),
131                               i4_3d_vector(p->x2,p->y2,p->z2+MAX_FLY_HEIGHT));
132
133    w8 flags =
134      (clip<0)? lod_node::CLIPPED :
135      (clip>0)? lod_node::IN_VIEW :
136      0;
137
138    p->flags = (p->flags & ~lod_node::CLIP_FLAGS) | flags;
139
140    return clip>=0;
141  }
142
143  void make_lod_node(lod_node **pp, lod_node *parent, int x1, int y1, int x2, int y2, int level=0)
144  {
145    int dx = x2-x1, dy = y2-y1;
146    int mx = (x1+x2)/2, my = (y1+y2)/2;
147
148    if (dx==0 || dy==0)
149      return;
150
151    lod_node *p;
152    *pp = p = new lod_node(x1,y1,x2,y2);
153   
154    // hack to get texture contexts
155    if (level<2)
156      p->texture_context = 0;
157    else if (level==2)
158    {
159      p->texture_context = ++num_context;
160      map_texture[num_context].x1 = x1;
161      map_texture[num_context].y1 = y1;
162      map_texture[num_context].sx = 1.0*div_table[x2-x1];
163      map_texture[num_context].sy = 1.0*div_table[y2-y1];
164    }
165    else
166      p->texture_context = parent->texture_context;
167
168    if (dx>1 || dy>1)
169    {
170      if (dx>=dy)
171      {
172        p->flags |= lod_node::V_SPLIT;
173        make_lod_node(&p->child[0], p, x1,y1,mx,y2, level+1);
174        make_lod_node(&p->child[1], p, mx,y1,x2,y2, level+1);
175      }
176      else
177      {
178        p->flags &= ~lod_node::V_SPLIT;
179        make_lod_node(&p->child[0], p, x1,y1,x2,my, level+1);
180        make_lod_node(&p->child[1], p, x1,my,x2,y2, level+1);
181      }
182      p->z1 = fmin(p->child[0]->z1, p->child[1]->z1);
183      p->z2 = fmax(p->child[0]->z2, p->child[1]->z2);
184
185      // area metric
186      p->metric = p->child[0]->metric + p->child[1]->metric;
187    }
188    else
189    {
190      i4_float
191        z11 = g1_get_map()->vertex(x1,y1)->get_height(),
192        z21 = g1_get_map()->vertex(x2,y1)->get_height(),
193        z12 = g1_get_map()->vertex(x1,y2)->get_height(),
194        z22 = g1_get_map()->vertex(x2,y2)->get_height();
195     
196      p->z1 = p->z2 = z11;
197      p->z1 = fmin(p->z1, z21);
198      p->z2 = fmax(p->z2, z21);
199      p->z1 = fmin(p->z1, z12);
200      p->z2 = fmax(p->z2, z12);
201      p->z1 = fmin(p->z1, z22);
202      p->z2 = fmax(p->z2, z22);
203
204      // area metric
205      i4_float dz1,dz2;
206
207      dz1 = z22 - z21;
208      dz2 = z11 - z21;
209      p->metric = sqrt(dz1*dz1 + dz2*dz2 + 1);
210      dz1 = z22 - z12;
211      dz2 = z11 - z12;
212      p->metric += dz1*dz1 + dz2*dz2 + 1;
213    }
214  }
215
216  void delete_lod_tree(lod_node *p)
217  {
218    if (!p)
219      return;
220    delete_lod_tree(p->child[0]);
221    delete_lod_tree(p->child[1]);
222    delete p;
223  }
224
225  void calculate_lod(lod_node *p)
226  {
227//     cont->view.get_camera_pos(pos);
228    cont->get_pos(pos);
229
230    num_quads=0;
231    front = num_queued = 0;
232    queue[num_queued++] = p;
233    root->flags = 0;
234
235    while (front<num_queued)
236    {
237      p = queue[front++];
238      int x1=p->x1,y1=p->y1,x2=p->x2,y2=p->y2;
239      w8 sub_flags=p->flags & lod_node::IN_VIEW;
240
241      // do some kind of clip test
242      if (!sub_flags)
243        if (test_clip(p))
244          sub_flags=p->flags & lod_node::IN_VIEW;
245        else
246          continue;
247
248//       int dx = x2-x1, dy = y2-y1;
249      int mx = (x1+x2)/2, my = (y1+y2)/2;
250
251      i4_float fx = pos.x - mx, fy = pos.y - my, fz = pos.z - g1_get_vertex(mx,my)->get_height();
252      i4_float d1 = fx*fx+fy*fy+fz*fz;
253      i4_float d2 = p->metric*20;
254
255      if (p->child[0] && d1<d2)
256      {
257        p->child[0]->flags = (p->child[0]->flags & ~lod_node::CLIP_FLAGS) | sub_flags;
258        p->child[1]->flags = (p->child[1]->flags & ~lod_node::CLIP_FLAGS) | sub_flags;
259        queue[num_queued++] = p->child[0];
260        queue[num_queued++] = p->child[1];
261
262        // count & mark t splits
263        lod_node *q = p->child[0];
264        if (p->flags & lod_node::V_SPLIT)
265        {
266          g1_get_vertex(q->x2,q->y1)->flags ^= g1_map_vertex_class::T_INTERSECTION;
267          g1_get_vertex(q->x2,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
268        }
269        else
270        {
271          g1_get_vertex(q->x1,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
272          g1_get_vertex(q->x2,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
273        }
274      }
275      else
276      {
277        g1_map_vertex_class *v11, *v12, *v21, *v22;
278     
279        v11 =  g1_get_vertex(x1,y1);
280        v21 =  g1_get_vertex(x2,y1);
281        v12 =  g1_get_vertex(x1,y2);
282        v22 =  g1_get_vertex(x2,y2);
283
284        v11->t_height = v11->get_height();
285        v21->t_height = v21->get_height();
286        v12->t_height = v12->get_height();
287        v22->t_height = v22->get_height();
288        quad[num_quads++] = p;
289      }
290    }
291
292    // T intersection fixing
293
294    // Map of directions
295    //          dzdx2
296    //    z22*  ---->  *
297    //       ^         ^
298    // dzdy1 |         | dzdy2
299    //       |         |
300    //    z12*  ---->  *
301    //      z11 dzdx1 z21
302    for (int test=0; test<2; test++)
303      for (front = 0; front<num_quads; front++)
304      {
305        int
306          x1=quad[front]->x1,y1=quad[front]->y1,
307          x2=quad[front]->x2,y2=quad[front]->y2;
308        int i,j;
309        i4_float z11,z12,z21,z22;
310        i4_float dzdx1,dzdx2,dzdy1,dzdy2;
311
312        z11 = g1_get_vertex(x1,y1)->t_height;
313        z21 = g1_get_vertex(x2,y1)->t_height;
314        z12 = g1_get_vertex(x1,y2)->t_height;
315        z22 = g1_get_vertex(x2,y2)->t_height;
316
317        dzdx1 = (z21 - z11)*div_table[x2 - x1];
318        dzdx2 = (z22 - z12)*div_table[x2 - x1];
319        dzdy1 = (z12 - z11)*div_table[y2 - y1];
320        dzdy2 = (z22 - z21)*div_table[y2 - y1];
321
322        z22 = z12;
323        z12 = z11;
324     
325        i4_float adj1,adj2;
326
327#define DEPIXEL_ADJ 0.1
328
329        adj1 = (pos.x<x1)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
330        adj2 = (pos.x>x2)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
331        for (j=y1+1; j<y2; j++)
332        {
333          z11 += dzdy1;
334          z21 += dzdy2;
335
336//           if (g1_get_vertex(x1,j)->flags & g1_map_vertex_class::T_INTERSECTION)
337            g1_get_vertex(x1,j)->t_height = z11 + adj1;
338//           if (g1_get_vertex(x2,j)->flags & g1_map_vertex_class::T_INTERSECTION)
339            g1_get_vertex(x2,j)->t_height = z21 + adj2;
340        }
341       
342        adj1 = (pos.y<y1)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
343        adj2 = (pos.y>y2)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
344        for (i=x1+1; i<x2; i++)
345        {
346          z12 += dzdx1;
347          z22 += dzdx2;
348//           if (g1_get_vertex(i,y1)->flags & g1_map_vertex_class::T_INTERSECTION)
349            g1_get_vertex(i,y1)->t_height = z12 + adj1;
350//           if (g1_get_vertex(i,y2)->flags & g1_map_vertex_class::T_INTERSECTION)
351            g1_get_vertex(i,y2)->t_height = z22 + adj2;
352        }
353      }
354  }
355
356} g1_lod;
357
358void g1_map_class::init_lod()
359{
360  g1_lod.init_lod();
361}
362
363void g1_map_class::calc_map_lod(g1_object_controller_class *cont)
364{
365  pf_calc_map_lod.start();
366
367  g1_lod.use_controller(cont);
368  g1_lod.calculate_lod(g1_lod.root);
369
370  pf_calc_map_lod.stop();
371}
372
373static r1_texture_ref g1_default_texture("tron_grid");
374const w32          g1_max_objs_in_view = 256;
375w32                g1_num_objs_in_view = 0;
376w32 g1_objs_in_view[g1_max_objs_in_view];
377r1_vert temp_buf_1[9];
378r1_vert temp_buf_2[9];
379
380i4_array<i4_transform_class> g1_obj_transforms_in_view(0, g1_max_objs_in_view);
381class transform_killer_class : public i4_init_class
382{
383  //fix this trey!  can't have global i4_array's without something to clean it up.
384  void uninit() { g1_obj_transforms_in_view.uninit(); }
385} transform_killer;
386
387
388i4_bool g1_draw_tri(r1_vert *points,
389                           w16 a, w16 b, w16 c,
390                           r1_texture_handle texture, w16 clip=1)
391//{{{
392{
393  pf_draw_tri.start();
394
395  g1_stat_counter.increment(g1_statistics_counter_class::TERRAIN_POLYS);           
396  g1_stat_counter.increment(g1_statistics_counter_class::TOTAL_POLYS);
397
398  i4_bool ret = i4_F;
399  r1_render_api_class *api = g1_render.r_api;
400  i4_float size=0;
401  sw32 num_poly_verts = 3;
402  r1_vert *clipped_poly, *v;
403  w16 *clipped_refs;
404  static w16 clipping_refs[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
405  w16 refs[3];
406  i4_float near_w=0.0001;     
407  int i,j;
408
409  refs[0] = a;
410  refs[1] = b;
411  refs[2] = c;
412  clipped_poly = points;
413  clipped_refs = &refs[0];
414
415  // hacked backface culling (should do this in worldspace before projection...)
416  i4_3d_vector vt1(clipped_poly[a].v),vt2(clipped_poly[c].v),normal;
417
418  vt1 -= clipped_poly[b].v;
419  vt2 -= clipped_poly[b].v;
420  normal.cross(vt2,vt1);
421  if (normal.dot(clipped_poly[b].v)>0)
422  {
423    pf_draw_tri.stop();
424    return i4_F;
425  }
426
427  if ((clipped_poly[a].outcode | clipped_poly[b].outcode | clipped_poly[c].outcode)==0)
428  {
429    for (j=0; j<num_poly_verts; j++)
430    {
431      v = &clipped_poly[clipped_refs[j]];
432      if (v->w > near_w)
433        near_w=v->w;
434    }
435  }
436  else
437  {
438    clipped_poly = api->clip_poly(&num_poly_verts,
439                                  clipped_poly,
440                                  clipped_refs,
441                                  temp_buf_1,
442                                  temp_buf_2,
443                                  R1_CLIP_NO_CALC_OUTCODE);
444
445    if (!clipped_poly || num_poly_verts<3)     
446      num_poly_verts=0;
447
448    if (num_poly_verts)     
449    {
450      clipped_refs = clipping_refs;
451
452      for (j=0; j<num_poly_verts; j++)
453      {
454        v = &clipped_poly[j];
455
456        float ooz = r1_ooz(v->v.z);           
457         
458        v->px = v->v.x*ooz*g1_render.center_x + g1_render.center_x;
459        v->py = v->v.y*ooz*g1_render.center_y + g1_render.center_y;
460        v->w  = ooz;                 
461        if (v->w > near_w)
462          near_w=v->w;
463      }
464    }
465  }
466
467  if (num_poly_verts)
468  {
469    if (texture)
470    {
471      sw32 texture_size=i4_f_to_i(g1_render.center_x * near_w * 0.5 * 0.5);
472      api->use_texture(texture, texture_size, 0);
473    }
474
475    if (g1_render.draw_mode==g1_render_class::WIREFRAME)
476    {     
477      api->set_constant_color(0x7f7f7f);
478      api->disable_texture();
479      api->set_shading_mode(R1_SHADE_DISABLED);
480
481      r1_vert v[4];
482      v[0]=clipped_poly[0];
483      v[1]=clipped_poly[1];
484      v[2]=clipped_poly[2];
485      v[3]=clipped_poly[0];
486
487      r1_clip_render_lines(3, v, g1_render.center_x, g1_render.center_y, api);
488      api->set_shading_mode(R1_WHITE_SHADING);
489    }
490    else
491      api->render_poly(num_poly_verts, clipped_poly, clipped_refs);
492
493    ret = i4_T;
494  }
495
496  pf_draw_tri.stop();
497  return ret;
498}
499
500static void gather_objects(int x1, int y1, int x2, int y2)
501{
502  pf_gather_objects.start();
503
504  for (int y=y1; y<y2; y++)
505  {
506    g1_map_cell_class *map_cell=g1_get_cell(x1,y);
507
508    for (int x=x1; x<x2; x++, map_cell++)
509    {
510      // collect objects
511      for (g1_object_chain_class *o=map_cell->get_obj_list(); o; o=o->next)
512      {
513        g1_object_class *obj=o->object;
514       
515        if (!obj->get_flag(g1_object_class::SCRATCH_BIT))
516        {
517          if (g1_num_objs_in_view<g1_max_objs_in_view)
518          {             
519         
520            g1_objs_in_view[g1_num_objs_in_view] = obj->global_id;
521            obj->world_transform = g1_obj_transforms_in_view.add();
522         
523            g1_num_objs_in_view++;
524         
525            //have the object update his transform
526            obj->calc_world_transform(g1_render.frame_ratio);         
527            obj->set_flag(g1_object_class::SCRATCH_BIT, 1);
528          }   
529        }
530      }
531    }
532  }
533
534  pf_gather_objects.stop();
535}
536
537
538static i4_transform_class comp_t;
539int object_compare(const void *a, const void *b)
540{
541  g1_object_class
542    *oa = g1_global_id.get(*((w32*)a)),
543    *ob = g1_global_id.get(*((w32*)b));
544
545
546  // sort objects with alpha last
547  if (oa->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
548  {
549    if (!ob->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
550      return -1;
551  }
552  else if (ob->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
553    return 1;
554   
555
556  i4_float
557    za = comp_t.x.z*oa->x + comp_t.y.z*oa->y + comp_t.z.z*oa->h + comp_t.t.z,
558    zb = comp_t.x.z*ob->x + comp_t.y.z*ob->y + comp_t.z.z*ob->h + comp_t.t.z;
559
560  if (za>zb)
561    return 1;
562  else
563    return -1;
564}
565
566void g1_map_class::fast_draw_cells(g1_draw_context_class  *context)
567{
568  pf_map_fast.start();
569
570  r1_render_api_class *api = g1_render.r_api;
571  i4_transform_class t(*context->transform);
572  i4_3d_vector pos;
573
574
575//   g1_lod.cont->view.get_camera_pos(pos);
576  pos = g1_lod.pos;
577
578  g1_num_objs_in_view = 0;
579  g1_obj_transforms_in_view.clear();
580
581  if (g1_render.draw_mode==g1_render_class::SOLID)
582    api->use_texture(g1_default_texture.get(), 1, 0);
583 
584  int i=0,j;
585  g1_map_vertex_class *vt[4];
586  g1_map_vertex_class *v=verts;
587
588  g1_lod.last_context=0;
589  for (j=0; j<g1_lod.num_quads; j++)
590  {
591    lod_node *p = g1_lod.quad[j];
592    int
593      x1 = p->x1, y1 = p->y1,
594      x2 = p->x2, y2 = p->y2,
595      clip = !(p->flags & lod_node::IN_VIEW);
596
597    sw32 mw_p1=width()+1;
598
599    vt[0]=v + x1 + y1 * mw_p1;         
600    vt[1]=v + x2 + y1 * mw_p1;         
601    vt[2]=v + x2 + y2 * mw_p1;         
602    vt[3]=v + x1 + y2 * mw_p1;         
603
604    vt[0]->transform(t, x1, y1, g1_render.scale_x,g1_render.scale_y);
605    vt[1]->transform(t, x2, y1, g1_render.scale_x,g1_render.scale_y);
606    vt[2]->transform(t, x2, y2, g1_render.scale_x,g1_render.scale_y);
607    vt[3]->transform(t, x1, y2, g1_render.scale_x,g1_render.scale_y);
608
609    if (vt[0]->calc_clip_code()==0)
610      vt[0]->project(g1_render.center_x, g1_render.center_y);
611    if (vt[1]->calc_clip_code()==0)
612      vt[1]->project(g1_render.center_x, g1_render.center_y);
613    if (vt[2]->calc_clip_code()==0)
614      vt[2]->project(g1_render.center_x, g1_render.center_y);
615    if (vt[3]->calc_clip_code()==0)     
616      vt[3]->project(g1_render.center_x, g1_render.center_y);
617
618    // collect objects
619    i4_3d_vector mid(i4_float(x2+x1)/2.0,i4_float(y2+y1)/2.0,i4_float(p->z2+p->z1)/2.0);
620    mid -= pos;
621
622
623    if (mid.dot(mid) < g1_resources.lod_disappear_dist)
624      gather_objects(x1,y1,x2,y2);
625    else
626      i++;
627
628    if (x1+1==x2 && y1+1==y2)
629    {
630      // single cell
631      g1_map_cell_class *map_cell=cells + x1 + y1*width();
632
633      g1_lod.last_context=0;
634      r1_texture_handle han = g1_tile_man.get_texture(map_cell->type);
635      if (han && han!=g1_tile_man.get_pink())
636      {
637        static float u[4]={0,1,1,0},v[4]={1,1,0,0};
638        int uv_on=map_cell->get_rotation();
639        int uv_dir=map_cell->mirrored() ? 3 : 1;
640        r1_vert poly[4];
641       
642        for (int i=0; i<4; i++)
643        {
644          vt[i]->set_r1_vert(&poly[i]);
645          poly[i].s=u[uv_on];
646          poly[i].t=v[uv_on];
647          poly[i].a=1.0;
648          uv_on=(uv_on+uv_dir)&3;
649        }
650        vt[0]->get_rgb(poly[0].r, poly[0].g, poly[0].b, x1, y1);
651        vt[1]->get_rgb(poly[1].r, poly[1].g, poly[1].b, x2, y1);
652        vt[2]->get_rgb(poly[2].r, poly[2].g, poly[2].b, x2, y2);
653        vt[3]->get_rgb(poly[3].r, poly[3].g, poly[3].b, x1, y2);
654       
655        if (post_cell_draw)
656          post_cell_draw(x1,y1, post_cell_draw_context);
657
658        if (g1_draw_tri(poly, 0,1,2, han))
659          han = 0;
660        g1_draw_tri(poly, 0,2,3, han);
661      }
662    }
663    else
664    {
665      // larger LOD cell
666
667      texture_context *tc = &g1_lod.map_texture[p->texture_context];
668      r1_texture_handle han;
669
670      if (g1_lod.last_context==p->texture_context)
671        han = 0;
672      else
673        han = tc->texture;
674
675      r1_vert poly[4];
676
677      for (int i=0; i<4; i++)
678      {
679        vt[i]->set_r1_vert(&poly[i]);
680        poly[i].a=1.0;
681      }
682      vt[0]->get_rgb(poly[0].r, poly[0].g, poly[0].b, x1, y1);
683      vt[1]->get_rgb(poly[1].r, poly[1].g, poly[1].b, x2, y1);
684      vt[2]->get_rgb(poly[2].r, poly[2].g, poly[2].b, x2, y2);
685      vt[3]->get_rgb(poly[3].r, poly[3].g, poly[3].b, x1, y2);
686
687      poly[0].s=(x1 - tc->x1)*tc->sx;
688      poly[0].t=(y1 - tc->y1)*tc->sy;
689      poly[1].s=(x2 - tc->x1)*tc->sx;
690      poly[1].t=(y1 - tc->y1)*tc->sy;
691      poly[2].s=(x2 - tc->x1)*tc->sx;
692      poly[2].t=(y2 - tc->y1)*tc->sy;
693      poly[3].s=(x1 - tc->x1)*tc->sx;
694      poly[3].t=(y2 - tc->y1)*tc->sy;
695
696      if (g1_draw_tri(poly, 0,1,2, han))
697        han = 0;
698      if (g1_draw_tri(poly, 0,2,3, han))
699        han = 0;
700      if (han==0)
701        g1_lod.last_context = p->texture_context;
702    }
703  }
704
705  for (i=0; i<g1_num_objs_in_view; i++)
706  {
707    g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
708    if (o)
709      o->set_flag(g1_object_class::SCRATCH_BIT, 0);
710  }
711
712
713  li_class *old_this=li_this;
714  //draw the objects BACK TO FRONT
715  comp_t = *context->transform;
716  qsort(g1_objs_in_view, g1_num_objs_in_view, sizeof(g1_objs_in_view[0]), object_compare);
717
718  for (i=g1_num_objs_in_view-1;i>=0;i--)
719  {
720    g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
721    if (o)
722    {
723      li_this=o->vars;
724
725      o->set_flag(g1_object_class::SCRATCH_BIT, 0);
726      if (o->world_transform!=0)
727        o->draw(context);
728      else
729        i4_warning("null transform");
730    }
731  }
732
733  if (context->draw_editor_stuff)
734  {
735    for (i=g1_num_objs_in_view-1;i>=0;i--)
736    {
737      g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
738      if (o)
739      {
740        li_this=o->vars;
741        o->editor_draw(context);
742      }
743    }
744  } 
745 
746  li_this=old_this;
747   
748  for (j=0; j<g1_lod.num_quads; j++)
749  {
750    lod_node *p = g1_lod.quad[j];
751    int
752      x1 = p->x1, y1 = p->y1,
753      x2 = p->x2, y2 = p->y2;
754
755    sw32 mw_p1=width()+1;
756
757    vt[0]=v + x1 + y1 * mw_p1;         
758    vt[1]=v + x2 + y1 * mw_p1;         
759    vt[2]=v + x2 + y2 * mw_p1;         
760    vt[3]=v + x1 + y2 * mw_p1;         
761
762    vt[0]->clear_calculations();
763    vt[1]->clear_calculations();
764    vt[2]->clear_calculations();
765    vt[3]->clear_calculations();
766  }
767
768  g1_stat_counter.increment(g1_statistics_counter_class::FRAMES);
769
770  pf_map_fast.stop();
771}
772
773
774class num_in_view_reset_class : public g1_global_id_reset_notifier
775{
776public:
777  virtual void reset()
778  {
779    g1_num_objs_in_view=0;   
780  }
781} num_in_view_reset_inst;
Note: See TracBrowser for help on using the repository browser.