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