diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/brushops.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/brushops.cpp')
| -rw-r--r-- | hammer/brushops.cpp | 353 |
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++]; +} + + |