summaryrefslogtreecommitdiff
path: root/hammer/brushops.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/brushops.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'hammer/brushops.cpp')
-rw-r--r--hammer/brushops.cpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/hammer/brushops.cpp b/hammer/brushops.cpp
new file mode 100644
index 0000000..a6308ec
--- /dev/null
+++ b/hammer/brushops.cpp
@@ -0,0 +1,353 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "stdafx.h"
+#include <stdio.h>
+#include <math.h>
+#include "hammer.h"
+#include "MapEntity.h"
+#include "MapDefs.h"
+#include "MapFace.h"
+#include "hammer_mathlib.h"
+#include "history.h"
+#include "Error3d.h"
+#include "BrushOps.h"
+#include "GlobalFunctions.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+#pragma warning( disable : 4244 ) // Disable warning messages
+
+
+#define SIDE_FRONT 0
+#define SIDE_BACK 1
+#define SIDE_ON 2
+
+#define BOGUS_RANGE ( MAX_COORD_INTEGER * 4 )
+
+
+float lightaxis[3] = {1, 0.6f, 0.75f};
+
+const int MAX_POINTS_ON_WINDING = 128;
+
+
+void Error(char* fmt, ...)
+{
+ char str[300];
+ sprintf(str, fmt, (&fmt)+1);
+ Msg(mwError, str);
+}
+
+
+/*
+=============================================================================
+
+ TURN PLANES INTO GROUPS OF FACES
+
+=============================================================================
+*/
+
+
+/*
+==================
+NewWinding
+==================
+*/
+winding_t *NewWinding (int points)
+{
+ winding_t *w;
+
+ if (points > MAX_POINTS_ON_WINDING)
+ Error ("NewWinding: %i points", points);
+
+ w = (winding_t *)malloc(sizeof(*w));
+ w->numpoints = 0; // None are occupied yet even though allocated.
+ w->p = (Vector *)calloc( points, sizeof(Vector) );
+
+ return w;
+}
+
+void FreeWinding (winding_t *w)
+{
+ if (*(unsigned *)w == 0xdeaddead)
+ Error ("FreeWinding: freed a freed winding");
+ *(unsigned *)w = 0xdeaddead;
+
+ if (w->p)
+ {
+ free (w->p);
+ w->p = NULL;
+ }
+ free (w);
+}
+
+size_t WindingSize(int points)
+{
+ return (size_t)(&((winding_t *)0)->p[points]);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes points that are withing a given distance from each other
+// from the winding.
+// Input : pWinding - The winding to remove duplicates from.
+// fMinDist - The minimum distance two points must be from one another
+// to be considered different. If this is zero, the points must be
+// identical to be considered duplicates.
+//-----------------------------------------------------------------------------
+void RemoveDuplicateWindingPoints(winding_t *pWinding, float fMinDist)
+{
+ for (int i = 0; i < pWinding->numpoints; i++)
+ {
+ for (int j = i + 1; j < pWinding->numpoints; j++)
+ {
+ Vector edge;
+ VectorSubtract(pWinding->p[i], pWinding->p[j], edge);
+
+ if (VectorLength(edge) < fMinDist)
+ {
+ if (j + 1 < pWinding->numpoints)
+ {
+ memmove(&pWinding->p[j], &pWinding->p[j + 1], (pWinding->numpoints - (j + 1)) * sizeof(pWinding->p[0]));
+ }
+
+ pWinding->numpoints--;
+ }
+ }
+ }
+}
+
+
+/*
+==================
+CopyWinding
+==================
+*/
+winding_t *CopyWinding (winding_t *w)
+{
+ int size;
+ winding_t *c;
+
+ c = NewWinding (w->numpoints);
+ c->numpoints = w->numpoints;
+ size = w->numpoints*sizeof(w->p[0]);
+ memcpy (c->p, w->p, size);
+ return c;
+}
+
+
+/*
+==================
+ClipWinding
+
+Clips the winding to the plane, returning the new winding on the positive side
+Frees the input winding.
+==================
+*/
+// YWB ADDED SPLIT EPS to match qcsg splitting
+#define SPLIT_EPSILON 0.01
+winding_t *ClipWinding (winding_t *in, PLANE *split)
+{
+ float dists[MAX_POINTS_ON_WINDING];
+ int sides[MAX_POINTS_ON_WINDING];
+ int counts[3];
+ float dot;
+ int i, j;
+ Vector *p1, *p2, *mid;
+ winding_t *neww;
+ int maxpts;
+
+ counts[0] = counts[1] = counts[2] = 0;
+
+ // determine sides for each point
+ for (i=0 ; i<in->numpoints ; i++)
+ {
+ dot = DotProduct (in->p[i], split->normal);
+ dot -= split->dist;
+ dists[i] = dot;
+ if (dot > SPLIT_EPSILON)
+ sides[i] = SIDE_FRONT;
+ else if (dot < -SPLIT_EPSILON)
+ sides[i] = SIDE_BACK;
+ else
+ {
+ sides[i] = SIDE_ON;
+ }
+ counts[sides[i]]++;
+ }
+ sides[i] = sides[0];
+ dists[i] = dists[0];
+
+ if (!counts[0] && !counts[1])
+ return in;
+
+ if (!counts[0])
+ {
+ free (in);
+ return NULL;
+ }
+ if (!counts[1])
+ return in;
+
+ maxpts = in->numpoints+4; // can't use counts[0]+2 because
+ // of fp grouping errors
+ neww = NewWinding (maxpts);
+
+ for (i=0 ; i<in->numpoints ; i++)
+ {
+ p1 = &in->p[i];
+
+ mid = &neww->p[neww->numpoints];
+
+ if (sides[i] == SIDE_FRONT || sides[i] == SIDE_ON)
+ {
+ *mid = *p1;
+ neww->numpoints++;
+ if (sides[i] == SIDE_ON)
+ continue;
+ mid = &neww->p[neww->numpoints];
+ }
+
+ if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+ continue;
+
+ // generate a split point
+ if (i == in->numpoints - 1)
+ p2 = &in->p[0];
+ else
+ p2 = p1 + 1;
+
+ neww->numpoints++;
+
+ dot = dists[i] / (dists[i]-dists[i+1]);
+ for (j=0 ; j<3 ; j++)
+ { // avoid round off error when possible
+ if (split->normal[j] == 1)
+ mid[0][j] = split->dist;
+ else if (split->normal[j] == -1)
+ mid[0][j] = -split->dist;
+ mid[0][j] = p1[0][j] + dot*(p2[0][j]-p1[0][j]);
+ }
+// mid[3] = p1[3] + dot*(p2[3]-p1[3]);
+// mid[4] = p1[4] + dot*(p2[4]-p1[4]);
+ }
+
+ if (neww->numpoints > maxpts)
+ Error ("ClipWinding: points exceeded estimate");
+
+// free the original winding
+ FreeWinding (in);
+
+ return neww;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates a huge quadrilateral winding given a plane.
+// Input : pPlane - Plane normal and distance to use when creating the winding.
+// Output : Returns a winding with 4 points.
+//-----------------------------------------------------------------------------
+// dvs: read through this and clean it up
+winding_t *CreateWindingFromPlane(PLANE *pPlane)
+{
+ int i, x;
+ float max, v;
+ Vector org, vright, vup;
+ winding_t *w;
+
+ // find the major axis
+ max = -BOGUS_RANGE;
+ x = -1;
+ for (i=0 ; i<3; i++)
+ {
+ v = fabs(pPlane->normal[i]);
+ if (v > max)
+ {
+ x = i;
+ max = v;
+ }
+ }
+ if (x==-1)
+ Error ("BasePolyForPlane: no axis found");
+
+ vup = vec3_origin;
+ switch (x)
+ {
+ case 0:
+ case 1:
+ vup[2] = 1;
+ break;
+ case 2:
+ vup[0] = 1;
+ break;
+ }
+
+ v = DotProduct (vup, pPlane->normal);
+ VectorMA (vup, -v, pPlane->normal, vup);
+ VectorNormalize (vup);
+
+ org = pPlane->normal * pPlane->dist;
+
+ CrossProduct (vup, pPlane->normal, vright);
+
+ vup = vup * MAX_TRACE_LENGTH;
+ vright = vright * MAX_TRACE_LENGTH;
+
+ // project a really big axis aligned box onto the plane
+ w = NewWinding (4);
+ w->numpoints = 4;
+
+ VectorSubtract (org, vright, w->p[0]);
+ VectorAdd (w->p[0], vup, w->p[0]);
+
+ VectorAdd (org, vright, w->p[1]);
+ VectorAdd (w->p[1], vup, w->p[1]);
+
+ VectorAdd (org, vright, w->p[2]);
+ VectorSubtract (w->p[2], vup, w->p[2]);
+
+ VectorSubtract (org, vright, w->p[3]);
+ VectorSubtract (w->p[3], vup, w->p[3]);
+
+ return w;
+}
+
+
+static CArray<error3d, error3d&> Errors;
+static int nErrors;
+
+void Add3dError(DWORD dwObjectID, LPCTSTR pszReason, PVOID pInfo)
+{
+ error3d err;
+ err.dwObjectID = dwObjectID;
+ err.pszReason = pszReason;
+ err.pInfo = pInfo;
+ Errors.Add(err);
+ ++nErrors;
+}
+
+int Get3dErrorCount()
+{
+ return nErrors;
+}
+
+error3d * Enum3dErrors(BOOL bStart)
+{
+ static int iCurrent = 0;
+
+ if(bStart)
+ iCurrent = 0;
+
+ if(iCurrent == nErrors)
+ return NULL;
+
+ return & Errors.GetData()[iCurrent++];
+}
+
+