From 6b635120d473de66e41186101cd1974bdd94eab2 Mon Sep 17 00:00:00 2001
From: Plagman <Plagman@1a8010ca-5511-0410-912e-c29ae57300e0>
Date: Sun, 15 Oct 2006 18:51:41 +0000
Subject: [PATCH] Frustum clipping and cliplanes for map limits. Performance
 should be alright now.

git-svn-id: https://svn.eduke32.com/eduke32@311 1a8010ca-5511-0410-912e-c29ae57300e0
---
 polymer/build/include/glbuild.h  |   1 +
 polymer/build/include/polymer.h  |  25 ++--
 polymer/build/src/engine.c       |   6 +-
 polymer/build/src/glbuild.c      |  40 +++---
 polymer/build/src/polymer.c      | 234 ++++++++++++++++++++++---------
 polymer/eduke32/source/duke3d.h  |   3 +
 polymer/eduke32/source/game.c    |   4 +
 polymer/eduke32/source/osdcmds.c |   9 +-
 8 files changed, 225 insertions(+), 97 deletions(-)

diff --git a/polymer/build/include/glbuild.h b/polymer/build/include/glbuild.h
index 546207c4e..5a7078a7c 100644
--- a/polymer/build/include/glbuild.h
+++ b/polymer/build/include/glbuild.h
@@ -63,6 +63,7 @@ extern void (APIENTRY * bglPushMatrix)( void );
 extern void (APIENTRY * bglPopMatrix)( void );
 extern void (APIENTRY * bglLoadIdentity)( void );
 extern void (APIENTRY * bglLoadMatrixf)( const GLfloat *m );
