diff --git a/SRB2.cbp b/SRB2.cbp
index 74ec96c6..5aa623fa 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 46a42a92..0602de9d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -350,6 +350,7 @@ if(${SRB2_CONFIG_HWRENDER})
set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
@@ -358,6 +359,7 @@ if(${SRB2_CONFIG_HWRENDER})
)
set (SRB2_HWRENDER_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
diff --git a/src/Makefile b/src/Makefile
index 7a67c3f0..b159de3b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -269,7 +269,7 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
- $(OBJDIR)/hw_main.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
+ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
endif
ifdef NOHS
@@ -719,7 +719,7 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
@@ -727,7 +727,7 @@ else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
@@ -880,7 +880,7 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -888,7 +888,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -896,7 +896,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
diff --git a/src/doomdef.h b/src/doomdef.h
index 7f641558..ff09144e 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -502,4 +502,11 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
//#define SECTORSPECIALSAFTERTHINK
+/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
+/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
+/// on the bright side it fixes some weird issues with translucent walls
+/// \note SRB2CB port.
+/// SRB2CB itself ported this from PrBoom+
+#define NEWCLIP
+
#endif // __DOOMDEF__
diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c
new file mode 100644
index 00000000..6d120efe
--- /dev/null
+++ b/src/hardware/hw_clip.c
@@ -0,0 +1,465 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom: a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ * Copyright 2005, 2006 by
+ * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION:
+ *
+ *---------------------------------------------------------------------
+ */
+
+/*
+ *
+ ** gl_clipper.cpp
+ **
+ ** Handles visibility checks.
+ ** Loosely based on the JDoom clipper.
+ **
+ **---------------------------------------------------------------------------
+ ** Copyright 2003 Tim Stump
+ ** 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.
+ **
+ ** 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
+#include "../v_video.h"
+#include "hw_clip.h"
+#include "hw_glob.h"
+#include "../r_state.h"
+#include "../tables.h"
+#include "r_opengl/r_opengl.h"
+
+#ifdef HAVE_SPHEREFRUSTRUM
+static GLdouble viewMatrix[16];
+static GLdouble projMatrix[16];
+float frustum[6][4];
+#endif
+
+typedef struct clipnode_s
+ {
+ struct clipnode_s *prev, *next;
+ angle_t start, end;
+ } clipnode_t;
+
+clipnode_t *freelist;
+clipnode_t *clipnodes;
+clipnode_t *cliphead;
+
+static clipnode_t * gld_clipnode_GetNew(void);
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end);
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle);
+static void gld_clipper_AddClipRange(angle_t start, angle_t end);
+static void gld_clipper_RemoveRange(clipnode_t * range);
+static void gld_clipnode_Free(clipnode_t *node);
+
+static clipnode_t * gld_clipnode_GetNew(void)
+{
+ if (freelist)
+ {
+ clipnode_t * p = freelist;
+ freelist = p->next;
+ return p;
+ }
+ else
+ {
+ return (clipnode_t*)malloc(sizeof(clipnode_t));
+ }
+}
+
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end)
+{
+ clipnode_t * c = gld_clipnode_GetNew();
+ c->start = start;
+ c->end = end;
+ c->next = c->prev=NULL;
+ return c;
+}
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle)
+{
+ if(startAngle > endAngle)
+ {
+ return (gld_clipper_IsRangeVisible(startAngle, ANGLE_MAX) || gld_clipper_IsRangeVisible(0, endAngle));
+ }
+
+ return gld_clipper_IsRangeVisible(startAngle, endAngle);
+}
+
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle)
+{
+ clipnode_t *ci;
+ ci = cliphead;
+
+ if (endAngle == 0 && ci && ci->start == 0)
+ return false;
+
+ while (ci != NULL && ci->start < endAngle)
+ {
+ if (startAngle >= ci->start && endAngle <= ci->end)
+ {
+ return false;
+ }
+ ci = ci->next;
+ }
+
+ return true;
+}
+
+static void gld_clipnode_Free(clipnode_t *node)
+{
+ node->next = freelist;
+ freelist = node;
+}
+
+static void gld_clipper_RemoveRange(clipnode_t *range)
+{
+ if (range == cliphead)
+ {
+ cliphead = cliphead->next;
+ }
+ else
+ {
+ if (range->prev)
+ {
+ range->prev->next = range->next;
+ }
+ if (range->next)
+ {
+ range->next->prev = range->prev;
+ }
+ }
+
+ gld_clipnode_Free(range);
+}
+
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle)
+{
+ if(startangle > endangle)
+ {
+ // The range has to added in two parts.
+ gld_clipper_AddClipRange(startangle, ANGLE_MAX);
+ gld_clipper_AddClipRange(0, endangle);
+ }
+ else
+ {
+ // Add the range as usual.
+ gld_clipper_AddClipRange(startangle, endangle);
+ }
+}
+
+static void gld_clipper_AddClipRange(angle_t start, angle_t end)
+{
+ clipnode_t *node, *temp, *prevNode, *node2, *delnode;
+
+ if (cliphead)
+ {
+ //check to see if range contains any old ranges
+ node = cliphead;
+ while (node != NULL && node->start < end)
+ {
+ if (node->start >= start && node->end <= end)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipper_RemoveRange(temp);
+ }
+ else
+ {
+ if (node->start <= start && node->end >= end)
+ {
+ return;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+ }
+
+ //check to see if range overlaps a range (or possibly 2)
+ node = cliphead;
+ while (node != NULL && node->start <= end)
+ {
+ if (node->end >= start)
+ {
+ // we found the first overlapping node
+ if (node->start > start)
+ {
+ // the new range overlaps with this node's start point
+ node->start = start;
+ }
+ if (node->end < end)
+ {
+ node->end = end;
+ }
+
+ node2 = node->next;
+ while (node2 && node2->start <= node->end)
+ {
+ if (node2->end > node->end)
+ {
+ node->end = node2->end;
+ }
+
+ delnode = node2;
+ node2 = node2->next;
+ gld_clipper_RemoveRange(delnode);
+ }
+ return;
+ }
+ node = node->next;
+ }
+
+ //just add range
+ node = cliphead;
+ prevNode = NULL;
+ temp = gld_clipnode_NewRange(start, end);
+ while (node != NULL && node->start < end)
+ {
+ prevNode = node;
+ node = node->next;
+ }
+ temp->next = node;
+ if (node == NULL)
+ {
+ temp->prev = prevNode;
+ if (prevNode)
+ {
+ prevNode->next = temp;
+ }
+ if (!cliphead)
+ {
+ cliphead = temp;
+ }
+ }
+ else
+ {
+ if (node == cliphead)
+ {
+ cliphead->prev = temp;
+ cliphead = temp;
+ }
+ else
+ {
+ temp->prev = prevNode;
+ prevNode->next = temp;
+ node->prev = temp;
+ }
+ }
+ }
+ else
+ {
+ temp = gld_clipnode_NewRange(start, end);
+ cliphead = temp;
+ return;
+ }
+}
+
+void gld_clipper_Clear(void)
+{
+ clipnode_t *node = cliphead;
+ clipnode_t *temp;
+
+ while (node != NULL)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipnode_Free(temp);
+ }
+
+ cliphead = NULL;
+}
+
+#define RMUL (1.6f/1.333333f)
+
+angle_t gld_FrustumAngle(void)
+{
+ double floatangle;
+ angle_t a1;
+
+ float tilt = (float)fabs(((double)(int)aimingangle) / ANG1);
+
+ // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
+
+ float render_fov = FIXED_TO_FLOAT(cv_grfov.value);
+ float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
+ float render_multiplier = 64.0f / render_fovratio / RMUL;
+
+ if (tilt > 90.0f)
+ {
+ tilt = 90.0f;
+ }
+
+ // If the pitch is larger than this you can look all around at a FOV of 90
+ if (abs((signed)aimingangle) > 46 * ANG1)
+ return 0xffffffff;
+
+ // ok, this is a gross hack that barely works...
+ // but at least it doesn't overestimate too much...
+ floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * (float)render_fov * 48.0f / render_multiplier / 90.0f;
+ a1 = ANG1 * (int)floatangle;
+ if (a1 >= ANGLE_180)
+ return 0xffffffff;
+ return a1;
+}
+
+// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
+// compiler complains about (p)glGetDoublev anyway, in case anyone wants this
+// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
+// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
+#ifdef HAVE_SPHEREFRUSTRUM
+//
+// gld_FrustrumSetup
+//
+
+#define CALCMATRIX(a, b, c, d, e, f, g, h)\
+(float)(viewMatrix[a] * projMatrix[b] + \
+viewMatrix[c] * projMatrix[d] + \
+viewMatrix[e] * projMatrix[f] + \
+viewMatrix[g] * projMatrix[h])
+
+#define NORMALIZE_PLANE(i)\
+t = (float)sqrt(\
+frustum[i][0] * frustum[i][0] + \
+frustum[i][1] * frustum[i][1] + \
+frustum[i][2] * frustum[i][2]); \
+frustum[i][0] /= t; \
+frustum[i][1] /= t; \
+frustum[i][2] /= t; \
+frustum[i][3] /= t
+
+void gld_FrustrumSetup(void)
+{
+ float t;
+ float clip[16];
+
+ pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+ pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
+
+ clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
+ clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);
+ clip[2] = CALCMATRIX(0, 2, 1, 6, 2, 10, 3, 14);
+ clip[3] = CALCMATRIX(0, 3, 1, 7, 2, 11, 3, 15);
+
+ clip[4] = CALCMATRIX(4, 0, 5, 4, 6, 8, 7, 12);
+ clip[5] = CALCMATRIX(4, 1, 5, 5, 6, 9, 7, 13);
+ clip[6] = CALCMATRIX(4, 2, 5, 6, 6, 10, 7, 14);
+ clip[7] = CALCMATRIX(4, 3, 5, 7, 6, 11, 7, 15);
+
+ clip[8] = CALCMATRIX(8, 0, 9, 4, 10, 8, 11, 12);
+ clip[9] = CALCMATRIX(8, 1, 9, 5, 10, 9, 11, 13);
+ clip[10] = CALCMATRIX(8, 2, 9, 6, 10, 10, 11, 14);
+ clip[11] = CALCMATRIX(8, 3, 9, 7, 10, 11, 11, 15);
+
+ clip[12] = CALCMATRIX(12, 0, 13, 4, 14, 8, 15, 12);
+ clip[13] = CALCMATRIX(12, 1, 13, 5, 14, 9, 15, 13);
+ clip[14] = CALCMATRIX(12, 2, 13, 6, 14, 10, 15, 14);
+ clip[15] = CALCMATRIX(12, 3, 13, 7, 14, 11, 15, 15);
+
+ // Right plane
+ frustum[0][0] = clip[ 3] - clip[ 0];
+ frustum[0][1] = clip[ 7] - clip[ 4];
+ frustum[0][2] = clip[11] - clip[ 8];
+ frustum[0][3] = clip[15] - clip[12];
+ NORMALIZE_PLANE(0);
+
+ // Left plane
+ frustum[1][0] = clip[ 3] + clip[ 0];
+ frustum[1][1] = clip[ 7] + clip[ 4];
+ frustum[1][2] = clip[11] + clip[ 8];
+ frustum[1][3] = clip[15] + clip[12];
+ NORMALIZE_PLANE(1);
+
+ // Bottom plane
+ frustum[2][0] = clip[ 3] + clip[ 1];
+ frustum[2][1] = clip[ 7] + clip[ 5];
+ frustum[2][2] = clip[11] + clip[ 9];
+ frustum[2][3] = clip[15] + clip[13];
+ NORMALIZE_PLANE(2);
+
+ // Top plane
+ frustum[3][0] = clip[ 3] - clip[ 1];
+ frustum[3][1] = clip[ 7] - clip[ 5];
+ frustum[3][2] = clip[11] - clip[ 9];
+ frustum[3][3] = clip[15] - clip[13];
+ NORMALIZE_PLANE(3);
+
+ // Far plane
+ frustum[4][0] = clip[ 3] - clip[ 2];
+ frustum[4][1] = clip[ 7] - clip[ 6];
+ frustum[4][2] = clip[11] - clip[10];
+ frustum[4][3] = clip[15] - clip[14];
+ NORMALIZE_PLANE(4);
+
+ // Near plane
+ frustum[5][0] = clip[ 3] + clip[ 2];
+ frustum[5][1] = clip[ 7] + clip[ 6];
+ frustum[5][2] = clip[11] + clip[10];
+ frustum[5][3] = clip[15] + clip[14];
+ NORMALIZE_PLANE(5);
+}
+
+boolean gld_SphereInFrustum(float x, float y, float z, float radius)
+{
+ int p;
+
+ for (p = 0; p < 4; p++)
+ {
+ if (frustum[p][0] * x +
+ frustum[p][1] * y +
+ frustum[p][2] * z +
+ frustum[p][3] <= -radius)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+#endif
diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h
new file mode 100644
index 00000000..3ba26e5e
--- /dev/null
+++ b/src/hardware/hw_clip.h
@@ -0,0 +1,24 @@
+/*
+ * hw_clip.h
+ * SRB2CB
+ *
+ * PrBoom's OpenGL clipping
+ *
+ *
+ */
+
+// OpenGL BSP clipping
+#include "../doomdef.h"
+#include "../tables.h"
+#include "../doomtype.h"
+
+//#define HAVE_SPHEREFRUSTRUM // enable if you want gld_SphereInFrustum and related code
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
+void gld_clipper_Clear(void);
+angle_t gld_FrustumAngle(void);
+#ifdef HAVE_SPHEREFRUSTRUM
+void gld_FrustrumSetup(void);
+boolean gld_SphereInFrustum(float x, float y, float z, float radius);
+#endif
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 7e815258..d9e65523 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -44,6 +44,10 @@
#endif
#include "hw_md2.h"
+#ifdef NEWCLIP
+#include "hw_clip.h"
+#endif
+
#define R_FAKEFLOORS
#define HWPRECIP
#define SORTING
@@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
boolean drawsky = true;
// needs fix: walls are incorrectly clipped one column less
+#ifndef NEWCLIP
static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-
+#endif
//development variables for diverse uses
static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1030,6 +1035,7 @@ static void HWR_ProjectWall(wallVert3D * wallVerts,
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
+#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{
float num, den;
@@ -1058,6 +1064,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den;
}
+#endif
//
// HWR_SplitWall
@@ -1333,7 +1340,11 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
// Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum
//
+#ifdef NEWCLIP
+static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
+#else
static void HWR_StoreWallRange(double startfrac, double endfrac)
+#endif
{
wallVert3D wallVerts[4];
v2d_t vs, ve; // start, end vertices of 2d line (view from above)
@@ -1358,8 +1369,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
extracolormap_t *colormap;
FSurfaceInfo Surf;
+#ifndef NEWCLIP
if (startfrac > endfrac)
return;
+#endif
gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef;
@@ -1408,15 +1421,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// x offset the texture
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
+#ifndef NEWCLIP
// clip texture s start/end coords with solidsegs
if (startfrac > 0.0f && startfrac < 1.0f)
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
else
+#endif
cliplow = (float)texturehpeg;
+#ifndef NEWCLIP
if (endfrac > 0.0f && endfrac < 1.0f)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
else
+#endif
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
}
@@ -2325,6 +2342,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
//Hurdler: end of 3d-floors test
}
+// From PrBoom:
+//
+// e6y: Check whether the player can look beyond this line
+//
+#ifdef NEWCLIP
+boolean checkforemptylines = true;
+// Don't modify anything here, just check
+// Kalaron: Modified for sloped linedefs
+static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
+{
+ fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+ fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+
+ // GZDoom method of sloped line clipping
+
+#ifdef ESLOPE
+ if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
+ {
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
+ SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
+ SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
+ SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
+#undef SLOPEPARAMS
+ }
+ else
+#endif
+ {
+ frontf1 = frontf2 = afrontsector->floorheight;
+ frontc1 = frontc2 = afrontsector->ceilingheight;
+ backf1 = backf2 = abacksector->floorheight;
+ backc1 = backc2 = abacksector->ceilingheight;
+ }
+
+ // now check for closed sectors!
+ if (backc1 <= frontf1 && backc2 <= frontf2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->toptexture)
+ return false;
+
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backf1 >= frontc1 && backf2 >= frontc2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->bottomtexture)
+ return false;
+
+ // properly render skies (consider door "open" if both floors are sky):
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 <= backf1 && backc2 <= backf2)
+ {
+ checkforemptylines = false;
+ // preserve a kind of transparent door/lift special effect:
+ if (backc1 < frontc1 || backc2 < frontc2)
+ {
+ if (!seg->sidedef->toptexture)
+ return false;
+ }
+ if (backf1 > frontf1 || backf2 > frontf2)
+ {
+ if (!seg->sidedef->bottomtexture)
+ return false;
+ }
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 != frontc1 || backc2 != frontc2
+ || backf1 != frontf1 || backf2 != frontf2)
+ {
+ checkforemptylines = false;
+ return false;
+ }
+
+ return false;
+}
+#else
//Hurdler: just like in r_bsp.c
#if 1
#define MAXSEGS MAXVIDWIDTH/2+1
@@ -2610,6 +2731,7 @@ static void HWR_ClearClipSegs(void)
gr_solidsegs[1].last = 0x7fffffff;
hw_newend = gr_solidsegs+2;
}
+#endif // NEWCLIP
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
@@ -2618,17 +2740,20 @@ static void HWR_ClearClipSegs(void)
// -----------------+
static void HWR_AddLine(seg_t * line)
{
- INT32 x1, x2;
angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 x1, x2;
angle_t span, tspan;
+#endif
// SoM: Backsector needs to be run through R_FakeFlat
static sector_t tempsec;
fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
-
+#ifdef POLYOBJECTS
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
+#endif
gr_curline = line;
@@ -2641,6 +2766,20 @@ static void HWR_AddLine(seg_t * line)
angle1 = R_PointToAngle(v1x, v1y);
angle2 = R_PointToAngle(v2x, v2y);
+#ifdef NEWCLIP
+ // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
+ if (angle2 - angle1 < ANGLE_180)
+ return;
+
+ // PrBoom: use REAL clipping math YAYYYYYYY!!!
+
+ if (!gld_clipper_SafeCheckRange(angle2, angle1))
+ {
+ return;
+ }
+
+ checkforemptylines = true;
+#else
// Clip to view edges.
span = angle1 - angle2;
@@ -2719,8 +2858,34 @@ static void HWR_AddLine(seg_t * line)
return;
}
*/
+#endif
+
gr_backsector = line->backsector;
+#ifdef NEWCLIP
+ if (!line->backsector)
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ }
+ else
+ {
+ gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true);
+ if (CheckClip(line, gr_frontsector, gr_backsector))
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ checkforemptylines = false;
+ }
+ // 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 (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector))
+ return;
+ }
+
+ HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
+ return;
+#else
// Single sided line?
if (!gr_backsector)
goto clipsolid;
@@ -2792,38 +2957,8 @@ static void HWR_AddLine(seg_t * line)
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
- if (
-#ifdef POLYOBJECTS
- !line->polyseg &&
-#endif
- gr_backsector->ceilingpic == gr_frontsector->ceilingpic
- && gr_backsector->floorpic == gr_frontsector->floorpic
-#ifdef ESLOPE
- && gr_backsector->f_slope == gr_frontsector->f_slope
- && gr_backsector->c_slope == gr_frontsector->c_slope
-#endif
- && gr_backsector->lightlevel == gr_frontsector->lightlevel
- && !gr_curline->sidedef->midtexture
- // Check offsets too!
- && gr_backsector->floor_xoffs == gr_frontsector->floor_xoffs
- && gr_backsector->floor_yoffs == gr_frontsector->floor_yoffs
- && gr_backsector->floorpic_angle == gr_frontsector->floorpic_angle
- && gr_backsector->ceiling_xoffs == gr_frontsector->ceiling_xoffs
- && gr_backsector->ceiling_yoffs == gr_frontsector->ceiling_yoffs
- && gr_backsector->ceilingpic_angle == gr_frontsector->ceilingpic_angle
- // Consider altered lighting.
- && gr_backsector->floorlightsec == gr_frontsector->floorlightsec
- && gr_backsector->ceilinglightsec == gr_frontsector->ceilinglightsec
- // Consider colormaps
- && gr_backsector->extra_colormap == gr_frontsector->extra_colormap
- && ((!gr_frontsector->ffloors && !gr_backsector->ffloors)
- || gr_frontsector->tag == gr_backsector->tag))
- // SoM: For 3D sides... Boris, would you like to take a
- // crack at rendering 3D sides? You would need to add the
- // above check and add code to HWR_StoreWallRange...
- {
+ if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
return;
- }
clippass:
if (x1 == x2)
@@ -2835,6 +2970,7 @@ clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
+#endif
}
// HWR_CheckBBox
@@ -2846,9 +2982,13 @@ clipsolid:
static boolean HWR_CheckBBox(fixed_t *bspcoord)
{
- INT32 boxpos, sx1, sx2;
+ INT32 boxpos;
fixed_t px1, py1, px2, py2;
- angle_t angle1, angle2, span, tspan;
+ angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 sx1, sx2;
+ angle_t span, tspan;
+#endif
// Find the corners of the box
// that define the edges from current viewpoint.
@@ -2874,6 +3014,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
+#ifdef NEWCLIP
+ angle1 = R_PointToAngle(px1, py1);
+ angle2 = R_PointToAngle(px2, py2);
+ return gld_clipper_SafeCheckRange(angle2, angle1);
+#else
// check clip list for an open space
angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle;
angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle;
@@ -2921,6 +3066,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
+#endif
}
#ifdef POLYOBJECTS
@@ -5694,7 +5840,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5704,6 +5862,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5730,6 +5889,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -5901,7 +6061,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5911,6 +6083,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5937,6 +6110,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -6079,7 +6253,9 @@ static inline void HWR_AddEngineCommands(void)
{
// engine state variables
//CV_RegisterVar(&cv_grzbuffer);
+#ifndef NEWCLIP
CV_RegisterVar(&cv_grclipwalls);
+#endif
// engine development mode variables
// - usage may vary from version to version..
diff --git a/src/r_bsp.c b/src/r_bsp.c
index abb11204..4ce89f00 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -365,6 +365,36 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
return sec;
}
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
+{
+ return (
+#ifdef POLYOBJECTS
+ !line->polyseg &&
+#endif
+ back->ceilingpic == front->ceilingpic
+ && back->floorpic == front->floorpic
+#ifdef ESLOPE
+ && back->f_slope == front->f_slope
+ && back->c_slope == front->c_slope
+#endif
+ && back->lightlevel == front->lightlevel
+ && !line->sidedef->midtexture
+ // Check offsets too!
+ && back->floor_xoffs == front->floor_xoffs
+ && back->floor_yoffs == front->floor_yoffs
+ && back->floorpic_angle == front->floorpic_angle
+ && back->ceiling_xoffs == front->ceiling_xoffs
+ && back->ceiling_yoffs == front->ceiling_yoffs
+ && back->ceilingpic_angle == front->ceilingpic_angle
+ // Consider altered lighting.
+ && back->floorlightsec == front->floorlightsec
+ && back->ceilinglightsec == front->ceilinglightsec
+ // Consider colormaps
+ && back->extra_colormap == front->extra_colormap
+ && ((!front->ffloors && !back->ffloors)
+ || front->tag == back->tag));
+}
+
//
// R_AddLine
// Clips the given segment and adds any visible pieces to the line list.
@@ -526,36 +556,8 @@ static void R_AddLine(seg_t *line)
// 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))
- {
+ if (R_IsEmptyLine(line, frontsector, backsector))
return;
- }
-
clippass:
R_ClipPassWallSegment(x1, x2 - 1);
diff --git a/src/r_bsp.h b/src/r_bsp.h
index e871b5dd..80824831 100644
--- a/src/r_bsp.h
+++ b/src/r_bsp.h
@@ -50,6 +50,7 @@ extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
INT32 *ceilinglightlevel, boolean back);
+boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector);