bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mState; if (state->renderdepth > r_mirror_recursions) { return false; } // A plane mirror needs to flip the portal exclusion logic because inside the mirror, up is down and down is up. std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); auto &vp = di->Viewpoint; old_pm = state->PlaneMirrorMode; // the player is always visible in a mirror. vp.showviewer = true; double planez = origin->ZatPoint(vp.Pos); vp.Pos.Z = 2 * planez - vp.Pos.Z; vp.ViewActor = nullptr; state->PlaneMirrorMode = origin->fC() < 0 ? -1 : 1; state->PlaneMirrorFlag++; di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; }
void GLPlaneMirrorPortal::DrawContents() { if (renderdepth>r_mirror_recursions) { ClearScreen(); return; } int old_pm=PlaneMirrorMode; fixed_t planez = origin->ZatPoint(viewx, viewy); viewz = 2*planez - viewz; GLRenderer->mViewActor = NULL; PlaneMirrorMode = ksgn(origin->c); validcount++; PlaneMirrorFlag++; GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); glEnable(GL_CLIP_PLANE0+renderdepth); // This only works properly for non-sloped planes so don't bother with the math. //double d[4]={origin->a/65536., origin->c/65536., origin->b/65536., FIXED2FLOAT(origin->d)}; double d[4]={0, static_cast<double>(PlaneMirrorMode), 0, FIXED2FLOAT(origin->d)}; glClipPlane(GL_CLIP_PLANE0+renderdepth, d); GLRenderer->DrawScene(); glDisable(GL_CLIP_PLANE0+renderdepth); PlaneMirrorFlag--; PlaneMirrorMode=old_pm; }
void GLPlaneMirrorPortal::DrawContents() { if (renderdepth>r_mirror_recursions) { ClearScreen(); return; } int old_pm=PlaneMirrorMode; double planez = origin->ZatPoint(ViewPos); ViewPos.Z = 2 * planez - ViewPos.Z; GLRenderer->mViewActor = NULL; PlaneMirrorMode = origin->fC() < 0 ? -1 : 1; PlaneMirrorFlag++; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); gl_RenderState.SetClipHeight(planez, PlaneMirrorMode < 0? -1.f : 1.f); GLRenderer->DrawScene(DM_PORTAL); gl_RenderState.SetClipHeight(0.f, 0.f); PlaneMirrorFlag--; PlaneMirrorMode=old_pm; }
//----------------------------------------------------------------------------- // // GLSectorStackPortal::DrawContents // //----------------------------------------------------------------------------- bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mState; FSectorPortalGroup *portal = origin; auto &vp = di->Viewpoint; vp.Pos += origin->mDisplacement; vp.ActorPos += origin->mDisplacement; vp.ViewActor = nullptr; // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); SetupCoverage(di); ClearClipper(di, clipper); // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. subsector_t *sub = di->Level->PointInRenderSubsector(vp.Pos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { clipper->SafeAddClipRange(0, ANGLE_MAX); clipper->SetBlocked(true); } return true; }
//----------------------------------------------------------------------------- // // GLSectorStackPortal::DrawContents // //----------------------------------------------------------------------------- void GLSectorStackPortal::DrawContents() { FPortal *portal = origin; ViewPos += origin->mDisplacement; GLRenderer->mViewActor = NULL; // avoid recursions! if (origin->plane != -1) instack[origin->plane]++; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); SaveMapSection(); SetupCoverage(); ClearClipper(); // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. subsector_t *sub = R_PointInSubsector(ViewPos); if (!(gl_drawinfo->ss_renderflags[sub - ::subsectors] & SSRF_SEEN)) { clipper.SafeAddClipRange(0, ANGLE_MAX); clipper.SetBlocked(true); } GLRenderer->DrawScene(DM_PORTAL); RestoreMapSection(); if (origin->plane != -1) instack[origin->plane]--; }
//----------------------------------------------------------------------------- // // // //----------------------------------------------------------------------------- void GLLineToLinePortal::DrawContents() { // TODO: Handle recursion more intelligently if (renderdepth>r_mirror_recursions) { ClearScreen(); return; } GLRenderer->mClipPortal = this; line_t *origin = glport->lines[0]->mOrigin; P_TranslatePortalXY(origin, ViewPos.X, ViewPos.Y); P_TranslatePortalAngle(origin, ViewAngle); P_TranslatePortalZ(origin, ViewPos.Z); P_TranslatePortalXY(origin, ViewPath[0].X, ViewPath[0].Y); P_TranslatePortalXY(origin, ViewPath[1].X, ViewPath[1].Y); if (!r_showviewer && camera != nullptr && P_PointOnLineSidePrecise(ViewPath[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(ViewPath[1], glport->lines[0]->mDestination)) { double distp = (ViewPath[0] - ViewPath[1]).Length(); if (distp > EQUAL_EPSILON) { double dist1 = (ViewPos - ViewPath[0]).Length(); double dist2 = (ViewPos - ViewPath[1]).Length(); if (dist1 + dist2 < distp + 1) { camera->renderflags |= RF_INVISIBLE; } } } SaveMapSection(); for (unsigned i = 0; i < lines.Size(); i++) { line_t *line = lines[i].seg->linedef->getPortalDestination(); subsector_t *sub; if (line->sidedef[0]->Flags & WALLF_POLYOBJ) sub = R_PointInSubsector(line->v1->fixX(), line->v1->fixY()); else sub = line->frontsector->subsectors[0]; int mapsection = sub->mapsection; currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); } GLRenderer->mViewActor = nullptr; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); gl_RenderState.SetClipLine(glport->lines[0]->mDestination); gl_RenderState.EnableClipLine(true); GLRenderer->DrawScene(DM_PORTAL); gl_RenderState.EnableClipLine(false); RestoreMapSection(); }
void GLSkyboxPortal::DrawContents() { int old_pm=PlaneMirrorMode; int saved_extralight = extralight; if (skyboxrecursion>=3) { ClearScreen(); return; } skyboxrecursion++; origin->flags|=MF_JUSTHIT; extralight = 0; PlaneMirrorMode=0; glDisable(GL_DEPTH_CLAMP_NV); viewx = origin->PrevX + FixedMul(r_TicFrac, origin->x - origin->PrevX); viewy = origin->PrevY + FixedMul(r_TicFrac, origin->y - origin->PrevY); viewz = origin->PrevZ + FixedMul(r_TicFrac, origin->z - origin->PrevZ); viewangle += origin->PrevAngle + FixedMul(r_TicFrac, origin->angle - origin->PrevAngle); // Don't let the viewpoint be too close to a floor or ceiling! fixed_t floorh = origin->Sector->floorplane.ZatPoint(origin->x, origin->y); fixed_t ceilh = origin->Sector->ceilingplane.ZatPoint(origin->x, origin->y); if (viewz<floorh+4*FRACUNIT) viewz=floorh+4*FRACUNIT; if (viewz>ceilh-4*FRACUNIT) viewz=ceilh-4*FRACUNIT; GLRenderer->mViewActor = origin; validcount++; inskybox=true; GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); GLRenderer->SetViewArea(); ClearClipper(); int mapsection = R_PointInSubsector(viewx, viewy)->mapsection; SaveMapSection(); currentmapsection[mapsection>>3] |= 1 << (mapsection & 7); GLRenderer->DrawScene(); origin->flags&=~MF_JUSTHIT; inskybox=false; glEnable(GL_DEPTH_CLAMP_NV); skyboxrecursion--; PlaneMirrorMode=old_pm; extralight = saved_extralight; RestoreMapSection(); }
//----------------------------------------------------------------------------- // // // //----------------------------------------------------------------------------- bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { // TODO: Handle recursion more intelligently auto &state = mState; if (state->renderdepth>r_mirror_recursions) { return false; } auto &vp = di->Viewpoint; di->mClipPortal = this; line_t *origin = glport->lines[0]->mOrigin; P_TranslatePortalXY(origin, vp.Pos.X, vp.Pos.Y); P_TranslatePortalXY(origin, vp.ActorPos.X, vp.ActorPos.Y); P_TranslatePortalAngle(origin, vp.Angles.Yaw); P_TranslatePortalZ(origin, vp.Pos.Z); P_TranslatePortalXY(origin, vp.Path[0].X, vp.Path[0].Y); P_TranslatePortalXY(origin, vp.Path[1].X, vp.Path[1].Y); if (!vp.showviewer && vp.camera != nullptr && P_PointOnLineSidePrecise(vp.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(vp.Path[1], glport->lines[0]->mDestination)) { double distp = (vp.Path[0] - vp.Path[1]).Length(); if (distp > EQUAL_EPSILON) { double dist1 = (vp.Pos - vp.Path[0]).Length(); double dist2 = (vp.Pos - vp.Path[1]).Length(); if (dist1 + dist2 < distp + 1) { vp.camera->renderflags |= RF_MAYBEINVISIBLE; } } } for (unsigned i = 0; i < lines.Size(); i++) { line_t *line = lines[i].seg->linedef->getPortalDestination(); subsector_t *sub; if (line->sidedef[0]->Flags & WALLF_POLYOBJ) sub = di->Level->PointInRenderSubsector(line->v1->fixX(), line->v1->fixY()); else sub = line->frontsector->subsectors[0]; di->CurrentMapSections.Set(sub->mapsection); } vp.ViewActor = nullptr; di->SetClipLine(glport->lines[0]->mDestination); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); ClearClipper(di, clipper); return true; }
void GLSkyboxPortal::DrawContents() { int old_pm = PlaneMirrorMode; int saved_extralight = extralight; if (skyboxrecursion >= 3) { ClearScreen(); return; } skyboxrecursion++; AActor *origin = portal->mSkybox; portal->mFlags |= PORTSF_INSKYBOX; extralight = 0; PlaneMirrorMode = 0; bool oldclamp = gl_RenderState.SetDepthClamp(false); ViewPos = origin->InterpolatedPosition(r_TicFracF); ViewAngle += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * r_TicFracF); // Don't let the viewpoint be too close to a floor or ceiling double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos()); double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos()); if (ViewPos.Z < floorh + 4) ViewPos.Z = floorh + 4; if (ViewPos.Z > ceilh - 4) ViewPos.Z = ceilh - 4; GLRenderer->mViewActor = origin; inskybox = true; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); GLRenderer->SetViewArea(); ClearClipper(); int mapsection = R_PointInSubsector(ViewPos)->mapsection; SaveMapSection(); currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); GLRenderer->DrawScene(DM_PORTAL); portal->mFlags &= ~PORTSF_INSKYBOX; inskybox = false; gl_RenderState.SetDepthClamp(oldclamp); skyboxrecursion--; PlaneMirrorMode = old_pm; extralight = saved_extralight; RestoreMapSection(); }
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mState; old_pm = state->PlaneMirrorMode; if (mState->skyboxrecursion >= 3) { return false; } auto &vp = di->Viewpoint; state->skyboxrecursion++; state->PlaneMirrorMode = 0; state->inskybox = true; AActor *origin = portal->mSkybox; portal->mFlags |= PORTSF_INSKYBOX; vp.extralight = 0; oldclamp = rstate.SetDepthClamp(false); vp.Pos = origin->InterpolatedPosition(vp.TicFrac); vp.ActorPos = origin->Pos(); vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac); // Don't let the viewpoint be too close to a floor or ceiling double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos()); double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos()); if (vp.Pos.Z < floorh + 4) vp.Pos.Z = floorh + 4; if (vp.Pos.Z > ceilh - 4) vp.Pos.Z = ceilh - 4; vp.ViewActor = origin; di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetViewArea(); ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; }
//----------------------------------------------------------------------------- // // GLSectorStackPortal::DrawContents // //----------------------------------------------------------------------------- void GLSectorStackPortal::DrawContents() { FPortal *portal = origin; viewx += origin->xDisplacement; viewy += origin->yDisplacement; GLRenderer->mViewActor = NULL; GLRenderer->mCurrentPortal = this; validcount++; // avoid recursions! if (origin->plane != -1) instack[origin->plane]++; GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); SaveMapSection(); SetupCoverage(); ClearClipper(); GLRenderer->DrawScene(); RestoreMapSection(); if (origin->plane != -1) instack[origin->plane]--; }