// // 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++); }
// // 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; } }