Skip to content

Commit

Permalink
add merge option to map viewer
Browse files Browse the repository at this point in the history
does a simple -noripent -noscript merge and gives alignment options if the maps overlap.
  • Loading branch information
wootguy committed Apr 26, 2024
1 parent e018ece commit fe0d84f
Show file tree
Hide file tree
Showing 9 changed files with 376 additions and 86 deletions.
38 changes: 33 additions & 5 deletions src/bsp/Bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,27 @@ Bsp::Bsp() {
valid = true;
}

Bsp::Bsp(const Bsp& other) {
header = other.header;
lumps = new byte*[HEADER_LUMPS];
path = other.path;
name = other.name;

for (int i = 0; i < HEADER_LUMPS; i++) {
lumps[i] = new byte[header.lump[i].nLength];
memcpy(lumps[i], other.lumps[i], header.lump[i].nLength);
}

load_ents();
update_lump_pointers();

valid = true;
}

Bsp::Bsp(std::string fpath)
{
lumps = NULL;

if (fpath.size() < 4 || toLowerCase(fpath).rfind(".bsp") != fpath.size() - 4) {
fpath = fpath + ".bsp";
}
Expand All @@ -84,10 +103,12 @@ Bsp::Bsp(std::string fpath)

Bsp::~Bsp()
{
for (int i = 0; i < HEADER_LUMPS; i++)
if (lumps[i])
delete [] lumps[i];
delete [] lumps;
if (lumps) {
for (int i = 0; i < HEADER_LUMPS; i++)
if (lumps[i])
delete[] lumps[i];
delete[] lumps;
}

for (int i = 0; i < ents.size(); i++)
delete ents[i];
Expand All @@ -105,6 +126,12 @@ void Bsp::get_bounding_box(vec3& mins, vec3& maxs) {

mins = thisWorld.nMins;
maxs = thisWorld.nMaxs;

if (ents.size() && ents[0]->hasKey("origin")) {
vec3 origin = ents[0]->getOrigin();
mins += origin;
maxs += origin;
}
}

void Bsp::get_model_vertex_bounds(int modelIdx, vec3& mins, vec3& maxs) {
Expand Down Expand Up @@ -3441,7 +3468,8 @@ bool Bsp::isValid() {
&& textureCount < g_limits.max_textures
&& lightDataLength < g_limits.max_lightdata
&& visDataLength < g_limits.max_visdata
&& ents.size() < g_limits.max_entities;
&& ents.size() < g_limits.max_entities
&& ceilf(calc_allocblock_usage()) < g_limits.max_allocblocks;
}

bool Bsp::validate_vis_data() {
Expand Down
1 change: 1 addition & 0 deletions src/bsp/Bsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Bsp
vector<Entity*> ents;

Bsp();
Bsp(const Bsp& other);
Bsp(std::string fname);
~Bsp();

Expand Down
47 changes: 39 additions & 8 deletions src/bsp/BspMerger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,28 @@ BspMerger::BspMerger() {

}

Bsp* BspMerger::merge(vector<Bsp*> maps, vec3 gap, string output_name, bool noripent, bool noscript) {
if (maps.size() < 1) {
MergeResult BspMerger::merge(vector<Bsp*> maps, vec3 gap, string output_name, bool noripent, bool noscript, bool nomove) {
MergeResult result;
result.fpath = "";
result.map = NULL;
result.moveFixes = vec3();
result.overflow = false;

if (maps.size() <= 1) {
logf("\nMore than 1 map is required for merging. Aborting merge.\n");
return NULL;
return result;
}

vector<vector<vector<MAPBLOCK>>> blocks = separate(maps, gap);
result.fpath = maps[1]->path;

vector<vector<vector<MAPBLOCK>>> blocks = separate(maps, gap, nomove, result);

if (blocks.empty()) {
return result;
}

logf("\nArranging maps so that they don't overlap:\n");
if (!nomove)
logf("\nArranging maps so that they don't overlap:\n");

for (int z = 0; z < blocks.size(); z++) {
for (int y = 0; y < blocks[z].size(); y++) {
Expand Down Expand Up @@ -108,7 +121,9 @@ Bsp* BspMerger::merge(vector<Bsp*> maps, vec3 gap, string output_name, bool nori
update_map_series_entity_logic(output, flattenedBlocks, maps, output_name, maps[0]->name, noscript);
}

return output;
result.map = output;
result.overflow = !output->isValid();
return result;
}

void BspMerger::merge(MAPBLOCK& dst, MAPBLOCK& src, string resultType) {
Expand All @@ -120,7 +135,7 @@ void BspMerger::merge(MAPBLOCK& dst, MAPBLOCK& src, string resultType) {
merge(*dst.map, *src.map);
}

vector<vector<vector<MAPBLOCK>>> BspMerger::separate(vector<Bsp*>& maps, vec3 gap) {
vector<vector<vector<MAPBLOCK>>> BspMerger::separate(vector<Bsp*>& maps, vec3 gap, bool nomove, MergeResult& result) {
vector<MAPBLOCK> blocks;

vector<vector<vector<MAPBLOCK>>> orderedBlocks;
Expand Down Expand Up @@ -153,25 +168,41 @@ vector<vector<vector<MAPBLOCK>>> BspMerger::separate(vector<Bsp*>& maps, vec3 ga
for (int k = 0; k < blocks.size(); k++) {
if (i != k && blocks[i].intersects(blocks[k])) {
noOverlap = false;

if (nomove) {
logf("Merge aborted because the maps overlap.\n");
blocks[i].suggest_intersection_fix(blocks[k], result);
}

break;
}
}
}

if (noOverlap) {
logf("Maps do not overlap. They will be merged without moving.\n");
if (!nomove)
logf("Maps do not overlap. They will be merged without moving.\n");

vector<vector<MAPBLOCK>> col;
vector<MAPBLOCK> row;
for (const MAPBLOCK& block : blocks) {
row.push_back(block);
if (block.map->ents[0]->hasKey("origin")) {
// apply the transform move in the GUI
block.map->move(block.map->ents[0]->getOrigin());
block.map->ents[0]->removeKeyvalue("origin");
}
}
col.push_back(row);
orderedBlocks.push_back(col);

return orderedBlocks;
}

if (nomove) {
return orderedBlocks;
}

maxDims += gap;

int maxMapsPerRow = (MAX_MAP_COORD * 2.0f) / maxDims.x;
Expand Down
32 changes: 30 additions & 2 deletions src/bsp/BspMerger.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
#pragma once
#include "util.h"
#include "Bsp.h"

struct MergeResult {
Bsp* map;

// merge failed if map is null, and below are suggested fixes
string fpath;
vec3 moveFixes;
vec3 moveFixes2;
bool overflow;
};

// bounding box for a map, used for arranging maps for merging
struct MAPBLOCK
{
Expand All @@ -13,6 +24,22 @@ struct MAPBLOCK
(mins.y <= other.maxs.y && maxs.y >= other.mins.y) &&
(mins.z <= other.maxs.z && maxs.z >= other.mins.z);
}

void suggest_intersection_fix(MAPBLOCK& other, MergeResult& result) {
float xdelta_neg = other.maxs.x - mins.x;
float xdelta_pos = maxs.x - other.mins.x;
float ydelta_neg = other.maxs.y - mins.y;
float ydelta_pos = maxs.y - other.mins.y;
float zdelta_neg = other.maxs.z - mins.z;
float zdelta_pos = maxs.z - other.mins.z;

int xdelta = xdelta_neg < xdelta_pos ? ceilf(xdelta_neg + 1.5f) : -ceilf(xdelta_pos + 1.5f);
int ydelta = ydelta_neg < ydelta_pos ? ceilf(ydelta_neg + 1.5f) : -ceilf(ydelta_pos + 1.5f);
int zdelta = zdelta_neg < zdelta_pos ? ceilf(zdelta_neg + 1.5f) : -ceilf(zdelta_pos + 1.5f);

result.moveFixes = vec3(ceilf(xdelta_neg + 1.5f), ceilf(ydelta_neg + 1.5f), ceilf(zdelta_neg + 1.5f));
result.moveFixes2 = vec3(-ceilf(xdelta_pos + 1.5f), -ceilf(ydelta_pos + 1.5f), -ceilf(zdelta_pos + 1.5f));
}
};

class BspMerger {
Expand All @@ -22,7 +49,8 @@ class BspMerger {
// merges all maps into one
// noripent - don't change any entity logic
// noscript - don't add support for the bspguy map script (worse performance + buggy, but simpler)
Bsp* merge(vector<Bsp*> maps, vec3 gap, string output_name, bool noripent, bool noscript);
// nomove - abort the merge if the maps overlap
MergeResult merge(vector<Bsp*> maps, vec3 gap, string output_name, bool noripent, bool noscript, bool nomove);

private:
int merge_ops = 0;
Expand All @@ -33,7 +61,7 @@ class BspMerger {
// merge BSP data
bool merge(Bsp& mapA, Bsp& mapB);

vector<vector<vector<MAPBLOCK>>> separate(vector<Bsp*>& maps, vec3 gap);
vector<vector<vector<MAPBLOCK>>> separate(vector<Bsp*>& maps, vec3 gap, bool nomove, MergeResult& result);

// for maps in a series:
// - changelevels should be replaced with teleports or respawn triggers
Expand Down
Loading

0 comments on commit fe0d84f

Please sign in to comment.