Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | Copyright (C) 1996-1997 Id Software, Inc. |
||
3 | |||
4 | This program is free software; you can redistribute it and/or |
||
5 | modify it under the terms of the GNU General Public License |
||
6 | as published by the Free Software Foundation; either version 2 |
||
7 | of the License, or (at your option) any later version. |
||
8 | |||
9 | This program is distributed in the hope that it will be useful, |
||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | |||
13 | See the GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
18 | |||
19 | */ |
||
20 | // d_polyset.c: routines for drawing sets of polygons sharing the same |
||
21 | // texture (used for Alias models) |
||
22 | |||
23 | #include "quakedef.h" |
||
24 | #include "r_local.h" |
||
25 | #include "d_local.h" |
||
26 | |||
27 | // TODO: put in span spilling to shrink list size |
||
28 | // !!! if this is changed, it must be changed in d_polysa.s too !!! |
||
29 | #define DPS_MAXSPANS MAXHEIGHT+1 |
||
30 | // 1 extra for spanpackage that marks end |
||
31 | |||
32 | // !!! if this is changed, it must be changed in asm_draw.h too !!! |
||
33 | typedef struct { |
||
34 | void *pdest; |
||
35 | short *pz; |
||
36 | int count; |
||
37 | byte *ptex; |
||
38 | int sfrac, tfrac, light, zi; |
||
39 | } spanpackage_t; |
||
40 | |||
41 | typedef struct { |
||
42 | int isflattop; |
||
43 | int numleftedges; |
||
44 | int *pleftedgevert0; |
||
45 | int *pleftedgevert1; |
||
46 | int *pleftedgevert2; |
||
47 | int numrightedges; |
||
48 | int *prightedgevert0; |
||
49 | int *prightedgevert1; |
||
50 | int *prightedgevert2; |
||
51 | } edgetable; |
||
52 | |||
53 | int r_p0[6], r_p1[6], r_p2[6]; |
||
54 | |||
55 | byte *d_pcolormap; |
||
56 | |||
57 | int d_aflatcolor; |
||
58 | int d_xdenom; |
||
59 | |||
60 | edgetable *pedgetable; |
||
61 | |||
62 | edgetable edgetables[12] = { |
||
63 | {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, |
||
64 | {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, |
||
65 | {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, |
||
66 | {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, |
||
67 | {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, |
||
68 | {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, |
||
69 | {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, |
||
70 | {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, |
||
71 | {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, |
||
72 | {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, |
||
73 | {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, |
||
74 | {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, |
||
75 | }; |
||
76 | |||
77 | // FIXME: some of these can become statics |
||
78 | int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; |
||
79 | int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; |
||
80 | int r_zistepx, r_zistepy; |
||
81 | int d_aspancount, d_countextrastep; |
||
82 | |||
83 | spanpackage_t *a_spans; |
||
84 | spanpackage_t *d_pedgespanpackage; |
||
85 | static int ystart; |
||
86 | byte *d_pdest, *d_ptex; |
||
87 | short *d_pz; |
||
88 | int d_sfrac, d_tfrac, d_light, d_zi; |
||
89 | int d_ptexextrastep, d_sfracextrastep; |
||
90 | int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; |
||
91 | int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; |
||
92 | int d_sfracbasestep, d_tfracbasestep; |
||
93 | int d_ziextrastep, d_zibasestep; |
||
94 | int d_pzextrastep, d_pzbasestep; |
||
95 | |||
96 | typedef struct { |
||
97 | int quotient; |
||
98 | int remainder; |
||
99 | } adivtab_t; |
||
100 | |||
101 | static adivtab_t adivtab[32*32] = { |
||
102 | #include "adivtab.h" |
||
103 | }; |
||
104 | |||
105 | byte *skintable[MAX_LBM_HEIGHT]; |
||
106 | int skinwidth; |
||
107 | byte *skinstart; |
||
108 | |||
109 | void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage); |
||
110 | void D_PolysetCalcGradients (int skinwidth); |
||
111 | void D_DrawSubdiv (void); |
||
112 | void D_DrawNonSubdiv (void); |
||
113 | void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3); |
||
114 | void D_PolysetSetEdgeTable (void); |
||
115 | void D_RasterizeAliasPolySmooth (void); |
||
116 | void D_PolysetScanLeftEdge (int height); |
||
117 | |||
118 | #if !id386 |
||
119 | |||
120 | /* |
||
121 | ================ |
||
122 | D_PolysetDraw |
||
123 | ================ |
||
124 | */ |
||
125 | void D_PolysetDraw (void) |
||
126 | { |
||
127 | spanpackage_t spans[DPS_MAXSPANS + 1 + |
||
128 | ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1]; |
||
129 | // one extra because of cache line pretouching |
||
130 | |||
131 | a_spans = (spanpackage_t *) |
||
132 | (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); |
||
133 | |||
134 | if (r_affinetridesc.drawtype) |
||
135 | { |
||
136 | D_DrawSubdiv (); |
||
137 | } |
||
138 | else |
||
139 | { |
||
140 | D_DrawNonSubdiv (); |
||
141 | } |
||
142 | } |
||
143 | |||
144 | |||
145 | /* |
||
146 | ================ |
||
147 | D_PolysetDrawFinalVerts |
||
148 | ================ |
||
149 | */ |
||
150 | void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts) |
||
151 | { |
||
152 | int i, z; |
||
153 | short *zbuf; |
||
154 | |||
155 | for (i=0 ; i |
||
156 | { |
||
157 | // valid triangle coordinates for filling can include the bottom and |
||
158 | // right clip edges, due to the fill rule; these shouldn't be drawn |
||
159 | if ((fv->v[0] < r_refdef.vrectright) && |
||
160 | (fv->v[1] < r_refdef.vrectbottom)) |
||
161 | { |
||
162 | z = fv->v[5]>>16; |
||
163 | zbuf = zspantable[fv->v[1]] + fv->v[0]; |
||
164 | if (z >= *zbuf) |
||
165 | { |
||
166 | int pix; |
||
167 | |||
168 | *zbuf = z; |
||
169 | pix = skintable[fv->v[3]>>16][fv->v[2]>>16]; |
||
170 | pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ]; |
||
171 | d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix; |
||
172 | } |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | |||
177 | |||
178 | /* |
||
179 | ================ |
||
180 | D_DrawSubdiv |
||
181 | ================ |
||
182 | */ |
||
183 | void D_DrawSubdiv (void) |
||
184 | { |
||
185 | mtriangle_t *ptri; |
||
186 | finalvert_t *pfv, *index0, *index1, *index2; |
||
187 | int i; |
||
188 | int lnumtriangles; |
||
189 | |||
190 | pfv = r_affinetridesc.pfinalverts; |
||
191 | ptri = r_affinetridesc.ptriangles; |
||
192 | lnumtriangles = r_affinetridesc.numtriangles; |
||
193 | |||
194 | for (i=0 ; i |
||
195 | { |
||
196 | index0 = pfv + ptri[i].vertindex[0]; |
||
197 | index1 = pfv + ptri[i].vertindex[1]; |
||
198 | index2 = pfv + ptri[i].vertindex[2]; |
||
199 | |||
200 | if (((index0->v[1]-index1->v[1]) * |
||
201 | (index0->v[0]-index2->v[0]) - |
||
202 | (index0->v[0]-index1->v[0]) * |
||
203 | (index0->v[1]-index2->v[1])) >= 0) |
||
204 | { |
||
205 | continue; |
||
206 | } |
||
207 | |||
208 | d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00]; |
||
209 | |||
210 | if (ptri[i].facesfront) |
||
211 | { |
||
212 | D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); |
||
213 | } |
||
214 | else |
||
215 | { |
||
216 | int s0, s1, s2; |
||
217 | |||
218 | s0 = index0->v[2]; |
||
219 | s1 = index1->v[2]; |
||
220 | s2 = index2->v[2]; |
||
221 | |||
222 | if (index0->flags & ALIAS_ONSEAM) |
||
223 | index0->v[2] += r_affinetridesc.seamfixupX16; |
||
224 | if (index1->flags & ALIAS_ONSEAM) |
||
225 | index1->v[2] += r_affinetridesc.seamfixupX16; |
||
226 | if (index2->flags & ALIAS_ONSEAM) |
||
227 | index2->v[2] += r_affinetridesc.seamfixupX16; |
||
228 | |||
229 | D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); |
||
230 | |||
231 | index0->v[2] = s0; |
||
232 | index1->v[2] = s1; |
||
233 | index2->v[2] = s2; |
||
234 | } |
||
235 | } |
||
236 | } |
||
237 | |||
238 | |||
239 | /* |
||
240 | ================ |
||
241 | D_DrawNonSubdiv |
||
242 | ================ |
||
243 | */ |
||
244 | void D_DrawNonSubdiv (void) |
||
245 | { |
||
246 | mtriangle_t *ptri; |
||
247 | finalvert_t *pfv, *index0, *index1, *index2; |
||
248 | int i; |
||
249 | int lnumtriangles; |
||
250 | |||
251 | pfv = r_affinetridesc.pfinalverts; |
||
252 | ptri = r_affinetridesc.ptriangles; |
||
253 | lnumtriangles = r_affinetridesc.numtriangles; |
||
254 | |||
255 | for (i=0 ; i |
||
256 | { |
||
257 | index0 = pfv + ptri->vertindex[0]; |
||
258 | index1 = pfv + ptri->vertindex[1]; |
||
259 | index2 = pfv + ptri->vertindex[2]; |
||
260 | |||
261 | d_xdenom = (index0->v[1]-index1->v[1]) * |
||
262 | (index0->v[0]-index2->v[0]) - |
||
263 | (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]); |
||
264 | |||
265 | if (d_xdenom >= 0) |
||
266 | { |
||
267 | continue; |
||
268 | } |
||
269 | |||
270 | r_p0[0] = index0->v[0]; // u |
||
271 | r_p0[1] = index0->v[1]; // v |
||
272 | r_p0[2] = index0->v[2]; // s |
||
273 | r_p0[3] = index0->v[3]; // t |
||
274 | r_p0[4] = index0->v[4]; // light |
||
275 | r_p0[5] = index0->v[5]; // iz |
||
276 | |||
277 | r_p1[0] = index1->v[0]; |
||
278 | r_p1[1] = index1->v[1]; |
||
279 | r_p1[2] = index1->v[2]; |
||
280 | r_p1[3] = index1->v[3]; |
||
281 | r_p1[4] = index1->v[4]; |
||
282 | r_p1[5] = index1->v[5]; |
||
283 | |||
284 | r_p2[0] = index2->v[0]; |
||
285 | r_p2[1] = index2->v[1]; |
||
286 | r_p2[2] = index2->v[2]; |
||
287 | r_p2[3] = index2->v[3]; |
||
288 | r_p2[4] = index2->v[4]; |
||
289 | r_p2[5] = index2->v[5]; |
||
290 | |||
291 | if (!ptri->facesfront) |
||
292 | { |
||
293 | if (index0->flags & ALIAS_ONSEAM) |
||
294 | r_p0[2] += r_affinetridesc.seamfixupX16; |
||
295 | if (index1->flags & ALIAS_ONSEAM) |
||
296 | r_p1[2] += r_affinetridesc.seamfixupX16; |
||
297 | if (index2->flags & ALIAS_ONSEAM) |
||
298 | r_p2[2] += r_affinetridesc.seamfixupX16; |
||
299 | } |
||
300 | |||
301 | D_PolysetSetEdgeTable (); |
||
302 | D_RasterizeAliasPolySmooth (); |
||
303 | } |
||
304 | } |
||
305 | |||
306 | |||
307 | /* |
||
308 | ================ |
||
309 | D_PolysetRecursiveTriangle |
||
310 | ================ |
||
311 | */ |
||
312 | void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3) |
||
313 | { |
||
314 | int *temp; |
||
315 | int d; |
||
316 | int new[6]; |
||
317 | int z; |
||
318 | short *zbuf; |
||
319 | |||
320 | d = lp2[0] - lp1[0]; |
||
321 | if (d < -1 || d > 1) |
||
322 | goto split; |
||
323 | d = lp2[1] - lp1[1]; |
||
324 | if (d < -1 || d > 1) |
||
325 | goto split; |
||
326 | |||
327 | d = lp3[0] - lp2[0]; |
||
328 | if (d < -1 || d > 1) |
||
329 | goto split2; |
||
330 | d = lp3[1] - lp2[1]; |
||
331 | if (d < -1 || d > 1) |
||
332 | goto split2; |
||
333 | |||
334 | d = lp1[0] - lp3[0]; |
||
335 | if (d < -1 || d > 1) |
||
336 | goto split3; |
||
337 | d = lp1[1] - lp3[1]; |
||
338 | if (d < -1 || d > 1) |
||
339 | { |
||
340 | split3: |
||
341 | temp = lp1; |
||
342 | lp1 = lp3; |
||
343 | lp3 = lp2; |
||
344 | lp2 = temp; |
||
345 | |||
346 | goto split; |
||
347 | } |
||
348 | |||
349 | return; // entire tri is filled |
||
350 | |||
351 | split2: |
||
352 | temp = lp1; |
||
353 | lp1 = lp2; |
||
354 | lp2 = lp3; |
||
355 | lp3 = temp; |
||
356 | |||
357 | split: |
||
358 | // split this edge |
||
359 | new[0] = (lp1[0] + lp2[0]) >> 1; |
||
360 | new[1] = (lp1[1] + lp2[1]) >> 1; |
||
361 | new[2] = (lp1[2] + lp2[2]) >> 1; |
||
362 | new[3] = (lp1[3] + lp2[3]) >> 1; |
||
363 | new[5] = (lp1[5] + lp2[5]) >> 1; |
||
364 | |||
365 | // draw the point if splitting a leading edge |
||
366 | if (lp2[1] > lp1[1]) |
||
367 | goto nodraw; |
||
368 | if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) |
||
369 | goto nodraw; |
||
370 | |||
371 | |||
372 | z = new[5]>>16; |
||
373 | zbuf = zspantable[new[1]] + new[0]; |
||
374 | if (z >= *zbuf) |
||
375 | { |
||
376 | int pix; |
||
377 | |||
378 | *zbuf = z; |
||
379 | pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; |
||
380 | d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; |
||
381 | } |
||
382 | |||
383 | nodraw: |
||
384 | // recursively continue |
||
385 | D_PolysetRecursiveTriangle (lp3, lp1, new); |
||
386 | D_PolysetRecursiveTriangle (lp3, new, lp2); |
||
387 | } |
||
388 | |||
389 | #endif // !id386 |
||
390 | |||
391 | |||
392 | /* |
||
393 | ================ |
||
394 | D_PolysetUpdateTables |
||
395 | ================ |
||
396 | */ |
||
397 | void D_PolysetUpdateTables (void) |
||
398 | { |
||
399 | int i; |
||
400 | byte *s; |
||
401 | |||
402 | if (r_affinetridesc.skinwidth != skinwidth || |
||
403 | r_affinetridesc.pskin != skinstart) |
||
404 | { |
||
405 | skinwidth = r_affinetridesc.skinwidth; |
||
406 | skinstart = r_affinetridesc.pskin; |
||
407 | s = skinstart; |
||
408 | for (i=0 ; i |
||
409 | skintable[i] = s; |
||
410 | } |
||
411 | } |
||
412 | |||
413 | |||
414 | #if !id386 |
||
415 | |||
416 | /* |
||
417 | =================== |
||
418 | D_PolysetScanLeftEdge |
||
419 | ==================== |
||
420 | */ |
||
421 | void D_PolysetScanLeftEdge (int height) |
||
422 | { |
||
423 | |||
424 | do |
||
425 | { |
||
426 | d_pedgespanpackage->pdest = d_pdest; |
||
427 | d_pedgespanpackage->pz = d_pz; |
||
428 | d_pedgespanpackage->count = d_aspancount; |
||
429 | d_pedgespanpackage->ptex = d_ptex; |
||
430 | |||
431 | d_pedgespanpackage->sfrac = d_sfrac; |
||
432 | d_pedgespanpackage->tfrac = d_tfrac; |
||
433 | |||
434 | // FIXME: need to clamp l, s, t, at both ends? |
||
435 | d_pedgespanpackage->light = d_light; |
||
436 | d_pedgespanpackage->zi = d_zi; |
||
437 | |||
438 | d_pedgespanpackage++; |
||
439 | |||
440 | errorterm += erroradjustup; |
||
441 | if (errorterm >= 0) |
||
442 | { |
||
443 | d_pdest += d_pdestextrastep; |
||
444 | d_pz += d_pzextrastep; |
||
445 | d_aspancount += d_countextrastep; |
||
446 | d_ptex += d_ptexextrastep; |
||
447 | d_sfrac += d_sfracextrastep; |
||
448 | d_ptex += d_sfrac >> 16; |
||
449 | |||
450 | d_sfrac &= 0xFFFF; |
||
451 | d_tfrac += d_tfracextrastep; |
||
452 | if (d_tfrac & 0x10000) |
||
453 | { |
||
454 | d_ptex += r_affinetridesc.skinwidth; |
||
455 | d_tfrac &= 0xFFFF; |
||
456 | } |
||
457 | d_light += d_lightextrastep; |
||
458 | d_zi += d_ziextrastep; |
||
459 | errorterm -= erroradjustdown; |
||
460 | } |
||
461 | else |
||
462 | { |
||
463 | d_pdest += d_pdestbasestep; |
||
464 | d_pz += d_pzbasestep; |
||
465 | d_aspancount += ubasestep; |
||
466 | d_ptex += d_ptexbasestep; |
||
467 | d_sfrac += d_sfracbasestep; |
||
468 | d_ptex += d_sfrac >> 16; |
||
469 | d_sfrac &= 0xFFFF; |
||
470 | d_tfrac += d_tfracbasestep; |
||
471 | if (d_tfrac & 0x10000) |
||
472 | { |
||
473 | d_ptex += r_affinetridesc.skinwidth; |
||
474 | d_tfrac &= 0xFFFF; |
||
475 | } |
||
476 | d_light += d_lightbasestep; |
||
477 | d_zi += d_zibasestep; |
||
478 | } |
||
479 | } while (--height); |
||
480 | } |
||
481 | |||
482 | #endif // !id386 |
||
483 | |||
484 | |||
485 | /* |
||
486 | =================== |
||
487 | D_PolysetSetUpForLineScan |
||
488 | ==================== |
||
489 | */ |
||
490 | void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, |
||
491 | fixed8_t endvertu, fixed8_t endvertv) |
||
492 | { |
||
493 | double dm, dn; |
||
494 | int tm, tn; |
||
495 | adivtab_t *ptemp; |
||
496 | |||
497 | // TODO: implement x86 version |
||
498 | |||
499 | errorterm = -1; |
||
500 | |||
501 | tm = endvertu - startvertu; |
||
502 | tn = endvertv - startvertv; |
||
503 | |||
504 | if (((tm <= 16) && (tm >= -15)) && |
||
505 | ((tn <= 16) && (tn >= -15))) |
||
506 | { |
||
507 | ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; |
||
508 | ubasestep = ptemp->quotient; |
||
509 | erroradjustup = ptemp->remainder; |
||
510 | erroradjustdown = tn; |
||
511 | } |
||
512 | else |
||
513 | { |
||
514 | dm = (double)tm; |
||
515 | dn = (double)tn; |
||
516 | |||
517 | FloorDivMod (dm, dn, &ubasestep, &erroradjustup); |
||
518 | |||
519 | erroradjustdown = dn; |
||
520 | } |
||
521 | } |
||
522 | |||
523 | |||
524 | #if !id386 |
||
525 | |||
526 | /* |
||
527 | ================ |
||
528 | D_PolysetCalcGradients |
||
529 | ================ |
||
530 | */ |
||
531 | void D_PolysetCalcGradients (int skinwidth) |
||
532 | { |
||
533 | float xstepdenominv, ystepdenominv, t0, t1; |
||
534 | float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; |
||
535 | |||
536 | p00_minus_p20 = r_p0[0] - r_p2[0]; |
||
537 | p01_minus_p21 = r_p0[1] - r_p2[1]; |
||
538 | p10_minus_p20 = r_p1[0] - r_p2[0]; |
||
539 | p11_minus_p21 = r_p1[1] - r_p2[1]; |
||
540 | |||
541 | xstepdenominv = 1.0 / (float)d_xdenom; |
||
542 | |||
543 | ystepdenominv = -xstepdenominv; |
||
544 | |||
545 | // ceil () for light so positive steps are exaggerated, negative steps |
||
546 | // diminished, pushing us away from underflow toward overflow. Underflow is |
||
547 | // very visible, overflow is very unlikely, because of ambient lighting |
||
548 | t0 = r_p0[4] - r_p2[4]; |
||
549 | t1 = r_p1[4] - r_p2[4]; |
||
550 | r_lstepx = (int) |
||
551 | ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); |
||
552 | r_lstepy = (int) |
||
553 | ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); |
||
554 | |||
555 | t0 = r_p0[2] - r_p2[2]; |
||
556 | t1 = r_p1[2] - r_p2[2]; |
||
557 | r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * |
||
558 | xstepdenominv); |
||
559 | r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * |
||
560 | ystepdenominv); |
||
561 | |||
562 | t0 = r_p0[3] - r_p2[3]; |
||
563 | t1 = r_p1[3] - r_p2[3]; |
||
564 | r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * |
||
565 | xstepdenominv); |
||
566 | r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * |
||
567 | ystepdenominv); |
||
568 | |||
569 | t0 = r_p0[5] - r_p2[5]; |
||
570 | t1 = r_p1[5] - r_p2[5]; |
||
571 | r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * |
||
572 | xstepdenominv); |
||
573 | r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * |
||
574 | ystepdenominv); |
||
575 | |||
576 | #if id386 |
||
577 | a_sstepxfrac = r_sstepx << 16; |
||
578 | a_tstepxfrac = r_tstepx << 16; |
||
579 | #else |
||
580 | a_sstepxfrac = r_sstepx & 0xFFFF; |
||
581 | a_tstepxfrac = r_tstepx & 0xFFFF; |
||
582 | #endif |
||
583 | |||
584 | a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); |
||
585 | } |
||
586 | |||
587 | #endif // !id386 |
||
588 | |||
589 | |||
590 | #if 0 |
||
591 | byte gelmap[256]; |
||
592 | void InitGel (byte *palette) |
||
593 | { |
||
594 | int i; |
||
595 | int r; |
||
596 | |||
597 | for (i=0 ; i<256 ; i++) |
||
598 | { |
||
599 | // r = (palette[i*3]>>4); |
||
600 | r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3); |
||
601 | gelmap[i] = /* 64 */ 0 + r; |
||
602 | } |
||
603 | } |
||
604 | #endif |
||
605 | |||
606 | |||
607 | #if !id386 |
||
608 | |||
609 | /* |
||
610 | ================ |
||
611 | D_PolysetDrawSpans8 |
||
612 | ================ |
||
613 | */ |
||
614 | void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage) |
||
615 | { |
||
616 | int lcount; |
||
617 | byte *lpdest; |
||
618 | byte *lptex; |
||
619 | int lsfrac, ltfrac; |
||
620 | int llight; |
||
621 | int lzi; |
||
622 | short *lpz; |
||
623 | |||
624 | do |
||
625 | { |
||
626 | lcount = d_aspancount - pspanpackage->count; |
||
627 | |||
628 | errorterm += erroradjustup; |
||
629 | if (errorterm >= 0) |
||
630 | { |
||
631 | d_aspancount += d_countextrastep; |
||
632 | errorterm -= erroradjustdown; |
||
633 | } |
||
634 | else |
||
635 | { |
||
636 | d_aspancount += ubasestep; |
||
637 | } |
||
638 | |||
639 | if (lcount) |
||
640 | { |
||
641 | lpdest = pspanpackage->pdest; |
||
642 | lptex = pspanpackage->ptex; |
||
643 | lpz = pspanpackage->pz; |
||
644 | lsfrac = pspanpackage->sfrac; |
||
645 | ltfrac = pspanpackage->tfrac; |
||
646 | llight = pspanpackage->light; |
||
647 | lzi = pspanpackage->zi; |
||
648 | |||
649 | do |
||
650 | { |
||
651 | if ((lzi >> 16) >= *lpz) |
||
652 | { |
||
653 | *lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)]; |
||
654 | // gel mapping *lpdest = gelmap[*lpdest]; |
||
655 | *lpz = lzi >> 16; |
||
656 | } |
||
657 | lpdest++; |
||
658 | lzi += r_zistepx; |
||
659 | lpz++; |
||
660 | llight += r_lstepx; |
||
661 | lptex += a_ststepxwhole; |
||
662 | lsfrac += a_sstepxfrac; |
||
663 | lptex += lsfrac >> 16; |
||
664 | lsfrac &= 0xFFFF; |
||
665 | ltfrac += a_tstepxfrac; |
||
666 | if (ltfrac & 0x10000) |
||
667 | { |
||
668 | lptex += r_affinetridesc.skinwidth; |
||
669 | ltfrac &= 0xFFFF; |
||
670 | } |
||
671 | } while (--lcount); |
||
672 | } |
||
673 | |||
674 | pspanpackage++; |
||
675 | } while (pspanpackage->count != -999999); |
||
676 | } |
||
677 | #endif // !id386 |
||
678 | |||
679 | |||
680 | /* |
||
681 | ================ |
||
682 | D_PolysetFillSpans8 |
||
683 | ================ |
||
684 | */ |
||
685 | void D_PolysetFillSpans8 (spanpackage_t *pspanpackage) |
||
686 | { |
||
687 | int color; |
||
688 | |||
689 | // FIXME: do z buffering |
||
690 | |||
691 | color = d_aflatcolor++; |
||
692 | |||
693 | while (1) |
||
694 | { |
||
695 | int lcount; |
||
696 | byte *lpdest; |
||
697 | |||
698 | lcount = pspanpackage->count; |
||
699 | |||
700 | if (lcount == -1) |
||
701 | return; |
||
702 | |||
703 | if (lcount) |
||
704 | { |
||
705 | lpdest = pspanpackage->pdest; |
||
706 | |||
707 | do |
||
708 | { |
||
709 | *lpdest++ = color; |
||
710 | } while (--lcount); |
||
711 | } |
||
712 | |||
713 | pspanpackage++; |
||
714 | } |
||
715 | } |
||
716 | |||
717 | /* |
||
718 | ================ |
||
719 | D_RasterizeAliasPolySmooth |
||
720 | ================ |
||
721 | */ |
||
722 | void D_RasterizeAliasPolySmooth (void) |
||
723 | { |
||
724 | int initialleftheight, initialrightheight; |
||
725 | int *plefttop, *prighttop, *pleftbottom, *prightbottom; |
||
726 | int working_lstepx, originalcount; |
||
727 | |||
728 | plefttop = pedgetable->pleftedgevert0; |
||
729 | prighttop = pedgetable->prightedgevert0; |
||
730 | |||
731 | pleftbottom = pedgetable->pleftedgevert1; |
||
732 | prightbottom = pedgetable->prightedgevert1; |
||
733 | |||
734 | initialleftheight = pleftbottom[1] - plefttop[1]; |
||
735 | initialrightheight = prightbottom[1] - prighttop[1]; |
||
736 | |||
737 | // |
||
738 | // set the s, t, and light gradients, which are consistent across the triangle |
||
739 | // because being a triangle, things are affine |
||
740 | // |
||
741 | D_PolysetCalcGradients (r_affinetridesc.skinwidth); |
||
742 | |||
743 | // |
||
744 | // rasterize the polygon |
||
745 | // |
||
746 | |||
747 | // |
||
748 | // scan out the top (and possibly only) part of the left edge |
||
749 | // |
||
750 | d_pedgespanpackage = a_spans; |
||
751 | |||
752 | ystart = plefttop[1]; |
||
753 | d_aspancount = plefttop[0] - prighttop[0]; |
||
754 | |||
755 | d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + |
||
756 | (plefttop[3] >> 16) * r_affinetridesc.skinwidth; |
||
757 | #if id386 |
||
758 | d_sfrac = (plefttop[2] & 0xFFFF) << 16; |
||
759 | d_tfrac = (plefttop[3] & 0xFFFF) << 16; |
||
760 | #else |
||
761 | d_sfrac = plefttop[2] & 0xFFFF; |
||
762 | d_tfrac = plefttop[3] & 0xFFFF; |
||
763 | #endif |
||
764 | d_light = plefttop[4]; |
||
765 | d_zi = plefttop[5]; |
||
766 | |||
767 | d_pdest = (byte *)d_viewbuffer + |
||
768 | ystart * screenwidth + plefttop[0]; |
||
769 | d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; |
||
770 | |||
771 | if (initialleftheight == 1) |
||
772 | { |
||
773 | d_pedgespanpackage->pdest = d_pdest; |
||
774 | d_pedgespanpackage->pz = d_pz; |
||
775 | d_pedgespanpackage->count = d_aspancount; |
||
776 | d_pedgespanpackage->ptex = d_ptex; |
||
777 | |||
778 | d_pedgespanpackage->sfrac = d_sfrac; |
||
779 | d_pedgespanpackage->tfrac = d_tfrac; |
||
780 | |||
781 | // FIXME: need to clamp l, s, t, at both ends? |
||
782 | d_pedgespanpackage->light = d_light; |
||
783 | d_pedgespanpackage->zi = d_zi; |
||
784 | |||
785 | d_pedgespanpackage++; |
||
786 | } |
||
787 | else |
||
788 | { |
||
789 | D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], |
||
790 | pleftbottom[0], pleftbottom[1]); |
||
791 | |||
792 | #if id386 |
||
793 | d_pzbasestep = (d_zwidth + ubasestep) << 1; |
||
794 | d_pzextrastep = d_pzbasestep + 2; |
||
795 | #else |
||
796 | d_pzbasestep = d_zwidth + ubasestep; |
||
797 | d_pzextrastep = d_pzbasestep + 1; |
||
798 | #endif |
||
799 | |||
800 | d_pdestbasestep = screenwidth + ubasestep; |
||
801 | d_pdestextrastep = d_pdestbasestep + 1; |
||
802 | |||
803 | // TODO: can reuse partial expressions here |
||
804 | |||
805 | // for negative steps in x along left edge, bias toward overflow rather than |
||
806 | // underflow (sort of turning the floor () we did in the gradient calcs into |
||
807 | // ceil (), but plus a little bit) |
||
808 | if (ubasestep < 0) |
||
809 | working_lstepx = r_lstepx - 1; |
||
810 | else |
||
811 | working_lstepx = r_lstepx; |
||
812 | |||
813 | d_countextrastep = ubasestep + 1; |
||
814 | d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + |
||
815 | ((r_tstepy + r_tstepx * ubasestep) >> 16) * |
||
816 | r_affinetridesc.skinwidth; |
||
817 | #if id386 |
||
818 | d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; |
||
819 | d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; |
||
820 | #else |
||
821 | d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; |
||
822 | d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; |
||
823 | #endif |
||
824 | d_lightbasestep = r_lstepy + working_lstepx * ubasestep; |
||
825 | d_zibasestep = r_zistepy + r_zistepx * ubasestep; |
||
826 | |||
827 | d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + |
||
828 | ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * |
||
829 | r_affinetridesc.skinwidth; |
||
830 | #if id386 |
||
831 | d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; |
||
832 | d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; |
||
833 | #else |
||
834 | d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; |
||
835 | d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; |
||
836 | #endif |
||
837 | d_lightextrastep = d_lightbasestep + working_lstepx; |
||
838 | d_ziextrastep = d_zibasestep + r_zistepx; |
||
839 | |||
840 | D_PolysetScanLeftEdge (initialleftheight); |
||
841 | } |
||
842 | |||
843 | // |
||
844 | // scan out the bottom part of the left edge, if it exists |
||
845 | // |
||
846 | if (pedgetable->numleftedges == 2) |
||
847 | { |
||
848 | int height; |
||
849 | |||
850 | plefttop = pleftbottom; |
||
851 | pleftbottom = pedgetable->pleftedgevert2; |
||
852 | |||
853 | height = pleftbottom[1] - plefttop[1]; |
||
854 | |||
855 | // TODO: make this a function; modularize this function in general |
||
856 | |||
857 | ystart = plefttop[1]; |
||
858 | d_aspancount = plefttop[0] - prighttop[0]; |
||
859 | d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + |
||
860 | (plefttop[3] >> 16) * r_affinetridesc.skinwidth; |
||
861 | d_sfrac = 0; |
||
862 | d_tfrac = 0; |
||
863 | d_light = plefttop[4]; |
||
864 | d_zi = plefttop[5]; |
||
865 | |||
866 | d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0]; |
||
867 | d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; |
||
868 | |||
869 | if (height == 1) |
||
870 | { |
||
871 | d_pedgespanpackage->pdest = d_pdest; |
||
872 | d_pedgespanpackage->pz = d_pz; |
||
873 | d_pedgespanpackage->count = d_aspancount; |
||
874 | d_pedgespanpackage->ptex = d_ptex; |
||
875 | |||
876 | d_pedgespanpackage->sfrac = d_sfrac; |
||
877 | d_pedgespanpackage->tfrac = d_tfrac; |
||
878 | |||
879 | // FIXME: need to clamp l, s, t, at both ends? |
||
880 | d_pedgespanpackage->light = d_light; |
||
881 | d_pedgespanpackage->zi = d_zi; |
||
882 | |||
883 | d_pedgespanpackage++; |
||
884 | } |
||
885 | else |
||
886 | { |
||
887 | D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], |
||
888 | pleftbottom[0], pleftbottom[1]); |
||
889 | |||
890 | d_pdestbasestep = screenwidth + ubasestep; |
||
891 | d_pdestextrastep = d_pdestbasestep + 1; |
||
892 | |||
893 | #if id386 |
||
894 | d_pzbasestep = (d_zwidth + ubasestep) << 1; |
||
895 | d_pzextrastep = d_pzbasestep + 2; |
||
896 | #else |
||
897 | d_pzbasestep = d_zwidth + ubasestep; |
||
898 | d_pzextrastep = d_pzbasestep + 1; |
||
899 | #endif |
||
900 | |||
901 | if (ubasestep < 0) |
||
902 | working_lstepx = r_lstepx - 1; |
||
903 | else |
||
904 | working_lstepx = r_lstepx; |
||
905 | |||
906 | d_countextrastep = ubasestep + 1; |
||
907 | d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + |
||
908 | ((r_tstepy + r_tstepx * ubasestep) >> 16) * |
||
909 | r_affinetridesc.skinwidth; |
||
910 | #if id386 |
||
911 | d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; |
||
912 | d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; |
||
913 | #else |
||
914 | d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; |
||
915 | d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; |
||
916 | #endif |
||
917 | d_lightbasestep = r_lstepy + working_lstepx * ubasestep; |
||
918 | d_zibasestep = r_zistepy + r_zistepx * ubasestep; |
||
919 | |||
920 | d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + |
||
921 | ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * |
||
922 | r_affinetridesc.skinwidth; |
||
923 | #if id386 |
||
924 | d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; |
||
925 | d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; |
||
926 | #else |
||
927 | d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; |
||
928 | d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; |
||
929 | #endif |
||
930 | d_lightextrastep = d_lightbasestep + working_lstepx; |
||
931 | d_ziextrastep = d_zibasestep + r_zistepx; |
||
932 | |||
933 | D_PolysetScanLeftEdge (height); |
||
934 | } |
||
935 | } |
||
936 | |||
937 | // scan out the top (and possibly only) part of the right edge, updating the |
||
938 | // count field |
||
939 | d_pedgespanpackage = a_spans; |
||
940 | |||
941 | D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], |
||
942 | prightbottom[0], prightbottom[1]); |
||
943 | d_aspancount = 0; |
||
944 | d_countextrastep = ubasestep + 1; |
||
945 | originalcount = a_spans[initialrightheight].count; |
||
946 | a_spans[initialrightheight].count = -999999; // mark end of the spanpackages |
||
947 | D_PolysetDrawSpans8 (a_spans); |
||
948 | |||
949 | // scan out the bottom part of the right edge, if it exists |
||
950 | if (pedgetable->numrightedges == 2) |
||
951 | { |
||
952 | int height; |
||
953 | spanpackage_t *pstart; |
||
954 | |||
955 | pstart = a_spans + initialrightheight; |
||
956 | pstart->count = originalcount; |
||
957 | |||
958 | d_aspancount = prightbottom[0] - prighttop[0]; |
||
959 | |||
960 | prighttop = prightbottom; |
||
961 | prightbottom = pedgetable->prightedgevert2; |
||
962 | |||
963 | height = prightbottom[1] - prighttop[1]; |
||
964 | |||
965 | D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], |
||
966 | prightbottom[0], prightbottom[1]); |
||
967 | |||
968 | d_countextrastep = ubasestep + 1; |
||
969 | a_spans[initialrightheight + height].count = -999999; |
||
970 | // mark end of the spanpackages |
||
971 | D_PolysetDrawSpans8 (pstart); |
||
972 | } |
||
973 | } |
||
974 | |||
975 | |||
976 | /* |
||
977 | ================ |
||
978 | D_PolysetSetEdgeTable |
||
979 | ================ |
||
980 | */ |
||
981 | void D_PolysetSetEdgeTable (void) |
||
982 | { |
||
983 | int edgetableindex; |
||
984 | |||
985 | edgetableindex = 0; // assume the vertices are already in |
||
986 | // top to bottom order |
||
987 | |||
988 | // |
||
989 | // determine which edges are right & left, and the order in which |
||
990 | // to rasterize them |
||
991 | // |
||
992 | if (r_p0[1] >= r_p1[1]) |
||
993 | { |
||
994 | if (r_p0[1] == r_p1[1]) |
||
995 | { |
||
996 | if (r_p0[1] < r_p2[1]) |
||
997 | pedgetable = &edgetables[2]; |
||
998 | else |
||
999 | pedgetable = &edgetables[5]; |
||
1000 | |||
1001 | return; |
||
1002 | } |
||
1003 | else |
||
1004 | { |
||
1005 | edgetableindex = 1; |
||
1006 | } |
||
1007 | } |
||
1008 | |||
1009 | if (r_p0[1] == r_p2[1]) |
||
1010 | { |
||
1011 | if (edgetableindex) |
||
1012 | pedgetable = &edgetables[8]; |
||
1013 | else |
||
1014 | pedgetable = &edgetables[9]; |
||
1015 | |||
1016 | return; |
||
1017 | } |
||
1018 | else if (r_p1[1] == r_p2[1]) |
||
1019 | { |
||
1020 | if (edgetableindex) |
||
1021 | pedgetable = &edgetables[10]; |
||
1022 | else |
||
1023 | pedgetable = &edgetables[11]; |
||
1024 | |||
1025 | return; |
||
1026 | } |
||
1027 | |||
1028 | if (r_p0[1] > r_p2[1]) |
||
1029 | edgetableindex += 2; |
||
1030 | |||
1031 | if (r_p1[1] > r_p2[1]) |
||
1032 | edgetableindex += 4; |
||
1033 | |||
1034 | pedgetable = &edgetables[edgetableindex]; |
||
1035 | } |
||
1036 | |||
1037 | |||
1038 | #if 0 |
||
1039 | |||
1040 | void D_PolysetRecursiveDrawLine (int *lp1, int *lp2) |
||
1041 | { |
||
1042 | int d; |
||
1043 | int new[6]; |
||
1044 | int ofs; |
||
1045 | |||
1046 | d = lp2[0] - lp1[0]; |
||
1047 | if (d < -1 || d > 1) |
||
1048 | goto split; |
||
1049 | d = lp2[1] - lp1[1]; |
||
1050 | if (d < -1 || d > 1) |
||
1051 | goto split; |
||
1052 | |||
1053 | return; // line is completed |
||
1054 | |||
1055 | split: |
||
1056 | // split this edge |
||
1057 | new[0] = (lp1[0] + lp2[0]) >> 1; |
||
1058 | new[1] = (lp1[1] + lp2[1]) >> 1; |
||
1059 | new[5] = (lp1[5] + lp2[5]) >> 1; |
||
1060 | new[2] = (lp1[2] + lp2[2]) >> 1; |
||
1061 | new[3] = (lp1[3] + lp2[3]) >> 1; |
||
1062 | new[4] = (lp1[4] + lp2[4]) >> 1; |
||
1063 | |||
1064 | // draw the point |
||
1065 | ofs = d_scantable[new[1]] + new[0]; |
||
1066 | if (new[5] > d_pzbuffer[ofs]) |
||
1067 | { |
||
1068 | int pix; |
||
1069 | |||
1070 | d_pzbuffer[ofs] = new[5]; |
||
1071 | pix = skintable[new[3]>>16][new[2]>>16]; |
||
1072 | // pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)]; |
||
1073 | d_viewbuffer[ofs] = pix; |
||
1074 | } |
||
1075 | |||
1076 | // recursively continue |
||
1077 | D_PolysetRecursiveDrawLine (lp1, new); |
||
1078 | D_PolysetRecursiveDrawLine (new, lp2); |
||
1079 | } |
||
1080 | |||
1081 | void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3) |
||
1082 | { |
||
1083 | int d; |
||
1084 | int new[4]; |
||
1085 | |||
1086 | d = lp2[0] - lp1[0]; |
||
1087 | if (d < -1 || d > 1) |
||
1088 | goto split; |
||
1089 | d = lp2[1] - lp1[1]; |
||
1090 | if (d < -1 || d > 1) |
||
1091 | goto split; |
||
1092 | return; |
||
1093 | |||
1094 | split: |
||
1095 | // split this edge |
||
1096 | new[0] = (lp1[0] + lp2[0]) >> 1; |
||
1097 | new[1] = (lp1[1] + lp2[1]) >> 1; |
||
1098 | new[5] = (lp1[5] + lp2[5]) >> 1; |
||
1099 | new[2] = (lp1[2] + lp2[2]) >> 1; |
||
1100 | new[3] = (lp1[3] + lp2[3]) >> 1; |
||
1101 | new[4] = (lp1[4] + lp2[4]) >> 1; |
||
1102 | |||
1103 | D_PolysetRecursiveDrawLine (new, lp3); |
||
1104 | |||
1105 | // recursively continue |
||
1106 | D_PolysetRecursiveTriangle (lp1, new, lp3); |
||
1107 | D_PolysetRecursiveTriangle (new, lp2, lp3); |
||
1108 | } |
||
1109 | |||
1110 | #endif>>>>>16; |
||
1111 |