void RenderViewport::SetViewport(FLevelLocals *Level, RenderThread *thread, int fullWidth, int fullHeight, float trueratio) { int virtheight, virtwidth, virtwidth2, virtheight2; if (!RenderingToCanvas) { // Set r_viewsize cvar to reflect the current view size UCVarValue value; char temp[16]; mysnprintf(temp, countof(temp), "%d x %d", viewwidth, viewheight); value.String = temp; r_viewsize.ForceSet(value, CVAR_String); } fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to CenterX = viewwindow.centerx; CenterY = viewwindow.centery; virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; if (AspectTallerThanWide(trueratio)) { virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48; } else { virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48; } if (AspectTallerThanWide(viewwindow.WidescreenRatio)) { virtheight = virtheight * AspectMultiplier(viewwindow.WidescreenRatio) / 48; } else { virtwidth = virtwidth * AspectMultiplier(viewwindow.WidescreenRatio) / 48; } double ypixelstretch = (Level->info) ? Level->info->pixelstretch : 1.2; BaseYaspectMul = 320.0 * virtheight2 / (r_Yaspect * virtwidth2); YaspectMul = 320.0 * virtheight / (r_Yaspect * virtwidth) * ypixelstretch / 1.2; IYaspectMul = (double)virtwidth * r_Yaspect / 320.0 / virtheight; InvZtoScale = YaspectMul * CenterX; WallTMapScale2 = IYaspectMul / CenterX * 1.2 / ypixelstretch; // thing clipping fillshort(screenheightarray, viewwidth, (short)viewheight); InitTextureMapping(); // Reset r_*Visibility vars thread->Light->SetVisibility(this, r_visibility, !!(Level->flags3 & LEVEL3_NOLIGHTFADE)); SetupBuffer(); }
void R_ClearPlanes (bool fullclear) { int i; // Don't clear fake planes if not doing a full clear. if (!fullclear) { for (i = 0; i <= MAXVISPLANES-1; i++) // new code -- killough { for (visplane_t **probe = &visplanes[i]; *probe != NULL; ) { if ((*probe)->sky < 0) { // fake: move past it probe = &(*probe)->next; } else { // not fake: move to freelist visplane_t *vis = *probe; *freehead = vis; *probe = vis->next; vis->next = NULL; freehead = &vis->next; } } } } else { for (i = 0; i <= MAXVISPLANES; i++) // new code -- killough { for (*freehead = visplanes[i], visplanes[i] = NULL; *freehead; ) { freehead = &(*freehead)->next; } } // opening / clipping determination fillshort (floorclip, viewwidth, viewheight); // [RH] clip ceiling to console bottom fillshort (ceilingclip, viewwidth, !screen->Accel2D && ConBottom > viewwindowy && !bRenderingToCanvas ? (ConBottom - viewwindowy) : 0); lastopening = 0; } }
DLightningThinker::DLightningThinker () : DThinker (STAT_LIGHTNING) { Stopped = false; LightningFlashCount = 0; NextLightningFlash = ((pr_lightning()&15)+5)*35; // don't flash at level start LightningLightLevels.Resize(level.sectors.Size()); fillshort(&LightningLightLevels[0], LightningLightLevels.Size(), SHRT_MAX); }
void P_FindParticleSubsectors (FLevelLocals *Level) { if (Level->ParticlesInSubsec.Size() < Level->subsectors.Size()) { Level->ParticlesInSubsec.Reserve (Level->subsectors.Size() - Level->ParticlesInSubsec.Size()); } fillshort (&Level->ParticlesInSubsec[0], Level->subsectors.Size(), NO_PARTICLE); if (!r_particles) { return; } for (uint16_t i = Level->ActiveParticles; i != NO_PARTICLE; i = Level->Particles[i].tnext) { // Try to reuse the subsector from the last portal check, if still valid. if (Level->Particles[i].subsector == nullptr) Level->Particles[i].subsector = Level->PointInRenderSubsector(Level->Particles[i].Pos); int ssnum = Level->Particles[i].subsector->Index(); Level->Particles[i].snext = Level->ParticlesInSubsec[ssnum]; Level->ParticlesInSubsec[ssnum] = i; } }
void DLightningThinker::LightningFlash () { int i, j; sector_t *tempSec; uint8_t flashLight; if (LightningFlashCount) { LightningFlashCount--; if (LightningFlashCount) { // reduce the brightness of the flash tempSec = &level.sectors[0]; for (i = level.sectors.Size(), j = 0; i > 0; ++j, --i, ++tempSec) { // [RH] Checking this sector's applicability to lightning now // is not enough to know if we should lower its light level, // because it might have changed since the lightning flashed. // Instead, change the light if this sector was effected by // the last flash. if (LightningLightLevels[j] < tempSec->lightlevel-4) { tempSec->ChangeLightLevel(-4); } } } else { // remove the alternate lightning flash special tempSec = &level.sectors[0]; for (i = level.sectors.Size(), j = 0; i > 0; ++j, --i, ++tempSec) { if (LightningLightLevels[j] != SHRT_MAX) { tempSec->SetLightLevel(LightningLightLevels[j]); } } fillshort(&LightningLightLevels[0], level.sectors.Size(), SHRT_MAX); level.flags &= ~LEVEL_SWAPSKIES; } return; } LightningFlashCount = (pr_lightning()&7)+8; flashLight = 200+(pr_lightning()&31); tempSec = &level.sectors[0]; for (i = level.sectors.Size(), j = 0; i > 0; ++j, --i, ++tempSec) { // allow combination of the lightning sector specials with bit masks int special = tempSec->special; if (tempSec->GetTexture(sector_t::ceiling) == skyflatnum || special == Light_IndoorLightning1 || special == Light_IndoorLightning2 || special == Light_OutdoorLightning) { LightningLightLevels[j] = tempSec->lightlevel; if (special == Light_IndoorLightning1) { tempSec->SetLightLevel(MIN<int> (tempSec->lightlevel+64, flashLight)); } else if (special == Light_IndoorLightning2) { tempSec->SetLightLevel(MIN<int> (tempSec->lightlevel+32, flashLight)); } else { tempSec->SetLightLevel(flashLight); } if (tempSec->lightlevel < LightningLightLevels[j]) { // The lightning is darker than this sector already is, so no lightning here. tempSec->SetLightLevel(LightningLightLevels[j]); LightningLightLevels[j] = SHRT_MAX; } } } level.flags |= LEVEL_SWAPSKIES; // set alternate sky S_Sound (CHAN_AUTO, "world/thunder", 1.0, ATTN_NONE); // [ZZ] just in case E_WorldLightning(); // start LIGHTNING scripts FBehavior::StaticStartTypedScripts (SCRIPT_Lightning, NULL, false); // [RH] Run lightning scripts // Calculate the next lighting flash if (!NextLightningFlash) { if (pr_lightning() < 50) { // Immediate Quick flash NextLightningFlash = (pr_lightning()&15)+16; } else { if (pr_lightning() < 128 && !(level.time&32)) { NextLightningFlash = ((pr_lightning()&7)+2)*35; } else { NextLightningFlash = ((pr_lightning()&15)+5)*35; } } } }
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop) { int intrl, intrh; int unionl, unionh; int x; assert (start >= 0 && start < viewwidth); assert (stop > start && stop <= viewwidth); if (start < pl->left) { intrl = pl->left; unionl = start; } else { unionl = pl->left; intrl = start; } if (stop > pl->right) { intrh = pl->right; unionh = stop; } else { unionh = pl->right; intrh = stop; } for (x = intrl; x < intrh && pl->top[x] == 0x7fff; x++) ; if (x >= intrh) { // use the same visplane pl->left = unionl; pl->right = unionh; } else { // make a new visplane unsigned hash; if (pl->portal != NULL && !(pl->portal->mFlags & PORTSF_INSKYBOX) && viewactive) { hash = MAXVISPLANES; } else { hash = visplane_hash (pl->picnum.GetIndex(), pl->lightlevel, pl->height); } visplane_t *new_pl = new_visplane (hash); new_pl->height = pl->height; new_pl->picnum = pl->picnum; new_pl->lightlevel = pl->lightlevel; new_pl->xform = pl->xform; new_pl->colormap = pl->colormap; new_pl->portal = pl->portal; new_pl->extralight = pl->extralight; new_pl->visibility = pl->visibility; new_pl->viewpos = pl->viewpos; new_pl->viewangle = pl->viewangle; new_pl->sky = pl->sky; new_pl->Alpha = pl->Alpha; new_pl->Additive = pl->Additive; new_pl->CurrentPortalUniq = pl->CurrentPortalUniq; new_pl->MirrorFlags = pl->MirrorFlags; new_pl->CurrentSkybox = pl->CurrentSkybox; pl = new_pl; pl->left = start; pl->right = stop; fillshort (pl->top, viewwidth, 0x7fff); } return pl; }
visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal) { secplane_t plane; visplane_t *check; unsigned hash; // killough bool isskybox; const FTransform *xform = &xxform; fixed_t alpha = FLOAT2FIXED(Alpha); //angle_t angle = (xform.Angle + xform.baseAngle).BAMs(); FTransform nulltransform; if (picnum == skyflatnum) // killough 10/98 { // most skies map together lightlevel = 0; xform = &nulltransform; nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0; nulltransform.xScale = nulltransform.yScale = 1; nulltransform.Angle = nulltransform.baseAngle = 0.0; additive = false; // [RH] Map floor skies and ceiling skies to separate visplanes. This isn't // always necessary, but it is needed if a floor and ceiling sky are in the // same column but separated by a wall. If they both try to reside in the // same visplane, then only the floor sky will be drawn. plane.set(0., 0., height.fC(), 0.); isskybox = portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX); } else if (portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX)) { plane = height; isskybox = true; } else { plane = height; isskybox = false; // kg3D - hack, store alpha in sky // i know there is ->alpha, but this also allows to identify fake plane // and ->alpha is for stacked sectors if (fake3D & (FAKE3D_FAKEFLOOR|FAKE3D_FAKECEILING)) sky = 0x80000000 | fakeAlpha; else sky = 0; // not skyflatnum so it can't be a sky portal = NULL; alpha = OPAQUE; } // New visplane algorithm uses hash table -- killough hash = isskybox ? MAXVISPLANES : visplane_hash (picnum.GetIndex(), lightlevel, height); for (check = visplanes[hash]; check; check = check->next) // killough { if (isskybox) { if (portal == check->portal && plane == check->height) { if (portal->mType != PORTS_SKYVIEWPOINT) { // This skybox is really a stacked sector, so we need to // check even more. if (check->extralight == stacked_extralight && check->visibility == stacked_visibility && check->viewpos == stacked_viewpos && ( // headache inducing logic... :( (portal->mType != PORTS_STACKEDSECTORTHING) || ( check->Alpha == alpha && check->Additive == additive && (alpha == 0 || // if alpha is > 0 everything needs to be checked (plane == check->height && picnum == check->picnum && lightlevel == check->lightlevel && basecolormap == check->colormap && // [RH] Add more checks *xform == check->xform ) ) && check->viewangle == stacked_angle ) ) ) { return check; } } else { return check; } } } else if (plane == check->height && picnum == check->picnum && lightlevel == check->lightlevel && basecolormap == check->colormap && // [RH] Add more checks *xform == check->xform && sky == check->sky && CurrentPortalUniq == check->CurrentPortalUniq && MirrorFlags == check->MirrorFlags && CurrentSkybox == check->CurrentSkybox && ViewPos == check->viewpos ) { return check; } } check = new_visplane (hash); // killough check->height = plane; check->picnum = picnum; check->lightlevel = lightlevel; check->xform = *xform; check->colormap = basecolormap; // [RH] Save colormap check->sky = sky; check->portal = portal; check->left = viewwidth; // Was SCREENWIDTH -- killough 11/98 check->right = 0; check->extralight = stacked_extralight; check->visibility = stacked_visibility; check->viewpos = stacked_viewpos; check->viewangle = stacked_angle; check->Alpha = alpha; check->Additive = additive; check->CurrentPortalUniq = CurrentPortalUniq; check->MirrorFlags = MirrorFlags; check->CurrentSkybox = CurrentSkybox; fillshort (check->top, viewwidth, 0x7fff); return check; }