1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 28unsigned char *r_turb_pbase, *r_turb_pdest; 29fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; 30int *r_turb_turb; 31int r_turb_spancount; 32 33void D_DrawTurbulent8Span (void); 34 35 36/* 37============= 38D_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*/ 44void 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============= 96D_DrawTurbulent8Span 97============= 98*/ 99void 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============= 117Turbulent8 118============= 119*/ 120void 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============= 252D_DrawSpans8 253============= 254*/ 255void 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============= 390D_DrawZSpans 391============= 392*/ 393void 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