• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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