qbsp: fix some issues with SplitBrush

This commit is contained in:
Eric Wasylishen 2017-07-23 01:21:41 -06:00
parent 3bb22ef22b
commit 9629134612
4 changed files with 121 additions and 17 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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 ; j<w->numpoints ; 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;

View File

@ -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;