diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/d_sprite.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/d_sprite.c | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/d_sprite.c b/apps/plugins/sdl/progs/quake/d_sprite.c new file mode 100644 index 0000000000..2f02ad2c64 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/d_sprite.c | |||
@@ -0,0 +1,442 @@ | |||
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_sprite.c: software top-level rasterization driver module for drawing | ||
21 | // sprites | ||
22 | |||
23 | #include "quakedef.h" | ||
24 | #include "d_local.h" | ||
25 | |||
26 | static int sprite_height; | ||
27 | static int minindex, maxindex; | ||
28 | static sspan_t *sprite_spans; | ||
29 | |||
30 | #if !id386 | ||
31 | |||
32 | /* | ||
33 | ===================== | ||
34 | D_SpriteDrawSpans | ||
35 | ===================== | ||
36 | */ | ||
37 | void D_SpriteDrawSpans (sspan_t *pspan) | ||
38 | { | ||
39 | int count, spancount, izistep; | ||
40 | int izi; | ||
41 | byte *pbase, *pdest; | ||
42 | fixed16_t s, t, snext, tnext, sstep, tstep; | ||
43 | float sdivz, tdivz, zi, z, du, dv, spancountminus1; | ||
44 | float sdivz8stepu, tdivz8stepu, zi8stepu; | ||
45 | byte btemp; | ||
46 | short *pz; | ||
47 | |||
48 | sstep = 0; // keep compiler happy | ||
49 | tstep = 0; // ditto | ||
50 | |||
51 | pbase = cacheblock; | ||
52 | |||
53 | sdivz8stepu = d_sdivzstepu * 8; | ||
54 | tdivz8stepu = d_tdivzstepu * 8; | ||
55 | zi8stepu = d_zistepu * 8; | ||
56 | |||
57 | // we count on FP exceptions being turned off to avoid range problems | ||
58 | izistep = (int)(d_zistepu * 0x8000 * 0x10000); | ||
59 | |||
60 | do | ||
61 | { | ||
62 | pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u; | ||
63 | pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; | ||
64 | |||
65 | count = pspan->count; | ||
66 | |||
67 | if (count <= 0) | ||
68 | goto NextSpan; | ||
69 | |||
70 | // calculate the initial s/z, t/z, 1/z, s, and t and clamp | ||
71 | du = (float)pspan->u; | ||
72 | dv = (float)pspan->v; | ||
73 | |||
74 | sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; | ||
75 | tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; | ||
76 | zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; | ||
77 | z = (float)0x10000 / zi; // prescale to 16.16 fixed-point | ||
78 | // we count on FP exceptions being turned off to avoid range problems | ||
79 | izi = (int)(zi * 0x8000 * 0x10000); | ||
80 | |||
81 | s = (int)(sdivz * z) + sadjust; | ||
82 | if (s > bbextents) | ||
83 | s = bbextents; | ||
84 | else if (s < 0) | ||
85 | s = 0; | ||
86 | |||
87 | t = (int)(tdivz * z) + tadjust; | ||
88 | if (t > bbextentt) | ||
89 | t = bbextentt; | ||
90 | else if (t < 0) | ||
91 | t = 0; | ||
92 | |||
93 | do | ||
94 | { | ||
95 | // calculate s and t at the far end of the span | ||
96 | if (count >= 8) | ||
97 | spancount = 8; | ||
98 | else | ||
99 | spancount = count; | ||
100 | |||
101 | count -= spancount; | ||
102 | |||
103 | if (count) | ||
104 | { | ||
105 | // calculate s/z, t/z, zi->fixed s and t at far end of span, | ||
106 | // calculate s and t steps across span by shifting | ||
107 | sdivz += sdivz8stepu; | ||
108 | tdivz += tdivz8stepu; | ||
109 | zi += zi8stepu; | ||
110 | z = (float)0x10000 / zi; // prescale to 16.16 fixed-point | ||
111 | |||
112 | snext = (int)(sdivz * z) + sadjust; | ||
113 | if (snext > bbextents) | ||
114 | snext = bbextents; | ||
115 | else if (snext < 8) | ||
116 | snext = 8; // prevent round-off error on <0 steps from | ||
117 | // from causing overstepping & running off the | ||
118 | // edge of the texture | ||
119 | |||
120 | tnext = (int)(tdivz * z) + tadjust; | ||
121 | if (tnext > bbextentt) | ||
122 | tnext = bbextentt; | ||
123 | else if (tnext < 8) | ||
124 | tnext = 8; // guard against round-off error on <0 steps | ||
125 | |||
126 | sstep = (snext - s) >> 3; | ||
127 | tstep = (tnext - t) >> 3; | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so | ||
132 | // can't step off polygon), clamp, calculate s and t steps across | ||
133 | // span by division, biasing steps low so we don't run off the | ||
134 | // texture | ||
135 | spancountminus1 = (float)(spancount - 1); | ||
136 | sdivz += d_sdivzstepu * spancountminus1; | ||
137 | tdivz += d_tdivzstepu * spancountminus1; | ||
138 | zi += d_zistepu * spancountminus1; | ||
139 | z = (float)0x10000 / zi; // prescale to 16.16 fixed-point | ||
140 | snext = (int)(sdivz * z) + sadjust; | ||
141 | if (snext > bbextents) | ||
142 | snext = bbextents; | ||
143 | else if (snext < 8) | ||
144 | snext = 8; // prevent round-off error on <0 steps from | ||
145 | // from causing overstepping & running off the | ||
146 | // edge of the texture | ||
147 | |||
148 | tnext = (int)(tdivz * z) + tadjust; | ||
149 | if (tnext > bbextentt) | ||
150 | tnext = bbextentt; | ||
151 | else if (tnext < 8) | ||
152 | tnext = 8; // guard against round-off error on <0 steps | ||
153 | |||
154 | if (spancount > 1) | ||
155 | { | ||
156 | sstep = (snext - s) / (spancount - 1); | ||
157 | tstep = (tnext - t) / (spancount - 1); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | do | ||
162 | { | ||
163 | btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); | ||
164 | if (btemp != 255) | ||
165 | { | ||
166 | if (*pz <= (izi >> 16)) | ||
167 | { | ||
168 | *pz = izi >> 16; | ||
169 | *pdest = btemp; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | izi += izistep; | ||
174 | pdest++; | ||
175 | pz++; | ||
176 | s += sstep; | ||
177 | t += tstep; | ||
178 | } while (--spancount > 0); | ||
179 | |||
180 | s = snext; | ||
181 | t = tnext; | ||
182 | |||
183 | } while (count > 0); | ||
184 | |||
185 | NextSpan: | ||
186 | pspan++; | ||
187 | |||
188 | } while (pspan->count != DS_SPAN_LIST_END); | ||
189 | } | ||
190 | |||
191 | #endif | ||
192 | |||
193 | |||
194 | /* | ||
195 | ===================== | ||
196 | D_SpriteScanLeftEdge | ||
197 | ===================== | ||
198 | */ | ||
199 | void D_SpriteScanLeftEdge (void) | ||
200 | { | ||
201 | int i, v, itop, ibottom, lmaxindex; | ||
202 | emitpoint_t *pvert, *pnext; | ||
203 | sspan_t *pspan; | ||
204 | float du, dv, vtop, vbottom, slope; | ||
205 | fixed16_t u, u_step; | ||
206 | |||
207 | pspan = sprite_spans; | ||
208 | i = minindex; | ||
209 | if (i == 0) | ||
210 | i = r_spritedesc.nump; | ||
211 | |||
212 | lmaxindex = maxindex; | ||
213 | if (lmaxindex == 0) | ||
214 | lmaxindex = r_spritedesc.nump; | ||
215 | |||
216 | vtop = ceil (r_spritedesc.pverts[i].v); | ||
217 | |||
218 | do | ||
219 | { | ||
220 | pvert = &r_spritedesc.pverts[i]; | ||
221 | pnext = pvert - 1; | ||
222 | |||
223 | vbottom = ceil (pnext->v); | ||
224 | |||
225 | if (vtop < vbottom) | ||
226 | { | ||
227 | du = pnext->u - pvert->u; | ||
228 | dv = pnext->v - pvert->v; | ||
229 | slope = du / dv; | ||
230 | u_step = (int)(slope * 0x10000); | ||
231 | // adjust u to ceil the integer portion | ||
232 | u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + | ||
233 | (0x10000 - 1); | ||
234 | itop = (int)vtop; | ||
235 | ibottom = (int)vbottom; | ||
236 | |||
237 | for (v=itop ; v<ibottom ; v++) | ||
238 | { | ||
239 | pspan->u = u >> 16; | ||
240 | pspan->v = v; | ||
241 | u += u_step; | ||
242 | pspan++; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | vtop = vbottom; | ||
247 | |||
248 | i--; | ||
249 | if (i == 0) | ||
250 | i = r_spritedesc.nump; | ||
251 | |||
252 | } while (i != lmaxindex); | ||
253 | } | ||
254 | |||
255 | |||
256 | /* | ||
257 | ===================== | ||
258 | D_SpriteScanRightEdge | ||
259 | ===================== | ||
260 | */ | ||
261 | void D_SpriteScanRightEdge (void) | ||
262 | { | ||
263 | int i, v, itop, ibottom; | ||
264 | emitpoint_t *pvert, *pnext; | ||
265 | sspan_t *pspan; | ||
266 | float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; | ||
267 | fixed16_t u, u_step; | ||
268 | |||
269 | pspan = sprite_spans; | ||
270 | i = minindex; | ||
271 | |||
272 | vvert = r_spritedesc.pverts[i].v; | ||
273 | if (vvert < r_refdef.fvrecty_adj) | ||
274 | vvert = r_refdef.fvrecty_adj; | ||
275 | if (vvert > r_refdef.fvrectbottom_adj) | ||
276 | vvert = r_refdef.fvrectbottom_adj; | ||
277 | |||
278 | vtop = ceil (vvert); | ||
279 | |||
280 | do | ||
281 | { | ||
282 | pvert = &r_spritedesc.pverts[i]; | ||
283 | pnext = pvert + 1; | ||
284 | |||
285 | vnext = pnext->v; | ||
286 | if (vnext < r_refdef.fvrecty_adj) | ||
287 | vnext = r_refdef.fvrecty_adj; | ||
288 | if (vnext > r_refdef.fvrectbottom_adj) | ||
289 | vnext = r_refdef.fvrectbottom_adj; | ||
290 | |||
291 | vbottom = ceil (vnext); | ||
292 | |||
293 | if (vtop < vbottom) | ||
294 | { | ||
295 | uvert = pvert->u; | ||
296 | if (uvert < r_refdef.fvrectx_adj) | ||
297 | uvert = r_refdef.fvrectx_adj; | ||
298 | if (uvert > r_refdef.fvrectright_adj) | ||
299 | uvert = r_refdef.fvrectright_adj; | ||
300 | |||
301 | unext = pnext->u; | ||
302 | if (unext < r_refdef.fvrectx_adj) | ||
303 | unext = r_refdef.fvrectx_adj; | ||
304 | if (unext > r_refdef.fvrectright_adj) | ||
305 | unext = r_refdef.fvrectright_adj; | ||
306 | |||
307 | du = unext - uvert; | ||
308 | dv = vnext - vvert; | ||
309 | slope = du / dv; | ||
310 | u_step = (int)(slope * 0x10000); | ||
311 | // adjust u to ceil the integer portion | ||
312 | u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + | ||
313 | (0x10000 - 1); | ||
314 | itop = (int)vtop; | ||
315 | ibottom = (int)vbottom; | ||
316 | |||
317 | for (v=itop ; v<ibottom ; v++) | ||
318 | { | ||
319 | pspan->count = (u >> 16) - pspan->u; | ||
320 | u += u_step; | ||
321 | pspan++; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | vtop = vbottom; | ||
326 | vvert = vnext; | ||
327 | |||
328 | i++; | ||
329 | if (i == r_spritedesc.nump) | ||
330 | i = 0; | ||
331 | |||
332 | } while (i != maxindex); | ||
333 | |||
334 | pspan->count = DS_SPAN_LIST_END; // mark the end of the span list | ||
335 | } | ||
336 | |||
337 | |||
338 | /* | ||
339 | ===================== | ||
340 | D_SpriteCalculateGradients | ||
341 | ===================== | ||
342 | */ | ||
343 | void D_SpriteCalculateGradients (void) | ||
344 | { | ||
345 | vec3_t p_normal, p_saxis, p_taxis, p_temp1; | ||
346 | float distinv; | ||
347 | |||
348 | TransformVector (r_spritedesc.vpn, p_normal); | ||
349 | TransformVector (r_spritedesc.vright, p_saxis); | ||
350 | TransformVector (r_spritedesc.vup, p_taxis); | ||
351 | VectorInverse (p_taxis); | ||
352 | |||
353 | distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)); | ||
354 | |||
355 | d_sdivzstepu = p_saxis[0] * xscaleinv; | ||
356 | d_tdivzstepu = p_taxis[0] * xscaleinv; | ||
357 | |||
358 | d_sdivzstepv = -p_saxis[1] * yscaleinv; | ||
359 | d_tdivzstepv = -p_taxis[1] * yscaleinv; | ||
360 | |||
361 | d_zistepu = p_normal[0] * xscaleinv * distinv; | ||
362 | d_zistepv = -p_normal[1] * yscaleinv * distinv; | ||
363 | |||
364 | d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - | ||
365 | ycenter * d_sdivzstepv; | ||
366 | d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - | ||
367 | ycenter * d_tdivzstepv; | ||
368 | d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - | ||
369 | ycenter * d_zistepv; | ||
370 | |||
371 | TransformVector (modelorg, p_temp1); | ||
372 | |||
373 | sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - | ||
374 | (-(cachewidth >> 1) << 16); | ||
375 | tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - | ||
376 | (-(sprite_height >> 1) << 16); | ||
377 | |||
378 | // -1 (-epsilon) so we never wander off the edge of the texture | ||
379 | bbextents = (cachewidth << 16) - 1; | ||
380 | bbextentt = (sprite_height << 16) - 1; | ||
381 | } | ||
382 | |||
383 | |||
384 | /* | ||
385 | ===================== | ||
386 | D_DrawSprite | ||
387 | ===================== | ||
388 | */ | ||
389 | void D_DrawSprite (void) | ||
390 | { | ||
391 | int i, nump; | ||
392 | float ymin, ymax; | ||
393 | emitpoint_t *pverts; | ||
394 | sspan_t spans[MAXHEIGHT+1]; | ||
395 | |||
396 | sprite_spans = spans; | ||
397 | |||
398 | // find the top and bottom vertices, and make sure there's at least one scan to | ||
399 | // draw | ||
400 | ymin = 999999.9; | ||
401 | ymax = -999999.9; | ||
402 | pverts = r_spritedesc.pverts; | ||
403 | |||
404 | for (i=0 ; i<r_spritedesc.nump ; i++) | ||
405 | { | ||
406 | if (pverts->v < ymin) | ||
407 | { | ||
408 | ymin = pverts->v; | ||
409 | minindex = i; | ||
410 | } | ||
411 | |||
412 | if (pverts->v > ymax) | ||
413 | { | ||
414 | ymax = pverts->v; | ||
415 | maxindex = i; | ||
416 | } | ||
417 | |||
418 | pverts++; | ||
419 | } | ||
420 | |||
421 | ymin = ceil (ymin); | ||
422 | ymax = ceil (ymax); | ||
423 | |||
424 | if (ymin >= ymax) | ||
425 | return; // doesn't cross any scans at all | ||
426 | |||
427 | cachewidth = r_spritedesc.pspriteframe->width; | ||
428 | sprite_height = r_spritedesc.pspriteframe->height; | ||
429 | cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0]; | ||
430 | |||
431 | // copy the first vertex to the last vertex, so we don't have to deal with | ||
432 | // wrapping | ||
433 | nump = r_spritedesc.nump; | ||
434 | pverts = r_spritedesc.pverts; | ||
435 | pverts[nump] = pverts[0]; | ||
436 | |||
437 | D_SpriteCalculateGradients (); | ||
438 | D_SpriteScanLeftEdge (); | ||
439 | D_SpriteScanRightEdge (); | ||
440 | D_SpriteDrawSpans (sprite_spans); | ||
441 | } | ||
442 | |||