bsputil: start a --compare feature for helping with qbsp testing
This commit is contained in:
parent
4a360989f3
commit
8a47233bbf
|
|
@ -32,6 +32,7 @@
|
|||
#include <set>
|
||||
#include <list>
|
||||
#include <algorithm> // std::sort
|
||||
#include <light/light.hh>
|
||||
|
||||
/* FIXME - share header with qbsp, etc. */
|
||||
typedef struct {
|
||||
|
|
@ -453,6 +454,49 @@ CheckBSPFile(const mbsp_t *bsp)
|
|||
bsp->dmodels[0].maxs[2]);
|
||||
}
|
||||
|
||||
static void
|
||||
CompareBSPFiles(const mbsp_t *refBsp, const mbsp_t *bsp)
|
||||
{
|
||||
printf("comparing %d with %d faces\n", refBsp->numfaces, bsp->numfaces);
|
||||
|
||||
const dmodel_t *world = BSP_GetWorldModel(bsp);
|
||||
const dmodel_t *refWorld = BSP_GetWorldModel(refBsp);
|
||||
|
||||
// iterate through the refBsp world faces
|
||||
for (int i=0; i<refWorld->numfaces; i++) {
|
||||
auto* refFace = BSP_GetFace(refBsp, refWorld->firstface + i);
|
||||
qvec3f refFaceCentroid = Face_Centroid(refBsp, refFace);
|
||||
|
||||
// FIXME:
|
||||
vec3_t wantedPoint;
|
||||
glm_to_vec3_t(refFaceCentroid, wantedPoint);
|
||||
|
||||
vec3_t wantedNormal;
|
||||
Face_Normal(refBsp, refFace, wantedNormal);
|
||||
|
||||
// Search for a face in bsp touching refFaceCentroid.
|
||||
auto* matchedFace = BSP_FindFaceAtPoint(bsp, world, wantedPoint, wantedNormal);
|
||||
if (matchedFace == nullptr) {
|
||||
printf("couldn't find a face at %f %f %f normal %f %f %f\n",
|
||||
wantedPoint[0], wantedPoint[1], wantedPoint[2],
|
||||
wantedNormal[0], wantedNormal[1], wantedNormal[2]);
|
||||
}
|
||||
|
||||
// TODO: run on some more complex maps
|
||||
// auto* refFaceSelfCheck = BSP_FindFaceAtPoint(refBsp, refWorld, wantedPoint, wantedNormal);
|
||||
// if (refFaceSelfCheck == refFace) {
|
||||
// matches ++;
|
||||
// } else {
|
||||
// printf("not match at %f %f %f wanted %p got %p\n", wantedPoint[0], wantedPoint[1], wantedPoint[2], refFace, refFaceSelfCheck);
|
||||
// Face_DebugPrint(refBsp, refFace);
|
||||
// Face_DebugPrint(refBsp, refFaceSelfCheck);
|
||||
// notmat++;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -465,7 +509,7 @@ main(int argc, char **argv)
|
|||
printf("---- bsputil / ericw-tools " stringify(ERICWTOOLS_VERSION) " ----\n");
|
||||
if (argc == 1) {
|
||||
printf("usage: bsputil [--extract-entities] [--extract-textures] [--convert bsp29|bsp2|bsp2rmq|q2bsp] [--check] [--modelinfo]"
|
||||
"[--check] bspfile\n");
|
||||
"[--check] [--compare otherbsp] bspfile\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +523,27 @@ main(int argc, char **argv)
|
|||
ConvertBSPFormat(GENERIC_BSP, &bspdata);
|
||||
|
||||
for (i = 0; i < argc - 1; i++) {
|
||||
if (!strcmp(argv[i], "--convert")) {
|
||||
if (!strcmp(argv[i], "--compare")) {
|
||||
i++;
|
||||
if (i == argc - 1) {
|
||||
Error("--compare requires two arguments");
|
||||
}
|
||||
// Load the reference BSP
|
||||
|
||||
char refbspname[1024];
|
||||
bspdata_t refbspdata;
|
||||
strcpy(refbspname, argv[i]);
|
||||
DefaultExtension(refbspname, ".bsp");
|
||||
LoadBSPFile(refbspname, &refbspdata);
|
||||
ConvertBSPFormat(GENERIC_BSP, &refbspdata);
|
||||
|
||||
printf("comparing reference bsp %s with test bsp %s\n", refbspname, source);
|
||||
|
||||
CompareBSPFiles(&refbspdata.data.mbsp,
|
||||
&bspdata.data.mbsp);
|
||||
|
||||
break;
|
||||
} else if (!strcmp(argv[i], "--convert")) {
|
||||
i++;
|
||||
if (!(i < argc - 1)) {
|
||||
Error("--convert requires an argument");
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ const bsp2_dnode_t *BSP_GetNode(const mbsp_t *bsp, int nodenum)
|
|||
return &bsp->dnodes[nodenum];
|
||||
}
|
||||
|
||||
const mleaf_t* BSP_GetLeaf(const mbsp_t *bsp, int leafnum)
|
||||
{
|
||||
if (leafnum < 0 || leafnum >= bsp->numleafs) {
|
||||
Error("Corrupt BSP: leaf %d is out of bounds (bsp->numleafs = %d)", leafnum, bsp->numleafs);
|
||||
}
|
||||
return &bsp->dleafs[leafnum];
|
||||
}
|
||||
|
||||
const mleaf_t* BSP_GetLeafFromNodeNum(const mbsp_t *bsp, int nodenum)
|
||||
{
|
||||
const int leafnum = (-1 - nodenum);
|
||||
return BSP_GetLeaf(bsp, leafnum);
|
||||
}
|
||||
|
||||
const dplane_t *BSP_GetPlane(const mbsp_t *bsp, int planenum)
|
||||
{
|
||||
Q_assert(planenum >= 0 && planenum < bsp->numplanes);
|
||||
|
|
@ -248,12 +262,7 @@ vec_t Plane_Dist(const vec3_t point, const dplane_t *plane)
|
|||
static bool Light_PointInSolid_r(const mbsp_t *bsp, const int nodenum, const vec3_t point)
|
||||
{
|
||||
if (nodenum < 0) {
|
||||
// FIXME: Factor out into bounds-checked getter
|
||||
const int leafnum = (-1 - nodenum);
|
||||
if (leafnum < 0 || leafnum >= bsp->numleafs) {
|
||||
Error("Corrupt BSP: leaf %d is out of bounds (bsp->numleafs = %d)", leafnum, bsp->numleafs);
|
||||
}
|
||||
mleaf_t *leaf = &bsp->dleafs[leafnum];
|
||||
const mleaf_t *leaf = BSP_GetLeafFromNodeNum(bsp, nodenum);
|
||||
|
||||
return (bsp->loadversion == Q2_BSPVERSION ? leaf->contents & Q2_CONTENTS_SOLID : (leaf->contents == CONTENTS_SOLID || leaf->contents == CONTENTS_SKY)); //mxd
|
||||
}
|
||||
|
|
@ -282,6 +291,63 @@ bool Light_PointInWorld(const mbsp_t *bsp, const vec3_t point)
|
|||
return Light_PointInSolid(bsp, &bsp->dmodels[0], point);
|
||||
}
|
||||
|
||||
static const bsp2_dface_t *BSP_FindFaceAtPoint_r(const mbsp_t *bsp, const int nodenum, const vec3_t point, const vec3_t wantedNormal)
|
||||
{
|
||||
if (nodenum < 0) {
|
||||
// we're only interested in nodes, since faces are owned by nodes.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bsp2_dnode_t *node = &bsp->dnodes[nodenum];
|
||||
const vec_t dist = Plane_Dist(point, &bsp->dplanes[node->planenum]);
|
||||
|
||||
if (dist > 0.1)
|
||||
return BSP_FindFaceAtPoint_r(bsp, node->children[0], point, wantedNormal);
|
||||
if (dist < -0.1)
|
||||
return BSP_FindFaceAtPoint_r(bsp, node->children[1], point, wantedNormal);
|
||||
|
||||
// Point is close to this node plane. Check all faces on the plane.
|
||||
for (int i=0; i<node->numfaces; i++) {
|
||||
const bsp2_dface_t *face = BSP_GetFace(bsp, node->firstface + i);
|
||||
// First check if it's facing the right way
|
||||
vec3_t faceNormal;
|
||||
Face_Normal(bsp, face, faceNormal);
|
||||
|
||||
if (DotProduct(faceNormal, wantedNormal) < 0) {
|
||||
// Opposite, so not the right face.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Next test if it's within the boundaries of the face
|
||||
plane_t *edgeplanes = Face_AllocInwardFacingEdgePlanes(bsp, face);
|
||||
const bool insideFace = EdgePlanes_PointInside(face, edgeplanes, point);
|
||||
free(edgeplanes);
|
||||
|
||||
// Found a match?
|
||||
if (insideFace) {
|
||||
return face;
|
||||
}
|
||||
}
|
||||
|
||||
// No match found on this plane. Check both sides of the tree.
|
||||
const bsp2_dface_t *side0Match = BSP_FindFaceAtPoint_r(bsp, node->children[0], point, wantedNormal);
|
||||
if (side0Match != nullptr) {
|
||||
return side0Match;
|
||||
} else {
|
||||
return BSP_FindFaceAtPoint_r(bsp, node->children[1], point, wantedNormal);
|
||||
}
|
||||
}
|
||||
|
||||
const bsp2_dface_t * BSP_FindFaceAtPoint(const mbsp_t *bsp, const dmodel_t *model, const vec3_t point, const vec3_t wantedNormal)
|
||||
{
|
||||
return BSP_FindFaceAtPoint_r(bsp, model->headnode[0], point, wantedNormal);
|
||||
}
|
||||
|
||||
const bsp2_dface_t * BSP_FindFaceAtPoint_InWorld(const mbsp_t *bsp, const vec3_t point, const vec3_t wantedNormal)
|
||||
{
|
||||
return BSP_FindFaceAtPoint(bsp, &bsp->dmodels[0], point, wantedNormal);
|
||||
}
|
||||
|
||||
plane_t *
|
||||
Face_AllocInwardFacingEdgePlanes(const mbsp_t *bsp, const bsp2_dface_t *face)
|
||||
{
|
||||
|
|
@ -360,3 +426,26 @@ qvec3f Face_Centroid(const mbsp_t *bsp, const bsp2_dface_t *face)
|
|||
// FIXME: GLM_PolyCentroid has a assertion that there are >= 3 points
|
||||
return GLM_PolyCentroid(GLM_FacePoints(bsp, face));
|
||||
}
|
||||
|
||||
void Face_DebugPrint(const mbsp_t *bsp, const bsp2_dface_t *face)
|
||||
{
|
||||
const gtexinfo_t *tex = &bsp->texinfo[face->texinfo];
|
||||
const char *texname = Face_TextureName(bsp, face);
|
||||
|
||||
logprint("face %d, texture '%s', %d edges...\n"
|
||||
" vectors (%3.3f, %3.3f, %3.3f) (%3.3f)\n"
|
||||
" (%3.3f, %3.3f, %3.3f) (%3.3f)\n",
|
||||
(int)(face - bsp->dfaces), texname, face->numedges,
|
||||
tex->vecs[0][0], tex->vecs[0][1], tex->vecs[0][2], tex->vecs[0][3],
|
||||
tex->vecs[1][0], tex->vecs[1][1], tex->vecs[1][2], tex->vecs[1][3]);
|
||||
|
||||
for (int i = 0; i < face->numedges; i++) {
|
||||
int edge = bsp->dsurfedges[face->firstedge + i];
|
||||
int vert = Face_VertexAtIndex(bsp, face, i);
|
||||
const vec_t *point = GetSurfaceVertexPoint(bsp, face, i);
|
||||
logprint("%s %3d (%3.3f, %3.3f, %3.3f) :: edge %d\n",
|
||||
i ? " " : " verts ", vert,
|
||||
point[0], point[1], point[2],
|
||||
edge);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ int Face_GetNum(const mbsp_t *bsp, const bsp2_dface_t *f);
|
|||
|
||||
// bounds-checked array access (assertion failure on out-of-bounds)
|
||||
const bsp2_dnode_t *BSP_GetNode(const mbsp_t *bsp, int nodenum);
|
||||
const mleaf_t* BSP_GetLeaf(const mbsp_t *bsp, int leafnum);
|
||||
const mleaf_t* BSP_GetLeafFromNodeNum(const mbsp_t *bsp, int nodenum);
|
||||
const dplane_t *BSP_GetPlane(const mbsp_t *bsp, int planenum);
|
||||
const bsp2_dface_t *BSP_GetFace(const mbsp_t *bsp, int fnum);
|
||||
bsp2_dface_t *BSP_GetFace(mbsp_t *bsp, int fnum);
|
||||
|
|
@ -52,6 +54,13 @@ const dmodel_t *BSP_DModelForModelString(const mbsp_t *bsp, const std::string &s
|
|||
vec_t Plane_Dist(const vec3_t point, const dplane_t *plane);
|
||||
bool Light_PointInSolid(const mbsp_t *bsp, const dmodel_t *model, const vec3_t point);
|
||||
bool Light_PointInWorld(const mbsp_t *bsp, const vec3_t point);
|
||||
/**
|
||||
* Searches for a face touching a point and facing a certain way.
|
||||
* Sometimes (water, sky?) there will be 2 overlapping candidates facing opposite ways, the provided normal
|
||||
* is used to disambiguate these.
|
||||
*/
|
||||
const bsp2_dface_t *BSP_FindFaceAtPoint(const mbsp_t *bsp, const dmodel_t *model, const vec3_t point, const vec3_t wantedNormal);
|
||||
const bsp2_dface_t *BSP_FindFaceAtPoint_InWorld(const mbsp_t *bsp, const vec3_t point, const vec3_t wantedNormal);
|
||||
plane_t *Face_AllocInwardFacingEdgePlanes(const mbsp_t *bsp, const bsp2_dface_t *face);
|
||||
bool EdgePlanes_PointInside(const bsp2_dface_t *face, const plane_t *edgeplanes, const vec3_t point);
|
||||
|
||||
|
|
@ -61,5 +70,6 @@ qvec3f Vertex_GetPos_E(const mbsp_t *bsp, int num);
|
|||
qvec3f Face_Normal_E(const mbsp_t *bsp, const bsp2_dface_t *f);
|
||||
std::vector<qvec3f> GLM_FacePoints(const mbsp_t *bsp, const bsp2_dface_t *face);
|
||||
qvec3f Face_Centroid(const mbsp_t *bsp, const bsp2_dface_t *face);
|
||||
void Face_DebugPrint(const mbsp_t *bsp, const bsp2_dface_t *face);
|
||||
|
||||
#endif /* __COMMON_BSPUTILS_HH__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue