source: golgotha/src/render/r1_clip.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 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: 17.0 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 "r1_clip.hh"
10#include "r1_vert.hh"
11#include "r1_api.hh"
12#include "image/context.hh"
13
14#define FPDIV_CORRECTION 0.0001
15
16int *r1_clip(r1_clip_vert_array *v_array,
17             int *src, int t_src,             // indexes into vertex array for initial verts
18             int *dst1, int *dst2,            // destination index arrays
19             int &t_dst,
20             float center_x, float center_y,
21             i4_bool clip_code_and_project_done)
22{
23  w32 ORCODE  = 0;
24  w32 ANDCODE = 0xffffffff;
25  w32 i,j,c0,c1;
26  w32 bitmask;
27  i4_float ooz,dx,dy,dz,ds,dt,dr,dg,db,da,t;
28
29 
30  t_dst=0;
31
32  r1_vert *vbuf=v_array->buf, *v;
33  int *sv=src;
34
35  if (clip_code_and_project_done)
36  {
37    for (i=0; i<t_src; i++, sv++)
38    {   
39      v=vbuf+*sv;
40      ORCODE  |= v->outcode;
41      ANDCODE &= v->outcode;
42    }
43  }
44  else
45  {
46    for (i=0; i<t_src; i++, sv++)
47    {   
48      v=vbuf+*sv;
49      v->outcode = r1_calc_outcode(v);
50
51      ORCODE  |= v->outcode;
52      ANDCODE &= v->outcode;
53     
54      if (!v->outcode)
55      {
56        ooz = r1_ooz(v->v.z);
57        v->w  = ooz;
58        v->px = ((v->v.x * ooz) * center_x) + center_x;
59        v->py = ((v->v.y * ooz) * center_y) + center_y;       
60      }
61    }
62  }
63
64  //all verts are outside one of the view planes return a poly with 0 vertices
65  if (ANDCODE)
66    return 0;
67 
68  if (!ORCODE)      // all verts are inside, return that no clipping occurred
69  {
70    t_dst=t_src;
71    return src;
72  }
73
74 
75  int *dst=dst1; 
76
77  for (bitmask=16; bitmask; bitmask=bitmask>>1)
78  {
79    if (bitmask & ORCODE)
80    {
81      t_dst=0;
82
83      for (i=0; i<t_src; i++)
84      {                 
85        j=i+1;
86        if (j==t_src) j=0;
87
88        r1_vert *vi=vbuf + src[i], *vj=vbuf + src[j], *cp;
89     
90        c0 = bitmask & vi->outcode;
91        c1 = bitmask & vj->outcode;
92     
93        //if c0 is not outside of this plane, add it
94        if (c0==0)
95          dst[t_dst++]=src[i];
96     
97        //if they are on the same
98        //side, move to the next vert
99        if (c0==c1) continue;
100     
101        //otherwise, generate a clipped point
102
103
104        dst[t_dst++]=v_array->total;
105        cp=v_array->add();
106
107        dx = vj->v.x - vi->v.x;
108        dy = vj->v.y - vi->v.y;
109        dz = vj->v.z - vi->v.z;
110        ds = vj->s - vi->s;
111        dt = vj->t - vi->t;
112        dr = vj->r - vi->r;
113        dg = vj->g - vi->g;
114        db = vj->b - vi->b;
115        da = vj->a - vi->a;
116     
117     
118
119        switch (bitmask | (ORCODE&128)) {
120          case 1: 
121            t = (-vi->v.x + vi->v.z) / ( dx - dz);                 
122            cp->v.y = vi->v.y + (t * dy);
123            cp->v.z = vi->v.z + (t * dz);                 
124            cp->v.x = cp->v.z;
125            break;
126
127          case 2:
128            t = ( vi->v.x + vi->v.z) / (-dx - dz);                 
129            cp->v.y = vi->v.y + (t * dy);
130            cp->v.z = vi->v.z + (t * dz);
131                 
132            cp->v.x = -cp->v.z;
133            break;
134       
135          case 4: 
136            t = (-vi->v.y + vi->v.z) / ( dy - dz);
137            cp->v.x = vi->v.x + (t * dx);                 
138            cp->v.z = vi->v.z + (t * dz);
139                 
140            cp->v.y = cp->v.z;
141            break;
142       
143          case 8:
144            t = ( vi->v.y + vi->v.z) / (-dy - dz);
145            cp->v.x = vi->v.x + (t * dx);                 
146            cp->v.z = vi->v.z + (t * dz);
147                 
148            cp->v.y = -cp->v.z;
149            break;
150
151          case 16:
152            t = (r1_near_clip_z - vi->v.z) / (dz);                             
153            cp->v.x = vi->v.x + (t * dx);
154            cp->v.y = vi->v.y + (t * dy);
155                 
156            cp->v.z = r1_near_clip_z;
157            break;
158
159          case 1|128:
160            t = (1.0 - vi->v.x) / dx;
161            cp->v.y = vi->v.y + (t * dy);
162            cp->v.z = vi->v.z + (t * dz);
163            cp->v.x = 1.0;
164            break;
165           
166          case 2|128:
167            t = (vi->v.x + 1.0) / -dx;
168            cp->v.y = vi->v.y + (t * dy);
169            cp->v.z = vi->v.z + (t * dz);
170                   
171            cp->v.x = -1.0;
172            break;
173       
174          case 4|128:
175            t = (1.0 - vi->v.y) / dy;
176            cp->v.x = vi->v.x + (t * dx);                 
177            cp->v.z = vi->v.z + (t * dz);
178                   
179            cp->v.y = 1.0;
180            break;
181       
182          case 8|128:
183            t = (vi->v.y + 1.0) / -dy;
184            cp->v.x = vi->v.x + (t * dx);                 
185            cp->v.z = vi->v.z + (t * dz);
186                 
187            cp->v.y = -1.0;
188            break;
189        }
190     
191        cp->s = vi->s + (t * ds);
192        cp->t = vi->t + (t * dt);
193        cp->r = vi->r + (t * dr);
194        cp->g = vi->g + (t * dg);
195        cp->b = vi->b + (t * db);
196        cp->a = vi->a + (t * da);
197     
198        // no far clip
199        cp->outcode = r1_calc_outcode(cp);
200
201        if (!cp->outcode)
202        {
203          ooz = r1_ooz(cp->v.z);
204          cp->px = ((cp->v.x * ooz) * center_x) + center_x;
205          cp->py = ((cp->v.y * ooz) * center_y) + center_y;         
206          cp->w  = ooz;
207        } 
208        ORCODE |= cp->outcode;     
209      }
210   
211      if (dst==dst1)
212      {
213        dst=dst2;
214        src=dst1;
215      }
216      else
217      {
218        dst=dst1;
219        src=dst2;
220      }
221     
222      t_src=t_dst;
223    }
224  }
225  return src;
226}
227
228
229void r1_clip_render_lines(int t_lines, r1_vert *verts,
230                          float center_x, float center_y,
231                          r1_render_api_class *api)
232{
233  r1_vert v[2];
234
235  w8 bitmask;
236
237  i4_float dz,dy,dx,dr,dg,db,t;
238
239  sw32 i;
240
241  for (i=0; i<t_lines+1; i++)
242    verts[i].outcode   = r1_calc_outcode(&verts[i]);
243
244  for (i=0;i<t_lines;i++)
245  {   
246    //both outside? continue
247   
248    if (verts[i].outcode & verts[i+1].outcode) continue;
249   
250    v[0] = verts[i];
251    v[1] = verts[i+1];
252
253    w8 outcode = v[0].outcode | v[1].outcode;
254
255    if (!outcode)
256    {
257      api->render_lines(1,v);
258      continue;
259    }
260
261    //gotta clip
262    for (bitmask=32; bitmask && (v[0].outcode & v[1].outcode)==0; bitmask = bitmask >> 1)
263    {     
264      if (bitmask & v[0].outcode)
265      {     
266        r1_vert clip_point;
267
268        dx = v[1].v.x - v[0].v.x;
269        dy = v[1].v.y - v[0].v.y;
270        dz = v[1].v.z - v[0].v.z;
271        dr = v[1].r - v[0].r;
272        dg = v[1].g - v[0].g;
273        db = v[1].b - v[0].b;
274 
275        switch (bitmask | (v[0].outcode&128))
276        {
277          case 1:
278            t = (-v[0].v.x + v[0].v.z) / ( dx - dz);                 
279            clip_point.v.y = v[0].v.y + (t * dy);
280            clip_point.v.z = v[0].v.z + (t * dz);
281                   
282            clip_point.v.x = clip_point.v.z;
283            break;
284
285          case 2:
286            t = ( v[0].v.x + v[0].v.z) / (-dx - dz);                 
287            clip_point.v.y = v[0].v.y + (t * dy);
288            clip_point.v.z = v[0].v.z + (t * dz);
289                   
290            clip_point.v.x = -clip_point.v.z;
291            break;
292       
293          case 4:
294            t = (-v[0].v.y + v[0].v.z) / ( dy - dz);
295            clip_point.v.x = v[0].v.x + (t * dx);                 
296            clip_point.v.z = v[0].v.z + (t * dz);
297                   
298            clip_point.v.y = clip_point.v.z;
299            break;
300       
301          case 8:
302            t = ( v[0].v.y + v[0].v.z) / (-dy - dz);
303            clip_point.v.x = v[0].v.x + (t * dx);                 
304            clip_point.v.z = v[0].v.z + (t * dz);
305                 
306            clip_point.v.y = -clip_point.v.z;
307            break;
308
309          case 16:
310            t = (r1_near_clip_z - v[0].v.z) / (dz);                             
311            clip_point.v.x = v[0].v.x + (t * dx);
312            clip_point.v.y = v[0].v.y + (t * dy);
313                 
314            clip_point.v.z = r1_near_clip_z;
315            break;
316
317
318          case 32:
319            t = -(r1_far_clip_z - v[0].v.z) / (dz);                             
320            clip_point.v.x = v[0].v.x + (t * dx);
321            clip_point.v.y = v[0].v.y + (t * dy);
322                 
323            clip_point.v.z = r1_far_clip_z;
324            break;
325
326          case 1|128:
327            t = (1.0 - v[0].v.x) / dx;
328            clip_point.v.y = v[0].v.y + (t * dy);
329            clip_point.v.z = v[0].v.z + (t * dz);
330            clip_point.v.x = 1.0;
331            break;
332           
333          case 2|128:
334            t = (1.0 + v[0].v.x) / -dx;
335            clip_point.v.y = v[0].v.y + (t * dy);
336            clip_point.v.z = v[0].v.z + (t * dz);
337            clip_point.v.x = -1.0;
338            break;
339       
340          case 4|128:
341            t = (1.0 - v[0].v.y) / dy;
342            clip_point.v.x = v[0].v.x + (t * dx);                 
343            clip_point.v.z = v[0].v.z + (t * dz);
344                   
345            clip_point.v.y = 1.0;
346            break;
347       
348          case 8|128:
349            t = ( 1.0 + v[0].v.y) / -dy;
350            clip_point.v.x = v[0].v.x + (t * dx);                 
351            clip_point.v.z = v[0].v.z + (t * dz);
352            clip_point.v.y = -1.0;
353            break;
354        }
355        clip_point.r = v[0].r + (t * dr);
356        clip_point.g = v[0].g + (t * dg);
357        clip_point.b = v[0].b + (t * db);       
358               
359        clip_point.outcode = r1_calc_outcode(&clip_point);
360
361        if (!clip_point.outcode)
362        {
363          i4_float ooz  = r1_ooz(clip_point.v.z);
364
365          clip_point.px = ((clip_point.v.x * ooz) * center_x) + center_x;
366          clip_point.py = ((clip_point.v.y * ooz) * center_y) + center_y;
367          clip_point.w  = ooz;
368        }
369       
370        v[0] = clip_point;
371      }
372     
373      if (bitmask & v[1].outcode)
374      {     
375        r1_vert clip_point;
376
377        clip_point = v[0];
378        v[0]       = v[1];
379        v[1]       = clip_point;
380
381        dx = v[1].v.x - v[0].v.x;
382        dy = v[1].v.y - v[0].v.y;
383        dz = v[1].v.z - v[0].v.z;
384        dr = v[1].r - v[0].r;
385        dg = v[1].g - v[0].g;
386        db = v[1].b - v[0].b;
387 
388        switch (bitmask | (v[1].outcode&128))
389        {
390          case 1:
391            t = (-v[0].v.x + v[0].v.z) / ( dx - dz);                 
392            clip_point.v.y = v[0].v.y + (t * dy);
393            clip_point.v.z = v[0].v.z + (t * dz);
394           
395            clip_point.v.x = clip_point.v.z;
396            break;
397
398          case 2:
399            t = ( v[0].v.x + v[0].v.z) / (-dx - dz);                 
400            clip_point.v.y = v[0].v.y + (t * dy);
401            clip_point.v.z = v[0].v.z + (t * dz);
402           
403            clip_point.v.x = -clip_point.v.z;
404            break;
405           
406          case 4:
407            t = (-v[0].v.y + v[0].v.z) / ( dy - dz);
408            clip_point.v.x = v[0].v.x + (t * dx);                 
409            clip_point.v.z = v[0].v.z + (t * dz);
410           
411            clip_point.v.y = clip_point.v.z;
412            break;
413           
414          case 8:
415            t = ( v[0].v.y + v[0].v.z) / (-dy - dz);
416            clip_point.v.x = v[0].v.x + (t * dx);                 
417            clip_point.v.z = v[0].v.z + (t * dz);
418           
419            clip_point.v.y = -clip_point.v.z;
420            break;
421           
422          case 16:
423            t = (r1_near_clip_z - v[0].v.z) / (dz);                             
424            clip_point.v.x = v[0].v.x + (t * dx);
425            clip_point.v.y = v[0].v.y + (t * dy);
426           
427            clip_point.v.z = r1_near_clip_z;
428            break;
429
430          case 32:
431            t = -(r1_far_clip_z - v[0].v.z) / (dz);                             
432            clip_point.v.x = v[0].v.x + (t * dx);
433            clip_point.v.y = v[0].v.y + (t * dy);
434           
435            clip_point.v.z = r1_far_clip_z;
436            break;
437
438          case 1|128:
439            t = (1.0 - v[0].v.x) / dx;
440            clip_point.v.y = v[0].v.y + (t * dy);
441            clip_point.v.z = v[0].v.z + (t * dz);
442            clip_point.v.x = 1.0;
443            break;
444           
445          case 2|128:
446            t = (1.0 + v[0].v.x) / -dx;
447            clip_point.v.y = v[0].v.y + (t * dy);
448            clip_point.v.z = v[0].v.z + (t * dz);
449            clip_point.v.x = -1.0;
450            break;
451       
452          case 4|128:
453            t = (1.0 - v[0].v.y) / dy;
454            clip_point.v.x = v[0].v.x + (t * dx);                 
455            clip_point.v.z = v[0].v.z + (t * dz);
456                   
457            clip_point.v.y = 1.0;
458            break;
459       
460          case 8|128:
461            t = ( 1.0 + v[0].v.y) / -dy;
462            clip_point.v.x = v[0].v.x + (t * dx);                 
463            clip_point.v.z = v[0].v.z + (t * dz);
464            clip_point.v.y = -1.0;
465            break;
466        }
467        clip_point.r = v[0].r + (t * dr);
468        clip_point.g = v[0].g + (t * dg);
469        clip_point.b = v[0].b + (t * db);       
470               
471        clip_point.outcode = r1_calc_outcode(&clip_point);
472
473        if (!clip_point.outcode)
474        {
475          i4_float ooz = r1_ooz(clip_point.v.z);
476          clip_point.px = ((clip_point.v.x * ooz) * center_x) + center_x;
477          clip_point.py = ((clip_point.v.y * ooz) * center_y) + center_y;         
478          clip_point.w  = ooz;
479        }
480       
481        v[0] = v[1];
482        v[1] = clip_point;
483      }     
484    }
485
486    if (!v[0].outcode && !v[1].outcode)
487      api->render_lines(1,v);
488  }
489}
490
491
492void r1_clip_clear_area(int x1, int y1, int x2, int y2, w32 color, float z,
493                        i4_draw_context_class &context,
494                        r1_render_api_class *api)
495{
496  api->set_alpha_mode(R1_ALPHA_DISABLED);
497  api->set_constant_color(color);
498  api->disable_texture();
499
500  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
501  {
502    int lx1,ly1,lx2,ly2;
503
504    if (x1<c->x1) lx1=c->x1; else lx1=x1;
505    if (y1<c->y1) ly1=c->y1; else ly1=y1;
506    if (x2>c->x2) lx2=c->x2; else lx2=x2;
507    if (y2>c->y2) ly2=c->y2; else ly2=y2;
508    if (!(lx1>lx2 || ly1>ly2))
509      api->clear_area(lx1, ly1, lx2, ly2, color, z);
510  }
511}
512
513
514void r1_clip_render_textured_rect(float x1, float y1, float x2, float y2, float z,  float a,
515                                  int win_width, int win_height,
516                                  r1_texture_handle handle,
517                                  int frame,
518                                  r1_render_api_class *api,
519                                  float s1, float t1,
520                                  float s2, float t2)
521{
522  float ooz=r1_ooz(z);
523
524  api->use_texture(handle, i4_f_to_i( x2-x1+1), frame);
525
526  r1_vert v[4];
527 
528  // should be counter-clockwise
529  v[0].px  = x2;
530  v[0].py  = y1;
531  v[0].v.z = z;
532  v[0].w   = ooz;
533  v[0].s   = s2;
534  v[0].t   = t1;
535     
536  v[1].px  = x1;
537  v[1].py  = y1;
538  v[1].v.z = z;
539  v[1].w   = ooz;     
540  v[1].s   = s1;
541  v[1].t   = t1;
542
543  v[2].px  = x1;
544  v[2].py  = y2;
545  v[2].v.z = z;
546  v[2].w   = ooz;     
547  v[2].s   = s1;
548  v[2].t   = t2;
549
550  v[3].px  = x2;
551  v[3].py  = y2;
552  v[3].v.z = z;
553  v[3].w   = ooz;     
554  v[3].s   = s2;
555  v[3].t   = t2;
556
557  v[0].r=v[1].r=v[2].r=v[3].r = 1;
558  v[0].g=v[1].g=v[2].g=v[3].g = 1;
559  v[0].b=v[1].b=v[2].b=v[3].b = 1;
560
561  v[0].a=v[1].a=v[2].a=v[3].a = a;
562                                 
563
564  int clip_x1=0, clip_y1=0, clip_x2=win_width, clip_y2=win_height;
565
566  //left x check
567  if (v[1].px < clip_x1)
568  {
569    i4_float diff = (clip_x1 - v[1].px) / (i4_float)(x2-x1+1);
570    v[1].s = s1+(s2-s1)*diff;
571    v[2].s = s1+(s2-s1)*diff;
572    v[1].px = clip_x1;
573    v[2].px = clip_x1;
574  }
575  else if (v[1].px > clip_x2)
576    return;
577
578  //right x check
579  if (v[0].px > clip_x2)
580  {
581    i4_float diff = (v[0].px - clip_x2) / (i4_float)(x2-x1+1);
582    v[0].s = s2 - diff*(s2-s1);       
583    v[3].s = s2 - diff*(s2-s1);
584    v[0].px = clip_x2;
585    v[3].px = clip_x2;
586  }
587  else if (v[0].px < clip_x1)
588    return;
589
590
591  //top y check
592  if (v[0].py < clip_y1)
593  {
594    i4_float diff = (clip_y1 - v[0].py) / (i4_float)(y2-y1+1);
595    v[0].t  = t1+(t2-t1)*diff;
596    v[1].t  = t1+(t2-t1)*diff;
597    v[0].py = clip_y1;
598    v[1].py = clip_y1;
599  }
600  else if (v[0].py > clip_y2)
601    return;
602
603  //bottom y check
604  if (v[2].py > clip_y2)
605  {
606    i4_float diff = (v[2].py - clip_y2) / (i4_float)(y2-y1+1);
607    v[2].t  = t2-diff*(t2-t1);
608    v[3].t  = t2-diff*(t2-t1);       
609    v[2].py = clip_y2;
610    v[3].py = clip_y2;
611  }
612  else if (v[2].py < clip_y1)
613    return;
614
615  api->render_sprite(v);
616}
617
618
Note: See TracBrowser for help on using the repository browser.