diff --git a/common/mathlib.cc b/common/mathlib.cc index ccdd906e..e01baa1f 100644 --- a/common/mathlib.cc +++ b/common/mathlib.cc @@ -122,6 +122,16 @@ void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs) } } +plane_t FlipPlane(plane_t input) +{ + plane_t result; + + VectorScale(input.normal, -1, result.normal); + result.dist = -input.dist; + + return result; +} + // from http://mathworld.wolfram.com/SpherePointPicking.html // eqns 6,7,8 void diff --git a/include/common/mathlib.hh b/include/common/mathlib.hh index 543c0f0a..1ffbcbad 100644 --- a/include/common/mathlib.hh +++ b/include/common/mathlib.hh @@ -145,6 +145,8 @@ VectorCopyFromGLM(const qvec3f &in, vec3_t out) void ClearBounds(vec3_t mins, vec3_t maxs); void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs); +plane_t FlipPlane(plane_t input); + static inline qvec3f VectorToGLM(const vec3_t in) { diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 60f4f766..f5b272a8 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -1429,16 +1429,6 @@ qboolean WindingIsHuge (winding_t *w) return false; } -static int -Brush_FaceCount (const brush_t *brush) -{ - int i=0; - for (const face_t *face = brush->faces; face; face = face->next) { - i++; - } - return i; -} - /* ================ SplitBrush @@ -1457,7 +1447,19 @@ void SplitBrush (const brush_t *brush, *front = nullptr; *back = nullptr; - const qbsp_plane_t *plane = &map.planes.at(planenum); + qbsp_plane_t plane; + { + const qbsp_plane_t *globalplane = &map.planes.at(planenum); + VectorCopy(globalplane->normal, plane.normal); + plane.dist = globalplane->dist; + if (planeside) { + VectorScale(plane.normal, -1, plane.normal); + plane.dist = -plane.dist; + } + // FIXME: dangerous.. + plane.type = -1000; + plane.outputplanenum = -1; + } // check all points vec_t d_front = 0; @@ -1468,7 +1470,7 @@ void SplitBrush (const brush_t *brush, continue; for (int j=0 ; jnumpoints ; j++) { - const vec_t d = DotProduct (w->points[j], plane->normal) - plane->dist; + const vec_t d = DotProduct (w->points[j], plane.normal) - plane.dist; if (d > 0 && d > d_front) d_front = d; if (d < 0 && d < d_back) @@ -1488,9 +1490,11 @@ void SplitBrush (const brush_t *brush, } // create a new winding from the split plane - winding_t *w = BaseWindingForPlane (plane); + winding_t *w = BaseWindingForPlane (&plane); for (const face_t *face = brush->faces; face; face = face->next) { - plane_t plane2 = Face_Plane(face); + if (!w) + break; + const plane_t plane2 = FlipPlane(Face_Plane(face)); ChopWindingInPlace (&w, plane2.normal, plane2.dist, 0); // PLANESIDE_EPSILON); } @@ -1501,7 +1505,7 @@ void SplitBrush (const brush_t *brush, if (w) FreeMem(w, WINDING, 1); - side = BrushMostlyOnSide (brush, plane->normal, plane->dist); + side = BrushMostlyOnSide (brush, plane.normal, plane.dist); if (side == SIDE_FRONT) *front = CopyBrush (brush); if (side == SIDE_BACK) @@ -1545,7 +1549,7 @@ void SplitBrush (const brush_t *brush, continue; winding_t *cw[2]; - DivideWinding(w, plane, &cw[0], &cw[1]); + DivideWinding(w, &plane, &cw[0], &cw[1]); for (int j=0 ; j<2 ; j++) { @@ -1586,7 +1590,7 @@ void SplitBrush (const brush_t *brush, } } - if (Brush_FaceCount(b[i]) < 4 /* was 3 */ || j < 3) + if (Brush_NumFaces(b[i]) < 4 /* was 3 */ || j < 3) { FreeBrush (b[i]); b[i] = nullptr; diff --git a/qbsp/test_qbsp.cc b/qbsp/test_qbsp.cc index 071fb158..e1123fe0 100644 --- a/qbsp/test_qbsp.cc +++ b/qbsp/test_qbsp.cc @@ -193,6 +193,94 @@ TEST(qbsp, BoundBrush) { FreeMem(brush, BRUSH, 1); } +static void checkForAllCubeNormals(const brush_t *brush) +{ + const vec3_t wanted[6] = { + { -1, 0, 0 },{ 1, 0, 0 }, + { 0,-1, 0 },{ 0, 1, 0 }, + { 0, 0,-1 },{ 0, 0, 1 } + }; + + bool found[6]; + for (int i=0; i<6; i++) { + found[i] = false; + } + + for (const face_t *face = brush->faces; face; face = face->next) { + const plane_t faceplane = Face_Plane(face); + + for (int i=0; i<6; i++) { + if (VectorCompare(wanted[i], faceplane.normal, NORMAL_EPSILON)) { + EXPECT_FALSE(found[i]); + found[i] = true; + } + } + } + + for (int i=0; i<6; i++) { + EXPECT_TRUE(found[i]); + } +} + +TEST(qbsp, SplitBrush) { + brush_t *brush = load128x128x32Brush(); + + const vec3_t planenormal = { -1, 0, 0 }; + int planeside; + const int planenum = FindPlane(planenormal, 0.0, &planeside); + + brush_t *front, *back; + SplitBrush(brush, planenum, planeside, &front, &back); + + ASSERT_NE(nullptr, front); + ASSERT_NE(nullptr, back); + + // front + EXPECT_FLOAT_EQ(-64, front->mins[0]); + EXPECT_FLOAT_EQ(-64, front->mins[1]); + EXPECT_FLOAT_EQ(-16, front->mins[2]); + + EXPECT_FLOAT_EQ(0, front->maxs[0]); + EXPECT_FLOAT_EQ(64, front->maxs[1]); + EXPECT_FLOAT_EQ(16, front->maxs[2]); + + EXPECT_EQ(6, Brush_NumFaces(front)); + checkForAllCubeNormals(front); + + // back + EXPECT_FLOAT_EQ(0, back->mins[0]); + EXPECT_FLOAT_EQ(-64, back->mins[1]); + EXPECT_FLOAT_EQ(-16, back->mins[2]); + + EXPECT_FLOAT_EQ(64, back->maxs[0]); + EXPECT_FLOAT_EQ(64, back->maxs[1]); + EXPECT_FLOAT_EQ(16, back->maxs[2]); + + EXPECT_EQ(6, Brush_NumFaces(back)); + checkForAllCubeNormals(back); + + FreeMem(brush, BRUSH, 1); + FreeMem(front, BRUSH, 1); + FreeMem(back, BRUSH, 1); +} + +TEST(qbsp, SplitBrushOnSide) { + brush_t *brush = load128x128x32Brush(); + + const vec3_t planenormal = { -1, 0, 0 }; + int planeside; + const int planenum = FindPlane(planenormal, -64.0, &planeside); + + brush_t *front, *back; + SplitBrush(brush, planenum, planeside, &front, &back); + + EXPECT_NE(nullptr, front); + EXPECT_EQ(6, Brush_NumFaces(front)); + checkForAllCubeNormals(front); + + EXPECT_EQ(nullptr, back); +} + TEST(mathlib, WindingArea) { winding_t w; w.numpoints = 5;