Ejemplo n.º 1
0
bool FDrawInfo::CheckAnchorFloor(subsector_t * sub)
{
    // This subsector has a one sided wall and can be used.
    if (sub->hacked==3) return true;
    if (sub->degenerate) return false;

    for(DWORD j=0; j<sub->numlines; j++)
    {
        seg_t * seg = sub->firstline + j;
        if (!seg->PartnerSeg) return true;

        subsector_t * backsub = seg->PartnerSeg->Subsector;

        // Find a linedef with a different visplane on the other side.
        if (!backsub->degenerate && seg->linedef &&
                (sub->render_sector != backsub->render_sector && sub->sector != backsub->sector))
        {
            // I'm ignoring slopes, scaling and rotation here. The likelihood of ZDoom maps
            // using such crap hacks is simply too small
            if (sub->render_sector->GetTexture(sector_t::floor)==backsub->render_sector->GetTexture(sector_t::floor) &&
                    sub->render_sector->GetPlaneTexZ(sector_t::floor)==backsub->render_sector->GetPlaneTexZ(sector_t::floor) &&
                    GetFloorLight(sub->render_sector)==GetFloorLight(backsub->render_sector))
            {
                continue;
            }
            // This means we found an adjoining subsector that clearly would go into another
            // visplane. That means that this subsector can be used as an anchor.
            return true;
        }
    }
    return false;
}
Ejemplo n.º 2
0
bool FDrawInfo::CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor)
{

    // mark it checked
    sub->validcount=validcount;


    // We must collect any subsector that either is connected to this one with a miniseg
    // or has the same visplane.
    // We must not collect any subsector that  has the anchor's visplane!
    if (!sub->degenerate)
    {
        // Is not being rendered so don't bother.
        if (!(ss_renderflags[DWORD(sub-subsectors)]&SSRF_PROCESSED)) return true;

        if (sub->render_sector->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
                sub->render_sector->GetPlaneTexZ(sector_t::floor)!=anchor->GetPlaneTexZ(sector_t::floor) ||
                GetFloorLight(sub->render_sector)!=GetFloorLight(anchor))
        {
            if (sub==viewsubsector && viewz<anchor->GetPlaneTexZ(sector_t::floor)) inview=true;
            HandledSubsectors.Push (sub);
        }
    }

    // We can assume that all segs in this subsector are connected to a subsector that has
    // to be checked as well
    for(DWORD j=0; j<sub->numlines; j++)
    {
        seg_t * seg = sub->firstline + j;
        if (seg->PartnerSeg)
        {
            subsector_t * backsub = seg->PartnerSeg->Subsector;

            // could be an anchor itself.
            if (!CheckAnchorFloor (backsub)) // must not be an anchor itself!
            {
                if (backsub->validcount!=validcount)
                {
                    if (!CollectSubsectorsFloor (backsub, anchor)) return false;
                }
            }
            else if (sub->render_sector == backsub->render_sector)
            {
                // Any anchor not within the original anchor's visplane terminates the processing.
                if (sub->render_sector->GetTexture(sector_t::floor)!=anchor->GetTexture(sector_t::floor) ||
                        sub->render_sector->GetPlaneTexZ(sector_t::floor)!=anchor->GetPlaneTexZ(sector_t::floor) ||
                        GetFloorLight(sub->render_sector)!=GetFloorLight(anchor))
                {
                    return false;
                }
            }
            if (!seg->linedef || (seg->frontsector==seg->backsector && sub->render_sector!=backsub->render_sector))
                lowersegs.Push(seg);
        }
    }
    return true;
}
Ejemplo n.º 3
0
void FDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor)
{
    sector_t fake;
    // mark it checked
    sub->validcount=validcount;

    // Has a sector stack or skybox itself!
    if (sub->render_sector->FloorSkyBox && sub->render_sector->FloorSkyBox->bAlways) return;

    // Don't bother processing unrendered subsectors
    if (sub->numlines>2 && !(ss_renderflags[DWORD(sub-subsectors)]&SSRF_PROCESSED)) return;

    // Must be the exact same visplane
    sector_t * me = gl_FakeFlat(sub->render_sector, &fake, false);
    if (me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
            me->floorplane != anchor->floorplane ||
            GetFloorLight(me) != GetFloorLight(anchor) ||
            me->ColorMap != anchor->ColorMap ||
            me->GetXOffset(sector_t::floor) != anchor->GetXOffset(sector_t::floor) ||
            me->GetYOffset(sector_t::floor) != anchor->GetYOffset(sector_t::floor) ||
            me->GetXScale(sector_t::floor) != anchor->GetXScale(sector_t::floor) ||
            me->GetYScale(sector_t::floor) != anchor->GetYScale(sector_t::floor) ||
            me->GetAngle(sector_t::floor) != anchor->GetAngle(sector_t::floor))
    {
        // different visplane so it can't belong to this stack
        return;
    }

    HandledSubsectors.Push (sub);

    for(DWORD j=0; j<sub->numlines; j++)
    {
        seg_t * seg = sub->firstline + j;
        if (seg->PartnerSeg)
        {
            subsector_t * backsub = seg->PartnerSeg->Subsector;

            if (backsub->validcount!=validcount) CollectSectorStacksFloor (backsub, anchor);
        }
    }
}
Ejemplo n.º 4
0
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
					 int *floorlightlevel, int *ceilinglightlevel,
					 bool back)
{
	// [RH] allow per-plane lighting
	if (floorlightlevel != NULL)
	{
		*floorlightlevel = GetFloorLight (sec);
	}

	if (ceilinglightlevel != NULL)
	{
		*ceilinglightlevel = GetCeilingLight (sec);
	}

	FakeSide = FAKED_Center;

	const sector_t *s = sec->GetHeightSec();
	if (s != NULL)
	{
		sector_t *heightsec = viewsector->heightsec;
		bool underwater = r_fakingunderwater ||
			(heightsec && viewz <= heightsec->floorplane.ZatPoint (viewx, viewy));
		bool doorunderwater = false;
		int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES);

		// Replace sector being drawn with a copy to be hacked
		*tempsec = *sec;

		// Replace floor and ceiling height with control sector's heights.
		if (diffTex)
		{
			if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane))
			{
				tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false);
			}
			else if (s->MoreFlags & SECF_FAKEFLOORONLY)
			{
				if (underwater)
				{
					tempsec->ColorMap = s->ColorMap;
					if (!(s->MoreFlags & SECF_NOFAKELIGHT))
					{
						tempsec->lightlevel = s->lightlevel;

						if (floorlightlevel != NULL)
						{
							*floorlightlevel = GetFloorLight (s);
						}

						if (ceilinglightlevel != NULL)
						{
							*ceilinglightlevel = GetCeilingLight (s);
						}
					}
					FakeSide = FAKED_BelowFloor;
					return tempsec;
				}
				return sec;
			}
		}
		else
		{
			tempsec->floorplane = s->floorplane;
		}

		if (!(s->MoreFlags & SECF_FAKEFLOORONLY))
		{
			if (diffTex)
			{
				if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane))
				{
					tempsec->SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false);
				}
			}
			else
			{
				tempsec->ceilingplane  = s->ceilingplane;
			}
		}

