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_scan.c
21 //
22 // Portable C scan-level rasterization code, all pixel depths.
23
24 #include "quakedef.h"
25 #include "r_local.h"
26 #include "d_local.h"
27
28 unsigned char *r_turb_pbase, *r_turb_pdest;
29 fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
30 int *r_turb_turb;
31 int r_turb_spancount;
32
33 void D_DrawTurbulent8Span (void);
34
35
36 /*
37 =============
38 D_WarpScreen
39
40 // this performs a slight compression of the screen at the same time as
41 // the sine warp, to keep the edges from wrapping
42 =============
43 */
D_WarpScreen(void)44 void D_WarpScreen (void)
45 {
46 int w, h;
47 int u,v;
48 byte *dest;
49 int *turb;
50 int *col;
51 byte **row;
52 byte *rowptr[1024];
53 int column[1280];
54 float wratio, hratio;
55
56 w = r_refdef.vrect.width;
57 h = r_refdef.vrect.height;
58
59 wratio = w / (float)scr_vrect.width;
60 hratio = h / (float)scr_vrect.height;
61
62 for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
63 {
64 rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
65 (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
66 }
67
68 for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
69 {
70 column[u] = r_refdef.vrect.x +
71 (int)((float)u * wratio * w / (w + AMP2 * 2));
72 }
73
74 turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
75 dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
76
77 for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
78 {
79 col = &column[turb[v]];
80 row = &rowptr[v];
81 for (u=0 ; u<scr_vrect.width ; u+=4)
82 {
83 dest[u+0] = row[turb[u+0]][col[u+0]];
84 dest[u+1] = row[turb[u+1]][col[u+1]];
85 dest[u+2] = row[turb[u+2]][col[u+2]];
86 dest[u+3] = row[turb[u+3]][col[u+3]];
87 }
88 }
89 }
90
91
92 #if !id386
93
94 /*
95 =============
96 D_DrawTurbulent8Span
97 =============
98 */
D_DrawTurbulent8Span(void)99 void D_DrawTurbulent8Span (void)
100 {
101 int sturb, tturb;
102
103 do
104 {
105 sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
106 tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
107 *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
108 r_turb_s += r_turb_sstep;
109 r_turb_t += r_turb_tstep;
110 } while (--r_turb_spancount > 0);
111 }
112
113 #endif // !id386
114
115 /*
116 =============
117 Turbulent8
118 =============
119 */
Turbulent8(espan_t * pspan)120 void Turbulent8 (espan_t *pspan)
121 {
122 int count;
123 fixed16_t snext, tnext;
124 float sdivz, tdivz, zi, z, du, dv, spancountminus1;
125 float sdivz16stepu, tdivz16stepu, zi16stepu;
126
127 r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
128
129 r_turb_sstep = 0; // keep compiler happy
130 r_turb_tstep = 0; // ditto
131
132 r_turb_pbase = (unsigned char *)cacheblock;
133
134 sdivz16stepu = d_sdivzstepu * 16;
135 tdivz16stepu = d_tdivzstepu * 16;
136 zi16stepu = d_zistepu * 16;
137
138 do
139 {
140 r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
141 (screenwidth * pspan->v) + pspan->u);
142
143 count = pspan->count;
144
145 // calculate the initial s/z, t/z, 1/z, s, and t and clamp
146 du = (float)pspan->u;
147 dv = (float)pspan->v;
148
149 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
150 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
151 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
152 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
153
154 r_turb_s = (int)(sdivz * z) + sadjust;
155 if (r_turb_s > bbextents)
156 r_turb_s = bbextents;
157 else if (r_turb_s < 0)
158 r_turb_s = 0;
159
160 r_turb_t = (int)(tdivz * z) + tadjust;
161 if (r_turb_t > bbextentt)
162 r_turb_t = bbextentt;
163 else if (r_turb_t < 0)
164 r_turb_t = 0;
165
166 do
167 {
168 // calculate s and t at the far end of the span
169 if (count >= 16)
170 r_turb_spancount = 16;
171 else
172 r_turb_spancount = count;
173
174 count -= r_turb_spancount;
175
176 if (count)
177 {
178 // calculate s/z, t/z, zi->fixed s and t at far end of span,
179 // calculate s and t steps across span by shifting
180 sdivz += sdivz16stepu;
181 tdivz += tdivz16stepu;
182 zi += zi16stepu;
183 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
184
185 snext = (int)(sdivz * z) + sadjust;
186 if (snext > bbextents)
187 snext = bbextents;
188 else if (snext < 16)
189 snext = 16; // prevent round-off error on <0 steps from
190 // from causing overstepping & running off the
191 // edge of the texture
192
193 tnext = (int)(tdivz * z) + tadjust;
194 if (tnext > bbextentt)
195 tnext = bbextentt;
196 else if (tnext < 16)
197 tnext = 16; // guard against round-off error on <0 steps
198
199 r_turb_sstep = (snext - r_turb_s) >> 4;
200 r_turb_tstep = (tnext - r_turb_t) >> 4;
201 }
202 else
203 {
204 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
205 // can't step off polygon), clamp, calculate s and t steps across
206 // span by division, biasing steps low so we don't run off the
207 // texture
208 spancountminus1 = (float)(r_turb_spancount - 1);
209 sdivz += d_sdivzstepu * spancountminus1;
210 tdivz += d_tdivzstepu * spancountminus1;
211 zi += d_zistepu * spancountminus1;
212 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
213 snext = (int)(sdivz * z) + sadjust;
214 if (snext > bbextents)
215 snext = bbextents;
216 else if (snext < 16)
217 snext = 16; // prevent round-off error on <0 steps from
218 // from causing overstepping & running off the
219 // edge of the texture
220
221 tnext = (int)(tdivz * z) + tadjust;
222 if (tnext > bbextentt)
223 tnext = bbextentt;
224 else if (tnext < 16)
225 tnext = 16; // guard against round-off error on <0 steps
226
227 if (r_turb_spancount > 1)
228 {
229 r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
230 r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
231 }
232 }
233
234 r_turb_s = r_turb_s & ((CYCLE<<16)-1);
235 r_turb_t = r_turb_t & ((CYCLE<<16)-1);
236
237 D_DrawTurbulent8Span ();
238
239 r_turb_s = snext;
240 r_turb_t = tnext;
241
242 } while (count > 0);
243
244 } while ((pspan = pspan->pnext) != NULL);
245 }
246
247
248 #if !id386
249
250 /*
251 =============
252 D_DrawSpans8
253 =============
254 */
D_DrawSpans8(espan_t * pspan)255 void D_DrawSpans8 (espan_t *pspan)
256 {
257 int count, spancount;
258 unsigned char *pbase, *pdest;
259 fixed16_t s, t, snext, tnext, sstep, tstep;
260 float sdivz, tdivz, zi, z, du, dv, spancountminus1;
261 float sdivz8stepu, tdivz8stepu, zi8stepu;
262
263 sstep = 0; // keep compiler happy
264 tstep = 0; // ditto
265
266 pbase = (unsigned char *)cacheblock;
267
268 sdivz8stepu = d_sdivzstepu * 8;
269 tdivz8stepu = d_tdivzstepu * 8;
270 zi8stepu = d_zistepu * 8;
271
272 do
273 {
274 pdest = (unsigned char *)((byte *)d_viewbuffer +
275 (screenwidth * pspan->v) + pspan->u);
276
277 count = pspan->count;
278
279 // calculate the initial s/z, t/z, 1/z, s, and t and clamp
280 du = (float)pspan->u;
281 dv = (float)pspan->v;
282
283 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
284 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
285 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
286 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
287
288 s = (int)(sdivz * z) + sadjust;
289 if (s > bbextents)
290 s = bbextents;
291 else if (s < 0)
292 s = 0;
293
294 t = (int)(tdivz * z) + tadjust;
295 if (t > bbextentt)
296 t = bbextentt;
297 else if (t < 0)
298 t = 0;
299
300 do
301 {
302 // calculate s and t at the far end of the span
303 if (count >= 8)
304 spancount = 8;
305 else
306 spancount = count;
307
308 count -= spancount;
309
310 if (count)
311 {
312 // calculate s/z, t/z, zi->fixed s and t at far end of span,
313 // calculate s and t steps across span by shifting
314 sdivz += sdivz8stepu;
315 tdivz += tdivz8stepu;
316 zi += zi8stepu;
317 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
318
319 snext = (int)(sdivz * z) + sadjust;
320 if (snext > bbextents)
321 snext = bbextents;
322 else if (snext < 8)
323 snext = 8; // prevent round-off error on <0 steps from
324 // from causing overstepping & running off the
325 // edge of the texture
326
327 tnext = (int)(tdivz * z) + tadjust;
328 if (tnext > bbextentt)
329 tnext = bbextentt;
330 else if (tnext < 8)
331 tnext = 8; // guard against round-off error on <0 steps
332
333 sstep = (snext - s) >> 3;
334 tstep = (tnext - t) >> 3;
335 }
336 else
337 {
338 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
339 // can't step off polygon), clamp, calculate s and t steps across
340 // span by division, biasing steps low so we don't run off the
341 // texture
342 spancountminus1 = (float)(spancount - 1);
343 sdivz += d_sdivzstepu * spancountminus1;
344 tdivz += d_tdivzstepu * spancountminus1;
345 zi += d_zistepu * spancountminus1;
346 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
347 snext = (int)(sdivz * z) + sadjust;
348 if (snext > bbextents)
349 snext = bbextents;
350 else if (snext < 8)
351 snext = 8; // prevent round-off error on <0 steps from
352 // from causing overstepping & running off the
353 // edge of the texture
354
355 tnext = (int)(tdivz * z) + tadjust;
356 if (tnext > bbextentt)
357 tnext = bbextentt;
358 else if (tnext < 8)
359 tnext = 8; // guard against round-off error on <0 steps
360
361 if (spancount > 1)
362 {
363 sstep = (snext - s) / (spancount - 1);
364 tstep = (tnext - t) / (spancount - 1);
365 }
366 }
367
368 do
369 {
370 *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
371 s += sstep;
372 t += tstep;
373 } while (--spancount > 0);
374
375 s = snext;
376 t = tnext;
377
378 } while (count > 0);
379
380 } while ((pspan = pspan->pnext) != NULL);
381 }
382
383 #endif
384
385
386 #if !id386
387
388 /*
389 =============
390 D_DrawZSpans
391 =============
392 */
D_DrawZSpans(espan_t * pspan)393 void D_DrawZSpans (espan_t *pspan)
394 {
395 int count, doublecount, izistep;
396 int izi;
397 short *pdest;
398 unsigned ltemp;
399 double zi;
400 float du, dv;
401
402 // FIXME: check for clamping/range problems
403 // we count on FP exceptions being turned off to avoid range problems
404 izistep = (int)(d_zistepu * 0x8000 * 0x10000);
405
406 do
407 {
408 pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
409
410 count = pspan->count;
411
412 // calculate the initial 1/z
413 du = (float)pspan->u;
414 dv = (float)pspan->v;
415
416 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
417 // we count on FP exceptions being turned off to avoid range problems
418 izi = (int)(zi * 0x8000 * 0x10000);
419
420 if ((long)pdest & 0x02)
421 {
422 *pdest++ = (short)(izi >> 16);
423 izi += izistep;
424 count--;
425 }
426
427 if ((doublecount = count >> 1) > 0)
428 {
429 do
430 {
431 ltemp = izi >> 16;
432 izi += izistep;
433 ltemp |= izi & 0xFFFF0000;
434 izi += izistep;
435 *(int *)pdest = ltemp;
436 pdest += 2;
437 } while (--doublecount > 0);
438 }
439
440 if (count & 1)
441 *pdest = (short)(izi >> 16);
442
443 } while ((pspan = pspan->pnext) != NULL);
444 }
445
446 #endif
447