static dboolean CheckClip(seg_t * seg, sector_t * frontsector, sector_t * backsector) { static sector_t tempsec_back, tempsec_front; backsector = R_FakeFlat(backsector, &tempsec_back, NULL, NULL, true); frontsector = R_FakeFlat(frontsector, &tempsec_front, NULL, NULL, false); // check for closed sectors! if (backsector->ceilingheight <= frontsector->floorheight) { if (seg->sidedef->toptexture == NO_TEXTURE) return false; if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum) return false; return true; } if (frontsector->ceilingheight <= backsector->floorheight) { if (seg->sidedef->bottomtexture == NO_TEXTURE) return false; // properly render skies (consider door "open" if both floors are sky): if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum) return false; return true; } if (backsector->ceilingheight <= backsector->floorheight) { // preserve a kind of transparent door/lift special effect: if (backsector->ceilingheight < frontsector->ceilingheight) { if (seg->sidedef->toptexture == NO_TEXTURE) return false; } if (backsector->floorheight > frontsector->floorheight) { if (seg->sidedef->bottomtexture == NO_TEXTURE) return false; } if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum) return false; if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum) return false; return true; } return false; }
void GL_RecalcSeg(seg_t *seg, sector_t *controlSector) { int index; bool fogBoundary = false; sector_t *backSector, ts; index = numsubsectors * 2; index += (seg - segs) * 3; backSector = R_FakeFlat(seg->backsector, &ts, NULL, NULL, false); if (backSector) { fogBoundary = IsFogBoundary(controlSector, backSector); } if (seg->linedef && seg->sidedef) { if (seg->backsector && seg->sidedef->toptexture) { GL_RecalcUpperWall(seg, controlSector, gl_polys + index); } if (seg->sidedef->midtexture || fogBoundary) { GL_RecalcMidWall(seg, controlSector, gl_polys + (index + 1)); } if (seg->backsector && seg->sidedef->bottomtexture) { GL_RecalcLowerWall(seg, controlSector, gl_polys + (index + 2)); } } }
// // R_Subsector // Determine floor/ceiling planes. // Add sprites of things in sector. // Draw one or more line segments. // static void R_Subsector(int num) { subsector_t *sub = &subsectors[num]; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 int count = sub->numlines; seg_t *line = &segs[sub->firstline]; frontsector = sub->sector; // [AM] Interpolate sector movement. Usually only needed // when you're standing inside the sector. R_MaybeInterpolateSector(frontsector); // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); floorplane = (frontsector->interpfloorheight < viewz // killough 3/7/98 || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->interpfloorheight, (frontsector->floorpic == skyflatnum // killough 10/98 && (frontsector->sky & PL_SKYFLAT) ? frontsector->sky : frontsector->floorpic), floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs) : NULL); ceilingplane = (frontsector->interpceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->interpceilingheight, // killough 3/8/98 (frontsector->ceilingpic == skyflatnum // killough 10/98 && (frontsector->sky & PL_SKYFLAT) ? frontsector->sky : frontsector->ceilingpic), ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs) : NULL); // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // // 10/98 killough: // // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // That is part of the 242 effect!!! If you simply pass sub->sector to // the old code you will not get correct lighting for underwater sprites!!! // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. if (sub->sector->validcount != validcount) { sub->sector->validcount = validcount; R_AddSprites(sub->sector, floorlightlevel); } while (count--) R_AddLine(line++); }
static void R_Subsector(int num) { subsector_t *sub = &subsectors[num]; int count = sub->numlines; seg_t *line = &segs[sub->firstline]; sector_t tempsec; int floorlightlevel; int ceilinglightlevel; frontsector = sub->sector; frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); floorplane = frontsector->floorheight < viewz || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, frontsector->floor_xoffs, frontsector->floor_yoffs) : NULL; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic == skyflatnum && frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs) : NULL; R_AddSprites(sub, (floorlightlevel + ceilinglightlevel) / 2); while (count--) { if (line->miniseg == false) R_AddLine(line); line++; curline = NULL; } }
void GL_RecalcMidWall(seg_t *seg, sector_t *frontSector, gl_poly_t *poly) { float height1, height2, v1[5], v2[5], v3[5], v4[5], txScale, tyScale; float yOffset1, yOffset2, yOffset, xOffset; float upperHeight, lowerHeight; float tmpOffset = seg->sidedef->rowoffset * INV_FRACUNIT; long offset = 0; int texHeight; FTexture *tex = NULL; texcoord_t ll, ul, lr, ur; sector_t *backSector, ts2; vertex_t *vert1, *vert2; if (!poly->initialized) GL_InitPolygon(poly); poly->lastUpdate = frameStartMS; poly->initialized = true; tex = TexMan(seg->sidedef->midtexture); vert1 = seg->v1; vert2 = seg->v2; backSector = R_FakeFlat(seg->backsector, &ts2, NULL, NULL, false); v1[0] = -vert1->x * MAP_SCALE; v1[2] = vert1->y * MAP_SCALE; v2[0] = -vert2->x * MAP_SCALE; v2[2] = vert2->y * MAP_SCALE; v1[1] = (float)frontSector->floorplane.ZatPoint(seg->v1); v2[1] = (float)frontSector->floorplane.ZatPoint(seg->v2); if ((seg->linedef->special == Line_Mirror && seg->backsector == NULL) || tex == NULL) { if (backSector) { height1 = (float)backSector->ceilingplane.ZatPoint(vert1); height2 = (float)backSector->ceilingplane.ZatPoint(vert2); } else { height1 = (float)frontSector->ceilingplane.ZatPoint(vert1); height2 = (float)frontSector->ceilingplane.ZatPoint(vert2); } } else { //yOffset = seg->sidedef->rowoffset * INV_FRACUNIT; yOffset = 0.f; tmpOffset = 0.f; offset = seg->sidedef->rowoffset; yOffset1 = yOffset2 = yOffset; // texscale: 8 = 1.0, 16 = 2.0, 4 = 0.5 txScale = tex->ScaleX ? tex->ScaleX / 8.f : 1.f; tyScale = tex->ScaleY ? tex->ScaleY / 8.f : 1.f; xOffset = (seg->offset * txScale) * INV_FRACUNIT; texHeight = (int)(tex->GetHeight() / tyScale); textureList.GetTexture(seg->sidedef->midtexture, true); ll.x = xOffset / tex->GetWidth(); ul.x = ll.x; lr.x = ll.x + (seg->length / tex->GetWidth() * txScale); ur.x = lr.x; if (backSector) { height1 = (float)MIN(frontSector->ceilingplane.ZatPoint(vert1), backSector->ceilingplane.ZatPoint(vert1)); height2 = (float)MIN(frontSector->ceilingplane.ZatPoint(vert2), backSector->ceilingplane.ZatPoint(vert2)); } else { height1 = (float)frontSector->ceilingplane.ZatPoint(vert1); height2 = (float)frontSector->ceilingplane.ZatPoint(vert2); } if (backSector && (textureList.IsTransparent() || seg->linedef->flags & ML_TWOSIDED)) { int h = texHeight; #if 0 if (seg->linedef->flags & ML_DONTPEGBOTTOM) { if (backSector) { v1[1] = MAX (frontSector->floortexz, backSector->floortexz) + offset; v2[1] = MAX (frontSector->floortexz, backSector->floortexz) + offset; } else { v1[1] = frontSector->floortexz + offset; v2[1] = frontSector->floortexz + offset; } } else { if (backSector) { v1[1] = MIN (frontSector->ceilingtexz, backSector->ceilingtexz) + offset - (h << FRACBITS); v2[1] = MIN (frontSector->ceilingtexz, backSector->ceilingtexz) + offset - (h << FRACBITS); } else { v1[1] = frontSector->ceilingtexz + offset - (h << FRACBITS); v2[1] = frontSector->ceilingtexz + offset - (h << FRACBITS); } } height1 = (h << FRACBITS) + v1[1]; height2 = (h << FRACBITS) + v2[1]; #else float rbceil = (float)backSector->ceilingtexz, rbfloor = (float)backSector->floortexz, rfceil = (float)frontSector->ceilingtexz, rffloor = (float)frontSector->floortexz; float gaptop, gapbottom; yOffset = (float)seg->sidedef->rowoffset; height1 = gaptop = MIN(rbceil, rfceil); v1[1] = gapbottom = MAX(rbfloor, rffloor); if (seg->linedef->flags & ML_DONTPEGBOTTOM) { v1[1] += yOffset; height1 = v1[1] + (tex->GetHeight() * FRACUNIT); } else { height1 += yOffset; v1[1] = height1 - (tex->GetHeight() * FRACUNIT); } height2 = height1; v2[1] = v1[1]; #endif } } // make sure to clip the geometry to the back sector... if (backSector) { if (seg->sidedef->bottomtexture) { v1[1] = MAX(v1[1], backSector->floorplane.ZatPoint(seg->v1)); v2[1] = MAX(v2[1], backSector->floorplane.ZatPoint(seg->v2)); } if (seg->sidedef->toptexture) { height1 = MIN(height1, backSector->ceilingplane.ZatPoint(seg->v1)); height2 = MIN(height2, backSector->ceilingplane.ZatPoint(seg->v2)); } } memcpy(v3, v1, sizeof(float) * 3); memcpy(v4, v2, sizeof(float) * 3); ul.y = ur.y = 1.f; ll.y = lr.y = 0.f; if (tex) { yOffset = 0.f; // code borrowed from Legacy ;) // damn pegged/unpegged/two sided lines! if (backSector) { float worldHigh = backSector->ceilingtexz * INV_FRACUNIT; float worldLow = backSector->floortexz * INV_FRACUNIT; float polyBottom, polyTop; lowerHeight = frontSector->floortexz * INV_FRACUNIT; upperHeight = frontSector->ceilingtexz * INV_FRACUNIT; float openTop = upperHeight < worldHigh ? upperHeight : worldHigh; float openBottom = lowerHeight > worldLow ? lowerHeight : worldLow; if (seg->linedef->flags & ML_DONTPEGBOTTOM) { polyBottom = openBottom + seg->sidedef->rowoffset * INV_FRACUNIT; polyTop = polyBottom + texHeight; upperHeight = MIN(openTop, polyTop); lowerHeight = MAX(openBottom, polyBottom); yOffset = lowerHeight + texHeight - upperHeight + polyBottom - lowerHeight; } else { polyTop = openTop + seg->sidedef->rowoffset * INV_FRACUNIT; polyBottom = polyTop - texHeight; yOffset = polyTop - upperHeight; } } else { lowerHeight = frontSector->floortexz * INV_FRACUNIT; upperHeight = frontSector->ceilingtexz * INV_FRACUNIT; yOffset = 0.f; if (seg->linedef->flags & ML_DONTPEGBOTTOM) { yOffset += lowerHeight + texHeight - upperHeight; } } ll.y = lr.y = yOffset / texHeight; ul.y = ur.y = ll.y + ((upperHeight - lowerHeight) / texHeight); // scale the coordinates //ul.y *= tyScale; //ur.y *= tyScale; //ll.y *= tyScale; //lr.y *= tyScale; // clip to slopes ul.y -= ((v1[1] * INV_FRACUNIT) - lowerHeight) / texHeight; ur.y -= ((v2[1] * INV_FRACUNIT) - lowerHeight) / texHeight; ll.y += (upperHeight - (height1 * INV_FRACUNIT)) / texHeight; lr.y += (upperHeight - (height2 * INV_FRACUNIT)) / texHeight; } v1[1] *= MAP_SCALE; v2[1] *= MAP_SCALE; v3[1] = height1 * MAP_SCALE; v4[1] = height2 * MAP_SCALE; v1[3] = ul.x; v1[4] = ul.y; v2[3] = ur.x; v2[4] = ur.y; v3[3] = ll.x; v3[4] = ll.y; v4[3] = lr.x; v4[4] = lr.y; memcpy(poly->vertices + (0 * 3), v3, sizeof(float) * 3); memcpy(poly->vertices + (1 * 3), v1, sizeof(float) * 3); memcpy(poly->vertices + (2 * 3), v2, sizeof(float) * 3); memcpy(poly->vertices + (3 * 3), v4, sizeof(float) * 3); memcpy(poly->texCoords + (0 * 2), v3 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (1 * 2), v1 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (2 * 2), v2 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (3 * 2), v4 + 3, sizeof(float) * 2); }
void R_AddLine (seg_t *line) { static sector_t tempsec; // killough 3/8/98: ceiling/water hack bool solid; fixed_t tx1, tx2, ty1, ty2; curline = line; // [RH] Color if not texturing line dc_color = (((int)(line - segs) * 8) + 4) & 255; tx1 = line->v1->x - viewx; tx2 = line->v2->x - viewx; ty1 = line->v1->y - viewy; ty2 = line->v2->y - viewy; // Reject lines not facing viewer if (DMulScale32 (ty1, tx1-tx2, tx1, ty2-ty1) >= 0) return; if (WallC.Init(tx1, ty1, tx2, ty2, 32)) return; if (WallC.sx1 >= WindowRight || WallC.sx2 <= WindowLeft) return; if (line->linedef == NULL) { if (R_CheckClipWallSegment (WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } return; } // reject lines that aren't seen from the portal (if any) // [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes. if (!CurrentPortalInSkybox && CurrentPortal && P_ClipLineToPortal(line->linedef, CurrentPortal->dst, viewx, viewy)) return; vertex_t *v1, *v2; v1 = line->linedef->v1; v2 = line->linedef->v2; if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2)) { // The seg is the entire wall. WallT.InitFromWallCoords(&WallC); } else { // The seg is only part of the wall. if (line->linedef->sidedef[0] != line->sidedef) { swapvalues (v1, v2); } WallT.InitFromLine(v1->x - viewx, v1->y - viewy, v2->x - viewx, v2->y - viewy); } if (!(fake3D & FAKE3D_FAKEBACK)) { backsector = line->backsector; } rw_frontcz1 = frontsector->ceilingplane.ZatPoint (line->v1->x, line->v1->y); rw_frontfz1 = frontsector->floorplane.ZatPoint (line->v1->x, line->v1->y); rw_frontcz2 = frontsector->ceilingplane.ZatPoint (line->v2->x, line->v2->y); rw_frontfz2 = frontsector->floorplane.ZatPoint (line->v2->x, line->v2->y); rw_mustmarkfloor = rw_mustmarkceiling = false; rw_havehigh = rw_havelow = false; // Single sided line? if (backsector == NULL || (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0])) { solid = true; } else { // kg3D - its fake, no transfer_heights if (!(fake3D & FAKE3D_FAKEBACK)) { // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true); } doorclosed = 0; // killough 4/16/98 rw_backcz1 = backsector->ceilingplane.ZatPoint (line->v1->x, line->v1->y); rw_backfz1 = backsector->floorplane.ZatPoint (line->v1->x, line->v1->y); rw_backcz2 = backsector->ceilingplane.ZatPoint (line->v2->x, line->v2->y); rw_backfz2 = backsector->floorplane.ZatPoint (line->v2->x, line->v2->y); // Cannot make these walls solid, because it can result in // sprite clipping problems for sprites near the wall if (rw_frontcz1 > rw_backcz1 || rw_frontcz2 > rw_backcz2) { rw_havehigh = true; WallMost (wallupper, backsector->ceilingplane, &WallC); } if (rw_frontfz1 < rw_backfz1 || rw_frontfz2 < rw_backfz2) { rw_havelow = true; WallMost (walllower, backsector->floorplane, &WallC); } // Closed door. if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2)) { solid = true; } else if ( // properly render skies (consider door "open" if both ceilings are sky): (backsector->GetTexture(sector_t::ceiling) != skyflatnum || frontsector->GetTexture(sector_t::ceiling) != skyflatnum) // if door is closed because back is shut: && rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2 // preserve a kind of transparent door/lift special effect: && ((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) || line->sidedef->GetTexture(side_t::top).isValid()) && ((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) || line->sidedef->GetTexture(side_t::bottom).isValid())) { // killough 1/18/98 -- This function is used to fix the automap bug which // showed lines behind closed doors simply because the door had a dropoff. // // It assumes that Doom has already ruled out a door being closed because // of front-back closure (e.g. front floor is taller than back ceiling). // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c doorclosed = true; solid = true; } else if (frontsector->ceilingplane != backsector->ceilingplane || frontsector->floorplane != backsector->floorplane) { // Window. solid = false; } else if (backsector->lightlevel != frontsector->lightlevel || backsector->GetTexture(sector_t::floor) != frontsector->GetTexture(sector_t::floor) || backsector->GetTexture(sector_t::ceiling) != frontsector->GetTexture(sector_t::ceiling) || curline->sidedef->GetTexture(side_t::mid).isValid() // killough 3/7/98: Take flats offsets into account: || backsector->GetXOffset(sector_t::floor) != frontsector->GetXOffset(sector_t::floor) || backsector->GetYOffset(sector_t::floor) != frontsector->GetYOffset(sector_t::floor) || backsector->GetXOffset(sector_t::ceiling) != frontsector->GetXOffset(sector_t::ceiling) || backsector->GetYOffset(sector_t::ceiling) != frontsector->GetYOffset(sector_t::ceiling) || backsector->GetPlaneLight(sector_t::floor) != frontsector->GetPlaneLight(sector_t::floor) || backsector->GetPlaneLight(sector_t::ceiling) != frontsector->GetPlaneLight(sector_t::ceiling) || backsector->GetFlags(sector_t::floor) != frontsector->GetFlags(sector_t::floor) || backsector->GetFlags(sector_t::ceiling) != frontsector->GetFlags(sector_t::ceiling) // [RH] Also consider colormaps || backsector->ColorMap != frontsector->ColorMap // [RH] and scaling || backsector->GetXScale(sector_t::floor) != frontsector->GetXScale(sector_t::floor) || backsector->GetYScale(sector_t::floor) != frontsector->GetYScale(sector_t::floor) || backsector->GetXScale(sector_t::ceiling) != frontsector->GetXScale(sector_t::ceiling) || backsector->GetYScale(sector_t::ceiling) != frontsector->GetYScale(sector_t::ceiling) // [RH] and rotation || backsector->GetAngle(sector_t::floor) != frontsector->GetAngle(sector_t::floor) || backsector->GetAngle(sector_t::ceiling) != frontsector->GetAngle(sector_t::ceiling) // kg3D - and fake lights || (frontsector->e && frontsector->e->XFloor.lightlist.Size()) || (backsector->e && backsector->e->XFloor.lightlist.Size()) ) { solid = false; } else { // Reject empty lines used for triggers and special events. // Identical floor and ceiling on both sides, identical light levels // on both sides, and no middle texture. // When using GL nodes, do a clipping test for these lines so we can // mark their subsectors as visible for automap texturing. if (hasglnodes && !(InSubsector->flags & SSECF_DRAWN)) { if (R_CheckClipWallSegment(WallC.sx1, WallC.sx2)) { InSubsector->flags |= SSECF_DRAWN; } } return; } } rw_prepped = false; if (line->linedef->special == Line_Horizon) { // Be aware: Line_Horizon does not work properly with sloped planes clearbufshort (walltop+WallC.sx1, WallC.sx2 - WallC.sx1, centery); clearbufshort (wallbottom+WallC.sx1, WallC.sx2 - WallC.sx1, centery); } else { rw_ceilstat = WallMost (walltop, frontsector->ceilingplane, &WallC); rw_floorstat = WallMost (wallbottom, frontsector->floorplane, &WallC); // [RH] treat off-screen walls as solid #if 0 // Maybe later... if (!solid) { if (rw_ceilstat == 12 && line->sidedef->GetTexture(side_t::top) != 0) { rw_mustmarkceiling = true; solid = true; } if (rw_floorstat == 3 && line->sidedef->GetTexture(side_t::bottom) != 0) { rw_mustmarkfloor = true; solid = true; } } #endif } if (R_ClipWallSegment (WallC.sx1, WallC.sx2, solid)) { InSubsector->flags |= SSECF_DRAWN; } }
// // R_AddLine // Clips the given segment and adds any visible pieces to the line list. // static void R_AddLine(seg_t *line) { INT32 x1, x2; angle_t angle1, angle2, span, tspan; static sector_t tempsec; // ceiling/water hack if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; curline = line; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle(line->v1->x, line->v1->y); angle2 = R_PointToAngle(line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side? i.e. backface culling? if (span >= ANGLE_180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > doubleclipangle) { tspan -= doubleclipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > doubleclipangle) { tspan -= doubleclipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = -(signed)clipangle; } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; backsector = line->backsector; // Portal line if (line->linedef->special == 40 && P_PointOnLineSide(viewx, viewy, line->linedef) == 0) { if (portalrender < cv_maxportals.value) { // Find the other side! INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); if (line->linedef == &lines[line2]) line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); if (line2 >= 0) // found it! { R_AddPortal(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering //return; // Don't fill in that space now! goto clipsolid; } } // Recursed TOO FAR (viewing a portal within a portal) // So uhhh, render it as a normal wall instead or something ??? } // Single sided line? if (!backsector) goto clipsolid; backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); doorclosed = 0; // Closed door. #ifdef ESLOPE // Just don't bother checking this if one side is sloped. This is probably inefficient, but it's better than // random renderer stopping around slopes... if (!(frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope)) #endif if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) { goto clipsolid; } // Check for automap fix. Store in doorclosed for r_segs.c doorclosed = R_DoorClosed(); if (doorclosed) goto clipsolid; // Window. if (backsector->ceilingheight != frontsector->ceilingheight || backsector->floorheight != frontsector->floorheight) { goto clippass; } // Reject empty lines used for triggers and special events. // Identical floor and ceiling on both sides, identical light levels on both sides, // and no middle texture. if ( #ifdef POLYOBJECTS !line->polyseg && #endif backsector->ceilingpic == frontsector->ceilingpic && backsector->floorpic == frontsector->floorpic #ifdef ESLOPE && backsector->f_slope == frontsector->f_slope && backsector->c_slope == frontsector->c_slope #endif && backsector->lightlevel == frontsector->lightlevel && !curline->sidedef->midtexture // Check offsets too! && backsector->floor_xoffs == frontsector->floor_xoffs && backsector->floor_yoffs == frontsector->floor_yoffs && backsector->floorpic_angle == frontsector->floorpic_angle && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && backsector->ceiling_yoffs == frontsector->ceiling_yoffs && backsector->ceilingpic_angle == frontsector->ceilingpic_angle // Consider altered lighting. && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec // Consider colormaps && backsector->extra_colormap == frontsector->extra_colormap && ((!frontsector->ffloors && !backsector->ffloors) || frontsector->tag == backsector->tag)) { return; } clippass: R_ClipPassWallSegment(x1, x2 - 1); return; clipsolid: R_ClipSolidWallSegment(x1, x2 - 1); }
static void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack // boolean solid = true; curline = line; angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side, i.e. backface culling if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = -clipangle; } // The seg is in the view range, // but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; backsector = line->backsector; /* cph - roll up linedef properties in flags */ if ((linedef = curline->linedef)->r_validcount != gametic) R_RecalcLineFlags(); // Single sided line? if (backsector) // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); if (linedef->r_flags & RF_IGNORE) return; else R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); }
static void R_Subsector(int num) { int count; seg_t *line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef GL_DOOM visplane_t dummyfloorplane; visplane_t dummyceilingplane; #endif #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = frontsector->floorheight < viewz || // killough 3/7/98 (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs ) : NULL; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs ) : NULL; #ifdef GL_DOOM // check if the sector is faked if ((frontsector==sub->sector) && (V_GetMode() == VID_MODEGL)) { // if the sector has bottomtextures, then the floorheight will be set to the // highest surounding floorheight if ((frontsector->no_bottomtextures) || (!floorplane)) { int i=frontsector->linecount; dummyfloorplane.height=INT_MIN; while (i--) { line_t *tmpline=frontsector->lines[i]; if (tmpline->backsector) if (tmpline->backsector != frontsector) if (tmpline->backsector->floorheight>dummyfloorplane.height) { dummyfloorplane.height=tmpline->backsector->floorheight; dummyfloorplane.lightlevel=tmpline->backsector->lightlevel; } if (tmpline->frontsector) if (tmpline->frontsector != frontsector) if (tmpline->frontsector->floorheight>dummyfloorplane.height) { dummyfloorplane.height=tmpline->frontsector->floorheight; dummyfloorplane.lightlevel=tmpline->frontsector->lightlevel; } } if (dummyfloorplane.height!=INT_MIN) floorplane=&dummyfloorplane; } // the same for ceilings. they will be set to the lowest ceilingheight if ((frontsector->no_toptextures) || (!ceilingplane)) { int i=frontsector->linecount; dummyceilingplane.height=INT_MAX; while (i--) { line_t *tmpline=frontsector->lines[i]; if (tmpline->backsector) if (tmpline->backsector != frontsector) if (tmpline->backsector->ceilingheight<dummyceilingplane.height) { dummyceilingplane.height=tmpline->backsector->ceilingheight; dummyceilingplane.lightlevel=tmpline->backsector->lightlevel; } if (tmpline->frontsector) if (tmpline->frontsector != frontsector) if (tmpline->frontsector->ceilingheight<dummyceilingplane.height) { dummyceilingplane.height=tmpline->frontsector->ceilingheight; dummyceilingplane.lightlevel=tmpline->frontsector->lightlevel; } } if (dummyceilingplane.height!=INT_MAX) ceilingplane=&dummyceilingplane; } } #endif // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // // 10/98 killough: // // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // That is part of the 242 effect!!! If you simply pass sub->sector to // the old code you will not get correct lighting for underwater sprites!!! // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2); while (count--) { if (line->miniseg == false) R_AddLine (line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ } #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) gld_AddPlane(num, floorplane, ceilingplane); #endif }
void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2) { int texnum; sector_t tempsec; // killough 4/13/98 const rpatch_t *patch; R_DrawColumn_f colfunc; draw_column_vars_t dcvars; angle_t angle; R_SetDefaultDrawColumnVars(&dcvars); // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? curline = ds->curline; // OPTIMIZE: get rid of LIGHTSEGSHIFT globally // killough 4/11/98: draw translucent 2s normal textures colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz); if (curline->linedef->tranlump >= 0 && general_translucency) { colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_TRANSLUCENT, drawvars.filterwall, drawvars.filterz); tranmap = main_tranmap; if (curline->linedef->tranlump > 0) tranmap = W_CacheLumpNum(curline->linedef->tranlump-1); } // killough 4/11/98: end translucent 2s normal code frontsector = curline->frontsector; backsector = curline->backsector; // cph 2001/11/25 - middle textures did not animate in v1.2 texnum = curline->sidedef->midtexture; if (!comp[comp_maskedanim]) texnum = texturetranslation[texnum]; // killough 4/13/98: get correct lightlevel for 2s normal textures rw_lightlevel = R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) ->lightlevel; walllights = GetLightTable(rw_lightlevel); walllightsnext = GetLightTable(rw_lightlevel + 1); maskedtexturecol = ds->maskedtexturecol; rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; mfloorclip = ds->sprbottomclip; mceilingclip = ds->sprtopclip; // find positioning if (curline->linedef->flags & ML_DONTPEGBOTTOM) { dcvars.texturemid = frontsector->floorheight > backsector->floorheight ? frontsector->floorheight : backsector->floorheight; dcvars.texturemid = dcvars.texturemid + textureheight[texnum] - viewz; } else { dcvars.texturemid =frontsector->ceilingheight<backsector->ceilingheight ? frontsector->ceilingheight : backsector->ceilingheight; dcvars.texturemid = dcvars.texturemid - viewz; } dcvars.texturemid += curline->sidedef->rowoffset; if (fixedcolormap) { dcvars.colormap = fixedcolormap; dcvars.nextcolormap = dcvars.colormap; // for filtering -- POPE } patch = R_CacheTextureCompositePatchNum(texnum); // draw the columns for (dcvars.x = x1 ; dcvars.x <= x2 ; dcvars.x++, spryscale += rw_scalestep) if (maskedtexturecol[dcvars.x] != INT_MAX) // dropoff overflow { // calculate texture offset - POPE angle = (ds->rw_centerangle + xtoviewangle[dcvars.x]) >> ANGLETOFINESHIFT; dcvars.texu = ds->rw_offset - FixedMul(finetangent[angle], ds->rw_distance); if (drawvars.filterwall == RDRAW_FILTER_LINEAR) dcvars.texu -= (FRACUNIT>>1); if (!fixedcolormap) dcvars.z = spryscale; // for filtering -- POPE if (!fixedcolormap) { int index = ((spryscale * 160 / wide_centerx) >> LIGHTSCALESHIFT); if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE - 1; dcvars.colormap = walllights[index]; dcvars.nextcolormap = walllightsnext[index]; }
// // R_AddLine // Clips the given segment // and adds any visible pieces to the line list. // static void R_AddLine(seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; angle1 = R_PointToAngleEx(line->v1->x, line->v1->y); angle2 = R_PointToAngleEx(line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side? I.e. backface culling? if (span >= ANG180) return; // Global angle needed by segcalc. angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2 * clipangle) { tspan -= 2 * clipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2 * clipangle) { tspan -= 2 * clipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = 0 - clipangle; } // The seg is in the view range, // but not necessarily visible. angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) return; backsector = line->backsector; // Single sided line? if (!backsector) goto clipsolid; // [AM] Interpolate sector movement before // running clipping tests. Frontsector // should already be interpolated. R_MaybeInterpolateSector(backsector); // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); doorclosed = false; // killough 4/16/98 // Closed door. if (backsector->interpceilingheight <= frontsector->interpfloorheight || backsector->interpfloorheight >= frontsector->interpceilingheight) goto clipsolid; // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c if ((doorclosed = R_DoorClosed())) goto clipsolid; // Window. if (backsector->interpceilingheight != frontsector->interpceilingheight || backsector->interpfloorheight != frontsector->interpfloorheight) goto clippass; // Reject empty lines used for triggers // and special events. // Identical floor and ceiling on both sides, // identical light levels on both sides, // and no middle texture. if (backsector->ceilingpic == frontsector->ceilingpic && backsector->floorpic == frontsector->floorpic && backsector->lightlevel == frontsector->lightlevel && !curline->sidedef->midtexture // killough 3/7/98: Take flats offsets into account: && backsector->floor_xoffs == frontsector->floor_xoffs && backsector->floor_yoffs == frontsector->floor_yoffs && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && backsector->ceiling_yoffs == frontsector->ceiling_yoffs // killough 4/16/98: consider altered lighting && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec) return; clippass: R_ClipPassWallSegment(x1, x2 - 1); return; clipsolid: R_ClipSolidWallSegment(x1, x2 - 1); }
static void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; curline = line; angle1 = R_PointToAngle(line->v1->x, line->v1->y); angle2 = R_PointToAngle(line->v2->x, line->v2->y); span = angle1 - angle2; if (span >= ANG180) return; rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2 * clipangle) { tspan -= 2 * clipangle; if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2 * clipangle) { tspan -= 2 * clipangle; if (tspan >= span) return; angle2 = 0-clipangle; } angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; if (x1 >= x2) return; backsector = line->backsector; if (backsector) backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); if ((linedef = curline->linedef)->r_validcount != gametic) R_RecalcLineFlags(); if (linedef->r_flags & RF_IGNORE) return; else R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); }
// // R_AddLine // Clips the given segment // and adds any visible pieces to the line list. // void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; // [RH] Color if not texturing line dc_color = ((line - segs) & 31) * 4; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). span = angle1 - angle2; // Back side? I.e. backface culling? if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle2 = (unsigned) (-(int)clipangle); } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; rw_start = x1; rw_stop = x2 - 1; rw_frontcz1 = P_CeilingHeight(line->v1->x, line->v1->y, frontsector); rw_frontfz1 = P_FloorHeight(line->v1->x, line->v1->y, frontsector); rw_frontcz2 = P_CeilingHeight(line->v2->x, line->v2->y, frontsector); rw_frontfz2 = P_FloorHeight(line->v2->x, line->v2->y, frontsector); backsector = line->backsector; // Single sided line? if (!backsector) goto clipsolid; // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true); rw_backcz1 = P_CeilingHeight(line->v1->x, line->v1->y, backsector); rw_backfz1 = P_FloorHeight(line->v1->x, line->v1->y, backsector); rw_backcz2 = P_CeilingHeight(line->v2->x, line->v2->y, backsector); rw_backfz2 = P_FloorHeight(line->v2->x, line->v2->y, backsector); // [SL] Check for closed doors or other scenarios that would make this // line seg solid. // // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c if (!(line->linedef->flags & ML_TWOSIDED) || (rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2) || // handle a case where the backsector slopes one direction // and the frontsector slopes the opposite: (rw_backcz1 <= rw_frontfz1 && rw_backfz1 >= rw_frontcz1) || (rw_backcz2 <= rw_frontfz2 && rw_backfz2 >= rw_frontcz2) || // if door is closed because back is shut: ((rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2) && // preserve a kind of transparent door/lift special effect: ((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) || line->sidedef->toptexture) && ((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) || line->sidedef->bottomtexture) && // properly render skies (consider door "open" if both ceilings are sky): (backsector->ceilingpic !=skyflatnum || frontsector->ceilingpic!=skyflatnum))) { doorclosed = true; goto clipsolid; } else { doorclosed = false; } // Window. if (!P_IdenticalPlanes(&frontsector->ceilingplane, &backsector->ceilingplane) || !P_IdenticalPlanes(&frontsector->floorplane, &backsector->floorplane)) goto clippass; // Reject empty lines used for triggers // and special events. // Identical floor and ceiling on both sides, // identical light levels on both sides, // and no middle texture. if (backsector->lightlevel == frontsector->lightlevel && backsector->floorpic == frontsector->floorpic && backsector->ceilingpic == frontsector->ceilingpic && curline->sidedef->midtexture == 0 // killough 3/7/98: Take flats offsets into account: && backsector->floor_xoffs == frontsector->floor_xoffs && (backsector->floor_yoffs + backsector->base_floor_yoffs) == (frontsector->floor_yoffs + backsector->base_floor_yoffs) && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && (backsector->ceiling_yoffs + backsector->base_ceiling_yoffs) == (frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs) // killough 4/16/98: consider altered lighting && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec // [RH] Also consider colormaps && backsector->floorcolormap == frontsector->floorcolormap && backsector->ceilingcolormap == frontsector->ceilingcolormap // [RH] and scaling && backsector->floor_xscale == frontsector->floor_xscale && backsector->floor_yscale == frontsector->floor_yscale && backsector->ceiling_xscale == frontsector->ceiling_xscale && backsector->ceiling_yscale == frontsector->ceiling_yscale // [RH] and rotation && (backsector->floor_angle + backsector->base_floor_angle) == (frontsector->floor_angle + frontsector->base_floor_angle) && (backsector->ceiling_angle + backsector->base_ceiling_angle) == (frontsector->ceiling_angle + frontsector->base_ceiling_angle) ) { return; } clippass: R_ClipPassWallSegment (x1, x2-1); return; clipsolid: R_ClipSolidWallSegment (x1, x2-1); }
// // R_AddLine // Clips the given segment and adds any visible pieces to the line list. // static void R_AddLine(seg_t *line) { INT32 x1, x2; angle_t angle1, angle2, span, tspan; static sector_t tempsec; // ceiling/water hack if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; curline = line; portalline = false; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle(line->v1->x, line->v1->y); angle2 = R_PointToAngle(line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side? i.e. backface culling? if (span >= ANGLE_180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > doubleclipangle) { tspan -= doubleclipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > doubleclipangle) { tspan -= doubleclipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = -(signed)clipangle; } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; backsector = line->backsector; // Portal line if (line->linedef->special == 40 && line->side == 0) { if (portalrender < cv_maxportals.value) { // Find the other side! INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); if (line->linedef == &lines[line2]) line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); if (line2 >= 0) // found it! { R_AddPortal(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering //return; // Don't fill in that space now! goto clipsolid; } } // Recursed TOO FAR (viewing a portal within a portal) // So uhhh, render it as a normal wall instead or something ??? } // Single sided line? if (!backsector) goto clipsolid; backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); doorclosed = 0; // Closed door. #ifdef ESLOPE if (frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope) { fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends #define SLOPEPARAMS(slope, end1, end2, normalheight) \ if (slope) { \ end1 = P_GetZAt(slope, line->v1->x, line->v1->y); \ end2 = P_GetZAt(slope, line->v2->x, line->v2->y); \ } else \ end1 = end2 = normalheight; SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector->floorheight) SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight) SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector->floorheight) SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight) #undef SLOPEPARAMS if ((backc1 <= frontf1 && backc2 <= frontf2) || (backf1 >= frontc1 && backf2 >= frontc2)) { goto clipsolid; } // Check for automap fix. Store in doorclosed for r_segs.c doorclosed = (backc1 <= backf1 && backc2 <= backf2 && ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture) && ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture) && (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum)); if (doorclosed) goto clipsolid; // Window. if (backc1 != frontc1 || backc2 != frontc2 || backf1 != frontf1 || backf2 != frontf2) { goto clippass; } }
static void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; angle1 = R_GetVertexViewAngle(line->v1); angle2 = R_GetVertexViewAngle(line->v2); #ifdef GL_DOOM if (V_GetMode() == VID_MODEGL) { if (curline->linedef->r_flags & RF_IGNORE_CURRENT) return; // Back side, i.e. backface culling - read: endAngle >= startAngle! if (angle2 - angle1 < ANG180 || !line->linedef) { return; } if (!gld_clipper_SafeCheckRange(angle2, angle1)) { return; } map_subsectors[currentsubsectornum] = 1; if (!line->backsector) { gld_clipper_SafeAddClipRange(angle2, angle1); } else { if (line->frontsector == line->backsector) { if (texturetranslation[line->sidedef->midtexture] == NO_TEXTURE) { //e6y: nothing to do here! return; } } if (CheckClip(line, line->frontsector, line->backsector)) { gld_clipper_SafeAddClipRange(angle2, angle1); } } if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM { unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a maxdrawsegs = newmax; } if(curline->miniseg == false) // figgi -- skip minisegs curline->linedef->flags |= ML_MAPPED; // proff 11/99: the rest of the calculations is not needed for OpenGL ds_p++->curline = curline; gld_AddWall(curline); return; } #endif // Clip to view edges. span = angle1 - angle2; // Back side, i.e. backface culling if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = 0-clipangle; } // The seg is in the view range, // but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; backsector = line->backsector; // Single sided line? if (backsector) // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); /* cph - roll up linedef properties in flags */ if ((linedef = curline->linedef)->r_validcount != gametic) R_RecalcLineFlags(linedef); if (linedef->r_flags & RF_IGNORE_CURRENT) { return; } else R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); }
void GL_RecalcLowerWall(seg_t *seg, sector_t *frontSector, gl_poly_t *poly) { FTexture *tex = TexMan(seg->sidedef->bottomtexture); float txScale, tyScale, yOffset, xOffset, dist, texHeight; float v1[5], v2[5], v3[5], v4[5]; float upperHeight, lowerHeight; texcoord_t ll, ul, lr, ur; sector_t *backSector, ts2; vertex_t *vert1, *vert2; fixed_t h1, h2; if (!poly->initialized) GL_InitPolygon(poly); poly->lastUpdate = frameStartMS; poly->initialized = true; vert1 = seg->v1; vert2 = seg->v2; dist = seg->length; backSector = R_FakeFlat(seg->backsector, &ts2, NULL, NULL, false); h1 = (backSector->floorplane.ZatPoint(vert1) - frontSector->floorplane.ZatPoint(vert1)); h2 = (backSector->floorplane.ZatPoint(vert2) - frontSector->floorplane.ZatPoint(vert2)); v1[0] = v3[0] = -vert1->x * MAP_SCALE; v1[2] = v3[2] = vert1->y * MAP_SCALE; v2[0] = v4[0] = -vert2->x * MAP_SCALE; v2[2] = v4[2] = vert2->y * MAP_SCALE; v1[1] = (float)frontSector->floorplane.ZatPoint(vert1); v2[1] = (float)frontSector->floorplane.ZatPoint(vert2); v3[1] = v1[1] + h1; v4[1] = v2[1] + h2; // texscale: 8 = 1.0, 16 = 2.0, 4 = 0.5 txScale = tex->ScaleX ? tex->ScaleX / 8.f : 1.f; tyScale = tex->ScaleY ? tex->ScaleY / 8.f : 1.f; xOffset = (seg->offset * txScale) * INV_FRACUNIT; ll.x = xOffset / tex->GetWidth(); ul.x = ll.x; lr.x = ll.x + (dist / tex->GetWidth() * txScale); ur.x = lr.x; ul.y = ur.y = 1.f; ll.y = lr.y = 0.f; if (tex) { texHeight = tex->GetHeight() / tyScale; lowerHeight = frontSector->floortexz * INV_FRACUNIT; upperHeight = backSector->floortexz * INV_FRACUNIT; if (seg->linedef->flags & ML_DONTPEGBOTTOM) { yOffset = (frontSector->ceilingtexz - backSector->floortexz) * INV_FRACUNIT; } else { yOffset = 0.f; } ul.y = ur.y = (yOffset + upperHeight - lowerHeight) / texHeight; ll.y = lr.y = yOffset / texHeight; // scale the coordinates //ul.y *= tyScale; //ur.y *= tyScale; //ll.y *= tyScale; //lr.y *= tyScale; // adjust for slopes ul.y -= ((v1[1] * INV_FRACUNIT) - lowerHeight) / texHeight; ur.y -= ((v2[1] * INV_FRACUNIT) - lowerHeight) / texHeight; ll.y += (upperHeight - (v3[1] * INV_FRACUNIT)) / texHeight; lr.y += (upperHeight - (v4[1] * INV_FRACUNIT)) / texHeight; } v1[1] *= MAP_SCALE; v2[1] *= MAP_SCALE; v3[1] *= MAP_SCALE; v4[1] *= MAP_SCALE; v1[3] = ul.x; v1[4] = ul.y; v2[3] = ur.x; v2[4] = ur.y; v3[3] = ll.x; v3[4] = ll.y; v4[3] = lr.x; v4[4] = lr.y; memcpy(poly->vertices + (0 * 3), v3, sizeof(float) * 3); memcpy(poly->vertices + (1 * 3), v1, sizeof(float) * 3); memcpy(poly->vertices + (2 * 3), v2, sizeof(float) * 3); memcpy(poly->vertices + (3 * 3), v4, sizeof(float) * 3); memcpy(poly->texCoords + (0 * 2), v3 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (1 * 2), v1 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (2 * 2), v2 + 3, sizeof(float) * 2); memcpy(poly->texCoords + (3 * 2), v4 + 3, sizeof(float) * 2); }
// // R_AddLine // Clips the given segment // and adds any visible pieces to the line list. // void R_AddLine (seg_t *line) { curline = line; // skip this line if it's not facing the camera if (R_PointOnSegSide(viewx, viewy, line) != 0) return; dcol.color = ((line - segs) & 31) * 4; // [RH] Color if not texturing line // translate the line seg endpoints from world-space to camera-space // and store in (t1.x, t1.y) and (t2.x, t2.y) v2fixed_t t1, t2; R_RotatePoint(line->v1->x - viewx, line->v1->y - viewy, ANG90 - viewangle, t1.x, t1.y); R_RotatePoint(line->v2->x - viewx, line->v2->y - viewy, ANG90 - viewangle, t2.x, t2.y); // Clip the line seg to the viewing window int32_t lclip, rclip; if (!R_ClipLineToFrustum(&t1, &t2, NEARCLIP, lclip, rclip)) return; // apply the view frustum clipping to t1 & t2 R_ClipLine(&t1, &t2, lclip, rclip, &t1, &t2); // project the line endpoints to determine which columns the line seg occupies int x1 = R_ProjectPointX(t1.x, t1.y); int x2 = R_ProjectPointX(t2.x, t2.y) - 1; if (!R_CheckProjectionX(x1, x2)) return; rw_start = x1; rw_stop = x2; // clip the line seg endpoints in world-space // and store in (w1.x, w1.y) and (w2.x, w2.y) v2fixed_t w1, w2; R_ClipLine(line->v1, line->v2, lclip, rclip, &w1, &w2); // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water static sector_t tempsec; backsector = line->backsector ? R_FakeFlat(line->backsector, &tempsec, NULL, NULL, true) : NULL; R_PrepWall(w1.x, w1.y, w2.x, w2.y, t1.y, t2.y, x1, x2); // [SL] Check for single-sided line, closed doors or other scenarios that // would make this line seg solid. // // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c if (!backsector || !(line->linedef->flags & ML_TWOSIDED) || (rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2) || // if door is closed because back is shut: ((rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2) && // preserve a kind of transparent door/lift special effect: ((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) || line->sidedef->toptexture) && ((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) || line->sidedef->bottomtexture) && // properly render skies (consider door "open" if both ceilings are sky): (backsector->ceilingpic !=skyflatnum || frontsector->ceilingpic!=skyflatnum))) { doorclosed = true; R_ClipWallSegment(x1, x2, true); return; } // Reject empty lines used for triggers and special events. // Identical floor and ceiling on both sides, // identical light levels on both sides, and no middle texture. if (P_IdenticalPlanes(&frontsector->ceilingplane, &backsector->ceilingplane) && P_IdenticalPlanes(&frontsector->floorplane, &backsector->floorplane) && backsector->lightlevel == frontsector->lightlevel && backsector->floorpic == frontsector->floorpic && backsector->ceilingpic == frontsector->ceilingpic && curline->sidedef->midtexture == 0 // killough 3/7/98: Take flats offsets into account: && backsector->floor_xoffs == frontsector->floor_xoffs && (backsector->floor_yoffs + backsector->base_floor_yoffs) == (frontsector->floor_yoffs + backsector->base_floor_yoffs) && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && (backsector->ceiling_yoffs + backsector->base_ceiling_yoffs) == (frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs) // killough 4/16/98: consider altered lighting && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec // [RH] Also consider colormaps && backsector->colormap == frontsector->colormap // [RH] and scaling && backsector->floor_xscale == frontsector->floor_xscale && backsector->floor_yscale == frontsector->floor_yscale && backsector->ceiling_xscale == frontsector->ceiling_xscale && backsector->ceiling_yscale == frontsector->ceiling_yscale // [RH] and rotation && (backsector->floor_angle + backsector->base_floor_angle) == (frontsector->floor_angle + frontsector->base_floor_angle) && (backsector->ceiling_angle + backsector->base_ceiling_angle) == (frontsector->ceiling_angle + frontsector->base_ceiling_angle) ) { return; } doorclosed = false; R_ClipWallSegment(x1, x2, false); }
// // R_Subsector // Determine floor/ceiling planes. // Add sprites of things in sector. // Draw one or more line segments. // void R_Subsector (int num) { int count; seg_t* line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 basecolormap = frontsector->colormap->maps; ceilingplane = P_CeilingHeight(camera) > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs, frontsector->ceiling_xscale, frontsector->ceiling_yscale, frontsector->ceiling_angle + frontsector->base_ceiling_angle ) : NULL; // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = P_FloorHeight(camera) < viewz || // killough 3/7/98 (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorplane, frontsector->floorpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs + frontsector->base_floor_yoffs, frontsector->floor_xscale, frontsector->floor_yscale, frontsector->floor_angle + frontsector->base_floor_angle ) : NULL; // [RH] set foggy flag foggy = level.fadeto_color[0] || level.fadeto_color[1] || level.fadeto_color[2] || level.fadeto_color[3] || frontsector->colormap->fade; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. R_AddSprites (sub->sector, (floorlightlevel + ceilinglightlevel) / 2, FakeSide); // [RH] Add particles if (r_particles) { for (WORD i = ParticlesInSubsec[num]; i != NO_PARTICLE; i = Particles[i].nextinsubsector) R_ProjectParticle(Particles + i, subsectors[num].sector, FakeSide); } if (sub->poly) { // Render the polyobj in the subsector first int polyCount = sub->poly->numsegs; seg_t **polySeg = sub->poly->segs; while (polyCount--) R_AddLine (*polySeg++); } while (count--) R_AddLine (line++); }
static void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. span = angle1 - angle2; // Back side, i.e. backface culling if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; // Totally off the left edge? if (tspan >= span) return; angle2 = 0-clipangle; } // The seg is in the view range, // but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; #ifdef GL_DOOM // proff 11/99: we have to add these segs to avoid gaps in OpenGL if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness { if (V_GetMode() == VID_MODEGL) { if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM { unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); //ds_p = drawsegs+maxdrawsegs; ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a maxdrawsegs = newmax; } ds_p->curline = curline; ds_p++; gld_AddWall(curline); return; } else return; } #else // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; #endif backsector = line->backsector; // Single sided line? if (backsector) // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); /* cph - roll up linedef properties in flags */ if ((linedef = curline->linedef)->r_validcount != gametic) R_RecalcLineFlags(); if (linedef->r_flags & RF_IGNORE) { return; } else R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); }
// // R_AddLine // Clips the given segment // and adds any visible pieces to the line list. // void R_AddLine (seg_t *line) { int x1; int x2; angle_t angle1; angle_t angle2; angle_t span; angle_t tspan; static sector_t tempsec; // killough 3/8/98: ceiling/water hack curline = line; // [RH] Color if not texturing line dc_color = ((line - segs) & 31) * 4; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // Clip to view edges. // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). span = angle1 - angle2; // Back side? I.e. backface culling? if (span >= ANG180) return; // Global angle needed by segcalc. rw_angle1 = angle1; angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { // Totally off the left edge? if (tspan - 2*clipangle >= span) return; angle2 = (unsigned) (-(int)clipangle); } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness return; backsector = line->backsector; // Single sided line? if (!backsector) goto clipsolid; // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true); doorclosed = 0; // killough 4/16/98 // Closed door. if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) goto clipsolid; // This fixes the automap floor height bug -- killough 1/18/98: // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c if ((doorclosed = R_DoorClosed())) goto clipsolid; // Window. if (backsector->ceilingheight != frontsector->ceilingheight || backsector->floorheight != frontsector->floorheight) goto clippass; // Reject empty lines used for triggers // and special events. // Identical floor and ceiling on both sides, // identical light levels on both sides, // and no middle texture. if (backsector->lightlevel == frontsector->lightlevel && backsector->floorpic == frontsector->floorpic && backsector->ceilingpic == frontsector->ceilingpic && curline->sidedef->midtexture == 0 // killough 3/7/98: Take flats offsets into account: && backsector->floor_xoffs == frontsector->floor_xoffs && (backsector->floor_yoffs + backsector->base_floor_yoffs) == (frontsector->floor_yoffs + backsector->base_floor_yoffs) && backsector->ceiling_xoffs == frontsector->ceiling_xoffs && (backsector->ceiling_yoffs + backsector->base_ceiling_yoffs) == (frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs) // killough 4/16/98: consider altered lighting && backsector->floorlightsec == frontsector->floorlightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec // [RH] Also consider colormaps && backsector->floorcolormap == frontsector->floorcolormap && backsector->ceilingcolormap == frontsector->ceilingcolormap // [RH] and scaling && backsector->floor_xscale == frontsector->floor_xscale && backsector->floor_yscale == frontsector->floor_yscale && backsector->ceiling_xscale == frontsector->ceiling_xscale && backsector->ceiling_yscale == frontsector->ceiling_yscale // [RH] and rotation && (backsector->floor_angle + backsector->base_floor_angle) == (frontsector->floor_angle + frontsector->base_floor_angle) && (backsector->ceiling_angle + backsector->base_ceiling_angle) == (frontsector->ceiling_angle + frontsector->base_ceiling_angle) ) { return; } clippass: R_ClipPassWallSegment (x1, x2-1); return; clipsolid: R_ClipSolidWallSegment (x1, x2-1); }
static void R_Subsector(int num) { int count; seg_t *line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, FALSE); // killough 4/11/98 // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = frontsector->floorheight < viewz || // killough 3/7/98 (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs ) : NULL; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs ) : NULL; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // // 10/98 killough: // // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // That is part of the 242 effect!!! If you simply pass sub->sector to // the old code you will not get correct lighting for underwater sprites!!! // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2); while (count--) { if (line->miniseg == FALSE) R_AddLine (line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ } }
// // R_Subsector // Determine floor/ceiling planes. // Add sprites of things in sector. // Draw one or more line segments. // void R_Subsector (int num) { int count; seg_t* line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 basecolormap = frontsector->ceilingcolormap->maps; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec && frontsector->heightsec->floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs, frontsector->ceiling_xscale, frontsector->ceiling_yscale, frontsector->ceiling_angle + frontsector->base_ceiling_angle ) : NULL; basecolormap = frontsector->floorcolormap->maps; // [RH] set basecolormap // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs floorplane = frontsector->floorheight < viewz || // killough 3/7/98 (frontsector->heightsec && frontsector->heightsec->ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && // killough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs + frontsector->base_floor_yoffs, frontsector->floor_xscale, frontsector->floor_yscale, frontsector->floor_angle + frontsector->base_floor_angle ) : NULL; // [RH] set foggy flag foggy = level.fadeto || frontsector->floorcolormap->fade || frontsector->ceilingcolormap->fade; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. R_AddSprites (sub->sector, (floorlightlevel + ceilinglightlevel) / 2); if (sub->poly) { // Render the polyobj in the subsector first int polyCount = sub->poly->numsegs; seg_t **polySeg = sub->poly->segs; while (polyCount--) { R_AddLine (*polySeg++); } } while (count--) { R_AddLine (line++); } }
static void R_Subsector(int num) { int count; seg_t *line; subsector_t *sub; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); #endif sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel floorplane = frontsector->floorheight < viewz || // killough 3/7/98 (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? R_FindPlane(frontsector->floorheight, frontsector->floorpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->floorpic, floorlightlevel, // killough 3/16/98 frontsector->floor_xoffs, // killough 3/7/98 frontsector->floor_yoffs ) : NULL; ceilingplane = frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum) ? R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 frontsector->ceilingpic == skyflatnum && // kilough 10/98 frontsector->sky & PL_SKYFLAT ? frontsector->sky : frontsector->ceilingpic, ceilinglightlevel, // killough 4/11/98 frontsector->ceiling_xoffs, // killough 3/7/98 frontsector->ceiling_yoffs ) : NULL; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // // 10/98 killough: // // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // That is part of the 242 effect!!! If you simply pass sub->sector to // the old code you will not get correct lighting for underwater sprites!!! // Either you must pass the fake sector and handle validcount here, on the // real sector, or you must account for the lighting in some other way, // like passing it as an argument. R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2); while (count--) R_AddLine (line++); }
sector_t *FSoftwareRenderer::FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) { return R_FakeFlat(sec, tempsec, floorlightlevel, ceilinglightlevel, back); }
static void R_Subsector(size_t num) { INT32 count, floorlightlevel, ceilinglightlevel, light; seg_t *line; subsector_t *sub; static sector_t tempsec; // Deep water hack extracolormap_t *floorcolormap; extracolormap_t *ceilingcolormap; #ifdef RANGECHECK if (num >= numsubsectors) I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); #endif // subsectors added at run-time if (num >= numsubsectors) return; sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; // Deep water/fake ceiling effect. frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); floorcolormap = ceilingcolormap = frontsector->extra_colormap; // Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps. if (frontsector->ffloors) { if (frontsector->moved) { frontsector->numlights = sub->sector->numlights = 0; R_Prep3DFloors(frontsector); sub->sector->lightlist = frontsector->lightlist; sub->sector->numlights = frontsector->numlights; sub->sector->moved = frontsector->moved = false; } light = R_GetPlaneLight(frontsector, #ifdef ESLOPE frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif frontsector->floorheight, false); if (frontsector->floorlightsec == -1) floorlightlevel = *frontsector->lightlist[light].lightlevel; floorcolormap = frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(frontsector, #ifdef ESLOPE frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif frontsector->ceilingheight, false); if (frontsector->ceilinglightsec == -1) ceilinglightlevel = *frontsector->lightlist[light].lightlevel; ceilingcolormap = frontsector->lightlist[light].extra_colormap; } sub->sector->extra_colormap = frontsector->extra_colormap; if ((( #ifdef ESLOPE frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : #endif frontsector->floorheight) < viewz || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))) { floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL #ifdef ESLOPE , frontsector->f_slope #endif ); } else floorplane = NULL; if ((( #ifdef ESLOPE frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : #endif frontsector->ceilingheight) > viewz || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))) { ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, ceilingcolormap, NULL #ifdef ESLOPE , frontsector->c_slope #endif ); } else ceilingplane = NULL; numffloors = 0; #ifdef ESLOPE ffloor[numffloors].slope = NULL; #endif ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; if (frontsector->ffloors) { ffloor_t *rover; fixed_t heightcheck; for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next) { if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) continue; if (frontsector->cullheight) { if (R_DoCulling(frontsector->cullheight, viewsector->cullheight, viewz, *rover->bottomheight, *rover->topheight)) { rover->norender = leveltime; continue; } } ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; heightcheck = #ifdef ESLOPE *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : #endif *rover->bottomheight; if (*rover->bottomheight <= frontsector->ceilingheight && *rover->bottomheight >= frontsector->floorheight && ((viewz < heightcheck && !(rover->flags & FF_INVERTPLANES)) || (viewz > heightcheck && (rover->flags & FF_BOTHPLANES)))) { #ifdef ESLOPE light = R_GetPlaneLight(frontsector, *rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) : *rover->bottomheight, viewz < heightcheck); #else light = R_GetPlaneLight(frontsector, *rover->bottomheight, viewz < *rover->bottomheight); #endif ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover #ifdef ESLOPE , *rover->b_slope #endif ); #ifdef ESLOPE ffloor[numffloors].slope = *rover->b_slope; // Tell the renderer this sector has slopes in it. if (ffloor[numffloors].slope) frontsector->hasslope = true; #endif ffloor[numffloors].height = #ifdef ESLOPE *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : #endif *rover->bottomheight; ffloor[numffloors].ffloor = rover; numffloors++; } if (numffloors >= MAXFFLOORS) break; ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; heightcheck = #ifdef ESLOPE *rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : #endif *rover->topheight; if (*rover->topheight >= frontsector->floorheight && *rover->topheight <= frontsector->ceilingheight && ((viewz > heightcheck && !(rover->flags & FF_INVERTPLANES)) || (viewz < heightcheck && (rover->flags & FF_BOTHPLANES)))) { #ifdef ESLOPE light = R_GetPlaneLight(frontsector, *rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : *rover->topheight, viewz < heightcheck); #else light = R_GetPlaneLight(frontsector, *rover->topheight, viewz < *rover->topheight); #endif ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, frontsector->lightlist[light].extra_colormap, rover #ifdef ESLOPE , *rover->t_slope #endif ); #ifdef ESLOPE ffloor[numffloors].slope = *rover->t_slope; // Tell the renderer this sector has slopes in it. if (ffloor[numffloors].slope) frontsector->hasslope = true; #endif ffloor[numffloors].height = #ifdef ESLOPE *rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : #endif *rover->topheight; ffloor[numffloors].ffloor = rover; numffloors++; } } } #ifdef POLYOBJECTS_PLANES // Polyobjects have planes, too! if (sub->polyList) { polyobj_t *po = sub->polyList; sector_t *polysec; while (po) { if (numffloors >= MAXFFLOORS) break; if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes { po = (polyobj_t *)(po->link.next); continue; } polysec = po->lines[0]->backsector; ffloor[numffloors].plane = NULL; if (polysec->floorheight <= frontsector->ceilingheight && polysec->floorheight >= frontsector->floorheight && (viewz < polysec->floorheight)) { fixed_t xoff, yoff; xoff = polysec->floor_xoffs; yoff = polysec->floor_yoffs; if (po->angle != 0) { angle_t fineshift = po->angle >> ANGLETOFINESHIFT; xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y); yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y); } else {
// // R_Subsector // Determine floor/ceiling planes. // Add sprites of things in sector. // Draw one or more line segments. // void R_Subsector (subsector_t *sub) { int count; seg_t* line; sector_t tempsec; // killough 3/7/98: deep water hack int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 bool outersubsector; int fll, cll, position; FSectorPortal *portal; // kg3D - fake floor stuff visplane_t *backupfp; visplane_t *backupcp; //secplane_t templane; lightlist_t *light; if (InSubsector != NULL) { // InSubsector is not NULL. This means we are rendering from a mini-BSP. outersubsector = false; } else { outersubsector = true; InSubsector = sub; } #ifdef RANGECHECK if (outersubsector && sub - subsectors >= (ptrdiff_t)numsubsectors) I_Error ("R_Subsector: ss %ti with numss = %i", sub - subsectors, numsubsectors); #endif assert(sub->sector != NULL); if (sub->polys) { // Render the polyobjs in the subsector first R_AddPolyobjs(sub); if (outersubsector) { InSubsector = NULL; } return; } frontsector = sub->sector; frontsector->MoreFlags |= SECF_DRAWN; count = sub->numlines; line = sub->firstline; // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // killough 4/11/98 fll = floorlightlevel; cll = ceilinglightlevel; // [RH] set foggy flag foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE); r_actualextralight = foggy ? 0 : extralight << 4; // kg3D - fake lights if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size()) { light = P_GetPlaneLight(frontsector, &frontsector->ceilingplane, false); basecolormap = light->extra_colormap; // If this is the real ceiling, don't discard plane lighting R_FakeFlat() // accounted for. if (light->p_lightlevel != &frontsector->lightlevel) { ceilinglightlevel = *light->p_lightlevel; } } else { basecolormap = frontsector->ColorMap; } portal = frontsector->ValidatePortal(sector_t::ceiling); ceilingplane = frontsector->ceilingplane.PointOnSide(ViewPos) > 0 || frontsector->GetTexture(sector_t::ceiling) == skyflatnum || portal != NULL || (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ? R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + r_actualextralight, // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), !!(frontsector->GetFlags(sector_t::ceiling) & PLANEF_ADDITIVE), frontsector->planes[sector_t::ceiling].xform, frontsector->sky, portal ) : NULL; if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size()) { light = P_GetPlaneLight(frontsector, &frontsector->floorplane, false); basecolormap = light->extra_colormap; // If this is the real floor, don't discard plane lighting R_FakeFlat() // accounted for. if (light->p_lightlevel != &frontsector->lightlevel) { floorlightlevel = *light->p_lightlevel; } } else { basecolormap = frontsector->ColorMap; } // killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/16/98: add floorlightlevel // killough 10/98: add support for skies transferred from sidedefs portal = frontsector->ValidatePortal(sector_t::floor); floorplane = frontsector->floorplane.PointOnSide(ViewPos) > 0 || // killough 3/7/98 frontsector->GetTexture(sector_t::floor) == skyflatnum || portal != NULL || (frontsector->heightsec && !(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ? R_FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + r_actualextralight, // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), !!(frontsector->GetFlags(sector_t::floor) & PLANEF_ADDITIVE), frontsector->planes[sector_t::floor].xform, frontsector->sky, portal ) : NULL; // kg3D - fake planes rendering if (r_3dfloors && frontsector->e && frontsector->e->XFloor.ffloors.Size()) { backupfp = floorplane; backupcp = ceilingplane; // first check all floors for (int i = 0; i < (int)frontsector->e->XFloor.ffloors.Size(); i++) { fakeFloor = frontsector->e->XFloor.ffloors[i]; if (!(fakeFloor->flags & FF_EXISTS)) continue; if (!fakeFloor->model) continue; if (fakeFloor->bottom.plane->isSlope()) continue; if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES|FF_RENDERSIDES))) { R_3D_AddHeight(fakeFloor->top.plane, frontsector); } if (!(fakeFloor->flags & FF_RENDERPLANES)) continue; if (fakeFloor->alpha == 0) continue; if (fakeFloor->flags & FF_THISINSIDE && fakeFloor->flags & FF_INVERTSECTOR) continue; fakeAlpha = MIN<fixed_t>(Scale(fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (fakeFloor->validcount != validcount) { fakeFloor->validcount = validcount; R_3D_NewClip(); } double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot); if (fakeHeight < ViewPos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot)) { fake3D = FAKE3D_FAKEFLOOR; tempsec = *fakeFloor->model; tempsec.floorplane = *fakeFloor->top.plane; tempsec.ceilingplane = *fakeFloor->bottom.plane; if (!(fakeFloor->flags & FF_THISINSIDE) && !(fakeFloor->flags & FF_INVERTSECTOR)) { tempsec.SetTexture(sector_t::floor, tempsec.GetTexture(sector_t::ceiling)); position = sector_t::ceiling; } else position = sector_t::floor; frontsector = &tempsec; if (fixedlightlev < 0 && sub->sector->e->XFloor.lightlist.Size()) { light = P_GetPlaneLight(sub->sector, &frontsector->floorplane, false); basecolormap = light->extra_colormap; floorlightlevel = *light->p_lightlevel; } ceilingplane = NULL; floorplane = R_FindPlane(frontsector->floorplane, frontsector->GetTexture(sector_t::floor), floorlightlevel + r_actualextralight, // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), !!(fakeFloor->flags & FF_ADDITIVETRANS), frontsector->planes[position].xform, frontsector->sky, NULL); R_FakeDrawLoop(sub); fake3D = 0; frontsector = sub->sector; } } // and now ceilings for (unsigned int i = 0; i < frontsector->e->XFloor.ffloors.Size(); i++) { fakeFloor = frontsector->e->XFloor.ffloors[i]; if (!(fakeFloor->flags & FF_EXISTS)) continue; if (!fakeFloor->model) continue; if (fakeFloor->top.plane->isSlope()) continue; if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES|FF_RENDERSIDES))) { R_3D_AddHeight(fakeFloor->bottom.plane, frontsector); } if (!(fakeFloor->flags & FF_RENDERPLANES)) continue; if (fakeFloor->alpha == 0) continue; if (!(fakeFloor->flags & FF_THISINSIDE) && (fakeFloor->flags & (FF_SWIMMABLE|FF_INVERTSECTOR)) == (FF_SWIMMABLE|FF_INVERTSECTOR)) continue; fakeAlpha = MIN<fixed_t>(Scale(fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (fakeFloor->validcount != validcount) { fakeFloor->validcount = validcount; R_3D_NewClip(); } double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot); if (fakeHeight > ViewPos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot)) { fake3D = FAKE3D_FAKECEILING; tempsec = *fakeFloor->model; tempsec.floorplane = *fakeFloor->top.plane; tempsec.ceilingplane = *fakeFloor->bottom.plane; if ((!(fakeFloor->flags & FF_THISINSIDE) && !(fakeFloor->flags & FF_INVERTSECTOR)) || (fakeFloor->flags & FF_THISINSIDE && fakeFloor->flags & FF_INVERTSECTOR)) { tempsec.SetTexture(sector_t::ceiling, tempsec.GetTexture(sector_t::floor)); position = sector_t::floor; } else position = sector_t::ceiling; frontsector = &tempsec; tempsec.ceilingplane.ChangeHeight(-1 / 65536.); if (fixedlightlev < 0 && sub->sector->e->XFloor.lightlist.Size()) { light = P_GetPlaneLight(sub->sector, &frontsector->ceilingplane, false); basecolormap = light->extra_colormap; ceilinglightlevel = *light->p_lightlevel; } tempsec.ceilingplane.ChangeHeight(1 / 65536.); floorplane = NULL; ceilingplane = R_FindPlane(frontsector->ceilingplane, // killough 3/8/98 frontsector->GetTexture(sector_t::ceiling), ceilinglightlevel + r_actualextralight, // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), !!(fakeFloor->flags & FF_ADDITIVETRANS), frontsector->planes[position].xform, frontsector->sky, NULL); R_FakeDrawLoop(sub); fake3D = 0; frontsector = sub->sector; } } fakeFloor = NULL; floorplane = backupfp; ceilingplane = backupcp; } basecolormap = frontsector->ColorMap; floorlightlevel = fll; ceilinglightlevel = cll; // killough 9/18/98: Fix underwater slowdown, by passing real sector // instead of fake one. Improve sprite lighting by basing sprite // lightlevels on floor & ceiling lightlevels in the surrounding area. // [RH] Handle sprite lighting like Duke 3D: If the ceiling is a sky, sprites are lit by // it, otherwise they are lit by the floor. R_AddSprites (sub->sector, frontsector->GetTexture(sector_t::ceiling) == skyflatnum ? ceilinglightlevel : floorlightlevel, FakeSide); // [RH] Add particles if ((unsigned int)(sub - subsectors) < (unsigned int)numsubsectors) { // Only do it for the main BSP. int shade = LIGHT2SHADE((floorlightlevel + ceilinglightlevel)/2 + r_actualextralight); for (WORD i = ParticlesInSubsec[(unsigned int)(sub-subsectors)]; i != NO_PARTICLE; i = Particles[i].snext) { R_ProjectParticle (Particles + i, subsectors[sub-subsectors].sector, shade, FakeSide); } } count = sub->numlines; line = sub->firstline; while (count--) { if (!outersubsector || line->sidedef == NULL || !(line->sidedef->Flags & WALLF_POLYOBJ)) { // kg3D - fake planes bounding calculation if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size()) { backupfp = floorplane; backupcp = ceilingplane; floorplane = NULL; ceilingplane = NULL; for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) { fakeFloor = line->backsector->e->XFloor.ffloors[i]; if (!(fakeFloor->flags & FF_EXISTS)) continue; if (!(fakeFloor->flags & FF_RENDERPLANES)) continue; if (!fakeFloor->model) continue; fake3D = FAKE3D_FAKEBACK; tempsec = *fakeFloor->model; tempsec.floorplane = *fakeFloor->top.plane; tempsec.ceilingplane = *fakeFloor->bottom.plane; backsector = &tempsec; if (fakeFloor->validcount != validcount) { fakeFloor->validcount = validcount; R_3D_NewClip(); } if (frontsector->CenterFloor() >= backsector->CenterFloor()) { fake3D |= FAKE3D_CLIPBOTFRONT; } if (frontsector->CenterCeiling() <= backsector->CenterCeiling()) { fake3D |= FAKE3D_CLIPTOPFRONT; } R_AddLine(line); // fake } fakeFloor = NULL; fake3D = 0; floorplane = backupfp; ceilingplane = backupcp; } R_AddLine (line); // now real } line++; } if (outersubsector) { InSubsector = NULL; } }