decompile: handling hull1 wip

This commit is contained in:
Eric Wasylishen 2021-02-07 17:01:45 -07:00
parent 7c1b90abf3
commit 4bb827cab8
3 changed files with 134 additions and 8 deletions

View File

@ -120,6 +120,7 @@ WriteNullTexdef(fmt::memory_buffer& file)
struct decomp_plane_t {
const bsp2_dnode_t* node; // can be nullptr
const bsp2_dclipnode_t* clipnode; // can be nullptr
bool nodefront; // only set if node is non-null. true = we are visiting the front side of the plane
// this should be an outward-facing plane
@ -127,7 +128,7 @@ struct decomp_plane_t {
double distance;
static decomp_plane_t make(const qvec3d& normalIn, double distanceIn) {
return { nullptr, false, normalIn, distanceIn };
return { nullptr, nullptr, false, normalIn, distanceIn };
}
};
@ -617,6 +618,11 @@ struct leaf_decompile_task {
const mleaf_t *leaf;
};
struct clipleaf_decompile_task {
std::vector<decomp_plane_t> allPlanes;
int32_t contents;
};
/**
* Preconditions:
* - The existing path of plane side choices have been pushed onto `planestack`
@ -712,13 +718,20 @@ DecompileLeafTask(const mbsp_t *bsp, const leaf_decompile_task& task)
/**
* @param front whether we are visiting the front side of the node plane
*/
decomp_plane_t MakeDecompPlane(const mbsp_t *bsp, const bsp2_dnode_t *node, const bool front) {
static decomp_plane_t MakeDecompPlane(const mbsp_t *bsp,
const bsp2_dnode_t *node,
const bsp2_dclipnode_t *clipnode,
const bool front)
{
assert(node == nullptr || clipnode == nullptr);
decomp_plane_t result;
result.node = node;
result.clipnode = clipnode;
result.nodefront = front;
const dplane_t *dplane = BSP_GetPlane(bsp, node->planenum);
const dplane_t *dplane = BSP_GetPlane(bsp, (node != nullptr) ? node->planenum : clipnode->planenum);
result.normal = qvec3d(dplane->normal[0],
dplane->normal[1],
@ -743,7 +756,7 @@ static void
DecompileNode(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp, const bsp2_dnode_t *node, std::vector<leaf_decompile_task>* result)
{
auto handleSide = [&](const bool front) {
planestack->push_back(MakeDecompPlane(bsp, node, front));
planestack->push_back(MakeDecompPlane(bsp, node, nullptr, front));
const int32_t child = node->children[front ? 0 : 1];
@ -763,8 +776,37 @@ DecompileNode(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp, const
handleSide(false);
}
/**
* Same as above but for clipnodes
*/
static void
DecompileClipNode(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp, const bsp2_dclipnode_t *clipnode, std::vector<clipleaf_decompile_task>* result)
{
auto handleSide = [&](const bool front) {
planestack->push_back(MakeDecompPlane(bsp, nullptr, clipnode, front));
const int32_t child = clipnode->children[front ? 0 : 1];
if (child < 0) {
const int32_t contents = child;
// it's a leaf on this side
result->push_back(clipleaf_decompile_task{*planestack, contents});
} else {
// it's another clip node - process it recursively
DecompileClipNode(planestack, bsp, BSP_GetClipNode(bsp, child), result);
}
planestack->pop_back();
};
// handle the front and back
handleSide(true);
handleSide(false);
}
void
AddMapBoundsToStack(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp, const bsp2_dnode_t* headnode)
AddMapBoundsToStack(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp, const dmodelh2_t* model)
{
for (int i=0; i<3; ++i) {
for (int sign=0; sign<2; ++sign) {
@ -775,9 +817,9 @@ AddMapBoundsToStack(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp,
double dist;
if (sign == 0) {
// positive
dist = headnode->maxs[i];
dist = model->maxs[i];
} else {
dist = -headnode->mins[i];
dist = -model->mins[i];
}
// we want outward-facing planes
@ -786,6 +828,72 @@ AddMapBoundsToStack(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp,
}
}
static std::vector<decomp_plane_t>
ExpandHull1Brush(const std::vector<decomp_plane_t>& planes)
{
std::vector<decomp_plane_t> result = planes;
for (auto& plane : result) {
// from LoadBrush
const qvec3d hull_size[2] = { {-16, -16, -32}, {16, 16, 24} };
// from ExpandBrush
qvec3d corner;
for (int x = 0; x < 3; x++) {
if (plane.normal[x] > 0) {
corner[x] = hull_size[1][x];
} else if (plane.normal[x] < 0) {
corner[x] = hull_size[0][x];
}
}
plane.distance += qv::dot(corner, plane.normal);
}
return result;
}
static void
SubtractBrush(const std::vector<decomp_plane_t>& lhs,
const std::vector<decomp_plane_t>& rhs,
std::vector<std::vector<decomp_plane_t>>* results)
{
}
static std::string
DecompileHull1(const mbsp_t *bsp, const std::vector<clipleaf_decompile_task>& tasks)
{
// 1. collect the empty leafs
fmt::memory_buffer file;
for (auto& task : tasks) {
if (task.contents == CONTENTS_EMPTY) {
auto reducedPlanes = RemoveRedundantPlanes(task.allPlanes);
if (reducedPlanes.empty()) {
printf("warning, skipping empty brush\n");
continue;
}
reducedPlanes = ExpandHull1Brush(reducedPlanes);
// write brush
fmt::format_to(file, "{{\n");
for (const auto& side : reducedPlanes) {
PrintPlanePoints(bsp, side, file);
// print a default face
fmt::format_to(file, " {} ", "clip");
WriteNullTexdef(file);
fmt::format_to(file, "\n");
}
fmt::format_to(file, "}}\n");
}
}
return fmt::to_string(file);
}
static void
DecompileEntity(const mbsp_t *bsp, const decomp_options& options, FILE* file, const entdict_t& dict, bool isWorld)
{
@ -824,7 +932,7 @@ DecompileEntity(const mbsp_t *bsp, const decomp_options& options, FILE* file, co
// recursively visit the nodes to gather up a list of leafs to decompile
std::vector<decomp_plane_t> stack;
std::vector<leaf_decompile_task> tasks;
AddMapBoundsToStack(&stack, bsp, headnode);
AddMapBoundsToStack(&stack, bsp, model);
DecompileNode(&stack, bsp, headnode, &tasks);
// decompile the leafs in parallel
@ -842,6 +950,16 @@ DecompileEntity(const mbsp_t *bsp, const decomp_options& options, FILE* file, co
for (auto& leafString : leafStrings) {
fprintf(file, "%s", leafString.c_str());
}
// decompile hull1 to clip brushes
{
const bsp2_dclipnode_t *clipnode_head = BSP_GetClipNode(bsp, model->headnode[1]);
std::vector<decomp_plane_t> stack1;
std::vector<clipleaf_decompile_task> tasks1;
AddMapBoundsToStack(&stack1, bsp, model);
DecompileClipNode(&stack1, bsp, clipnode_head, &tasks1);
fprintf(file, "%s", DecompileHull1(bsp, tasks1).c_str());
}
}
fprintf(file, "}\n");

View File

@ -47,6 +47,13 @@ const bsp2_dnode_t *BSP_GetNode(const mbsp_t *bsp, int nodenum)
return &bsp->dnodes[nodenum];
}
const bsp2_dclipnode_t *BSP_GetClipNode(const mbsp_t *bsp, int nodenum)
{
Q_assert(nodenum >= 0 && nodenum < bsp->numclipnodes);
return &bsp->dclipnodes[nodenum];
}
const mleaf_t* BSP_GetLeaf(const mbsp_t *bsp, int leafnum)
{
if (leafnum < 0 || leafnum >= bsp->numleafs) {

View File

@ -31,6 +31,7 @@ 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 bsp2_dclipnode_t *BSP_GetClipNode(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);