r_plane.cpp (9208B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "Precompiled.h" 30 #include "globaldata.h" 31 32 #include <stdlib.h> 33 34 #include "i_system.h" 35 #include "z_zone.h" 36 #include "w_wad.h" 37 38 #include "doomdef.h" 39 #include "doomstat.h" 40 41 #include "r_local.h" 42 #include "r_sky.h" 43 44 45 46 47 // 48 // opening 49 // 50 51 // Here comes the obnoxious "visplane". 52 53 54 55 // 56 // Clip values are the solid pixel bounding the range. 57 // ::g->floorclip starts out SCREENHEIGHT 58 // ::g->ceilingclip starts out -1 59 // 60 61 // 62 // ::g->spanstart holds the start of a plane span 63 // initialized to 0 at start 64 // 65 66 // 67 // texture mapping 68 // 69 70 71 72 73 74 // 75 // R_InitPlanes 76 // Only at game startup. 77 // 78 void R_InitPlanes (void) 79 { 80 // Doh! 81 } 82 83 84 // 85 // R_MapPlane 86 // 87 // Uses global vars: 88 // ::g->planeheight 89 // ::g->ds_source 90 // ::g->basexscale 91 // ::g->baseyscale 92 // ::g->viewx 93 // ::g->viewy 94 // 95 // BASIC PRIMITIVE 96 // 97 void 98 R_MapPlane 99 ( int y, 100 int x1, 101 int x2 ) 102 { 103 angle_t angle; 104 fixed_t distance; 105 fixed_t length; 106 unsigned index; 107 108 //#ifdef RANGECHECK 109 if ( x2 < x1 || x1<0 || x2>=::g->viewwidth || y>::g->viewheight ) 110 { 111 //I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); 112 return; 113 } 114 //#endif 115 116 if (::g->planeheight != ::g->cachedheight[y]) 117 { 118 ::g->cachedheight[y] = ::g->planeheight; 119 distance = ::g->cacheddistance[y] = FixedMul (::g->planeheight, ::g->yslope[y]); 120 ::g->ds_xstep = ::g->cachedxstep[y] = FixedMul (distance,::g->basexscale); 121 ::g->ds_ystep = ::g->cachedystep[y] = FixedMul (distance,::g->baseyscale); 122 } 123 else 124 { 125 distance = ::g->cacheddistance[y]; 126 ::g->ds_xstep = ::g->cachedxstep[y]; 127 ::g->ds_ystep = ::g->cachedystep[y]; 128 } 129 130 extern angle_t GetViewAngle(); 131 length = FixedMul (distance,::g->distscale[x1]); 132 angle = (GetViewAngle() + ::g->xtoviewangle[x1])>>ANGLETOFINESHIFT; 133 extern fixed_t GetViewX(); extern fixed_t GetViewY(); 134 ::g->ds_xfrac = GetViewX() + FixedMul(finecosine[angle], length); 135 ::g->ds_yfrac = -GetViewY() - FixedMul(finesine[angle], length); 136 137 if (::g->fixedcolormap) 138 ::g->ds_colormap = ::g->fixedcolormap; 139 else 140 { 141 index = distance >> LIGHTZSHIFT; 142 143 if (index >= MAXLIGHTZ ) 144 index = MAXLIGHTZ-1; 145 146 ::g->ds_colormap = ::g->planezlight[index]; 147 } 148 149 ::g->ds_y = y; 150 ::g->ds_x1 = x1; 151 ::g->ds_x2 = x2; 152 153 // high or low detail 154 spanfunc ( 155 ::g->ds_xfrac, 156 ::g->ds_yfrac, 157 ::g->ds_y, 158 ::g->ds_x1, 159 ::g->ds_x2, 160 ::g->ds_xstep, 161 ::g->ds_ystep, 162 ::g->ds_colormap, 163 ::g->ds_source ); 164 } 165 166 167 // 168 // R_ClearPlanes 169 // At begining of frame. 170 // 171 void R_ClearPlanes (void) 172 { 173 int i; 174 angle_t angle; 175 176 // opening / clipping determination 177 for (i=0 ; i < ::g->viewwidth ; i++) 178 { 179 ::g->floorclip[i] = ::g->viewheight; 180 ::g->ceilingclip[i] = -1; 181 } 182 183 ::g->lastvisplane = ::g->visplanes; 184 ::g->lastopening = ::g->openings; 185 186 // texture calculation 187 memset (::g->cachedheight, 0, sizeof(::g->cachedheight)); 188 189 // left to right mapping 190 extern angle_t GetViewAngle(); 191 angle = (GetViewAngle()-ANG90)>>ANGLETOFINESHIFT; 192 193 // scale will be unit scale at SCREENWIDTH/2 distance 194 ::g->basexscale = FixedDiv (finecosine[angle],::g->centerxfrac); 195 ::g->baseyscale = -FixedDiv (finesine[angle],::g->centerxfrac); 196 } 197 198 199 200 201 // 202 // R_FindPlane 203 // 204 visplane_t* R_FindPlane( fixed_t height, int picnum, int lightlevel ) { 205 visplane_t* check; 206 207 if (picnum == ::g->skyflatnum) { 208 height = 0; // all skys map together 209 lightlevel = 0; 210 } 211 212 for (check=::g->visplanes; check < ::g->lastvisplane; check++) { 213 if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel) { 214 break; 215 } 216 } 217 218 if (check < ::g->lastvisplane) 219 return check; 220 221 //if (::g->lastvisplane - ::g->visplanes == MAXVISPLANES) 222 //I_Error ("R_FindPlane: no more visplanes"); 223 if ( ::g->lastvisplane - ::g->visplanes == MAXVISPLANES ) { 224 check = ::g->visplanes; 225 return check; 226 } 227 228 ::g->lastvisplane++; 229 230 check->height = height; 231 check->picnum = picnum; 232 check->lightlevel = lightlevel; 233 check->minx = SCREENWIDTH; 234 check->maxx = -1; 235 236 memset(check->top,0xff,sizeof(check->top)); 237 238 return check; 239 } 240 241 242 // 243 // R_CheckPlane 244 // 245 visplane_t* 246 R_CheckPlane 247 ( visplane_t* pl, 248 int start, 249 int stop ) 250 { 251 int intrl; 252 int intrh; 253 int unionl; 254 int unionh; 255 int x; 256 257 if (start < pl->minx) 258 { 259 intrl = pl->minx; 260 unionl = start; 261 } 262 else 263 { 264 unionl = pl->minx; 265 intrl = start; 266 } 267 268 if (stop > pl->maxx) 269 { 270 intrh = pl->maxx; 271 unionh = stop; 272 } 273 else 274 { 275 unionh = pl->maxx; 276 intrh = stop; 277 } 278 279 for (x=intrl ; x<= intrh ; x++) 280 if (pl->top[x] != 0xffff) 281 break; 282 283 if (x > intrh) 284 { 285 pl->minx = unionl; 286 pl->maxx = unionh; 287 288 // use the same one 289 return pl; 290 } 291 292 if ( ::g->lastvisplane - ::g->visplanes == MAXVISPLANES ) { 293 return pl; 294 } 295 296 // make a new visplane 297 ::g->lastvisplane->height = pl->height; 298 ::g->lastvisplane->picnum = pl->picnum; 299 ::g->lastvisplane->lightlevel = pl->lightlevel; 300 301 pl = ::g->lastvisplane++; 302 pl->minx = start; 303 pl->maxx = stop; 304 305 memset(pl->top,0xff,sizeof(pl->top)); 306 307 return pl; 308 } 309 310 311 // 312 // R_MakeSpans 313 // 314 void 315 R_MakeSpans 316 ( int x, 317 int t1, 318 int b1, 319 int t2, 320 int b2 ) 321 { 322 while (t1 < t2 && t1<=b1) 323 { 324 R_MapPlane (t1,::g->spanstart[t1],x-1); 325 t1++; 326 } 327 while (b1 > b2 && b1>=t1) 328 { 329 R_MapPlane (b1,::g->spanstart[b1],x-1); 330 b1--; 331 } 332 333 while (t2 < t1 && t2<=b2) 334 { 335 ::g->spanstart[t2] = x; 336 t2++; 337 } 338 while (b2 > b1 && b2>=t2) 339 { 340 ::g->spanstart[b2] = x; 341 b2--; 342 } 343 } 344 345 346 347 // 348 // R_DrawPlanes 349 // At the end of each frame. 350 // 351 void R_DrawPlanes (void) 352 { 353 visplane_t* pl; 354 int light; 355 int x; 356 int stop; 357 int angle; 358 359 #ifdef RANGECHECK 360 if (::g->ds_p - ::g->drawsegs > MAXDRAWSEGS) 361 I_Error ("R_DrawPlanes: ::g->drawsegs overflow (%i)", 362 ::g->ds_p - ::g->drawsegs); 363 364 if (::g->lastvisplane - ::g->visplanes > MAXVISPLANES) 365 I_Error ("R_DrawPlanes: visplane overflow (%i)", 366 ::g->lastvisplane - ::g->visplanes); 367 368 if (::g->lastopening - ::g->openings > MAXOPENINGS) 369 I_Error ("R_DrawPlanes: opening overflow (%i)", 370 ::g->lastopening - ::g->openings); 371 #endif 372 373 for (pl = ::g->visplanes ; pl < ::g->lastvisplane ; pl++) 374 { 375 if (pl->minx > pl->maxx) 376 continue; 377 378 379 // sky flat 380 if (pl->picnum == ::g->skyflatnum) 381 { 382 ::g->dc_iscale = ::g->pspriteiscale>>::g->detailshift; 383 384 // Sky is allways drawn full bright, 385 // i.e. ::g->colormaps[0] is used. 386 // Because of this hack, sky is not affected 387 // by INVUL inverse mapping. 388 ::g->dc_colormap = ::g->colormaps; 389 ::g->dc_texturemid = ::g->skytexturemid; 390 for (x=pl->minx ; x <= pl->maxx ; x++) 391 { 392 ::g->dc_yl = pl->top[x]; 393 ::g->dc_yh = pl->bottom[x]; 394 395 if (::g->dc_yl <= ::g->dc_yh) 396 { 397 extern angle_t GetViewAngle(); 398 angle = (GetViewAngle() + ::g->xtoviewangle[x])>>ANGLETOSKYSHIFT; 399 ::g->dc_x = x; 400 ::g->dc_source = R_GetColumn(::g->skytexture, angle); 401 colfunc ( ::g->dc_colormap, ::g->dc_source ); 402 } 403 } 404 continue; 405 } 406 407 // regular flat 408 ::g->ds_source = (byte*)W_CacheLumpNum(::g->firstflat + 409 ::g->flattranslation[pl->picnum], 410 PU_CACHE_SHARED); 411 412 ::g->planeheight = abs(pl->height-::g->viewz); 413 light = (pl->lightlevel >> LIGHTSEGSHIFT)+::g->extralight; 414 415 if (light >= LIGHTLEVELS) 416 light = LIGHTLEVELS-1; 417 418 if (light < 0) 419 light = 0; 420 421 ::g->planezlight = ::g->zlight[light]; 422 423 pl->top[pl->maxx+1] = 0xffff; 424 pl->top[pl->minx-1] = 0xffff; 425 426 stop = pl->maxx + 1; 427 428 for (x=pl->minx ; x<= stop ; x++) 429 { 430 R_MakeSpans(x,pl->top[x-1], 431 pl->bottom[x-1], 432 pl->top[x], 433 pl->bottom[x]); 434 } 435 } 436 } 437