version 2.8
ztriangle.h
1 /*
2  * We draw a triangle with various interpolations
3  */
4 
5 {
6  ZBufferPoint *t,*pr1,*pr2,*l1,*l2;
7  float fdx1, fdx2, fdy1, fdy2, fz, d1, d2;
8  unsigned short *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,dzdx,dzdy,dzdl_min,dzdl_max;
21 #endif
22 #ifdef INTERP_RGB
23  int r1,drdx,drdy,drdl_min,drdl_max;
24  int g1,dgdx,dgdy,dgdl_min,dgdl_max;
25  int b1,dbdx,dbdy,dbdl_min,dbdl_max;
26 #endif
27 #ifdef INTERP_ST
28  int s1,dsdx,dsdy,dsdl_min,dsdl_max;
29  int t1,dtdx,dtdy,dtdl_min,dtdl_max;
30 #endif
31 #ifdef INTERP_STZ
32  float sz1,dszdx,dszdy,dszdl_min,dszdl_max;
33  float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max;
34 #endif
35 
36  /* we sort the vertex with increasing y */
37  if (p1->y < p0->y) {
38  t = p0;
39  p0 = p1;
40  p1 = t;
41  }
42  if (p2->y < p0->y) {
43  t = p2;
44  p2 = p1;
45  p1 = p0;
46  p0 = t;
47  } else if (p2->y < p1->y) {
48  t = p1;
49  p1 = p2;
50  p2 = t;
51  }
52 
53  /* we compute dXdx and dXdy for all interpolated values */
54 
55  fdx1 = p1->x - p0->x;
56  fdy1 = p1->y - p0->y;
57 
58  fdx2 = p2->x - p0->x;
59  fdy2 = p2->y - p0->y;
60 
61  fz = fdx1 * fdy2 - fdx2 * fdy1;
62  if (fz == 0)
63  return;
64  fz = 1.0 / fz;
65 
66  fdx1 *= fz;
67  fdy1 *= fz;
68  fdx2 *= fz;
69  fdy2 *= fz;
70 
71 #ifdef INTERP_Z
72  d1 = p1->z - p0->z;
73  d2 = p2->z - p0->z;
74  dzdx = (int) (fdy2 * d1 - fdy1 * d2);
75  dzdy = (int) (fdx1 * d2 - fdx2 * d1);
76 #endif
77 
78 #ifdef INTERP_RGB
79  d1 = p1->r - p0->r;
80  d2 = p2->r - p0->r;
81  drdx = (int) (fdy2 * d1 - fdy1 * d2);
82  drdy = (int) (fdx1 * d2 - fdx2 * d1);
83 
84  d1 = p1->g - p0->g;
85  d2 = p2->g - p0->g;
86  dgdx = (int) (fdy2 * d1 - fdy1 * d2);
87  dgdy = (int) (fdx1 * d2 - fdx2 * d1);
88 
89  d1 = p1->b - p0->b;
90  d2 = p2->b - p0->b;
91  dbdx = (int) (fdy2 * d1 - fdy1 * d2);
92  dbdy = (int) (fdx1 * d2 - fdx2 * d1);
93 
94 #endif
95 
96 #ifdef INTERP_ST
97  d1 = p1->s - p0->s;
98  d2 = p2->s - p0->s;
99  dsdx = (int) (fdy2 * d1 - fdy1 * d2);
100  dsdy = (int) (fdx1 * d2 - fdx2 * d1);
101 
102  d1 = p1->t - p0->t;
103  d2 = p2->t - p0->t;
104  dtdx = (int) (fdy2 * d1 - fdy1 * d2);
105  dtdy = (int) (fdx1 * d2 - fdx2 * d1);
106 #endif
107 
108 #ifdef INTERP_STZ
109  {
110  float zz;
111  zz=(float) p0->z;
112  p0->sz= (float) p0->s * zz;
113  p0->tz= (float) p0->t * zz;
114  zz=(float) p1->z;
115  p1->sz= (float) p1->s * zz;
116  p1->tz= (float) p1->t * zz;
117  zz=(float) p2->z;
118  p2->sz= (float) p2->s * zz;
119  p2->tz= (float) p2->t * zz;
120 
121  d1 = p1->sz - p0->sz;
122  d2 = p2->sz - p0->sz;
123  dszdx = (fdy2 * d1 - fdy1 * d2);
124  dszdy = (fdx1 * d2 - fdx2 * d1);
125 
126  d1 = p1->tz - p0->tz;
127  d2 = p2->tz - p0->tz;
128  dtzdx = (fdy2 * d1 - fdy1 * d2);
129  dtzdy = (fdx1 * d2 - fdx2 * d1);
130  }
131 #endif
132 
133  /* screen coordinates */
134 
135  pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y);
136  pz1 = zb->zbuf + p0->y * zb->xsize;
137 
138  DRAW_INIT();
139 
140  for(part=0;part<2;part++) {
141  if (part == 0) {
142  if (fz > 0) {
143  update_left=1;
144  update_right=1;
145  l1=p0;
146  l2=p2;
147  pr1=p0;
148  pr2=p1;
149  } else {
150  update_left=1;
151  update_right=1;
152  l1=p0;
153  l2=p1;
154  pr1=p0;
155  pr2=p2;
156  }
157  nb_lines = p1->y - p0->y;
158  } else {
159  /* second part */
160  if (fz > 0) {
161  update_left=0;
162  update_right=1;
163  pr1=p1;
164  pr2=p2;
165  } else {
166  update_left=1;
167  update_right=0;
168  l1=p1;
169  l2=p2;
170  }
171  nb_lines = p2->y - p1->y + 1;
172  }
173 
174  /* compute the values for the left edge */
175 
176  if (update_left) {
177  dy1 = l2->y - l1->y;
178  dx1 = l2->x - l1->x;
179  if (dy1 > 0)
180  tmp = (dx1 << 16) / dy1;
181  else
182  tmp = 0;
183  x1 = l1->x;
184  error = 0;
185  derror = tmp & 0x0000ffff;
186  dxdy_min = tmp >> 16;
187  dxdy_max = dxdy_min + 1;
188 
189 #ifdef INTERP_Z
190  z1=l1->z;
191  dzdl_min=(dzdy + dzdx * dxdy_min);
192  dzdl_max=dzdl_min + dzdx;
193 #endif
194 #ifdef INTERP_RGB
195  r1=l1->r;
196  drdl_min=(drdy + drdx * dxdy_min);
197  drdl_max=drdl_min + drdx;
198 
199  g1=l1->g;
200  dgdl_min=(dgdy + dgdx * dxdy_min);
201  dgdl_max=dgdl_min + dgdx;
202 
203  b1=l1->b;
204  dbdl_min=(dbdy + dbdx * dxdy_min);
205  dbdl_max=dbdl_min + dbdx;
206 #endif
207 #ifdef INTERP_ST
208  s1=l1->s;
209  dsdl_min=(dsdy + dsdx * dxdy_min);
210  dsdl_max=dsdl_min + dsdx;
211 
212  t1=l1->t;
213  dtdl_min=(dtdy + dtdx * dxdy_min);
214  dtdl_max=dtdl_min + dtdx;
215 #endif
216 #ifdef INTERP_STZ
217  sz1=l1->sz;
218  dszdl_min=(dszdy + dszdx * dxdy_min);
219  dszdl_max=dszdl_min + dszdx;
220 
221  tz1=l1->tz;
222  dtzdl_min=(dtzdy + dtzdx * dxdy_min);
223  dtzdl_max=dtzdl_min + dtzdx;
224 #endif
225  }
226 
227  /* compute values for the right edge */
228 
229  if (update_right) {
230  dx2 = (pr2->x - pr1->x);
231  dy2 = (pr2->y - pr1->y);
232  if (dy2>0)
233  dx2dy2 = ( dx2 << 16) / dy2;
234  else
235  dx2dy2 = 0;
236  x2 = pr1->x << 16;
237  }
238 
239  /* we draw all the scan line of the part */
240 
241  while (nb_lines>0) {
242  nb_lines--;
243 #ifndef DRAW_LINE
244  /* generic draw line */
245  {
246  register PIXEL *pp;
247  register int n;
248 #ifdef INTERP_Z
249  register unsigned short *pz;
250  register unsigned int z,zz;
251 #endif
252 #ifdef INTERP_RGB
253  register unsigned int or1,og1,ob1;
254 #endif
255 #ifdef INTERP_ST
256  register unsigned int s,t;
257 #endif
258 #ifdef INTERP_STZ
259  float sz,tz;
260 #endif
261 
262  n=(x2 >> 16) - x1;
263  pp=(PIXEL *)((char *)pp1 + x1 * PSZB);
264 #ifdef INTERP_Z
265  pz=pz1+x1;
266  z=z1;
267 #endif
268 #ifdef INTERP_RGB
269  or1 = r1;
270  og1 = g1;
271  ob1 = b1;
272 #endif
273 #ifdef INTERP_ST
274  s=s1;
275  t=t1;
276 #endif
277 #ifdef INTERP_STZ
278  sz=sz1;
279  tz=tz1;
280 #endif
281  while (n>=3) {
282  PUT_PIXEL(0);
283  PUT_PIXEL(1);
284  PUT_PIXEL(2);
285  PUT_PIXEL(3);
286 #ifdef INTERP_Z
287  pz+=4;
288 #endif
289  pp=(PIXEL *)((char *)pp + 4 * PSZB);
290  n-=4;
291  }
292  while (n>=0) {
293  PUT_PIXEL(0);
294 #ifdef INTERP_Z
295  pz+=1;
296 #endif
297  pp=(PIXEL *)((char *)pp + PSZB);
298  n-=1;
299  }
300  }
301 #else
302  DRAW_LINE();
303 #endif
304 
305  /* left edge */
306  error+=derror;
307  if (error > 0) {
308  error-=0x10000;
309  x1+=dxdy_max;
310 #ifdef INTERP_Z
311  z1+=dzdl_max;
312 #endif
313 #ifdef INTERP_RGB
314  r1+=drdl_max;
315  g1+=dgdl_max;
316  b1+=dbdl_max;
317 #endif
318 #ifdef INTERP_ST
319  s1+=dsdl_max;
320  t1+=dtdl_max;
321 #endif
322 #ifdef INTERP_STZ
323  sz1+=dszdl_max;
324  tz1+=dtzdl_max;
325 #endif
326  } else {
327  x1+=dxdy_min;
328 #ifdef INTERP_Z
329  z1+=dzdl_min;
330 #endif
331 #ifdef INTERP_RGB
332  r1+=drdl_min;
333  g1+=dgdl_min;
334  b1+=dbdl_min;
335 #endif
336 #ifdef INTERP_ST
337  s1+=dsdl_min;
338  t1+=dtdl_min;
339 #endif
340 #ifdef INTERP_STZ
341  sz1+=dszdl_min;
342  tz1+=dtzdl_min;
343 #endif
344  }
345 
346  /* right edge */
347  x2+=dx2dy2;
348 
349  /* screen coordinates */
350  pp1=(PIXEL *)((char *)pp1 + zb->linesize);
351  pz1+=zb->xsize;
352  }
353  }
354 }
355 
356 #undef INTERP_Z
357 #undef INTERP_RGB
358 #undef INTERP_ST
359 #undef INTERP_STZ
360 
361 #undef DRAW_INIT
362 #undef DRAW_LINE
363 #undef PUT_PIXEL