//		fixed_t refflorz = s->floorplane.ZatPoint (viewx, viewy);
		fixed_t refceilz = s->ceilingplane.ZatPoint (viewx, viewy);
//		fixed_t orgflorz = sec->floorplane.ZatPoint (viewx, viewy);
		fixed_t orgceilz = sec->ceilingplane.ZatPoint (viewx, viewy);

#if 1
		// [RH] Allow viewing underwater areas through doors/windows that
		// are underwater but not in a water sector themselves.
		// Only works if you cannot see the top surface of any deep water
		// sectors at the same time.
		if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL)
		{
			if (rw_frontcz1 <= s->floorplane.ZatPoint (curline->v1->x, curline->v1->y) &&
				rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y))
			{
				// Check that the window is actually visible
				for (int z = WallSX1; z < WallSX2; ++z)
				{
					if (floorclip[z] > ceilingclip[z])
					{
						doorunderwater = true;
						r_fakingunderwater = true;
						break;
					}
				}
			}
		}
#endif

		if (underwater || doorunderwater)
		{
			tempsec->floorplane = sec->floorplane;
			tempsec->ceilingplane = s->floorplane;
			tempsec->ceilingplane.FlipVert ();
			tempsec->ceilingplane.ChangeHeight (-1);
			tempsec->ColorMap = s->ColorMap;
		}

		// killough 11/98: prevent sudden light changes from non-water sectors:
		if ((underwater && !back) || doorunderwater)
		{					// head-below-floor hack
			tempsec->SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false);
			tempsec->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;

			tempsec->ceilingplane		= s->floorplane;
			tempsec->ceilingplane.FlipVert ();
			tempsec->ceilingplane.ChangeHeight (-1);
			if (s->GetTexture(sector_t::ceiling) == skyflatnum)
			{
				tempsec->floorplane			= tempsec->ceilingplane;
				tempsec->floorplane.FlipVert ();
				tempsec->floorplane.ChangeHeight (+1);
				tempsec->SetTexture(sector_t::ceiling, tempsec->GetTexture(sector_t::floor), false);
				tempsec->planes[sector_t::ceiling].xform = tempsec->planes[sector_t::floor].xform;
			}
			else
			{
				tempsec->SetTexture(sector_t::ceiling, diffTex ? s->GetTexture(sector_t::floor) : s->GetTexture(sector_t::ceiling), false);
				tempsec->planes[sector_t::ceiling].xform = s->planes[sector_t::ceiling].xform;
			}

			if (!(s->MoreFlags & SECF_NOFAKELIGHT))
			{
				tempsec->lightlevel = s->lightlevel;

				if (floorlightlevel != NULL)
				{
					*floorlightlevel = GetFloorLight (s);
				}

				if (ceilinglightlevel != NULL)
				{
					*ceilinglightlevel = GetCeilingLight (s);
				}
			}
			FakeSide = FAKED_BelowFloor;
		}
		else if (heightsec && viewz >= heightsec->ceilingplane.ZatPoint (viewx, viewy) &&
				 orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY))
		{	// Above-ceiling hack
			tempsec->ceilingplane		= s->ceilingplane;
			tempsec->floorplane			= s->ceilingplane;
			tempsec->floorplane.FlipVert ();
			tempsec->floorplane.ChangeHeight (+1);
			tempsec->ColorMap			= s->ColorMap;
			tempsec->ColorMap			= s->ColorMap;

			tempsec->SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false);
			tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false);
			tempsec->planes[sector_t::ceiling].xform = tempsec->planes[sector_t::floor].xform = s->planes[sector_t::ceiling].xform;

			if (s->GetTexture(sector_t::floor) != skyflatnum)
			{
				tempsec->ceilingplane	= sec->ceilingplane;
				tempsec->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false);
				tempsec->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;
			}

			if (!(s->MoreFlags & SECF_NOFAKELIGHT))
			{
				tempsec->lightlevel  = s->lightlevel;

				if (floorlightlevel != NULL)
				{
					*floorlightlevel = GetFloorLight (s);
				}

				if (ceilinglightlevel != NULL)
				{
					*ceilinglightlevel = GetCeilingLight (s);
				}
			}
			FakeSide = FAKED_AboveCeiling;
		}
		sec = tempsec;					// Use other sector
	}
	return sec;
}
Ejemplo n.º 5
0
//==========================================================================
//
// Draw the plane segment into the gap
//
//==========================================================================
void GLDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling)
{
	GLSectorPlane plane;
	int lightlevel;
	FColormap Colormap;
	FGLTexture * gltexture;

	plane.GetFromSector(sec, ceiling);

	gltexture=FGLTexture::ValidateTexture(plane.texture);
	if (!gltexture) return;

	if (gl_fixedcolormap) 
	{
		Colormap.GetFixedColormap();
		lightlevel=255;
	}
	else
	{
		Colormap=sec->ColorMap;
		if (gltexture->tex->isFullbright())
		{
			Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
			lightlevel=255;
		}
		else lightlevel=abs(ceiling? GetCeilingLight(sec) : GetFloorLight(sec));
	}

	int rel = extralight * gl_weaponlight;
	gl_SetColor(lightlevel, rel, &Colormap, 1.0f);
	gl_SetFog(lightlevel, rel, &Colormap, false);
	gltexture->Bind(Colormap.LightColor.a);
	gl_SetPlaneTextureRotation(&plane, gltexture);

	float fviewx = TO_GL(viewx);
	float fviewy = TO_GL(viewy);
	float fviewz = TO_GL(viewz);

	gl_ApplyShader();
	gl.Begin(GL_TRIANGLE_FAN);
	float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz);
	float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz);

	float px1 = fviewx + prj_fac1 * (ws->x1-fviewx);
	float py1 = fviewy + prj_fac1 * (ws->y1-fviewy);

	float px2 = fviewx + prj_fac2 * (ws->x1-fviewx);
	float py2 = fviewy + prj_fac2 * (ws->y1-fviewy);

	float px3 = fviewx + prj_fac2 * (ws->x2-fviewx);
	float py3 = fviewy + prj_fac2 * (ws->y2-fviewy);

	float px4 = fviewx + prj_fac1 * (ws->x2-fviewx);
	float py4 = fviewy + prj_fac1 * (ws->y2-fviewy);

	gl.TexCoord2f(px1 / 64, -py1 / 64);
	gl.Vertex3f(px1, planez, py1);

	gl.TexCoord2f(px2 / 64, -py2 / 64);
	gl.Vertex3f(px2, planez, py2);

	gl.TexCoord2f(px3 / 64, -py3 / 64);
	gl.Vertex3f(px3, planez, py3);

	gl.TexCoord2f(px4 / 64, -py4 / 64);
	gl.Vertex3f(px4, planez, py4);

	gl.End();

	gl.MatrixMode(GL_TEXTURE);
	gl.PopMatrix();
	gl.MatrixMode(GL_MODELVIEW);
}
Ejemplo n.º 6
0
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
					 int *floorlightlevel, int *ceilinglightlevel,
					 bool back)
{
   // [ZDoomGL] - convenience, so you don't have to check for NULL before calling function
   if (!sec)
   {
      return NULL;
   }
	// [RH] allow per-plane lighting
	if (floorlightlevel != NULL)
	{
		*floorlightlevel = GetFloorLight (sec);
	}

	if (ceilinglightlevel != NULL)
	{
		*ceilinglightlevel = GetCeilingLight (sec);
	}

	FakeSide = FAKED_Center;

	if (sec->heightsec && !(sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
	{
		const sector_t *s = sec->heightsec;
		sector_t *heightsec = viewsector->heightsec;
		bool underwater = r_fakingunderwater ||
			(heightsec && viewz <= heightsec->floorplane.ZatPoint (viewx, viewy));
		bool doorunderwater = false;
		int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES);

		// Replace sector being drawn with a copy to be hacked
		*tempsec = *sec;

		// Replace floor and ceiling height with control sector's heights.
		if (diffTex)
		{
			if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane))
			{
				tempsec->floorpic = s->floorpic;
			}
			else if (s->MoreFlags & SECF_FAKEFLOORONLY)
			{
				if (underwater)
				{
					tempsec->ColorMap = s->ColorMap;
					if (!(s->MoreFlags & SECF_NOFAKELIGHT))
					{
						tempsec->lightlevel = s->lightlevel;

						if (floorlightlevel != NULL)
						{
							*floorlightlevel = GetFloorLight (s);
						}

						if (ceilinglightlevel != NULL)
						{
							*ceilinglightlevel = GetCeilingLight (s);
						}
					}
					FakeSide = FAKED_BelowFloor;
					return tempsec;
				}
				return sec;
			}
		}
		else
		{
			tempsec->floorplane = s->floorplane;
		}

		if (!(s->MoreFlags & SECF_FAKEFLOORONLY))
		{
			if (diffTex)
			{
				if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane))
				{
					tempsec->ceilingpic = s->ceilingpic;
				}
			}
			else
			{
				tempsec->ceilingplane  = s->ceilingplane;
			}
		}

