42#define CH_DIST_EPSILON 0.001f
43#define CH_DIST_EPSILON_SQR 0.000001
45#define CH_DIST_EPSILON_COLLINEAR_POINTS 0.02f
48#define COS_EPSILON 0.9999f
51#define SIN_EPSILON 0.0001f
67#define NEARDOWN_COS 0.985
200 return Q_streq(tex->
name,
"tex_common/weaponclip");
226 const char* texname = tex->
name;
273 return numNodraws == b->
numsides ? false :
true;
281 for (
int i = 0;
i < 3;
i++)
297 static bool done =
false;
320 bbuf[numNear++] = jBrush;
331 Sys_Error(
"Check_Nearlist: out of memory");
333 for (j = 0; j < numNear; j++)
366static void Check_SetError (
side_t* s)
389 for (
int i = 0;
i < 2;
i++) {
393 for (
int j = 0; j < w->
numpoints ; j++) {
408 static bool done =
false;
409 int i, j, k, l, numMembers, numDone = 0, numTodo;
433 for (
int is = 0; is < iBrush->
numsides; is++) {
448 for (j = 0; j < iBrush->
numNear; j++)
454 bDone[numDone++] = iBrush;
456 while (numTodo > 0) {
458 if (bChecking ==
nullptr)
460 bDone[numDone++] = bChecking;
462 for (j = 0; j < bChecking->
numsides; j++) {
471 for (k = 0; k < numMembers; k++) {
474 sbuf[numMembers++] = sChecking;
478 for (l = 0; l < newMembersBrush->
numNear;l++) {
487 for (
int m = 0;
m < numDone;
m++) {
488 if (nearListBrush == bDone[
m])
489 goto skip_add_brush_to_todo_list;
491 bTodo[numTodo++] = nearListBrush;
493 skip_add_brush_to_todo_list:
496 goto next_brush_todo;
505 if (numMembers > 1) {
508 if (!sidesInNewComposite)
509 Sys_Error(
"Check_FindCompositeSides: out of memory");
517 for (j = 0; j < numMembers; j++) {
559 VectorAdd(vert1, direction, intersection);
574 for (bi = 0; bi < brush->
numsides; bi++) {
575 for (vi = 0; vi < winding->
numpoints; vi++) {
576 const int val = vi + 1;
577 const int vj = (winding->
numpoints == val) ? 0 : val;
600 for (
int j = 0; j < iBrush->
numNear; j++) {
607 for (
int is = 0; is < iBrush->
numsides; is++) {
630 vec3_t dir1, dir2, unitDir1, unitDir2;
631 vec3_t dirClosestApproach, from1To2, e1p1ToIntersection, e2p1ToIntersection;
633 float cosAngle, length1, length2, dist, magCross2, param1;
634 float e1p1Dist, e2p1Dist;
647 cosAngle = fabs(
DotProduct(unitDir1, unitDir2));
656 dist = fabs(
DotProduct(dirClosestApproach, from1To2));
664 param1 =
DotProduct(cross1, cross2) / (magCross2 * magCross2);
666 VectorAdd(e1p1, e1p1ToIntersection, intersection);
667 e1p1Dist =
DotProduct(e1p1ToIntersection, unitDir1);
669 if (e1p1Dist < CH_DIST_EPSILON || e1p1Dist > (length1 -
CH_DIST_EPSILON))
673 e2p1Dist =
DotProduct(e2p1ToIntersection, unitDir2);
674 if (e2p1Dist < CH_DIST_EPSILON || e2p1Dist > (length2 -
CH_DIST_EPSILON))
691 float d1d, d2d, d3d, offLineDist;
705 if (d1d >= d2d && d1d >= d3d) {
708 }
else if (d2d >= d1d && d2d >= d3d) {
722 float longestSqr = 0;
726 longestSqr = longestSqr > lengthSqr ? longestSqr : lengthSqr;
728 return sqrt(longestSqr);
731#define VERT_BUF_SIZE_DISJOINT_SIDES 21
732#define OVERLAP_AREA_TOL 0.2f
733#define OVERLAP_WIDTH_TOL 0.1f
756 for (
i = 0;
i < 2;
i++) {
760 Check_Printf(
VERB_CHECK,
false, b[
i]->entitynum, b[
i]->brushnum,
"warning: Check_SidesAreDisjoint buffer too small");
771 const int pointIndex = (
i + 1) % w[0]->numpoints;
772 for (
int k = 0; k < w[1]->
numpoints; k++) {
773 const int pointIndex2 = (k + 1) % w[1]->numpoints;
777 Check_Printf(
VERB_CHECK,
false, b[
i]->entitynum, b[
i]->brushnum,
"warning: Check_SidesAreDisjoint buffer too small");
789 float overlapArea, longestEdge, width;
792 memcpy(overlap->
p, vertbuf, numVert *
sizeof(
vec3_t));
796 for (
int i = 0;
i < numVert;
i++) {
809 width = overlapArea / longestEdge;
816 vec3_t from0to1, one, zero;
822 if ((
i + 1) >= numVert)
829 for (
i++;
i < numVert;
i++) {
830 if (!Check_PointsAreCollinear(zero, one, vertbuf[
i])) {
855 for (
int j = 0; j < iBrush->
numNear; j++) {
864 for (
int is = 0; is < iBrush->
numsides; is++) {
874 for (
int js = 0; js < jBrush->
numsides; js++) {
887 Com_Printf(
"CheckZFighting: plane indices %i %i \n",
893 if ( overlapWidth > 0.0f) {
895 "z-fighting with brush %i (entity %i). overlap width: %.3g units\n",
898 Check_SetError(iSide);
899 Check_SetError(jSide);
924 for (
int j = 0; j < iBrush->
numNear; j++) {
926 int numSidesInside = 0;
931 for (
int js = 0; js < jBrush->
numsides; js++) {
938 if (numSidesInside == jBrush->
numsides) {
975#define CH_COMP_NDR_EDGE_INTSCT_BUF 21
986 int i, j, k, l, is, js;
987 int numSetFromSingleSide = 0, numSetPointingDown = 0, numSetFromCompositeSide = 0, iBrushNumSet = 0;
1003 for (is = 0; is < iBrush->
numsides; is++) {
1015 numSetPointingDown++;
1023 if (numSetPointingDown)
1024 Check_Printf(
VERB_CHECK,
true, -1, -1,
"total of %i nodraws set (point down, or are close to pointing down)\n", numSetPointingDown);
1036 for (j = 0; j < iBrush->
numNear; j++) {
1044 for (is = 0; is < iBrush->
numsides; is++) {
1058 for (js = 0; js < jBrush->
numsides; js++) {
1070 const int diff = maxIndex - minIndex, minOdd = (minIndex & 1);
1071 if ((diff != 1) || minOdd) {
1072 Com_Printf(
"CheckNodraws: facing and coincident plane indices %i %i diff:%i minOdd:%i\n",
1083 numSetFromSingleSide++;
1100 for (is = 0; is < iBrush->
numsides; is++) {
1103 vec3_t lastIntersection = {0, 0, 0};
1119 for (k = 0; k < iWinding->
numpoints; k++) {
1120 bool pointOnComposite =
false;
1121 for (l = 0; l < composite->
numMembers; l++) {
1130 pointOnComposite =
true;
1134 if (!pointOnComposite)
1139 for (k = 0; k < iWinding->
numpoints; k++) {
1141 int lastIntersectionMembInd = -1;
1148 for (l = 0; l < composite->
numMembers; l++) {
1153 iWinding->
p[k], iWinding->
p[(k + 1) % iWinding->
numpoints],
1158 bool coincident =
false;
1160 for (
int n = 0; n < numIntsct; n++) {
1161 float distSq =
VectorDistSqr(intersection, intersections[n]);
1170 VectorCopy(intersection, intersections[numIntsct]);
1182 if ((lastIntersectionMembInd == l)
1187 lastIntersectionMembInd = l;
1195 for (l = 0; l < numIntsct; l++) {
1205 numSetFromCompositeSide++;
1215 if (numSetFromSingleSide)
1216 Check_Printf(
VERB_CHECK,
true, -1, -1,
"%i nodraws set (covered by another brush).\n", numSetFromSingleSide);
1218 if (numSetFromCompositeSide)
1219 Check_Printf(
VERB_CHECK,
true, -1, -1,
"%i nodraws set (covered by a composite side).\n", numSetFromCompositeSide);
1234 for (
int j = 0; j <
i; j++) {
1235 if (sides[
i].planenum == sides[j].planenum) {
1241 if (sides[
i].planenum == (sides[j].planenum ^ 1)) {
1258 vec_t d, area, volume;
1298 if (vol <
config.mapMicrovol) {
1315#define M(x) if (flags & CONTENTS_##x) Check_Printf(VERB_CHECK, false, NUM_SAME, NUM_SAME, " " #x)
1344 int firstSetLevel = 0, lastSetLevel = 0;
1345 int scanLevel, flagFill = 0;
1348 if (scanLevel & contentFlags) {
1349 if (!firstSetLevel) {
1350 firstSetLevel = scanLevel;
1352 lastSetLevel = scanLevel;
1356 for (scanLevel = firstSetLevel << 1 ; scanLevel < lastSetLevel; scanLevel <<= 1)
1357 flagFill |= scanLevel & ~contentFlags;
1376 for (
int j = 0; j < brush->
numsides; j++)
1388 int allLevelFlagsForBrush;
1395 bool allNodraw =
true;
1396 for (j = 0; j < brush->
numsides; j++) {
1408 allLevelFlagsForBrush = 0;
1413 for (j = 0; j < brush->
numsides; j++) {
1429 const int flagsToSet = allLevelFlagsForBrush ? allLevelFlagsForBrush :
CONTENTS_LEVEL_ALL;
1431 for (j = 0; j < brush->
numsides; j++) {
1450 const char* texname = tex->
name;
1456 const char* flagsDescription =
nullptr;
1457 if (
Q_streq(texname,
"tex_common/actorclip")) {
1459 flagsDescription =
"CONTENTS_ACTORCLIP";
1460 }
else if (
Q_streq(texname,
"tex_common/caulk")) {
1463 flagsDescription =
"SURF_NODRAW";
1464 }
else if (
Q_streq(texname,
"tex_common/hint")) {
1467 flagsDescription =
"SURF_HINT";
1468 }
else if (
Q_streq(texname,
"tex_common/ladder")) {
1472 flagsDescription =
"CONTENTS_LADDER";
1473 }
else if (
Q_streq(texname,
"tex_common/lightclip")) {
1475 flagsDescription =
"CONTENTS_LIGHTCLIP";
1476 }
else if (
Q_streq(texname,
"tex_common/nodraw")) {
1480 flagsDescription =
"SURF_NODRAW";
1481 }
else if (
Q_streq(texname,
"tex_common/trigger")) {
1484 flagsDescription =
"SURF_NODRAW";
1485 }
else if (
Q_streq(texname,
"tex_common/origin")) {
1487 flagsDescription =
"CONTENTS_ORIGIN";
1488 }
else if (
Q_streq(texname,
"tex_common/slick")) {
1490 flagsDescription =
"SURF_SLICK";
1491 }
else if (
Q_streq(texname,
"tex_common/weaponclip")) {
1493 flagsDescription =
"CONTENTS_WEAPONCLIP";
1496 if (strstr(texname,
"water")) {
1503 flagsDescription =
"CONTENTS_WATER and CONTENTS_PASSABLE";
1509 "%s implied by %s texture has been set\n", flagsDescription ? flagsDescription :
"-", texname);
1519 "SURF_PHONG unset, as it has SURF_NODRAW set\n");
1525 "removing legacy flag, SURF_SKIP\n");
1537 for (
int j = 0; j < brush->
numsides; j++) {
1560 for (
int j = 0; j < brush->
numsides; j++) {
1569 if (tex->
name[0] ==
'\0') {
1621 int notInformedMixedFace = 1;
1626 if (contentFlagDiff) {
1628 if (notInformedMixedFace) {
1632 notInformedMixedFace = 0;
1666 for (j = 0; j < brush->
numsides; j++) {
1673 const int jNotZero = side->
contentFlags & ~side0->contentFlags;
1674 const int zeroNotJ = side0->
contentFlags & ~side->contentFlags;
1690 if (nfActorclip && nfActorclip != brush->
numsides) {
1692 for (j = 0; j < brush->
numsides; j++) {
1715 for (
int j = 0; j < brush->
numsides; j++) {
side_t brushsides[MAX_MAP_SIDES]
brush_texture_t side_brushtextures[MAX_MAP_SIDES]
plane_t mapplanes[MAX_MAP_PLANES]
mapbrush_t mapbrushes[MAX_MAP_BRUSHES]
entity_t entities[MAX_MAP_ENTITIES]
const char * ValueForKey(const entity_t *ent, const char *key)
static int Check_LevelForNodraws(const side_t *coverer, const side_t *coveree)
static bool Check_SideIsInBrush(const side_t *side, const mapbrush_t *brush, pointInBrush_t mode)
tests the vertices in the winding of side s.
static bool Check_SurfProps(const int flags, const side_t *s)
textures take priority over flags. checks if a tex marks a side as having a special property.
void Check_ContainedBrushes(void)
find duplicated brushes and brushes contained inside brushes
static vec_t Check_MapBrushVolume(const mapbrush_t *brush)
static float Check_LongestEdge(const winding_t *w)
static bool Check_IsPointInsideBrush(const vec3_t point, const mapbrush_t *brush, const pointInBrush_t mode)
tests if a point is in a map brush.
compositeSide_t compositeSides[MAX_MAP_SIDES/2]
static bool FacingAndCoincidentTo(const side_t *side1, const side_t *side2)
calculates whether side1 faces side2 and touches.
pointInBrush_t
wether the surface of a brush is included when testing if a point is in a brush determines how epsilo...
@ PIB_INCL_SURF_EXCL_EDGE
static bool Check_WindingIntersects(const winding_t *winding, const mapbrush_t *brush)
tests the lines joining the vertices in the winding
void CheckFlagsBasedOnTextures(void)
sets content flags based on textures
static bool Check_SurfProp(const int flag, const side_t *s)
textures take priority over flags. checks if a tex marks a side as having a special property.
static void Check_NearList(void)
add a list of near brushes to each mapbrush. near meaning that the bounding boxes are intersecting or...
#define CH_DIST_EPSILON_SQR
static bool Check_BoundingBoxIntersects(const mapbrush_t *a, const mapbrush_t *b)
void CheckTexturesBasedOnFlags(void)
check that sides have textures and that where content/surface flags are set the texture is correct.
static bool Check_SidesTouch(side_t *a, side_t *b)
test if sides abut or intersect
static float Check_SidesOverlap(const side_t *s1, const side_t *s2)
tests if sides overlap, for z-fighting check
#define CH_DIST_EPSILON_COLLINEAR_POINTS
void CheckPropagateParserContentFlags(mapbrush_t *b)
some contentlflags are set as a result of some surface flag. For example, if one face is TRANS* then ...
#define CH_COMP_NDR_EDGE_INTSCT_BUF
void CheckMixedFaceContents(void)
contentflags should be the same on each face of a brush. print warnings if they are not....
void CheckNodraws(void)
check for faces which can safely be set to SURF_NODRAW because they are pressed against the faces of ...
static bool ParallelAndCoincidentTo(const side_t *side1, const side_t *side2)
calculates whether side1 and side2 are on a common plane
static int Check_CalculateLevelFlagFill(int contentFlags)
calculate the bits that have to be set to fill levelflags such that they are contiguous
void Check_BrushIntersection(void)
reports intersection between optimisable map brushes
void CheckLevelFlags(void)
sets all levelflags, if none are set.
#define OVERLAP_WIDTH_TOL
static void Check_SetNodraw(side_t *s)
#define VERT_BUF_SIZE_DISJOINT_SIDES
void CheckFillLevelFlags(void)
ensures set levelflags are in one contiguous block
void SetImpliedFlags(side_t *side, brush_texture_t *tex, const mapbrush_t *brush)
Sets surface flags dependent on assigned texture.
void CheckMapMicro(void)
report brushes from the map below 1 unit^3
static int Check_EdgePlaneIntersection(const vec3_t vert1, const vec3_t vert2, const plane_t *plane, vec3_t intersection)
calculate where an edge (defined by the vertices) intersects a plane. http://local....
static bool Check_SidePointsDown(const side_t *s)
faces that are near pointing down may be set nodraw, as views are always slightly down
static float Check_PointPlaneDistance(const vec3_t point, const plane_t *plane)
distance from a point to a plane.
static bool Check_IsOptimisable(const mapbrush_t *b)
static bool Check_DuplicateBrushPlanes(const mapbrush_t *b)
void CheckZFighting(void)
check all brushes for overlapping shared faces
static bool Check_EdgeEdgeIntersection(const vec3_t e1p1, const vec3_t e1p2, const vec3_t e2p1, const vec3_t e2p2, vec3_t intersection)
finds point of intersection of two finite lines, if one exists
void DisplayContentFlags(const int flags)
prints a list of the names of the set content flags or "no contentflags" if all bits are 0
static void Check_FindCompositeSides(void)
a composite side is a side made of sides from neighbouring brushes. the sides abut....
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
void Check_Printf(verbosityLevel_t msgVerbLevel, bool change, int entnum, int brushnum, const char *format,...)
decides wether to proceed with output based on verbosity and ufo2map's mode: check/fix/compile
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
void Com_Printf(const char *const fmt,...)
#define CONTENTS_TRANSLUCENT
#define CONTENTS_WEAPONCLIP
#define CONTENTS_LEVEL_ALL
#define CONTENTS_ACTORCLIP
#define CONTENTS_PASSABLE
#define CONTENTS_LIGHTCLIP
Handles definition of entities, parsing them from entities.ufo.
void Sys_Error(const char *error,...)
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross)
binary operation on vectors in a three-dimensional space
#define Mem_AllocTypeN(type, n)
winding_t * AllocWinding(int points)
Allocate a new winding (polygon).
vec_t WindingArea(const winding_t *w)
QGL_EXTERN int GLboolean GLfloat * v
QGL_EXTERN GLuint GLsizei GLsizei * length
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
struct side_s ** memberSides
struct mapbrush_s ** nearBrushes
struct side_s * original_sides
struct mapbrush_s * brush
for storing the vertices of the side of a brush or other polygon
#define VectorMul(scalar, b, dest)
#define VectorSubtract(a, b, dest)
#define VectorCopy(src, dest)
#define VectorDistSqr(a, b)
#define VectorAdd(a, b, dest)
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
#define VectorScale(in, scale, out)
#define VectorLengthSqr(a)