decompile: handling hull1 wip
This commit is contained in:
parent
7c1b90abf3
commit
4bb827cab8
|
|
@ -120,6 +120,7 @@ WriteNullTexdef(fmt::memory_buffer& file)
|
||||||
|
|
||||||
struct decomp_plane_t {
|
struct decomp_plane_t {
|
||||||
const bsp2_dnode_t* node; // can be nullptr
|
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
|
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
|
// this should be an outward-facing plane
|
||||||
|
|
@ -127,7 +128,7 @@ struct decomp_plane_t {
|
||||||
double distance;
|
double distance;
|
||||||
|
|
||||||
static decomp_plane_t make(const qvec3d& normalIn, double distanceIn) {
|
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;
|
const mleaf_t *leaf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct clipleaf_decompile_task {
|
||||||
|
std::vector<decomp_plane_t> allPlanes;
|
||||||
|
int32_t contents;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preconditions:
|
* Preconditions:
|
||||||
* - The existing path of plane side choices have been pushed onto `planestack`
|
* - 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
|
* @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;
|
decomp_plane_t result;
|
||||||
|
|
||||||
result.node = node;
|
result.node = node;
|
||||||
|
result.clipnode = clipnode;
|
||||||
result.nodefront = front;
|
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],
|
result.normal = qvec3d(dplane->normal[0],
|
||||||
dplane->normal[1],
|
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)
|
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) {
|
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];
|
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);
|
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
|
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 i=0; i<3; ++i) {
|
||||||
for (int sign=0; sign<2; ++sign) {
|
for (int sign=0; sign<2; ++sign) {
|
||||||
|
|
@ -775,9 +817,9 @@ AddMapBoundsToStack(std::vector<decomp_plane_t>* planestack, const mbsp_t *bsp,
|
||||||
double dist;
|
double dist;
|
||||||
if (sign == 0) {
|
if (sign == 0) {
|
||||||
// positive
|
// positive
|
||||||
dist = headnode->maxs[i];
|
dist = model->maxs[i];
|
||||||
} else {
|
} else {
|
||||||
dist = -headnode->mins[i];
|
dist = -model->mins[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want outward-facing planes
|
// 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
|
static void
|
||||||
DecompileEntity(const mbsp_t *bsp, const decomp_options& options, FILE* file, const entdict_t& dict, bool isWorld)
|
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
|
// recursively visit the nodes to gather up a list of leafs to decompile
|
||||||
std::vector<decomp_plane_t> stack;
|
std::vector<decomp_plane_t> stack;
|
||||||
std::vector<leaf_decompile_task> tasks;
|
std::vector<leaf_decompile_task> tasks;
|
||||||
AddMapBoundsToStack(&stack, bsp, headnode);
|
AddMapBoundsToStack(&stack, bsp, model);
|
||||||
DecompileNode(&stack, bsp, headnode, &tasks);
|
DecompileNode(&stack, bsp, headnode, &tasks);
|
||||||
|
|
||||||
// decompile the leafs in parallel
|
// 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) {
|
for (auto& leafString : leafStrings) {
|
||||||
fprintf(file, "%s", leafString.c_str());
|
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");
|
fprintf(file, "}\n");
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,13 @@ const bsp2_dnode_t *BSP_GetNode(const mbsp_t *bsp, int nodenum)
|
||||||
return &bsp->dnodes[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)
|
const mleaf_t* BSP_GetLeaf(const mbsp_t *bsp, int leafnum)
|
||||||
{
|
{
|
||||||
if (leafnum < 0 || leafnum >= bsp->numleafs) {
|
if (leafnum < 0 || leafnum >= bsp->numleafs) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
// bounds-checked array access (assertion failure on out-of-bounds)
|
||||||
const bsp2_dnode_t *BSP_GetNode(const mbsp_t *bsp, int nodenum);
|
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_GetLeaf(const mbsp_t *bsp, int leafnum);
|
||||||
const mleaf_t* BSP_GetLeafFromNodeNum(const mbsp_t *bsp, int nodenum);
|
const mleaf_t* BSP_GetLeafFromNodeNum(const mbsp_t *bsp, int nodenum);
|
||||||
const dplane_t *BSP_GetPlane(const mbsp_t *bsp, int planenum);
|
const dplane_t *BSP_GetPlane(const mbsp_t *bsp, int planenum);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue