1 /*
2 
3     3DKIT   version   1.3
4     High speed 3D graphics and rendering library for Linux.
5 
6     Copyright (C) 1996, 1997  Paul Sheer   psheer@icon.co.za
7 
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17 
18     You should have received a copy of the GNU Library General Public
19     License along with this library; if not, write to the Free
20     Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21     MA 02111-1307, USA
22 
23 */
24 
25 
26 #ifdef WRAP
27 #ifdef INTERP
gl_wtriangle(int x0,int y0,int xd0,int yd0,int z0,int x1,int y1,int xd1,int yd1,int z1,int x2,int y2,int xd2,int yd2,int z2,TD_tridata * tri)28 void gl_wtriangle (int x0, int y0, int xd0, int yd0, int z0,
29 		   int x1, int y1, int xd1, int yd1, int z1,
30 		   int x2, int y2, int xd2, int yd2, int z2,
31 		   TD_tridata * tri)
32 #else
33 void gl_swtriangle (int x0, int y0, int xd0, int yd0,
34 		    int x1, int y1, int xd1, int yd1,
35 		    int x2, int y2, int xd2, int yd2, int z0,
36 		    TD_tridata * tri)
37 #endif
38 #else
39 #ifdef INTERP
40 void gl_triangle (int x0, int y0, int z0,
41 		  int x1, int y1, int z1,
42 		  int x2, int y2, int z2, int bf)
43 #else
44 void gl_striangle (int x0, int y0,
45 		   int x1, int y1,
46 		   int x2, int y2, int z0, int bf)
47 #endif
48 #endif
49 {
50     void (*colhline_pos) (void);
51     void (*colhline_neg) (void);
52 
53     int dir;
54     long X;
55 
56     long nz;
57     long g0, g1h = 0, g1l = 0;
58 #ifdef INTERP
59     long c0;
60     long c_y;
61 #endif
62 #ifdef WRAP
63     long X0, Y0;
64     int bf = tri->bf;
65     long xd_y, yd_y;
66 #endif
67 
68     dir = 1;
69 
70 /*Max triangle size in the order of (2^31) >> SHLB)^(.5) : */
71 
72     if ((nz = (x0 - x1) * (y0 - y2) - (y0 - y1) * (x0 - x2)) == 0)
73 	return;			/*the points are collinear. */
74 
75 #ifdef INTERP
76     c_x = -(((y0 - y1) * (z0 - z2) - (z0 - z1) * (y0 - y2)) << SHLB) / nz;
77     c_y = -(((z0 - z1) * (x0 - x2) - (x0 - x1) * (z0 - z2)) << SHLB) / nz;
78 #endif
79 
80 #ifdef WRAP
81     xd_x = -(((y0 - y1) * (xd0 - xd2) - (xd0 - xd1) * (y0 - y2)) << SHLB) / nz;
82     xd_y = -(((xd0 - xd1) * (x0 - x2) - (x0 - x1) * (xd0 - xd2)) << SHLB) / nz;
83 
84     yd_x = -(((y0 - y1) * (yd0 - yd2) - (yd0 - yd1) * (y0 - y2)) << SHLB) / nz;
85     yd_y = -(((yd0 - yd1) * (x0 - x2) - (x0 - x1) * (yd0 - yd2)) << SHLB) / nz;
86 #endif
87 
88 #ifdef INTERP
89     if ((abs (c_x) > (6 << SHLB)) || (abs (c_y) > (6 << SHLB))) {
90 	int tz0, tz1;
91 
92 	/*so that high colour gradients don't screw up at the edges. */
93 	/*4 is the maximum gradient per pixel. */
94 
95 	c_x >>= 2;
96 	c_y >>= 2;
97 	tz0 = ((2 * z0 + z1 + z2) << SHLB) / 4;
98 	tz1 = ((z0 + 2 * z1 + z2) << SHLB) / 4;
99 	z2 = ((z0 + z1 + 2 * z2) << SHLB) / 4;
100 	z0 = tz0;
101 	z1 = tz1;
102     } else {
103 	z0 <<= SHLB;
104 	z1 <<= SHLB;
105 	z2 <<= SHLB;
106     }
107 #endif
108 
109 /************** BOOLEAN LOGIC HERE ************/
110 /* The following allows a triangle to have a different picture on either side */
111 /* To print triangles that don't appear when viewed from behind use bf = 0|1  */
112 /* To print triangles that appear with a different picture when viewed from   */
113 /*   behind use bf = 2|3                                                      */
114 
115 #ifdef WRAP
116     dat = tri->bitmap1;
117     if (nz > 0) {		/* nz is the cross product of the vectors of the two sides
118 				   it indicates whether the points were ordered clockwise
119 				   or anti-clockwise (you can find out which way by testing) */
120 	if (bf == 1)
121 	    return;
122 	if (bf == 3)
123 	    dat = tri->bitmap1;
124 	dir++;
125     } else {
126 	if (!bf)
127 	    return;
128 	if (bf == 2)
129 	    dat = tri->bitmap2;
130     }
131 #else
132     if (nz > 0) {
133 	if (bf == 1)
134 	    return;
135 	dir++;
136     } else {
137 	if (!bf)
138 	    return;
139     }
140 #endif
141 
142 #define Xchg(a,b) {X=(a);(a)=(b);(b)=X;}
143 
144     if (y1 < y0) {
145 	Xchg (y0, y1);
146 	Xchg (x0, x1);
147 #ifdef INTERP
148 	Xchg (z0, z1);
149 #endif
150 #ifdef WRAP
151 	Xchg (xd0, xd1);
152 	Xchg (yd0, yd1);
153 #endif
154 	dir++;
155     }
156     if (y2 < y1) {
157 	Xchg (y2, y1);
158 	Xchg (x2, x1);
159 #ifdef INTERP
160 	Xchg (z2, z1);
161 #endif
162 #ifdef WRAP
163 	Xchg (xd2, xd1);
164 	Xchg (yd2, yd1);
165 #endif
166 
167 	dir++;
168     }
169     if (y1 < y0) {
170 	Xchg (y0, y1);
171 	Xchg (x0, x1);
172 #ifdef INTERP
173 	Xchg (z0, z1);
174 #endif
175 #ifdef WRAP
176 	Xchg (xd0, xd1);
177 	Xchg (yd0, yd1);
178 #endif
179 	dir++;
180     }
181     _color_lookup = color_lookup;
182 #ifdef INTERP
183     c0 = z0;
184 #else
185     if(BYTESPERPIXEL == 1) {
186 	c = z0;
187     } else {
188 	c = _color_lookup[z0];
189     }
190 #endif
191 
192 #ifdef WRAP
193     X0 = xd0 << SHLB;
194     Y0 = yd0 << SHLB;
195 #endif
196 
197     if (y2 == y0)
198 	return;
199     g0 = ((long) (x2 - x0) << SHLB) / (y2 - y0);
200     if (y1 != y0)
201 	g1h = ((long) (x1 - x0) << SHLB) / (y1 - y0);
202     if (y2 != y1)
203 	g1l = ((long) (x2 - x1) << SHLB) / (y2 - y1);
204 
205     dir = dir & 1;
206 
207 
208 /* Very large triangles (larger than the screen) sometimes become a problem,
209    if so: */
210     if (__clip) {
211 	if (((abs (x0 - x1) + abs (x1 - x2) + abs (x0 - x2)) >
212 	     ((__clipx2 - __clipx1) * 2)) || ((y2 - y0) > (__clipy2 - __clipy1)))
213 	    return;
214 	if (y2 < __clipy1 || y0 > __clipy2 ||
215 	    (x0 < __clipx1 && x1 < __clipx1 && x2 < __clipx1) ||
216 	    (x0 > __clipx2 && x1 > __clipx2 && x2 > __clipx2))
217 	    return;
218     }
219     dx0 = x0;
220     dy0 = y0;
221 
222     if(tri_drawpoint) {
223 	_tri_drawpoint = tri_drawpoint;
224 	colhline_pos = linefuncs[(7 * 2) + (BYTESPERPIXEL - 1) * 16];
225 	colhline_neg = linefuncs[(7 * 2) + (BYTESPERPIXEL - 1) * 16 + 1];
226     } else {
227 	_tri_drawpoint = gl_setpixel;
228 	colhline_pos = linefuncs[(MODETYPE * 2) + (BYTESPERPIXEL - 1) * 16];
229 	colhline_neg = linefuncs[(MODETYPE * 2) + (BYTESPERPIXEL - 1) * 16 + 1];
230     }
231 
232 #ifdef tri_set_color
233 #undef tri_set_color
234 #endif
235 
236 
237 
238 #ifdef WRAP
239 #ifdef INTERP
240 #define tri_set_color \
241 		xd = X0 + xd_x * px1 + xd_y * py; \
242 		yd = Y0 + yd_x * px1 + yd_y * py; \
243 		c = c0 + c_x * px1 + c_y * py;
244 #else
245 #define tri_set_color \
246 		xd = X0 + xd_x * px1 + xd_y * py; \
247 		yd = Y0 + yd_x * px1 + yd_y * py;
248 #endif
249 #else
250 #ifdef INTERP
251 #define tri_set_color \
252 		c = c0 + c_x * px1 + c_y * py;
253 #else
254 #define tri_set_color
255 #endif
256 #endif
257 
258     if (dir == 1) {
259 	if (y1 != y0) {
260 	    py = 0;
261 	    if (x1 < x0) {
262 		px1 = 0;
263 		px2 = -((abs (g1h) >> 1)) >> SHLB;
264 	    } else {
265 		px1 = ((abs (g0) >> 1)) >> SHLB;
266 		px2 = 0;
267 	    }
268 	    tri_set_color;
269 
270 	    colhline_neg ();
271 	    if ((py = 1) < y1 - y0)
272 		for (; py < y1 - y0; py++) {
273 		    px1 = ((g0 * py) + (abs (g0) >> 1)) >> SHLB;
274 		    px2 = ((g1h * py) - (abs (g1h) >> 1)) >> SHLB;
275 		    tri_set_color;
276 
277 		    colhline_neg ();
278 		}
279 	    px1 = min (((g0 * py) + (abs (g0) >> 1)) >> SHLB, max (x2, x0) - x0);
280 	    px2 = x1 - x0;
281 	    tri_set_color;
282 	    colhline_neg ();
283 	} else {
284 	    py = 0;
285 	    px1 = 0;
286 	    px2 = x1 - x0;
287 	    tri_set_color;
288 
289 	    colhline_neg ();
290 	}
291 	if (y1 != y2) {
292 	    if ((py = y1 - y0 + 1) < y2 - y0)
293 		for (; py < y2 - y0; py++) {
294 		    px1 = ((g0 * py) + (abs (g0) >> 1)) >> SHLB;
295 		    px2 = (((g1l * (py - y1 + y0)) - (abs (g1l) >> 1)) >> SHLB) + x1 - x0;
296 		    tri_set_color;
297 
298 		    colhline_neg ();
299 		}
300 	    if (x1 < x2) {
301 		px1 = x2 - x0;
302 		px2 = x2 - x0 - ((abs (g1l) >> 1) >> SHLB);
303 	    } else {
304 		px1 = x2 - x0 + ((abs (g0) >> 1) >> SHLB);
305 		px2 = x2 - x0;
306 	    }
307 	    tri_set_color;
308 
309 	    colhline_neg ();
310 	}
311     } else {
312 	if (y1 != y0) {
313 	    py = 0;
314 	    if (x1 > x0) {
315 		px1 = 0;
316 		px2 = ((abs (g1h) >> 1)) >> SHLB;
317 	    } else {
318 		px1 = -((abs (g0) >> 1)) >> SHLB;
319 		px2 = 0;
320 	    }
321 	    tri_set_color;
322 
323 	    colhline_pos ();
324 	    if ((py = 1) < y1 - y0)
325 		for (; py < y1 - y0; py++) {
326 		    px1 = ((g0 * py) - (abs (g0) >> 1)) >> SHLB;
327 		    px2 = ((g1h * py) + (abs (g1h) >> 1)) >> SHLB;
328 		    tri_set_color;
329 
330 		    colhline_pos ();
331 		}
332 	    px1 = max (((g0 * py) - (abs (g0) >> 1)) >> SHLB, min (x2, x0) - x0);
333 	    px2 = x1 - x0;
334 	    tri_set_color;
335 	    colhline_pos ();
336 	} else {
337 	    py = 0;
338 	    px1 = 0;
339 	    px2 = x1 - x0;
340 	    tri_set_color;
341 	    colhline_pos ();
342 	}
343 	if (y1 != y2) {
344 	    if ((py = y1 - y0 + 1) < y2 - y0)
345 		for (; py < y2 - y0; py++) {
346 		    px1 = ((g0 * py) - (abs (g0) >> 1)) >> SHLB;
347 		    px2 = (((g1l * (py - y1 + y0)) + (abs (g1l) >> 1)) >> SHLB) + x1 - x0;
348 		    tri_set_color;
349 
350 		    colhline_pos ();
351 		}
352 	    if (x1 > x2) {
353 		px1 = x2 - x0;
354 		px2 = x2 - x0 + ((abs (g1l) >> 1) >> SHLB);
355 	    } else {
356 		px1 = x2 - x0 - ((abs (g0) >> 1) >> SHLB);
357 		px2 = x2 - x0;
358 	    }
359 
360 	    tri_set_color;
361 
362 	    colhline_pos ();
363 	}
364     }
365 }
366