2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gl_flat.cpp
|
|
|
|
** Flat rendering
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2000-2005 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
|
|
|
|
** covered by the terms of the GNU Lesser General Public License as published
|
|
|
|
** by the Free Software Foundation; either version 2.1 of the License, or (at
|
|
|
|
** your option) any later version.
|
|
|
|
** 5. Full disclosure of the entire project's source code, except for third
|
|
|
|
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gl/system/gl_system.h"
|
|
|
|
#include "a_sharedglobal.h"
|
|
|
|
#include "r_defs.h"
|
|
|
|
#include "r_sky.h"
|
|
|
|
#include "r_utility.h"
|
|
|
|
#include "g_level.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "d_player.h"
|
2016-02-16 21:01:04 +00:00
|
|
|
#include "portal.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2013-09-03 16:29:39 +00:00
|
|
|
#include "gl/system/gl_interface.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/system/gl_cvars.h"
|
|
|
|
#include "gl/renderer/gl_renderer.h"
|
|
|
|
#include "gl/renderer/gl_lightdata.h"
|
|
|
|
#include "gl/renderer/gl_renderstate.h"
|
|
|
|
#include "gl/data/gl_data.h"
|
|
|
|
#include "gl/data/gl_vertexbuffer.h"
|
|
|
|
#include "gl/dynlights/gl_dynlight.h"
|
|
|
|
#include "gl/dynlights/gl_glow.h"
|
2014-08-01 18:59:39 +00:00
|
|
|
#include "gl/dynlights/gl_lightbuffer.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/scene/gl_drawinfo.h"
|
|
|
|
#include "gl/shaders/gl_shader.h"
|
|
|
|
#include "gl/textures/gl_material.h"
|
|
|
|
#include "gl/utility/gl_clock.h"
|
|
|
|
#include "gl/utility/gl_convert.h"
|
|
|
|
#include "gl/utility/gl_templates.h"
|
2016-08-25 22:02:32 +00:00
|
|
|
#include "gl/renderer/gl_quaddrawer.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-11-27 09:46:28 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
CVAR(Int, gl_breaksec, -1, 0)
|
|
|
|
#endif
|
2013-06-23 07:49:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Sets the texture matrix according to the plane's texture positioning
|
|
|
|
// information
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2014-09-02 08:31:48 +00:00
|
|
|
static float tics;
|
2014-07-13 18:41:20 +00:00
|
|
|
void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
// only manipulate the texture matrix if needed.
|
2016-03-31 07:50:59 +00:00
|
|
|
if (!secplane->Offs.isZero() ||
|
|
|
|
secplane->Scale.X != 1. || secplane->Scale.Y != 1 ||
|
|
|
|
secplane->Angle != 0 ||
|
2014-08-22 21:50:38 +00:00
|
|
|
gltexture->TextureWidth() != 64 ||
|
|
|
|
gltexture->TextureHeight() != 64)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-03-31 07:50:59 +00:00
|
|
|
float uoffs = secplane->Offs.X / gltexture->TextureWidth();
|
|
|
|
float voffs = secplane->Offs.Y / gltexture->TextureHeight();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-03-31 07:50:59 +00:00
|
|
|
float xscale1 = secplane->Scale.X;
|
|
|
|
float yscale1 = secplane->Scale.Y;
|
2013-06-23 07:49:34 +00:00
|
|
|
if (gltexture->tex->bHasCanvas)
|
|
|
|
{
|
|
|
|
yscale1 = 0 - yscale1;
|
|
|
|
}
|
2016-03-31 07:50:59 +00:00
|
|
|
float angle = -secplane->Angle;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-03-31 07:50:59 +00:00
|
|
|
float xscale2 = 64.f / gltexture->TextureWidth();
|
|
|
|
float yscale2 = 64.f / gltexture->TextureHeight();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-07-13 18:41:20 +00:00
|
|
|
gl_RenderState.mTextureMatrix.loadIdentity();
|
2016-03-31 07:50:59 +00:00
|
|
|
gl_RenderState.mTextureMatrix.scale(xscale1, yscale1, 1.0f);
|
|
|
|
gl_RenderState.mTextureMatrix.translate(uoffs, voffs, 0.0f);
|
|
|
|
gl_RenderState.mTextureMatrix.scale(xscale2, yscale2, 1.0f);
|
|
|
|
gl_RenderState.mTextureMatrix.rotate(angle, 0.0f, 0.0f, 1.0f);
|
2014-07-13 18:41:20 +00:00
|
|
|
gl_RenderState.EnableTextureMatrix(true);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-15 18:49:21 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Flats
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2014-07-15 18:49:21 +00:00
|
|
|
extern FDynLightData lightdata;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
Plane p;
|
|
|
|
|
2016-05-18 20:20:18 +00:00
|
|
|
if (renderstyle == STYLE_Add) return; // no lights on additively blended surfaces.
|
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
if (dli != NULL && *dli != -1)
|
|
|
|
{
|
|
|
|
gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli));
|
|
|
|
(*dli)++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-15 18:49:21 +00:00
|
|
|
lightdata.Clear();
|
|
|
|
FLightNode * node = sub->lighthead;
|
2013-06-23 07:49:34 +00:00
|
|
|
while (node)
|
|
|
|
{
|
|
|
|
ADynamicLight * light = node->lightsource;
|
2014-07-15 18:49:21 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
if (light->flags2&MF2_DORMANT)
|
|
|
|
{
|
|
|
|
node=node->nextLight;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
iter_dlightf++;
|
|
|
|
|
|
|
|
// we must do the side check here because gl_SetupLight needs the correct plane orientation
|
|
|
|
// which we don't have for Legacy-style 3D-floors
|
2016-03-30 18:01:44 +00:00
|
|
|
double planeh = plane.plane.ZatPoint(light);
|
|
|
|
if (gl_lights_checkside && ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling)))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-03-30 18:01:44 +00:00
|
|
|
node = node->nextLight;
|
2013-06-23 07:49:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
p.Set(plane.plane);
|
2016-03-08 20:22:12 +00:00
|
|
|
gl_GetLight(sub->sector->PortalGroup, p, light, false, false, lightdata);
|
2013-06-23 07:49:34 +00:00
|
|
|
node = node->nextLight;
|
|
|
|
}
|
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
int d = GLRenderer->mLights->UploadLights(lightdata);
|
|
|
|
if (pass == GLPASS_LIGHTSONLY)
|
|
|
|
{
|
|
|
|
GLRenderer->mLights->StoreIndex(d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl_RenderState.ApplyLightIndex(d);
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::DrawSubsector(subsector_t * sub)
|
|
|
|
{
|
2014-06-14 23:14:41 +00:00
|
|
|
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
|
2016-04-03 09:40:14 +00:00
|
|
|
for (unsigned int k = 0; k < sub->numlines; k++)
|
2014-05-10 23:23:27 +00:00
|
|
|
{
|
2016-04-03 09:40:14 +00:00
|
|
|
vertex_t *vt = sub->firstline[k].v1;
|
|
|
|
ptr->x = vt->fX();
|
|
|
|
ptr->z = plane.plane.ZatPoint(vt) + dz;
|
2016-04-14 11:22:15 +00:00
|
|
|
ptr->y = vt->fY();
|
2016-04-03 09:40:14 +00:00
|
|
|
ptr->u = vt->fX() / 64.f;
|
|
|
|
ptr->v = -vt->fY() / 64.f;
|
|
|
|
ptr++;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-06-14 23:14:41 +00:00
|
|
|
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
flatvertices += sub->numlines;
|
|
|
|
flatprimitives++;
|
|
|
|
}
|
|
|
|
|
2014-05-10 23:23:27 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
2016-04-26 11:50:05 +00:00
|
|
|
// this is only used by LM_DEFERRED
|
2013-06-23 07:49:34 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
void GLFlat::ProcessLights(bool istrans)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-08-19 12:18:21 +00:00
|
|
|
dynlightindex = GLRenderer->mLights->GetIndexPtr();
|
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
// Draw the subsectors belonging to this sector
|
|
|
|
for (int i=0; i<sector->subsectorcount; i++)
|
2014-08-19 12:18:21 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
subsector_t * sub = sector->subsectors[i];
|
|
|
|
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
|
2014-08-19 12:18:21 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
SetupSubsectorLights(GLPASS_LIGHTSONLY, sub);
|
2014-08-19 12:18:21 +00:00
|
|
|
}
|
2016-08-25 22:04:29 +00:00
|
|
|
}
|
2014-08-19 12:18:21 +00:00
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
// Draw the subsectors assigned to it due to missing textures
|
|
|
|
if (!(renderflags&SSRF_RENDER3DPLANES))
|
|
|
|
{
|
|
|
|
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR)?
|
|
|
|
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
|
|
|
|
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
|
2014-08-19 12:18:21 +00:00
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
while (node)
|
|
|
|
{
|
|
|
|
SetupSubsectorLights(GLPASS_LIGHTSONLY, node->sub);
|
|
|
|
node = node->next;
|
2014-08-19 12:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::DrawSubsectors(int pass, bool processlights, bool istrans)
|
|
|
|
{
|
|
|
|
int dli = dynlightindex;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_RenderState.Apply();
|
2016-08-25 22:04:29 +00:00
|
|
|
if (vboindex >= 0)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
int index = vboindex;
|
|
|
|
for (int i=0; i<sector->subsectorcount; i++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
subsector_t * sub = sector->subsectors[i];
|
2014-08-19 12:18:21 +00:00
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
|
|
|
|
{
|
|
|
|
if (processlights) SetupSubsectorLights(GLPASS_ALL, sub, &dli);
|
|
|
|
drawcalls.Clock();
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines);
|
|
|
|
drawcalls.Unclock();
|
|
|
|
flatvertices += sub->numlines;
|
|
|
|
flatprimitives++;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-08-25 22:04:29 +00:00
|
|
|
index += sub->numlines;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-08-25 22:04:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Draw the subsectors belonging to this sector
|
|
|
|
for (int i=0; i<sector->subsectorcount; i++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
subsector_t * sub = sector->subsectors[i];
|
|
|
|
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-08-25 22:04:29 +00:00
|
|
|
if (processlights) SetupSubsectorLights(GLPASS_ALL, sub, &dli);
|
|
|
|
DrawSubsector(sub);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-25 22:04:29 +00:00
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
// Draw the subsectors assigned to it due to missing textures
|
|
|
|
if (!(renderflags&SSRF_RENDER3DPLANES))
|
|
|
|
{
|
|
|
|
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR)?
|
|
|
|
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
|
|
|
|
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-08-25 22:04:29 +00:00
|
|
|
while (node)
|
|
|
|
{
|
|
|
|
if (processlights) SetupSubsectorLights(GLPASS_ALL, node->sub, &dli);
|
|
|
|
DrawSubsector(node->sub);
|
|
|
|
node = node->next;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-14 11:22:15 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// special handling for skyboxes which need texture clamping.
|
|
|
|
// This will find the bounding rectangle of the sector and just
|
|
|
|
// draw one single polygon filling that rectangle with a clamped
|
|
|
|
// texture.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::DrawSkyboxSector(int pass, bool processlights)
|
|
|
|
{
|
|
|
|
|
|
|
|
float minx = FLT_MAX, miny = FLT_MAX;
|
|
|
|
float maxx = -FLT_MAX, maxy = -FLT_MAX;
|
|
|
|
|
|
|
|
for (int i = 0; i < sector->linecount; i++)
|
|
|
|
{
|
|
|
|
line_t *ln = sector->lines[i];
|
|
|
|
float x = ln->v1->fX();
|
|
|
|
float y = ln->v1->fY();
|
|
|
|
if (x < minx) minx = x;
|
|
|
|
if (y < miny) miny = y;
|
|
|
|
if (x > maxx) maxx = x;
|
|
|
|
if (y > maxy) maxy = y;
|
|
|
|
x = ln->v2->fX();
|
|
|
|
y = ln->v2->fY();
|
|
|
|
if (x < minx) minx = x;
|
|
|
|
if (y < miny) miny = y;
|
|
|
|
if (x > maxx) maxx = x;
|
|
|
|
if (y > maxy) maxy = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
float z = plane.plane.ZatPoint(0., 0.) + dz;
|
2016-04-17 09:58:26 +00:00
|
|
|
static float uvals[] = { 0, 0, 1, 1 };
|
|
|
|
static float vvals[] = { 1, 0, 0, 1 };
|
|
|
|
int rot = -xs_FloorToInt(plane.Angle / 90.f);
|
|
|
|
|
2016-08-25 22:02:32 +00:00
|
|
|
FQuadDrawer qd;
|
2016-04-14 11:22:15 +00:00
|
|
|
|
2016-08-25 22:02:32 +00:00
|
|
|
qd.Set(0, minx, z, miny, uvals[rot & 3], vvals[rot & 3]);
|
|
|
|
qd.Set(1, minx, z, maxy, uvals[(rot + 1) & 3], vvals[(rot + 1) & 3]);
|
|
|
|
qd.Set(2, maxx, z, maxy, uvals[(rot + 2) & 3], vvals[(rot + 2) & 3]);
|
|
|
|
qd.Set(3, maxx, z, miny, uvals[(rot + 3) & 3], vvals[(rot + 3) & 3]);
|
|
|
|
qd.Render(GL_TRIANGLE_FAN);
|
2016-04-14 11:22:15 +00:00
|
|
|
|
|
|
|
flatvertices += 4;
|
|
|
|
flatprimitives++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2014-08-19 12:18:21 +00:00
|
|
|
void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIGHTSONLY
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
int rel = getExtraLight();
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2014-11-27 09:46:28 +00:00
|
|
|
if (sector->sectornum == gl_breaksec)
|
2014-05-08 07:48:39 +00:00
|
|
|
{
|
|
|
|
int a = 0;
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
switch (pass)
|
|
|
|
{
|
|
|
|
case GLPASS_PLAIN: // Single-pass rendering
|
2016-04-26 11:50:05 +00:00
|
|
|
case GLPASS_ALL: // Same, but also creates the dynlight data.
|
2014-05-11 22:13:19 +00:00
|
|
|
gl_SetColor(lightlevel, rel, Colormap,1.0f);
|
2014-07-15 18:49:21 +00:00
|
|
|
gl_SetFog(lightlevel, rel, &Colormap, false);
|
2016-04-14 11:22:15 +00:00
|
|
|
if (sector->special != GLSector_Skybox)
|
|
|
|
{
|
|
|
|
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
|
|
|
|
gl_SetPlaneTextureRotation(&plane, gltexture);
|
|
|
|
DrawSubsectors(pass, (pass == GLPASS_ALL || dynlightindex > -1), false);
|
|
|
|
gl_RenderState.EnableTextureMatrix(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl_RenderState.SetMaterial(gltexture, CLAMP_XY, 0, -1, false);
|
|
|
|
DrawSkyboxSector(pass, (pass == GLPASS_ALL || dynlightindex > -1));
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
break;
|
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
case GLPASS_LIGHTSONLY:
|
|
|
|
if (!trans || gltexture)
|
|
|
|
{
|
|
|
|
ProcessLights(trans);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
case GLPASS_TRANSLUCENT:
|
|
|
|
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE);
|
2014-05-11 22:13:19 +00:00
|
|
|
gl_SetColor(lightlevel, rel, Colormap, alpha);
|
2013-06-23 07:49:34 +00:00
|
|
|
gl_SetFog(lightlevel, rel, &Colormap, false);
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
2013-06-23 07:49:34 +00:00
|
|
|
if (!gltexture)
|
|
|
|
{
|
|
|
|
gl_RenderState.EnableTexture(false);
|
2014-08-19 12:18:21 +00:00
|
|
|
DrawSubsectors(pass, false, true);
|
2013-06-23 07:49:34 +00:00
|
|
|
gl_RenderState.EnableTexture(true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-09 10:00:42 +00:00
|
|
|
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
|
2014-07-13 18:41:20 +00:00
|
|
|
gl_SetPlaneTextureRotation(&plane, gltexture);
|
2016-04-26 22:41:00 +00:00
|
|
|
DrawSubsectors(pass, gl.lightmethod != LM_SOFTWARE, true);
|
2014-07-13 18:41:20 +00:00
|
|
|
gl_RenderState.EnableTextureMatrix(false);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
break;
|
2016-05-05 08:28:21 +00:00
|
|
|
|
|
|
|
case GLPASS_LIGHTTEX:
|
|
|
|
case GLPASS_LIGHTTEX_ADDITIVE:
|
2016-08-24 07:26:11 +00:00
|
|
|
case GLPASS_LIGHTTEX_FOGGY:
|
2016-05-05 08:28:21 +00:00
|
|
|
DrawLightsCompat(pass);
|
|
|
|
break;
|
2016-05-08 20:07:18 +00:00
|
|
|
|
|
|
|
case GLPASS_TEXONLY:
|
|
|
|
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
|
|
|
|
gl_SetPlaneTextureRotation(&plane, gltexture);
|
|
|
|
DrawSubsectors(pass, false, false);
|
2016-05-19 10:22:39 +00:00
|
|
|
gl_RenderState.EnableTextureMatrix(false);
|
2016-05-08 22:58:55 +00:00
|
|
|
break;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GLFlat::PutFlat
|
|
|
|
//
|
|
|
|
// Checks texture, lighting and translucency settings and puts this
|
|
|
|
// plane in the appropriate render list.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
inline void GLFlat::PutFlat(bool fog)
|
|
|
|
{
|
|
|
|
int list;
|
|
|
|
|
|
|
|
if (gl_fixedcolormap)
|
|
|
|
{
|
2014-05-11 20:57:42 +00:00
|
|
|
Colormap.Clear();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-05-04 21:07:16 +00:00
|
|
|
if (gl.lightmethod == LM_SOFTWARE)
|
|
|
|
{
|
|
|
|
if (PutFlatCompat(fog)) return;
|
|
|
|
}
|
2014-07-27 19:55:25 +00:00
|
|
|
if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog || gltexture == NULL)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-07-15 18:49:21 +00:00
|
|
|
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.
|
|
|
|
list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-07-27 19:55:25 +00:00
|
|
|
else
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
|
2014-08-30 11:04:41 +00:00
|
|
|
list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-04-26 11:50:05 +00:00
|
|
|
dynlightindex = -1; // make sure this is always initialized to something proper.
|
2014-07-15 18:49:21 +00:00
|
|
|
gl_drawinfo->drawlists[list].AddFlat (this);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// This draws one flat
|
|
|
|
// The passed sector does not indicate the area which is rendered.
|
|
|
|
// It is only used as source for the plane data.
|
|
|
|
// The whichplane boolean indicates if the flat is a floor(false) or a ceiling(true)
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::Process(sector_t * model, int whichplane, bool fog)
|
|
|
|
{
|
|
|
|
plane.GetFromSector(model, whichplane);
|
|
|
|
|
|
|
|
if (!fog)
|
|
|
|
{
|
2014-08-22 21:50:38 +00:00
|
|
|
gltexture=FMaterial::ValidateTexture(plane.texture, false, true);
|
2013-06-23 07:49:34 +00:00
|
|
|
if (!gltexture) return;
|
|
|
|
if (gltexture->tex->isFullbright())
|
|
|
|
{
|
|
|
|
Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff;
|
|
|
|
lightlevel=255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gltexture = NULL;
|
|
|
|
lightlevel = abs(lightlevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// get height from vplane
|
|
|
|
if (whichplane == sector_t::floor && sector->transdoor) dz = -1;
|
|
|
|
else dz = 0;
|
|
|
|
|
|
|
|
z = plane.plane.ZatPoint(0.f, 0.f);
|
|
|
|
|
|
|
|
PutFlat(fog);
|
|
|
|
rendered_flats++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Sets 3D floor info. Common code for all 4 cases
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside)
|
|
|
|
{
|
|
|
|
F3DFloor::planeref & plane = top? rover->top : rover->bottom;
|
|
|
|
|
|
|
|
// FF_FOG requires an inverted logic where to get the light from
|
|
|
|
lightlist_t *light = P_GetPlaneLight(sector, plane.plane, underside);
|
2016-04-06 12:03:21 +00:00
|
|
|
lightlevel = gl_ClampLight(*light->p_lightlevel);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (rover->flags & FF_FOG) Colormap.LightColor = (light->extra_colormap)->Fade;
|
2016-01-29 16:13:14 +00:00
|
|
|
else Colormap.CopyFrom3DLight(light);
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
alpha = rover->alpha/255.0f;
|
|
|
|
renderstyle = rover->flags&FF_ADDITIVETRANS? STYLE_Add : STYLE_Translucent;
|
|
|
|
if (plane.model->VBOHeightcheck(plane.isceiling))
|
|
|
|
{
|
|
|
|
vboindex = plane.vindex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vboindex = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Process a sector's flats for rendering
|
|
|
|
// This function is only called once per sector.
|
|
|
|
// Subsequent subsectors are just quickly added to the ss_renderflags array
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void GLFlat::ProcessSector(sector_t * frontsector)
|
|
|
|
{
|
|
|
|
lightlist_t * light;
|
2016-04-20 18:08:53 +00:00
|
|
|
FSectorPortal *port;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2016-04-07 14:25:30 +00:00
|
|
|
if (frontsector->sectornum == gl_breaksec)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-05-08 07:48:39 +00:00
|
|
|
int a = 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Get the real sector for this one.
|
2016-04-07 14:25:30 +00:00
|
|
|
sector = §ors[frontsector->sectornum];
|
2013-06-23 07:49:34 +00:00
|
|
|
extsector_t::xfloor &x = sector->e->XFloor;
|
2014-08-01 18:59:39 +00:00
|
|
|
dynlightindex = -1;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
byte &srf = gl_drawinfo->sectorrenderflags[sector->sectornum];
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// do floors
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
2016-04-02 21:17:16 +00:00
|
|
|
if (frontsector->floorplane.ZatPoint(ViewPos) <= ViewPos.Z)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
// process the original floor first.
|
|
|
|
|
|
|
|
srf |= SSRF_RENDERFLOOR;
|
|
|
|
|
|
|
|
lightlevel = gl_ClampLight(frontsector->GetFloorLight());
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap = frontsector->ColorMap;
|
2016-04-20 18:08:53 +00:00
|
|
|
port = frontsector->ValidatePortal(sector_t::floor);
|
|
|
|
if ((stack = (port != NULL)))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
if (port->mType == PORTS_STACKEDSECTORTHING)
|
2016-02-15 12:11:31 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
gl_drawinfo->AddFloorStack(sector); // stacked sector things require visplane merging.
|
2016-02-15 12:11:31 +00:00
|
|
|
}
|
2016-04-24 11:35:43 +00:00
|
|
|
alpha = frontsector->GetAlpha(sector_t::floor);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
alpha = 1.0f - frontsector->GetReflect(sector_t::floor);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2016-04-24 12:17:06 +00:00
|
|
|
if (alpha != 0.f && frontsector->GetTexture(sector_t::floor) != skyflatnum)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
if (frontsector->VBOHeightcheck(sector_t::floor))
|
|
|
|
{
|
|
|
|
vboindex = frontsector->vboindex[sector_t::floor];
|
|
|
|
}
|
|
|
|
else
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
vboindex = -1;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 18:08:53 +00:00
|
|
|
ceiling = false;
|
|
|
|
renderflags = SSRF_RENDERFLOOR;
|
|
|
|
|
|
|
|
if (x.ffloors.Size())
|
|
|
|
{
|
|
|
|
light = P_GetPlaneLight(sector, &frontsector->floorplane, false);
|
|
|
|
if ((!(sector->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING) || light->lightsource == NULL)
|
|
|
|
&& (light->p_lightlevel != &frontsector->lightlevel))
|
|
|
|
{
|
|
|
|
lightlevel = gl_ClampLight(*light->p_lightlevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
Colormap.CopyFrom3DLight(light);
|
|
|
|
}
|
|
|
|
renderstyle = STYLE_Translucent;
|
|
|
|
Process(frontsector, false, false);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// do ceilings
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
2016-04-02 21:17:16 +00:00
|
|
|
if (frontsector->ceilingplane.ZatPoint(ViewPos) >= ViewPos.Z)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
// process the original ceiling first.
|
|
|
|
|
|
|
|
srf |= SSRF_RENDERCEILING;
|
|
|
|
|
|
|
|
lightlevel = gl_ClampLight(frontsector->GetCeilingLight());
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap = frontsector->ColorMap;
|
2016-04-20 18:08:53 +00:00
|
|
|
port = frontsector->ValidatePortal(sector_t::ceiling);
|
|
|
|
if ((stack = (port != NULL)))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
if (port->mType == PORTS_STACKEDSECTORTHING)
|
2016-02-15 12:11:31 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
gl_drawinfo->AddCeilingStack(sector);
|
2016-02-15 12:11:31 +00:00
|
|
|
}
|
2016-04-24 11:35:43 +00:00
|
|
|
alpha = frontsector->GetAlpha(sector_t::ceiling);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
alpha = 1.0f - frontsector->GetReflect(sector_t::ceiling);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2016-04-24 12:17:06 +00:00
|
|
|
if (alpha != 0.f && frontsector->GetTexture(sector_t::ceiling) != skyflatnum)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
if (frontsector->VBOHeightcheck(sector_t::ceiling))
|
|
|
|
{
|
|
|
|
vboindex = frontsector->vboindex[sector_t::ceiling];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vboindex = -1;
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-04-20 18:08:53 +00:00
|
|
|
ceiling = true;
|
|
|
|
renderflags = SSRF_RENDERCEILING;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-04-20 18:08:53 +00:00
|
|
|
if (x.ffloors.Size())
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-20 18:08:53 +00:00
|
|
|
light = P_GetPlaneLight(sector, §or->ceilingplane, true);
|
|
|
|
|
|
|
|
if ((!(sector->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING))
|
|
|
|
&& (light->p_lightlevel != &frontsector->lightlevel))
|
|
|
|
{
|
|
|
|
lightlevel = gl_ClampLight(*light->p_lightlevel);
|
|
|
|
}
|
|
|
|
Colormap.CopyFrom3DLight(light);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-04-20 18:08:53 +00:00
|
|
|
renderstyle = STYLE_Translucent;
|
|
|
|
Process(frontsector, true, false);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// do 3D floors
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2016-04-07 14:25:30 +00:00
|
|
|
stack = false;
|
2013-06-23 07:49:34 +00:00
|
|
|
if (x.ffloors.Size())
|
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
player_t * player = players[consoleplayer].camera->player;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-04-07 14:25:30 +00:00
|
|
|
renderflags = SSRF_RENDER3DPLANES;
|
2013-06-23 07:49:34 +00:00
|
|
|
srf |= SSRF_RENDER3DPLANES;
|
|
|
|
// 3d-floors must not overlap!
|
2016-04-07 14:25:30 +00:00
|
|
|
double lastceilingheight = sector->CenterCeiling(); // render only in the range of the
|
|
|
|
double lastfloorheight = sector->CenterFloor(); // current sector part (if applicable)
|
|
|
|
F3DFloor * rover;
|
2013-06-23 07:49:34 +00:00
|
|
|
int k;
|
2016-04-07 14:25:30 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
// floors are ordered now top to bottom so scanning the list for the best match
|
|
|
|
// is no longer necessary.
|
|
|
|
|
2016-04-07 14:25:30 +00:00
|
|
|
ceiling = true;
|
|
|
|
for (k = 0; k < (int)x.ffloors.Size(); k++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
rover = x.ffloors[k];
|
|
|
|
|
|
|
|
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
if (rover->flags&FF_FOG && gl_fixedcolormap) continue;
|
2016-04-07 14:25:30 +00:00
|
|
|
if (!rover->top.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
|
|
|
if (ff_top < lastceilingheight)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-02 21:17:16 +00:00
|
|
|
if (ViewPos.Z <= rover->top.plane->ZatPoint(ViewPos))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap.FadeColor = frontsector->ColorMap->Fade;
|
2013-06-23 07:49:34 +00:00
|
|
|
Process(rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG));
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
lastceilingheight = ff_top;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-27 09:49:03 +00:00
|
|
|
if (!rover->bottom.copied && !(rover->flags&FF_INVERTPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
|
|
|
if (ff_bottom < lastceilingheight)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
if (ViewPos.Z <= rover->bottom.plane->ZatPoint(ViewPos))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap.FadeColor = frontsector->ColorMap->Fade;
|
2013-06-23 07:49:34 +00:00
|
|
|
Process(rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG));
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
lastceilingheight = ff_bottom;
|
|
|
|
if (rover->alpha < 255) lastceilingheight += EQUAL_EPSILON;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
|
|
|
|
ceiling = false;
|
|
|
|
for (k = x.ffloors.Size() - 1; k >= 0; k--)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
rover = x.ffloors[k];
|
|
|
|
|
|
|
|
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
if (rover->flags&FF_FOG && gl_fixedcolormap) continue;
|
2016-04-07 14:25:30 +00:00
|
|
|
if (!rover->bottom.copied && rover->flags&(FF_INVERTPLANES | FF_BOTHPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
|
|
|
if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-02 21:17:16 +00:00
|
|
|
if (ViewPos.Z >= rover->bottom.plane->ZatPoint(ViewPos))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap.FadeColor = frontsector->ColorMap->Fade;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (rover->flags&FF_FIX)
|
|
|
|
{
|
|
|
|
lightlevel = gl_ClampLight(rover->model->lightlevel);
|
|
|
|
Colormap = rover->GetColormap();
|
|
|
|
}
|
|
|
|
|
|
|
|
Process(rover->bottom.model, rover->bottom.isceiling, !!(rover->flags&FF_FOG));
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
lastfloorheight = ff_bottom;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-27 09:49:03 +00:00
|
|
|
if (!rover->top.copied && !(rover->flags&FF_INVERTPLANES))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-07 14:25:30 +00:00
|
|
|
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
|
|
|
if (ff_top > lastfloorheight)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-04-02 21:17:16 +00:00
|
|
|
if (ViewPos.Z >= rover->top.plane->ZatPoint(ViewPos))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
2016-04-07 14:25:30 +00:00
|
|
|
Colormap.FadeColor = frontsector->ColorMap->Fade;
|
2013-06-23 07:49:34 +00:00
|
|
|
Process(rover->top.model, rover->top.isceiling, !!(rover->flags&FF_FOG));
|
|
|
|
}
|
2016-04-07 14:25:30 +00:00
|
|
|
lastfloorheight = ff_top;
|
|
|
|
if (rover->alpha < 255) lastfloorheight -= EQUAL_EPSILON;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|