//		fixed_t refflorz = s->floorplane.ZatPoint (viewx, viewy);
		fixed_t refceilz = s->ceilingplane.ZatPoint (viewx, viewy);
//		fixed_t orgflorz = sec->floorplane.ZatPoint (viewx, viewy);
		fixed_t orgceilz = sec->ceilingplane.ZatPoint (viewx, viewy);

#if 1
		if ( OPENGL_GetCurrentRenderer( ) == RENDERER_SOFTWARE )
		{
			// [RH] Allow viewing underwater areas through doors/windows that
			// are underwater but not in a water sector themselves.
			// Only works if you cannot see the top surface of any deep water
			// sectors at the same time.
			if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL)
			{
				if (rw_frontcz1 <= s->floorplane.ZatPoint (curline->v1->x, curline->v1->y) &&
					rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y))
				{
					// Check that the window is actually visible
					for (int z = WallSX1; z < WallSX2; ++z)
					{
						if (floorclip[z] > ceilingclip[z])
						{
							doorunderwater = true;
							r_fakingunderwater = true;
							break;
						}
					}
				}
			}
		}
		else
		{
			// have to do this a different way for the hardware engine...
		}
#endif

		if (underwater || doorunderwater)
		{
			tempsec->floorplane = sec->floorplane;
			tempsec->ceilingplane = s->floorplane;
			tempsec->ceilingplane.FlipVert ();
			tempsec->ceilingplane.ChangeHeight (-1);
			tempsec->ColorMap = s->ColorMap;
		}

		// killough 11/98: prevent sudden light changes from non-water sectors:
		if ((underwater && !back) || doorunderwater)
		{					// head-below-floor hack
			tempsec->floorpic			= diffTex ? sec->floorpic : s->floorpic;
			tempsec->floor_xoffs		= s->floor_xoffs;
			tempsec->floor_yoffs		= s->floor_yoffs;
			tempsec->floor_xscale		= s->floor_xscale;
			tempsec->floor_yscale		= s->floor_yscale;
			tempsec->floor_angle		= s->floor_angle;
			tempsec->base_floor_angle	= s->base_floor_angle;
			tempsec->base_floor_yoffs	= s->base_floor_yoffs;

			tempsec->ceilingplane		= s->floorplane;
			tempsec->ceilingplane.FlipVert ();
			tempsec->ceilingplane.ChangeHeight (-1);
			if (s->ceilingpic == skyflatnum)
			{
				tempsec->floorplane			= tempsec->ceilingplane;
				tempsec->floorplane.FlipVert ();
				tempsec->floorplane.ChangeHeight (+1);
				tempsec->ceilingpic			= tempsec->floorpic;
				tempsec->ceiling_xoffs		= tempsec->floor_xoffs;
				tempsec->ceiling_yoffs		= tempsec->floor_yoffs;
				tempsec->ceiling_xscale		= tempsec->floor_xscale;
				tempsec->ceiling_yscale		= tempsec->floor_yscale;
				tempsec->ceiling_angle		= tempsec->floor_angle;
				tempsec->base_ceiling_angle	= tempsec->base_floor_angle;
				tempsec->base_ceiling_yoffs	= tempsec->base_floor_yoffs;
			}
			else
			{
				tempsec->ceilingpic			= diffTex ? s->floorpic : s->ceilingpic;
				tempsec->ceiling_xoffs		= s->ceiling_xoffs;
				tempsec->ceiling_yoffs		= s->ceiling_yoffs;
				tempsec->ceiling_xscale		= s->ceiling_xscale;
				tempsec->ceiling_yscale		= s->ceiling_yscale;
				tempsec->ceiling_angle		= s->ceiling_angle;
				tempsec->base_ceiling_angle	= s->base_ceiling_angle;
				tempsec->base_ceiling_yoffs	= s->base_ceiling_yoffs;
			}

			if (!(s->MoreFlags & SECF_NOFAKELIGHT))
			{
				tempsec->lightlevel = s->lightlevel;

				if (floorlightlevel != NULL)
				{
					*floorlightlevel = GetFloorLight (s);
				}

				if (ceilinglightlevel != NULL)
				{
					*ceilinglightlevel = GetCeilingLight (s);
				}
			}
			FakeSide = FAKED_BelowFloor;
		}
		else if (heightsec && viewz >= heightsec->ceilingplane.ZatPoint (viewx, viewy) &&
				 orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY))
		{	// Above-ceiling hack
			tempsec->ceilingplane		= s->ceilingplane;
			tempsec->floorplane			= s->ceilingplane;
			tempsec->floorplane.FlipVert ();
			tempsec->floorplane.ChangeHeight (+1);
			tempsec->ColorMap			= s->ColorMap;
			tempsec->ColorMap			= s->ColorMap;

			tempsec->ceilingpic = diffTex ? sec->ceilingpic : s->ceilingpic;
			tempsec->floorpic											= s->ceilingpic;
			tempsec->floor_xoffs		= tempsec->ceiling_xoffs		= s->ceiling_xoffs;
			tempsec->floor_yoffs		= tempsec->ceiling_yoffs		= s->ceiling_yoffs;
			tempsec->floor_xscale		= tempsec->ceiling_xscale		= s->ceiling_xscale;
			tempsec->floor_yscale		= tempsec->ceiling_yscale		= s->ceiling_yscale;
			tempsec->floor_angle		= tempsec->ceiling_angle		= s->ceiling_angle;
			tempsec->base_floor_angle	= tempsec->base_ceiling_angle	= s->base_ceiling_angle;
			tempsec->base_floor_yoffs	= tempsec->base_ceiling_yoffs	= s->base_ceiling_yoffs;

			if (s->floorpic != skyflatnum)
			{
				tempsec->ceilingplane	= sec->ceilingplane;
				tempsec->floorpic		= s->floorpic;
				tempsec->floor_xoffs	= s->floor_xoffs;
				tempsec->floor_yoffs	= s->floor_yoffs;
				tempsec->floor_xscale	= s->floor_xscale;
				tempsec->floor_yscale	= s->floor_yscale;
				tempsec->floor_angle	= s->floor_angle;
			}

			if (!(s->MoreFlags & SECF_NOFAKELIGHT))
			{
				tempsec->lightlevel  = s->lightlevel;

				if (floorlightlevel != NULL)
				{
					*floorlightlevel = GetFloorLight (s);
				}

				if (ceilinglightlevel != NULL)
				{
					*ceilinglightlevel = GetCeilingLight (s);
				}
			}
			FakeSide = FAKED_AboveCeiling;
		}
		sec = tempsec;					// Use other sector
	}
	return sec;
}