Panda3D
ztriangle.h
1 /*
2  * We draw a triangle with various interpolations
3  */
4 
5 {
6  ZBufferPoint *t,*pr1,*pr2,*l1,*l2;
7  PN_stdfloat fdx1, fdx2, fdy1, fdy2, fz, d1, d2;
8  ZPOINT *pz1;
9  PIXEL *pp1;
10  int part, update_left, update_right;
11 
12  int nb_lines, dx1, dy1, tmp, dx2, dy2;
13 
14  int error, derror;
15  int x1, dxdy_min, dxdy_max;
16  /* warning: x2 is multiplied by 2^16 */
17  int x2, dx2dy2;
18 
19 #ifdef INTERP_Z
20  int z1 = 0, dzdx = 0, dzdy = 0, dzdl_min = 0, dzdl_max = 0;
21 #endif
22 #ifdef INTERP_RGB
23  int r1 = 0, drdx = 0, drdy = 0, drdl_min = 0, drdl_max = 0;
24  int g1 = 0, dgdx = 0, dgdy = 0, dgdl_min = 0, dgdl_max = 0;
25  int b1 = 0, dbdx = 0, dbdy = 0, dbdl_min = 0, dbdl_max = 0;
26  int a1 = 0, dadx = 0, dady = 0, dadl_min = 0, dadl_max = 0;
27 #endif
28 #ifdef INTERP_ST
29  int s1 = 0, dsdx = 0, dsdy = 0, dsdl_min = 0, dsdl_max = 0;
30  int t1 = 0, dtdx = 0, dtdy = 0, dtdl_min = 0, dtdl_max = 0;
31 #endif
32 #ifdef INTERP_STZ
33  PN_stdfloat sz1 = 0, dszdx = 0, dszdy = 0, dszdl_min = 0, dszdl_max = 0;
34  PN_stdfloat tz1 = 0, dtzdx = 0, dtzdy = 0, dtzdl_min = 0, dtzdl_max = 0;
35 #endif
36 #ifdef INTERP_STZA
37  PN_stdfloat sza1 = 0, dszadx = 0, dszady = 0, dszadl_min = 0, dszadl_max = 0;
38  PN_stdfloat tza1 = 0, dtzadx = 0, dtzady = 0, dtzadl_min = 0, dtzadl_max = 0;
39 #endif
40 #ifdef INTERP_STZB
41  PN_stdfloat szb1 = 0, dszbdx = 0, dszbdy = 0, dszbdl_min = 0, dszbdl_max = 0;
42  PN_stdfloat tzb1 = 0, dtzbdx = 0, dtzbdy = 0, dtzbdl_min = 0, dtzbdl_max = 0;
43 #endif
44 #if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ))
45  unsigned int mipmap_dx = 0, mipmap_level = 0;
46 #endif
47 #if defined(INTERP_MIPMAP) && defined(INTERP_STZA)
48  unsigned int mipmap_dxa = 0, mipmap_levela = 0;
49 #endif
50 #if defined(INTERP_MIPMAP) && defined(INTERP_STZB)
51  unsigned int mipmap_dxb = 0, mipmap_levelb = 0;
52 #endif
53 
54  EARLY_OUT();
55 
56  COUNT_PIXELS(PIXEL_COUNT, p0, p1, p2);
57 
58  /* we sort the vertex with increasing y */
59  if (p1->y < p0->y) {
60  t = p0;
61  p0 = p1;
62  p1 = t;
63  }
64  if (p2->y < p0->y) {
65  t = p2;
66  p2 = p1;
67  p1 = p0;
68  p0 = t;
69  } else if (p2->y < p1->y) {
70  t = p1;
71  p1 = p2;
72  p2 = t;
73  }
74 
75  /* we compute dXdx and dXdy for all interpolated values */
76 
77  fdx1 = (PN_stdfloat) (p1->x - p0->x);
78  fdy1 = (PN_stdfloat) (p1->y - p0->y);
79 
80  fdx2 = (PN_stdfloat) (p2->x - p0->x);
81  fdy2 = (PN_stdfloat) (p2->y - p0->y);
82 
83  fz = fdx1 * fdy2 - fdx2 * fdy1;
84  if (fz == 0)
85  return;
86  fz = 1.0f / fz;
87 
88  fdx1 *= fz;
89  fdy1 *= fz;
90  fdx2 *= fz;
91  fdy2 *= fz;
92 
93 #ifdef INTERP_Z
94  d1 = (PN_stdfloat) (p1->z - p0->z);
95  d2 = (PN_stdfloat) (p2->z - p0->z);
96  dzdx = (int) (fdy2 * d1 - fdy1 * d2);
97  dzdy = (int) (fdx1 * d2 - fdx2 * d1);
98 #endif
99 
100 #ifdef INTERP_RGB
101  d1 = (PN_stdfloat) (p1->r - p0->r);
102  d2 = (PN_stdfloat) (p2->r - p0->r);
103  drdx = (int) (fdy2 * d1 - fdy1 * d2);
104  drdy = (int) (fdx1 * d2 - fdx2 * d1);
105 
106  d1 = (PN_stdfloat) (p1->g - p0->g);
107  d2 = (PN_stdfloat) (p2->g - p0->g);
108  dgdx = (int) (fdy2 * d1 - fdy1 * d2);
109  dgdy = (int) (fdx1 * d2 - fdx2 * d1);
110 
111  d1 = (PN_stdfloat) (p1->b - p0->b);
112  d2 = (PN_stdfloat) (p2->b - p0->b);
113  dbdx = (int) (fdy2 * d1 - fdy1 * d2);
114  dbdy = (int) (fdx1 * d2 - fdx2 * d1);
115 
116  d1 = (PN_stdfloat) (p1->a - p0->a);
117  d2 = (PN_stdfloat) (p2->a - p0->a);
118  dadx = (int) (fdy2 * d1 - fdy1 * d2);
119  dady = (int) (fdx1 * d2 - fdx2 * d1);
120 
121 #endif
122 
123 #ifdef INTERP_ST
124  d1 = (PN_stdfloat) (p1->s - p0->s);
125  d2 = (PN_stdfloat) (p2->s - p0->s);
126  dsdx = (int) (fdy2 * d1 - fdy1 * d2);
127  dsdy = (int) (fdx1 * d2 - fdx2 * d1);
128 
129  d1 = (PN_stdfloat) (p1->t - p0->t);
130  d2 = (PN_stdfloat) (p2->t - p0->t);
131  dtdx = (int) (fdy2 * d1 - fdy1 * d2);
132  dtdy = (int) (fdx1 * d2 - fdx2 * d1);
133 
134  CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);
135 #endif
136 
137 #ifdef INTERP_STZ
138  {
139  PN_stdfloat zz;
140  zz=(PN_stdfloat) p0->z;
141  p0->sz= (PN_stdfloat) p0->s * zz;
142  p0->tz= (PN_stdfloat) p0->t * zz;
143  zz=(PN_stdfloat) p1->z;
144  p1->sz= (PN_stdfloat) p1->s * zz;
145  p1->tz= (PN_stdfloat) p1->t * zz;
146  zz=(PN_stdfloat) p2->z;
147  p2->sz= (PN_stdfloat) p2->s * zz;
148  p2->tz= (PN_stdfloat) p2->t * zz;
149 
150  d1 = p1->sz - p0->sz;
151  d2 = p2->sz - p0->sz;
152  dszdx = (fdy2 * d1 - fdy1 * d2);
153  dszdy = (fdx1 * d2 - fdx2 * d1);
154 
155  d1 = p1->tz - p0->tz;
156  d2 = p2->tz - p0->tz;
157  dtzdx = (fdy2 * d1 - fdy1 * d2);
158  dtzdy = (fdx1 * d2 - fdx2 * d1);
159  }
160 #endif
161 
162 #ifdef INTERP_STZA
163  {
164  PN_stdfloat zz;
165  zz=(PN_stdfloat) p0->z;
166  p0->sza= (PN_stdfloat) p0->sa * zz;
167  p0->tza= (PN_stdfloat) p0->ta * zz;
168  zz=(PN_stdfloat) p1->z;
169  p1->sza= (PN_stdfloat) p1->sa * zz;
170  p1->tza= (PN_stdfloat) p1->ta * zz;
171  zz=(PN_stdfloat) p2->z;
172  p2->sza= (PN_stdfloat) p2->sa * zz;
173  p2->tza= (PN_stdfloat) p2->ta * zz;
174 
175  d1 = p1->sza - p0->sza;
176  d2 = p2->sza - p0->sza;
177  dszadx = (fdy2 * d1 - fdy1 * d2);
178  dszady = (fdx1 * d2 - fdx2 * d1);
179 
180  d1 = p1->tza - p0->tza;
181  d2 = p2->tza - p0->tza;
182  dtzadx = (fdy2 * d1 - fdy1 * d2);
183  dtzady = (fdx1 * d2 - fdx2 * d1);
184  }
185 #endif
186 
187 #ifdef INTERP_STZB
188  {
189  PN_stdfloat zz;
190  zz=(PN_stdfloat) p0->z;
191  p0->szb= (PN_stdfloat) p0->sb * zz;
192  p0->tzb= (PN_stdfloat) p0->tb * zz;
193  zz=(PN_stdfloat) p1->z;
194  p1->szb= (PN_stdfloat) p1->sb * zz;
195  p1->tzb= (PN_stdfloat) p1->tb * zz;
196  zz=(PN_stdfloat) p2->z;
197  p2->szb= (PN_stdfloat) p2->sb * zz;
198  p2->tzb= (PN_stdfloat) p2->tb * zz;
199 
200  d1 = p1->szb - p0->szb;
201  d2 = p2->szb - p0->szb;
202  dszbdx = (fdy2 * d1 - fdy1 * d2);
203  dszbdy = (fdx1 * d2 - fdx2 * d1);
204 
205  d1 = p1->tzb - p0->tzb;
206  d2 = p2->tzb - p0->tzb;
207  dtzbdx = (fdy2 * d1 - fdy1 * d2);
208  dtzbdy = (fdx1 * d2 - fdx2 * d1);
209  }
210 #endif
211 
212  /* screen coordinates */
213 
214  pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y);
215  pz1 = zb->zbuf + p0->y * zb->xsize;
216 
217  DRAW_INIT();
218 
219  for(part=0;part<2;part++) {
220  if (part == 0) {
221  if (fz > 0) {
222  update_left=1;
223  update_right=1;
224  l1=p0;
225  l2=p2;
226  pr1=p0;
227  pr2=p1;
228  } else {
229  update_left=1;
230  update_right=1;
231  l1=p0;
232  l2=p1;
233  pr1=p0;
234  pr2=p2;
235  }
236  nb_lines = p1->y - p0->y;
237  } else {
238  /* second part */
239  if (fz > 0) {
240  update_left=0;
241  update_right=1;
242  pr1=p1;
243  pr2=p2;
244  } else {
245  update_left=1;
246  update_right=0;
247  l1=p1;
248  l2=p2;
249  }
250  nb_lines = p2->y - p1->y + 1;
251  }
252 
253  /* compute the values for the left edge */
254 
255  if (update_left) {
256  dy1 = l2->y - l1->y;
257  dx1 = l2->x - l1->x;
258  if (dy1 > 0)
259  tmp = (dx1 << 16) / dy1;
260  else
261  tmp = 0;
262  x1 = l1->x;
263  error = 0;
264  derror = tmp & 0x0000ffff;
265  dxdy_min = tmp >> 16;
266  dxdy_max = dxdy_min + 1;
267 
268 #ifdef INTERP_Z
269  z1=l1->z;
270  dzdl_min=(dzdy + dzdx * dxdy_min);
271  dzdl_max=dzdl_min + dzdx;
272 #endif
273 #ifdef INTERP_RGB
274  r1=l1->r;
275  drdl_min=(drdy + drdx * dxdy_min);
276  drdl_max=drdl_min + drdx;
277 
278  g1=l1->g;
279  dgdl_min=(dgdy + dgdx * dxdy_min);
280  dgdl_max=dgdl_min + dgdx;
281 
282  b1=l1->b;
283  dbdl_min=(dbdy + dbdx * dxdy_min);
284  dbdl_max=dbdl_min + dbdx;
285 
286  a1=l1->a;
287  dadl_min=(dady + dadx * dxdy_min);
288  dadl_max=dadl_min + dadx;
289 #endif
290 #ifdef INTERP_ST
291  s1=l1->s;
292  dsdl_min=(dsdy + dsdx * dxdy_min);
293  dsdl_max=dsdl_min + dsdx;
294 
295  t1=l1->t;
296  dtdl_min=(dtdy + dtdx * dxdy_min);
297  dtdl_max=dtdl_min + dtdx;
298 #endif
299 #ifdef INTERP_STZ
300  sz1=l1->sz;
301  dszdl_min=(dszdy + dszdx * dxdy_min);
302  dszdl_max=dszdl_min + dszdx;
303 
304  tz1=l1->tz;
305  dtzdl_min=(dtzdy + dtzdx * dxdy_min);
306  dtzdl_max=dtzdl_min + dtzdx;
307 #endif
308 #ifdef INTERP_STZA
309  sza1=l1->sza;
310  dszadl_min=(dszady + dszadx * dxdy_min);
311  dszadl_max=dszadl_min + dszadx;
312 
313  tza1=l1->tza;
314  dtzadl_min=(dtzady + dtzadx * dxdy_min);
315  dtzadl_max=dtzadl_min + dtzadx;
316 #endif
317 #ifdef INTERP_STZB
318  szb1=l1->szb;
319  dszbdl_min=(dszbdy + dszbdx * dxdy_min);
320  dszbdl_max=dszbdl_min + dszbdx;
321 
322  tzb1=l1->tzb;
323  dtzbdl_min=(dtzbdy + dtzbdx * dxdy_min);
324  dtzbdl_max=dtzbdl_min + dtzbdx;
325 #endif
326  }
327 
328  /* compute values for the right edge */
329 
330  if (update_right) {
331  dx2 = (pr2->x - pr1->x);
332  dy2 = (pr2->y - pr1->y);
333  if (dy2>0)
334  dx2dy2 = ( dx2 << 16) / dy2;
335  else
336  dx2dy2 = 0;
337  x2 = pr1->x << 16;
338  }
339 
340  /* we draw all the scan line of the part */
341 
342  while (nb_lines>0) {
343  nb_lines--;
344 #ifndef DRAW_LINE
345  /* generic draw line */
346  {
347  PIXEL *pp;
348  int n;
349 #ifdef INTERP_Z
350  ZPOINT *pz;
351  unsigned int z,zz;
352 #endif
353 #ifdef INTERP_RGB
354  unsigned int or1,og1,ob1,oa1;
355 #endif
356 #ifdef INTERP_ST
357  unsigned int s,t;
358 #endif
359 #ifdef INTERP_STZ
360  PN_stdfloat sz,tz;
361 #endif
362 #ifdef INTERP_STZA
363  PN_stdfloat sza,tza;
364 #endif
365 #ifdef INTERP_STZB
366  PN_stdfloat szb,tzb;
367 #endif
368 
369  n=(x2 >> 16) - x1;
370  pp=(PIXEL *)((char *)pp1 + x1 * PSZB);
371 #ifdef INTERP_Z
372  pz=pz1+x1;
373  z=z1;
374 #endif
375 #ifdef INTERP_RGB
376  or1 = r1;
377  og1 = g1;
378  ob1 = b1;
379  oa1 = a1;
380 #endif
381 #ifdef INTERP_ST
382  s=s1;
383  t=t1;
384 #endif
385 #ifdef INTERP_STZ
386  sz=sz1;
387  tz=tz1;
388 #endif
389 #ifdef INTERP_STZA
390  sza=sza1;
391  tza=tza1;
392 #endif
393 #ifdef INTERP_STZB
394  szb=szb1;
395  tzb=tzb1;
396 #endif
397  while (n>=3) {
398  PUT_PIXEL(0);
399  PUT_PIXEL(1);
400  PUT_PIXEL(2);
401  PUT_PIXEL(3);
402 #ifdef INTERP_Z
403  pz+=4;
404 #endif
405  pp=(PIXEL *)((char *)pp + 4 * PSZB);
406  n-=4;
407  }
408  while (n>=0) {
409  PUT_PIXEL(0);
410 #ifdef INTERP_Z
411  pz+=1;
412 #endif
413  pp=(PIXEL *)((char *)pp + PSZB);
414  n-=1;
415  }
416  }
417 #else
418  DRAW_LINE();
419 #endif
420 
421  /* left edge */
422  error+=derror;
423  if (error > 0) {
424  error-=0x10000;
425  x1+=dxdy_max;
426 #ifdef INTERP_Z
427  z1+=dzdl_max;
428 #endif
429 #ifdef INTERP_RGB
430  r1+=drdl_max;
431  g1+=dgdl_max;
432  b1+=dbdl_max;
433  a1+=dadl_max;
434 #endif
435 #ifdef INTERP_ST
436  s1+=dsdl_max;
437  t1+=dtdl_max;
438 #endif
439 #ifdef INTERP_STZ
440  sz1+=dszdl_max;
441  tz1+=dtzdl_max;
442 #endif
443 #ifdef INTERP_STZA
444  sza1+=dszadl_max;
445  tza1+=dtzadl_max;
446 #endif
447 #ifdef INTERP_STZB
448  szb1+=dszbdl_max;
449  tzb1+=dtzbdl_max;
450 #endif
451  } else {
452  x1+=dxdy_min;
453 #ifdef INTERP_Z
454  z1+=dzdl_min;
455 #endif
456 #ifdef INTERP_RGB
457  r1+=drdl_min;
458  g1+=dgdl_min;
459  b1+=dbdl_min;
460  a1+=dadl_min;
461 #endif
462 #ifdef INTERP_ST
463  s1+=dsdl_min;
464  t1+=dtdl_min;
465 #endif
466 #ifdef INTERP_STZ
467  sz1+=dszdl_min;
468  tz1+=dtzdl_min;
469 #endif
470 #ifdef INTERP_STZA
471  sza1+=dszadl_min;
472  tza1+=dtzadl_min;
473 #endif
474 #ifdef INTERP_STZB
475  szb1+=dszbdl_min;
476  tzb1+=dtzbdl_min;
477 #endif
478  }
479 
480  /* right edge */
481  x2+=dx2dy2;
482 
483  /* screen coordinates */
484  pp1=(PIXEL *)((char *)pp1 + zb->linesize);
485  pz1+=zb->xsize;
486  }
487  }
488 }
489 
490 #undef INTERP_Z
491 #undef INTERP_RGB
492 #undef INTERP_ST
493 #undef INTERP_STZ
494 #undef INTERP_STZA
495 #undef INTERP_STZB
496 
497 #undef EARLY_OUT
498 #undef EARLY_OUT_FZ
499 #undef DRAW_INIT
500 #undef DRAW_LINE
501 #undef PUT_PIXEL
502 #undef PIXEL_COUNT