+extern void (APIENTRY * bglMultMatrixf)( const GLfloat *m );
 extern void (APIENTRY * bglRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
 extern void (APIENTRY * bglScalef)(GLfloat x, GLfloat y, GLfloat z);
 extern void (APIENTRY * bglTranslatef)(GLfloat x, GLfloat y, GLfloat z);
diff --git a/polymer/build/include/polymer.h b/polymer/build/include/polymer.h
index 77e317cd4..98b7b8613 100644
--- a/polymer/build/include/polymer.h
+++ b/polymer/build/include/polymer.h
@@ -17,9 +17,11 @@
 # include "pragmas.h"
 
 // CVARS
-extern unsigned int pr_fov;
-extern char         pr_verbosity;
-extern char         pr_wireframe;
+extern int          pr_cliplanes;
+extern int          pr_fov;
+extern int          pr_frustumculling;
+extern int          pr_verbosity;
+extern int          pr_wireframe;
 
 // DATA
 typedef struct      s_prsector {
@@ -36,8 +38,7 @@ typedef struct      s_prsector {
     short           curindice;
     int             indicescount;
 
-    short           wallcount;
-    char            invalidate;
+    char            controlstate; // bit 1: up-to-date, bit 2: geometry invalidated
     char            drawingstate; // 0: fcuk, 1: in queue, 2: todraw, 3: drawn
 }                   _prsector;
 
@@ -45,6 +46,7 @@ typedef struct      s_prwall {
     // geometry
     GLfloat*        wallbuffer;
     GLfloat*        overbuffer;
+    GLfloat*        portal;
     // attributes
     GLfloat         wallcolor[4], overcolor[4];
     GLfloat         wallglpic, overglpic;
@@ -56,12 +58,14 @@ typedef struct      s_prwall {
 typedef struct      s_cliplane {
     _equation       left, right, clip;
     _point2d        ref;
-    char            clipsign;
 }                   _cliplane;
 
 extern _prsector*   prsectors[MAXSECTORS];
 extern _prwall*     prwalls[MAXWALLS];
 
+// CONTROL
+extern int          updatesectors;
+
 // EXTERNAL FUNCTIONS
 int                 polymer_init(void);
 void                polymer_glinit(void);
@@ -70,7 +74,7 @@ void                polymer_drawrooms(long daposx, long daposy, long daposz, sho
 void                polymer_rotatesprite(long sx, long sy, long z, short a, short picnum, signed char dashade, char dapalnum, char dastat, long cx1, long cy1, long cx2, long cy2);
 void                polymer_drawmaskwall(long damaskwallcnt);
 void                polymer_drawsprite(long snum);
-// SECTOR MANAGEMENT
+// SECTORS
 int                 polymer_initsector(short sectnum);
 int                 polymer_updatesector(short sectnum);
 void PR_CALLBACK    polymer_tesscombine(GLdouble v[3], GLdouble *data[4], GLfloat weight[4], GLdouble **out);
@@ -79,11 +83,14 @@ void PR_CALLBACK    polymer_tessedgeflag(GLenum error);
 void PR_CALLBACK    polymer_tessvertex(void* vertex, void* sector);
 int                 polymer_buildfloor(short sectnum);
 void                polymer_drawsector(short sectnum);
-// WALL MANAGEMENT
+// WALLS
 int                 polymer_initwall(short wallnum);
 void                polymer_updatewall(short wallnum);
 void                polymer_drawwall(short wallnum);
 // HSR
-int                 wallincliplane(short wallnum, _cliplane* cliplane);
+void                polymer_extractfrustum(void);
+int                 polymer_portalinfrustum(short wallnum);
+void                polymer_addcliplane(_equation clip, _equation left, _equation right, long refx, long refy);
+int                 polymer_wallincliplanes(short wallnum);
 
 #endif // !_polymer_h_
diff --git a/polymer/build/src/engine.c b/polymer/build/src/engine.c
index d746bc23d..a7c1aeb0d 100644
--- a/polymer/build/src/engine.c
+++ b/polymer/build/src/engine.c
@@ -8461,13 +8461,13 @@ void dragpoint(short pointhighlight, long dax, long day)
     wall[pointhighlight].x = dax;
     wall[pointhighlight].y = day;
 
-    if (rendmode == 4)
+    if ((rendmode == 4) && 0)
     {
         tempshort = wall[pointhighlight].nextwall;
         if (tempshort >= 0)
         {
-            prsectors[wall[pointhighlight].nextsector]->invalidate = 1;
-            prsectors[wall[tempshort].nextsector]->invalidate = 1;
+            prsectors[wall[pointhighlight].nextsector]->controlstate |= 2;
+            prsectors[wall[tempshort].nextsector]->controlstate |= 2;
         }
     }
 
diff --git a/polymer/build/src/glbuild.c b/polymer/build/src/glbuild.c
index c4fd23677..a4ac72274 100644
--- a/polymer/build/src/glbuild.c
+++ b/polymer/build/src/glbuild.c
@@ -47,6 +47,7 @@ void (APIENTRY * bglPushMatrix)( void );
 void (APIENTRY * bglPopMatrix)( void );
 void (APIENTRY * bglLoadIdentity)( void );
 void (APIENTRY * bglLoadMatrixf)( const GLfloat *m );
+void (APIENTRY * bglMultMatrixf)( const GLfloat *m );
 void (APIENTRY * bglRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
 void (APIENTRY * bglScalef)(GLfloat x, GLfloat y, GLfloat z);
 void (APIENTRY * bglTranslatef)(GLfloat x, GLfloat y, GLfloat z);
@@ -223,6 +224,7 @@ int loadgldriver(const char *driver)
     bglPopMatrix		= GETPROC("glPopMatrix");
     bglLoadIdentity		= GETPROC("glLoadIdentity");
     bglLoadMatrixf		= GETPROC("glLoadMatrixf");
+    bglMultMatrixf		= GETPROC("glMultMatrixf");
     bglRotatef          = GETPROC("glRotatef");
     bglScalef          = GETPROC("glScalef");
     bglTranslatef          = GETPROC("glTranslatef");
@@ -315,23 +317,23 @@ int unloadgldriver(void)
 #endif
 
     bglClearColor		= NULL;
-    bglClear		= NULL;
+    bglClear		    = NULL;
     bglColorMask		= NULL;
     bglAlphaFunc		= NULL;
     bglBlendFunc		= NULL;
-    bglCullFace		= NULL;
+    bglCullFace		    = NULL;
     bglFrontFace		= NULL;
     bglPolygonOffset	= NULL;
-    bglPolygonMode   = NULL;
-    bglEnable		= NULL;
-    bglDisable		= NULL;
+    bglPolygonMode      = NULL;
+    bglEnable		    = NULL;
+    bglDisable		    = NULL;
     bglGetFloatv		= NULL;
     bglGetIntegerv		= NULL;
     bglPushAttrib		= NULL;
     bglPopAttrib		= NULL;
-    bglGetError		= NULL;
+    bglGetError		    = NULL;
     bglGetString		= NULL;
-    bglHint			= NULL;
+    bglHint			    = NULL;
 
     // Depth
     bglDepthFunc		= NULL;
@@ -340,13 +342,17 @@ int unloadgldriver(void)
 
     // Matrix
     bglMatrixMode		= NULL;
-    bglOrtho		= NULL;
-    bglFrustum		= NULL;
-    bglViewport		= NULL;
+    bglOrtho		    = NULL;
+    bglFrustum		    = NULL;
+    bglViewport		    = NULL;
     bglPushMatrix		= NULL;
     bglPopMatrix		= NULL;
     bglLoadIdentity		= NULL;
     bglLoadMatrixf		= NULL;
+    bglMultMatrixf      = NULL;
+    bglRotatef          = NULL;
+    bglScalef           = NULL;
+    bglTranslatef       = NULL;
 
     // Drawing
     bglBegin		= NULL;
@@ -354,11 +360,11 @@ int unloadgldriver(void)
     bglVertex2f		= NULL;
     bglVertex2i		= NULL;
     bglVertex3d		= NULL;
-    bglVertex3fv		= NULL;
+    bglVertex3fv    = NULL;
     bglColor4f		= NULL;
     bglColor4ub		= NULL;
-    bglTexCoord2d		= NULL;
-    bglTexCoord2f		= NULL;
+    bglTexCoord2d	= NULL;
+    bglTexCoord2f	= NULL;
 
     // Lighting
     bglShadeModel		= NULL;
@@ -367,7 +373,7 @@ int unloadgldriver(void)
     bglReadPixels		= NULL;
 
     // Texture mapping
-    bglTexEnvf		= NULL;
+    bglTexEnvf		    = NULL;
     bglGenTextures		= NULL;
     bglDeleteTextures	= NULL;
     bglBindTexture		= NULL;
@@ -385,9 +391,9 @@ int unloadgldriver(void)
     bglFogfv		= NULL;
 
     // Display Lists
-    bglNewList      = NULL;
-    bglEndList      = NULL;
-    bglCallList      = NULL;
+    bglNewList          = NULL;
+    bglEndList          = NULL;
+    bglCallList         = NULL;
 
     // Vertex Arrays
     bglEnableClientState    = NULL;
diff --git a/polymer/build/src/polymer.c b/polymer/build/src/polymer.c
index 673217aab..843f52799 100644
--- a/polymer/build/src/polymer.c
+++ b/polymer/build/src/polymer.c
@@ -3,15 +3,23 @@
 #include "polymer.h"
 
 // CVARS
-unsigned int    pr_fov = 340; // 60 degrees, appears to be the classic setting.
-char            pr_verbosity = 1; // 0: silent, 1: errors and one-times, 2: multiple-times, 3: flood
-char            pr_wireframe = 0;
+int             pr_cliplanes = 1;
+int             pr_fov = 426;           // appears to be the classic setting.
+int             pr_frustumculling = 1;
+int             pr_verbosity = 1;       // 0: silent, 1: errors and one-times, 2: multiple-times, 3: flood
+int             pr_wireframe = 0;
 
 // DATA
 _prsector       *prsectors[MAXSECTORS];
 _prwall         *prwalls[MAXWALLS];
 
-_cliplane       cliplane;
+// CONTROL
+float           frustum[16]; // left right top bottom
+
+_cliplane       *cliplanes;
+int             cliplanecount, maxcliplanecount;
+
+int             updatesectors = 1;
 
 GLUtesselator*  prtess;
 int             tempverticescount;
@@ -38,6 +46,9 @@ int                 polymer_init(void)
         i++;
     }
 
+    cliplanes = NULL;
+    cliplanecount = maxcliplanecount = 0;
+
     prtess = gluNewTess();
     if (prtess == 0)
     {
@@ -93,7 +104,6 @@ void                polymer_loadboard(void)
     {
         polymer_initsector(i);
         polymer_updatesector(i);
-        polymer_buildfloor(i);
         i++;
     }
 
@@ -119,24 +129,11 @@ void                polymer_drawrooms(long daposx, long daposy, long daposz, sho
 
     if (pr_verbosity >= 3) OSD_Printf("PR : Drawing rooms...\n");
 
-    OSD_Printf("PR : %d\n", dahoriz);
-
     ang = (float)(daang) / (2048.0f / 360.0f);
     horizang = (float)(100 - dahoriz) / (512.0f / 180.0f);
     tiltang = (gtang * 90.0f);
     fov = (pr_fov * (float)xdim / (float)ydim * 1) / 2;
 
-    // FOV cliplane
-    rotatepoint(daposx, daposy, daposx, daposy - 1000, daang, &ref.x, &ref.y);
-    cliplane.clip = equation(daposx, daposy, ref.x, ref.y);
-    rotatepoint(daposx, daposy, daposx, daposy - 1000, (daang + 512 - fov) & 2047, &ref.x, &ref.y);
-    cliplane.left = equation(daposx, daposy, ref.x, ref.y);
-    rotatepoint(daposx, daposy, daposx, daposy - 1000, (daang + 512 + fov) & 2047, &ref.x, &ref.y);
-    cliplane.right = equation(daposx, daposy, ref.x, ref.y);
-    rotatepoint(daposx, daposy, daposx, daposy - 1000, (daang + 512) & 2047, &ref.x, &ref.y);
-    cliplane.ref = ref;
-    cliplane.clipsign = 1;
-
     pos[0] = -daposy;
     pos[1] = daposz;
     pos[2] = daposx;
@@ -144,26 +141,45 @@ void                polymer_drawrooms(long daposx, long daposy, long daposz, sho
     bglMatrixMode(GL_MODELVIEW);
     bglLoadIdentity();
 
+    bglRotatef(tiltang, 0.0f, 0.0f, -1.0f);
     bglRotatef(horizang, 1.0f, 0.0f, 0.0f);
     bglRotatef(ang, 0.0f, 1.0f, 0.0f);
-    bglRotatef(tiltang, 0.0f, 0.0f, -1.0f);
 
     bglScalef(1.0f, 1.0f / 16.0f, 1.0f);
     bglTranslatef(pos[0], pos[1], pos[2]);
 
+    if (pr_frustumculling)
+        polymer_extractfrustum();
+
+    cliplanecount = 0;
+
+    if (updatesectors)
+    {
+        i = 0;
+        while (i < numsectors)
+        {
+            polymer_updatesector(i);
+            i++;
+        }
+
+        i = 0;
+        while (i < numwalls)
+        {
+            polymer_updatewall(i);
+            i++;
+        }
+        updatesectors = 0;
+    }
+        
     i = 0;
     while (i < numsectors)
     {
-        if (prsectors[i])
-        {
-            if (i == dacursectnum)
-                prsectors[i]->drawingstate = 2;
-            else
-                prsectors[i]->drawingstate = 0;
-        }
+        prsectors[i]->drawingstate = 0;
         i++;
     }
 
+    prsectors[dacursectnum]->drawingstate = 2; // SEED OF LIFE
+
     drawnsectors = 1;
     while (drawnsectors > 0)
     {
@@ -182,11 +198,20 @@ void                polymer_drawrooms(long daposx, long daposy, long daposz, sho
                 j = 0;
                 while (j < sec->wallnum)
                 {
-                    if (wallincliplane(sec->wallptr + j, &cliplane))
+                    if (((pr_frustumculling == 0) || polymer_portalinfrustum(sec->wallptr + j)) &&
+                        ((pr_cliplanes == 0) || polymer_wallincliplanes(sec->wallptr + j)))
                     {
                         polymer_drawwall(sec->wallptr + j);
-                        if ((wal->nextsector != -1) && (prsectors[wal->nextsector]->drawingstate == 0))
+                        if ((wal->nextsector != -1) && (prsectors[wal->nextsector]) && (prsectors[wal->nextsector]->drawingstate == 0))
                             prsectors[wal->nextsector]->drawingstate = 1;
+                        if (wal->nextsector == -1 && pr_cliplanes)
+                        {   // add a 2D cliplane for map limits
+                            polymer_addcliplane(equation(wal->x, wal->y, wall[wal->point2].x, wall[wal->point2].y),
+                                                equation(daposx, daposy, wal->x, wal->y),
+                                                equation(daposx, daposy, wall[wal->point2].x, wall[wal->point2].y),
+                                                (daposx + wal->x + wall[wal->point2].x) / 3,
+                                                (daposy + wal->y + wall[wal->point2].y) / 3);
+                        }
                     }
 
                     j++;
@@ -223,7 +248,7 @@ void                polymer_drawsprite(long snum)
 {
 }
 
-// SECTOR MANAGEMENT
+// SECTORS
 int                 polymer_initsector(short sectnum)
 {
     sectortype      *sec;
@@ -240,8 +265,6 @@ int                 polymer_initsector(short sectnum)
         return (0);
     }
 
-    s->invalidate = 0;
-
     s->verts = calloc(sec->wallnum, sizeof(GLdouble) * 3);
     s->floorbuffer = calloc(sec->wallnum, sizeof(GLfloat) * 5);
     s->ceilbuffer = calloc(sec->wallnum, sizeof(GLfloat) * 5);
@@ -253,14 +276,9 @@ int                 polymer_initsector(short sectnum)
    
     s->floorindices = s->ceilindices = NULL;
 
-    prsectors[sectnum] = s;
+    s->controlstate = s->drawingstate = 0;
 
-    /*i = sec->wallptr;
-    while (i < (sec->wallptr + sec->wallnum))
-    {
-        polymer_initwall(i);
-        i++;
-    }*/
+    prsectors[sectnum] = s;
 
     if (pr_verbosity >= 2) OSD_Printf("PR : Initalized sector %i.\n", sectnum);
 
@@ -295,6 +313,8 @@ int                 polymer_updatesector(short sectnum)
         return (-1);
     }
 
+    s->controlstate = 0;
+
     if ((sec->floorstat & 64) || (sec->ceilingstat & 64))
     {
         ang = (getangle(wall[wal->point2].x - wal->x, wall[wal->point2].y - wal->y) + 512) & 2047;
@@ -306,8 +326,16 @@ int                 polymer_updatesector(short sectnum)
     i = 0;
     while (i < sec->wallnum)
     {
-        s->verts[(i*3)+2] = s->floorbuffer[(i*5)+2] = s->ceilbuffer[(i*5)+2] = -wal->x;
-        s->verts[i*3] = s->floorbuffer[i*5] = s->ceilbuffer[i*5] = wal->y;
+        if ((-wal->x != s->verts[(i*3)+2]) || 0)
+        {
+            s->verts[(i*3)+2] = s->floorbuffer[(i*5)+2] = s->ceilbuffer[(i*5)+2] = -wal->x;
+            s->controlstate |= 2;
+        }
+        if ((wal->y != s->verts[i*3]) || 0)
+        {
+            s->verts[i*3] = s->floorbuffer[i*5] = s->ceilbuffer[i*5] = wal->y;
+            s->controlstate |= 2;
+        }
         getzsofslope(sectnum, wal->x, wal->y, &ceilz, &florz);
         s->verts[(i*3)+1] = 0;
         s->floorbuffer[(i*5)+1] = -florz;
@@ -387,6 +415,12 @@ int                 polymer_updatesector(short sectnum)
         wal = &wall[sec->wallptr + i];
     }
 
+    if (s->controlstate & 2)
+    {
+        polymer_buildfloor(sectnum);
+        s->controlstate ^= 2;
+    }
+
     if (pr_verbosity >= 3) OSD_Printf("PR : Updated sector %i.\n", sectnum);
 
     return (0);
@@ -513,20 +547,6 @@ void                polymer_drawsector(short sectnum)
     {
         polymer_initsector(sectnum);
         polymer_updatesector(sectnum);
-        polymer_buildfloor(sectnum);
-    }
-    else if (prsectors[sectnum]->invalidate || 1)
-    {
-        if (pr_verbosity >= 2) OSD_Printf("PR : Sector %i invalidated. Tesselating...\n", sectnum);
-        polymer_updatesector(sectnum);
-        i = 0;
-        while (i < sec->wallnum)
-        {
-            polymer_updatewall(sec->wallptr + i);
-            i++;
-        }
-        polymer_buildfloor(sectnum);
-        prsectors[sectnum]->invalidate = 0;
     }
 
     // floor
@@ -552,7 +572,7 @@ void                polymer_drawsector(short sectnum)
     if (pr_verbosity >= 3) OSD_Printf("PR : Finished drawing sector %i...\n", sectnum);
 }
 
-// WALL MANAGEMENT
+// WALLS
 int                 polymer_initwall(short wallnum)
 {
     _prwall         *w;
@@ -567,7 +587,7 @@ int                 polymer_initwall(short wallnum)
     }
 
     w->invalidate = w->underover = 0;
-    w->wallbuffer = w->overbuffer = NULL;
+    w->wallbuffer = w->overbuffer = w->portal = NULL;
 
     prwalls[wallnum] = w;
 
@@ -752,6 +772,14 @@ void                polymer_updatewall(short wallnum)
         }
     }
 
+    if (w->portal == NULL)
+        w->portal = calloc(4, sizeof(GLfloat) * 3);
+
+    memcpy(w->portal, &s->floorbuffer[(wallnum - sec->wallptr) * 5], sizeof(GLfloat) * 3);
+    memcpy(&w->portal[3], &s->floorbuffer[(wal->point2 - sec->wallptr) * 5], sizeof(GLfloat) * 3);
+    memcpy(&w->portal[6], &s->ceilbuffer[(wal->point2 - sec->wallptr) * 5], sizeof(GLfloat) * 3);
+    memcpy(&w->portal[9], &s->ceilbuffer[(wallnum - sec->wallptr) * 5], sizeof(GLfloat) * 3);
+
     if (pr_verbosity >= 3) OSD_Printf("PR : Updated wall %i.\n", wallnum);
 }
 
@@ -784,10 +812,79 @@ void                polymer_drawwall(short wallnum)
 }
 
 // HSR
-int                 wallincliplane(short wallnum, _cliplane* cliplane)
+void                polymer_extractfrustum(void)
+{
+    GLfloat         matrix[16];
+    int             i;
+
+    bglMatrixMode(GL_TEXTURE);
+    bglGetFloatv(GL_PROJECTION_MATRIX, matrix);
+    bglLoadMatrixf(matrix);
+    bglGetFloatv(GL_MODELVIEW_MATRIX, matrix);
+    bglMultMatrixf(matrix);
+    bglGetFloatv(GL_TEXTURE_MATRIX, matrix);
+    bglLoadIdentity();
+
+    i = 0;
+    while (i < 4)
+    {
+        frustum[i] = matrix[(4 * i) + 3] + matrix[4 * i];               // left
+        frustum[i + 4] = matrix[(4 * i) + 3] - matrix[4 * i];           // right
+        frustum[i + 8] = matrix[(4 * i) + 3] - matrix[(4 * i) + 1];     // top
+        frustum[i + 12] = matrix[(4 * i) + 3] + matrix[(4 * i) + 1];    // bottom
+        i++;
+    }
+}
+
+int                 polymer_portalinfrustum(short wallnum)
+{
+    int             i, j, k;
+    float           sqdist;
+    _prwall         *w;
+
+    w = prwalls[wallnum];
+
+    i = 0;
+    while (i < 4)
+    {
+        j = k = 0;
+        while (j < 4)
+        {
+            sqdist = frustum[(i * 4) + 0] * w->portal[(j * 3) + 0] +
+                     frustum[(i * 4) + 1] * w->portal[(j * 3) + 1] + 
+                     frustum[(i * 4) + 2] * w->portal[(j * 3) + 2] + 
+                     frustum[(i * 4) + 3];
+            if (sqdist  < 0)
+                k++;
+            j++;
+        }
+        if (k == 4)
+            return (0); // OUT !
+        i++;
+    }
+
+    return (1);
+}
+
+void                polymer_addcliplane(_equation clip, _equation left, _equation right, long refx, long refy)
+{
+    if (cliplanecount == maxcliplanecount)
+        cliplanes = realloc(cliplanes, sizeof(_cliplane) * ++maxcliplanecount);
+
+    cliplanes[cliplanecount].clip = clip;
+    cliplanes[cliplanecount].left = left;
+    cliplanes[cliplanecount].right = right;
+    cliplanes[cliplanecount].ref.x = refx;
+    cliplanes[cliplanecount].ref.y = refy;
+
+    cliplanecount++;
+}
+
+int                 polymer_wallincliplanes(short wallnum)
 {
     walltype        *wal;
     _point2d        p1, p2;
+    int             i, j;
     
     wal = &wall[wallnum];
 
@@ -797,14 +894,25 @@ int                 wallincliplane(short wallnum, _cliplane* cliplane)
     p2.x = wall[wal->point2].x;
     p2.y = wall[wal->point2].y;
 
-    if ((sameside(&cliplane->clip, &cliplane->ref, &p1) != cliplane->clipsign) && (sameside(&cliplane->clip, &cliplane->ref, &p2) != cliplane->clipsign))
-        return (0);
+    i = 0;
+    while (i < cliplanecount)
+    {
+        j = 0;
 
-    /*if ((sameside(&cliplane->left, &cliplane->ref, &p1) == 0) && (sameside(&cliplane->left, &cliplane->ref, &p2) == 0))
-        return (0);
+        if ((sameside(&cliplanes[i].clip, &cliplanes[i].ref, &p1) == 0) && (sameside(&cliplanes[i].clip, &cliplanes[i].ref, &p2) == 0))
+            j++;
 
-    if ((sameside(&cliplane->right, &cliplane->ref, &p1) == 0) && (sameside(&cliplane->right, &cliplane->ref, &p2) == 0))
-        return (0);*/
+        if ((sameside(&cliplanes[i].left, &cliplanes[i].ref, &p1) == 1) && (sameside(&cliplanes[i].left, &cliplanes[i].ref, &p2) == 1))
+            j++;
+
+        if ((sameside(&cliplanes[i].right, &cliplanes[i].ref, &p1) == 1) && (sameside(&cliplanes[i].right, &cliplanes[i].ref, &p2) == 1))
+            j++;
+
+        if (j == 3)
+            return (0);
+
+        i++;
+    }
 
     return (1);
 }
diff --git a/polymer/eduke32/source/duke3d.h b/polymer/eduke32/source/duke3d.h
index cf5c5770a..fc30fc5fe 100644
--- a/polymer/eduke32/source/duke3d.h
+++ b/polymer/eduke32/source/duke3d.h
@@ -30,6 +30,9 @@ extern "C" {
 #include "compat.h"
 #include "a.h"
 #include "build.h"
+#if defined(POLYMOST) && defined(USE_OPENGL)
+# include "polymer.h"
+#endif
 #include "cache1d.h"
 #include "pragmas.h"
 #include "mmulti.h"
diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c
index fcd15a684..deced674f 100644
--- a/polymer/eduke32/source/game.c
+++ b/polymer/eduke32/source/game.c
@@ -10562,6 +10562,10 @@ char domovethings(void)
         movecyclers();
         pan3dsound();
     }
+
+    //polymer invalidate
+    updatesectors = 1;
+
     return 0;
 }
 
diff --git a/polymer/eduke32/source/osdcmds.c b/polymer/eduke32/source/osdcmds.c
index 49386938f..b4ffc2220 100644
--- a/polymer/eduke32/source/osdcmds.c
+++ b/polymer/eduke32/source/osdcmds.c
@@ -23,9 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "baselayer.h"
 #include "duke3d.h"
 #include "crc32.h"
-#if defined(POLYMOST) && defined(USE_OPENGL)
-# include "polymer.h"
-#endif
 #include <ctype.h>
 
 struct osdcmd_cheatsinfo osdcmd_cheatsinfo_stat;
@@ -472,9 +469,11 @@ struct cvarmappings {
         { "r_anamorphic", "r_anamorphic: enable/disable widescreen mode", (void*)&glwidescreen, CVAR_BOOL, 0, 0, 1 },
         { "r_projectionhack", "r_projectionhack: enable/disable projection hack", (void*)&glprojectionhacks, CVAR_BOOL, 0, 0, 1 },
         // polymer cvars
-        { "pr_fov", "pr_fov: sets the field of vision in build angle", (void*)&pr_fov, CVAR_UNSIGNEDINT, 0, 0, 1024},
+        { "pr_cliplanes", "pr_cliplanes: toggles clipping behind map limits (recommended yet may decrease performance in complex maps)", (void*)&pr_cliplanes, CVAR_INT, 0, 0, 1 },
+        { "pr_fov", "pr_fov: sets the field of vision in build angle", (void*)&pr_fov, CVAR_INT, 0, 0, 1023},
+        { "pr_frustumculling", "pr_frustumculling: toggles frustum culling (recommended)", (void*)&pr_frustumculling, CVAR_INT, 0, 0, 1 },
         { "pr_verbosity", "pr_verbosity: verbosity level of the polymer renderer", (void*)&pr_verbosity, CVAR_INT, 0, 0, 3 },
-        { "pr_wireframe", "pr_wireframe: toggles wireframe mode", (void*)&pr_wireframe, CVAR_BOOL, 0, 0, 1 },
+        { "pr_wireframe", "pr_wireframe: toggles wireframe mode", (void*)&pr_wireframe, CVAR_INT, 0, 0, 1 },
 #endif
         { "r_precache", "r_precache: enable/disable the pre-level caching routine", (void*)&useprecache, CVAR_BOOL, 0, 0, 1 }
     };