Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_scan.c (14695B)


      1 /*
      2 Copyright (C) 1997-2001 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 "r_local.h"
     25 
     26 unsigned char	*r_turb_pbase, *r_turb_pdest;
     27 fixed16_t		r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
     28 int				*r_turb_turb;
     29 int				r_turb_spancount;
     30 
     31 void D_DrawTurbulent8Span (void);
     32 
     33 
     34 /*
     35 =============
     36 D_WarpScreen
     37 
     38 this performs a slight compression of the screen at the same time as
     39 the sine warp, to keep the edges from wrapping
     40 =============
     41 */
     42 void D_WarpScreen (void)
     43 {
     44 	int		w, h;
     45 	int		u,v, u2, v2;
     46 	byte	*dest;
     47 	int		*turb;
     48 	int		*col;
     49 	byte	**row;
     50 
     51 	static int	cached_width, cached_height;
     52 	static byte	*rowptr[1200+AMP2*2];
     53 	static int	column[1600+AMP2*2];
     54 
     55 	//
     56 	// these are constant over resolutions, and can be saved
     57 	//
     58 	w = r_newrefdef.width;
     59 	h = r_newrefdef.height;
     60 	if (w != cached_width || h != cached_height)
     61 	{
     62 		cached_width = w;
     63 		cached_height = h;
     64 		for (v=0 ; v<h+AMP2*2 ; v++)
     65 		{
     66 			v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
     67 			rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
     68 		}
     69 
     70 		for (u=0 ; u<w+AMP2*2 ; u++)
     71 		{
     72 			u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
     73 			column[u] = u2;
     74 		}
     75 	}
     76 
     77 	turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
     78 	dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
     79 
     80 	for (v=0 ; v<h ; v++, dest += vid.rowbytes)
     81 	{
     82 		col = &column[turb[v]];
     83 		row = &rowptr[v];
     84 		for (u=0 ; u<w ; u+=4)
     85 		{
     86 			dest[u+0] = row[turb[u+0]][col[u+0]];
     87 			dest[u+1] = row[turb[u+1]][col[u+1]];
     88 			dest[u+2] = row[turb[u+2]][col[u+2]];
     89 			dest[u+3] = row[turb[u+3]][col[u+3]];
     90 		}
     91 	}
     92 }
     93 
     94 
     95 #if	!id386
     96 
     97 /*
     98 =============
     99 D_DrawTurbulent8Span
    100 =============
    101 */
    102 void D_DrawTurbulent8Span (void)
    103 {
    104 	int		sturb, tturb;
    105 
    106 	do
    107 	{
    108 		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
    109 		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
    110 		*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
    111 		r_turb_s += r_turb_sstep;
    112 		r_turb_t += r_turb_tstep;
    113 	} while (--r_turb_spancount > 0);
    114 }
    115 
    116 #endif	// !id386
    117 
    118 
    119 /*
    120 =============
    121 Turbulent8
    122 =============
    123 */
    124 void Turbulent8 (espan_t *pspan)
    125 {
    126 	int				count;
    127 	fixed16_t		snext, tnext;
    128 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
    129 	float			sdivz16stepu, tdivz16stepu, zi16stepu;
    130 	
    131 	r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
    132 
    133 	r_turb_sstep = 0;	// keep compiler happy
    134 	r_turb_tstep = 0;	// ditto
    135 
    136 	r_turb_pbase = (unsigned char *)cacheblock;
    137 
    138 	sdivz16stepu = d_sdivzstepu * 16;
    139 	tdivz16stepu = d_tdivzstepu * 16;
    140 	zi16stepu = d_zistepu * 16;
    141 
    142 	do
    143 	{
    144 		r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
    145 				(r_screenwidth * pspan->v) + pspan->u);
    146 
    147 		count = pspan->count;
    148 
    149 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
    150 		du = (float)pspan->u;
    151 		dv = (float)pspan->v;
    152 
    153 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
    154 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
    155 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
    156 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    157 
    158 		r_turb_s = (int)(sdivz * z) + sadjust;
    159 		if (r_turb_s > bbextents)
    160 			r_turb_s = bbextents;
    161 		else if (r_turb_s < 0)
    162 			r_turb_s = 0;
    163 
    164 		r_turb_t = (int)(tdivz * z) + tadjust;
    165 		if (r_turb_t > bbextentt)
    166 			r_turb_t = bbextentt;
    167 		else if (r_turb_t < 0)
    168 			r_turb_t = 0;
    169 
    170 		do
    171 		{
    172 		// calculate s and t at the far end of the span
    173 			if (count >= 16)
    174 				r_turb_spancount = 16;
    175 			else
    176 				r_turb_spancount = count;
    177 
    178 			count -= r_turb_spancount;
    179 
    180 			if (count)
    181 			{
    182 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
    183 			// calculate s and t steps across span by shifting
    184 				sdivz += sdivz16stepu;
    185 				tdivz += tdivz16stepu;
    186 				zi += zi16stepu;
    187 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    188 
    189 				snext = (int)(sdivz * z) + sadjust;
    190 				if (snext > bbextents)
    191 					snext = bbextents;
    192 				else if (snext < 16)
    193 					snext = 16;	// prevent round-off error on <0 steps from
    194 								//  from causing overstepping & running off the
    195 								//  edge of the texture
    196 
    197 				tnext = (int)(tdivz * z) + tadjust;
    198 				if (tnext > bbextentt)
    199 					tnext = bbextentt;
    200 				else if (tnext < 16)
    201 					tnext = 16;	// guard against round-off error on <0 steps
    202 
    203 				r_turb_sstep = (snext - r_turb_s) >> 4;
    204 				r_turb_tstep = (tnext - r_turb_t) >> 4;
    205 			}
    206 			else
    207 			{
    208 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
    209 			// can't step off polygon), clamp, calculate s and t steps across
    210 			// span by division, biasing steps low so we don't run off the
    211 			// texture
    212 				spancountminus1 = (float)(r_turb_spancount - 1);
    213 				sdivz += d_sdivzstepu * spancountminus1;
    214 				tdivz += d_tdivzstepu * spancountminus1;
    215 				zi += d_zistepu * spancountminus1;
    216 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    217 				snext = (int)(sdivz * z) + sadjust;
    218 				if (snext > bbextents)
    219 					snext = bbextents;
    220 				else if (snext < 16)
    221 					snext = 16;	// prevent round-off error on <0 steps from
    222 								//  from causing overstepping & running off the
    223 								//  edge of the texture
    224 
    225 				tnext = (int)(tdivz * z) + tadjust;
    226 				if (tnext > bbextentt)
    227 					tnext = bbextentt;
    228 				else if (tnext < 16)
    229 					tnext = 16;	// guard against round-off error on <0 steps
    230 
    231 				if (r_turb_spancount > 1)
    232 				{
    233 					r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
    234 					r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
    235 				}
    236 			}
    237 
    238 			r_turb_s = r_turb_s & ((CYCLE<<16)-1);
    239 			r_turb_t = r_turb_t & ((CYCLE<<16)-1);
    240 
    241 			D_DrawTurbulent8Span ();
    242 
    243 			r_turb_s = snext;
    244 			r_turb_t = tnext;
    245 
    246 		} while (count > 0);
    247 
    248 	} while ((pspan = pspan->pnext) != NULL);
    249 }
    250 
    251 //====================
    252 //PGM
    253 /*
    254 =============
    255 NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
    256 	but the turbulence is automatically 0.
    257 =============
    258 */
    259 void NonTurbulent8 (espan_t *pspan)
    260 {
    261 	int				count;
    262 	fixed16_t		snext, tnext;
    263 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
    264 	float			sdivz16stepu, tdivz16stepu, zi16stepu;
    265 	
    266 //	r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
    267 	r_turb_turb = blanktable;
    268 
    269 	r_turb_sstep = 0;	// keep compiler happy
    270 	r_turb_tstep = 0;	// ditto
    271 
    272 	r_turb_pbase = (unsigned char *)cacheblock;
    273 
    274 	sdivz16stepu = d_sdivzstepu * 16;
    275 	tdivz16stepu = d_tdivzstepu * 16;
    276 	zi16stepu = d_zistepu * 16;
    277 
    278 	do
    279 	{
    280 		r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
    281 				(r_screenwidth * pspan->v) + pspan->u);
    282 
    283 		count = pspan->count;
    284 
    285 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
    286 		du = (float)pspan->u;
    287 		dv = (float)pspan->v;
    288 
    289 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
    290 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
    291 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
    292 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    293 
    294 		r_turb_s = (int)(sdivz * z) + sadjust;
    295 		if (r_turb_s > bbextents)
    296 			r_turb_s = bbextents;
    297 		else if (r_turb_s < 0)
    298 			r_turb_s = 0;
    299 
    300 		r_turb_t = (int)(tdivz * z) + tadjust;
    301 		if (r_turb_t > bbextentt)
    302 			r_turb_t = bbextentt;
    303 		else if (r_turb_t < 0)
    304 			r_turb_t = 0;
    305 
    306 		do
    307 		{
    308 		// calculate s and t at the far end of the span
    309 			if (count >= 16)
    310 				r_turb_spancount = 16;
    311 			else
    312 				r_turb_spancount = count;
    313 
    314 			count -= r_turb_spancount;
    315 
    316 			if (count)
    317 			{
    318 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
    319 			// calculate s and t steps across span by shifting
    320 				sdivz += sdivz16stepu;
    321 				tdivz += tdivz16stepu;
    322 				zi += zi16stepu;
    323 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    324 
    325 				snext = (int)(sdivz * z) + sadjust;
    326 				if (snext > bbextents)
    327 					snext = bbextents;
    328 				else if (snext < 16)
    329 					snext = 16;	// prevent round-off error on <0 steps from
    330 								//  from causing overstepping & running off the
    331 								//  edge of the texture
    332 
    333 				tnext = (int)(tdivz * z) + tadjust;
    334 				if (tnext > bbextentt)
    335 					tnext = bbextentt;
    336 				else if (tnext < 16)
    337 					tnext = 16;	// guard against round-off error on <0 steps
    338 
    339 				r_turb_sstep = (snext - r_turb_s) >> 4;
    340 				r_turb_tstep = (tnext - r_turb_t) >> 4;
    341 			}
    342 			else
    343 			{
    344 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
    345 			// can't step off polygon), clamp, calculate s and t steps across
    346 			// span by division, biasing steps low so we don't run off the
    347 			// texture
    348 				spancountminus1 = (float)(r_turb_spancount - 1);
    349 				sdivz += d_sdivzstepu * spancountminus1;
    350 				tdivz += d_tdivzstepu * spancountminus1;
    351 				zi += d_zistepu * spancountminus1;
    352 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    353 				snext = (int)(sdivz * z) + sadjust;
    354 				if (snext > bbextents)
    355 					snext = bbextents;
    356 				else if (snext < 16)
    357 					snext = 16;	// prevent round-off error on <0 steps from
    358 								//  from causing overstepping & running off the
    359 								//  edge of the texture
    360 
    361 				tnext = (int)(tdivz * z) + tadjust;
    362 				if (tnext > bbextentt)
    363 					tnext = bbextentt;
    364 				else if (tnext < 16)
    365 					tnext = 16;	// guard against round-off error on <0 steps
    366 
    367 				if (r_turb_spancount > 1)
    368 				{
    369 					r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
    370 					r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
    371 				}
    372 			}
    373 
    374 			r_turb_s = r_turb_s & ((CYCLE<<16)-1);
    375 			r_turb_t = r_turb_t & ((CYCLE<<16)-1);
    376 
    377 			D_DrawTurbulent8Span ();
    378 
    379 			r_turb_s = snext;
    380 			r_turb_t = tnext;
    381 
    382 		} while (count > 0);
    383 
    384 	} while ((pspan = pspan->pnext) != NULL);
    385 }
    386 //PGM
    387 //====================
    388 
    389 
    390 #if	!id386
    391 
    392 /*
    393 =============
    394 D_DrawSpans16
    395 
    396   FIXME: actually make this subdivide by 16 instead of 8!!!
    397 =============
    398 */
    399 void D_DrawSpans16 (espan_t *pspan)
    400 {
    401 	int				count, spancount;
    402 	unsigned char	*pbase, *pdest;
    403 	fixed16_t		s, t, snext, tnext, sstep, tstep;
    404 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
    405 	float			sdivz8stepu, tdivz8stepu, zi8stepu;
    406 
    407 	sstep = 0;	// keep compiler happy
    408 	tstep = 0;	// ditto
    409 
    410 	pbase = (unsigned char *)cacheblock;
    411 
    412 	sdivz8stepu = d_sdivzstepu * 8;
    413 	tdivz8stepu = d_tdivzstepu * 8;
    414 	zi8stepu = d_zistepu * 8;
    415 
    416 	do
    417 	{
    418 		pdest = (unsigned char *)((byte *)d_viewbuffer +
    419 				(r_screenwidth * pspan->v) + pspan->u);
    420 
    421 		count = pspan->count;
    422 
    423 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
    424 		du = (float)pspan->u;
    425 		dv = (float)pspan->v;
    426 
    427 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
    428 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
    429 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
    430 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    431 
    432 		s = (int)(sdivz * z) + sadjust;
    433 		if (s > bbextents)
    434 			s = bbextents;
    435 		else if (s < 0)
    436 			s = 0;
    437 
    438 		t = (int)(tdivz * z) + tadjust;
    439 		if (t > bbextentt)
    440 			t = bbextentt;
    441 		else if (t < 0)
    442 			t = 0;
    443 
    444 		do
    445 		{
    446 		// calculate s and t at the far end of the span
    447 			if (count >= 8)
    448 				spancount = 8;
    449 			else
    450 				spancount = count;
    451 
    452 			count -= spancount;
    453 
    454 			if (count)
    455 			{
    456 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
    457 			// calculate s and t steps across span by shifting
    458 				sdivz += sdivz8stepu;
    459 				tdivz += tdivz8stepu;
    460 				zi += zi8stepu;
    461 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    462 
    463 				snext = (int)(sdivz * z) + sadjust;
    464 				if (snext > bbextents)
    465 					snext = bbextents;
    466 				else if (snext < 8)
    467 					snext = 8;	// prevent round-off error on <0 steps from
    468 								//  from causing overstepping & running off the
    469 								//  edge of the texture
    470 
    471 				tnext = (int)(tdivz * z) + tadjust;
    472 				if (tnext > bbextentt)
    473 					tnext = bbextentt;
    474 				else if (tnext < 8)
    475 					tnext = 8;	// guard against round-off error on <0 steps
    476 
    477 				sstep = (snext - s) >> 3;
    478 				tstep = (tnext - t) >> 3;
    479 			}
    480 			else
    481 			{
    482 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
    483 			// can't step off polygon), clamp, calculate s and t steps across
    484 			// span by division, biasing steps low so we don't run off the
    485 			// texture
    486 				spancountminus1 = (float)(spancount - 1);
    487 				sdivz += d_sdivzstepu * spancountminus1;
    488 				tdivz += d_tdivzstepu * spancountminus1;
    489 				zi += d_zistepu * spancountminus1;
    490 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
    491 				snext = (int)(sdivz * z) + sadjust;
    492 				if (snext > bbextents)
    493 					snext = bbextents;
    494 				else if (snext < 8)
    495 					snext = 8;	// prevent round-off error on <0 steps from
    496 								//  from causing overstepping & running off the
    497 								//  edge of the texture
    498 
    499 				tnext = (int)(tdivz * z) + tadjust;
    500 				if (tnext > bbextentt)
    501 					tnext = bbextentt;
    502 				else if (tnext < 8)
    503 					tnext = 8;	// guard against round-off error on <0 steps
    504 
    505 				if (spancount > 1)
    506 				{
    507 					sstep = (snext - s) / (spancount - 1);
    508 					tstep = (tnext - t) / (spancount - 1);
    509 				}
    510 			}
    511 
    512 			do
    513 			{
    514 				*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
    515 				s += sstep;
    516 				t += tstep;
    517 			} while (--spancount > 0);
    518 
    519 			s = snext;
    520 			t = tnext;
    521 
    522 		} while (count > 0);
    523 
    524 	} while ((pspan = pspan->pnext) != NULL);
    525 }
    526 
    527 #endif
    528 
    529 
    530 #if	!id386
    531 
    532 /*
    533 =============
    534 D_DrawZSpans
    535 =============
    536 */
    537 void D_DrawZSpans (espan_t *pspan)
    538 {
    539 	int				count, doublecount, izistep;
    540 	int				izi;
    541 	short			*pdest;
    542 	unsigned		ltemp;
    543 	float			zi;
    544 	float			du, dv;
    545 
    546 // FIXME: check for clamping/range problems
    547 // we count on FP exceptions being turned off to avoid range problems
    548 	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
    549 
    550 	do
    551 	{
    552 		pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
    553 
    554 		count = pspan->count;
    555 
    556 	// calculate the initial 1/z
    557 		du = (float)pspan->u;
    558 		dv = (float)pspan->v;
    559 
    560 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
    561 	// we count on FP exceptions being turned off to avoid range problems
    562 		izi = (int)(zi * 0x8000 * 0x10000);
    563 
    564 		if ((long)pdest & 0x02)
    565 		{
    566 			*pdest++ = (short)(izi >> 16);
    567 			izi += izistep;
    568 			count--;
    569 		}
    570 
    571 		if ((doublecount = count >> 1) > 0)
    572 		{
    573 			do
    574 			{
    575 				ltemp = izi >> 16;
    576 				izi += izistep;
    577 				ltemp |= izi & 0xFFFF0000;
    578 				izi += izistep;
    579 				*(int *)pdest = ltemp;
    580 				pdest += 2;
    581 			} while (--doublecount > 0);
    582 		}
    583 
    584 		if (count & 1)
    585 			*pdest = (short)(izi >> 16);
    586 
    587 	} while ((pspan = pspan->pnext) != NULL);
    588 }
    589 
    590 #endif
    591