Skip to content

Commit

Permalink
HotFix missing origin! Bugfixes! ! Added new featu
Browse files Browse the repository at this point in the history
HotFix missing origin! Bugfixes! !

Added new feature : generate map overlay (for example for special effects)
  • Loading branch information
UnrealKaraulov committed Dec 24, 2024
1 parent 8562559 commit 37cbdb9
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 75 deletions.
88 changes: 84 additions & 4 deletions src/bsp/Bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4535,7 +4535,7 @@ void Bsp::update_ent_lump(bool stripNodes)

vec3 Bsp::get_model_center(int modelIdx)
{
if (modelIdx < 0 || modelIdx > bsp_header.lump[LUMP_MODELS].nLength / (int)sizeof(BSPMODEL))
if (modelIdx < 0 || modelIdx >= modelCount)
{
print_log(get_localized_string(LANG_0072), modelIdx);
return vec3();
Expand Down Expand Up @@ -6461,7 +6461,7 @@ void Bsp::print_clipnode_tree(int iNode, int depth)

void Bsp::print_model_hull(int modelIdx, int hull_number)
{
if (modelIdx < 0 || modelIdx > bsp_header.lump[LUMP_MODELS].nLength / (int)sizeof(BSPMODEL))
if (modelIdx < 0 || modelIdx >= modelCount)
{
print_log(PRINT_RED | PRINT_INTENSITY, get_localized_string(LANG_1024), modelIdx);
return;
Expand Down Expand Up @@ -8581,7 +8581,7 @@ int Bsp::create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetMod
{
int sharedSolidLeaf = 0;
int anyEmptyLeaf = leafIdx;
if (anyEmptyLeaf == 0)
if (anyEmptyLeaf == -1)
{
for (int i = 0; i < leafCount; i++)
{
Expand All @@ -8591,7 +8591,7 @@ int Bsp::create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetMod
break;
}
}
if (anyEmptyLeaf == 0)
if (anyEmptyLeaf == -1)
{
anyEmptyLeaf = create_leaf(CONTENTS_EMPTY);
targetModel->nVisLeafs += 1;
Expand Down Expand Up @@ -14803,6 +14803,67 @@ bool Bsp::is_texture_with_pal(int textureid)
return is_texture_has_pal;
}

void Bsp::fix_all_duplicate_vertices()
{
std::set<int> verts_usage;
std::set<int> edges_usage;

for (int faceIdx = 0; faceIdx < faceCount; faceIdx++)
{
BSPFACE32 face = faces[faceIdx];

for (int e = face.iFirstEdge; e < face.iFirstEdge + face.nEdges; e++)
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];

if (edges_usage.count(abs(edgeIdx)))
{
int newedge_id = create_edge();

if (edgeIdx >= 0)
{
edgeIdx = newedge_id;
}
else
{
edgeIdx = -newedge_id;
}

BSPEDGE32& newedge = edges[newedge_id];
newedge = edge;

int v1 = create_vert();
verts[v1] = verts[edge.iVertex[0]];
newedge.iVertex[0] = v1;

int v2 = create_vert();
verts[v2] = verts[edge.iVertex[1]];
newedge.iVertex[1] = v1;
}
else
{
int vert1 = edge.iVertex[0];
int vert2 = edge.iVertex[1];

if (verts_usage.count(vert1) || verts_usage.count(vert2))
{
int v1 = create_vert();
verts[v1] = verts[vert1];
edge.iVertex[0] = v1;
int v2 = create_vert();
verts[v2] = verts[vert2];
edge.iVertex[1] = v2;
}

edges_usage.insert(abs(edgeIdx));
verts_usage.insert(vert2);
verts_usage.insert(vert1);
}
}
}
}

void Bsp::face_fix_duplicate_edges_index(int faceIdx)
{
if (faceIdx < 0 || faceIdx >= faceCount)
Expand Down Expand Up @@ -15071,4 +15132,23 @@ int Bsp::AddTriggerTexture()
{
//print_log(get_localized_string(LANG_0295));
return add_texture("aaatrigger", aaatriggerTex->get_data(), aaatriggerTex->width, aaatriggerTex->height);
}

vec3 Bsp::getEntOrigin(Entity* ent)
{
vec3 origin = ent->origin;
return origin + getEntOffset(ent);
}

vec3 Bsp::getEntOffset(Entity* ent)
{
if (ent->isBspModel())
{
int mdl = ent->getBspModelIdx();
if (mdl >= 0 && mdl < modelCount)
{
return get_model_center(mdl);
}
}
return vec3();
}
7 changes: 6 additions & 1 deletion src/bsp/Bsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class Bsp
void create_solid_nodes(Solid& solid, BSPMODEL* targetModel);
// returns index of the solid node

int create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetModel, bool empty = false, int leafIdx = 0);
int create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetModel, bool empty = false, int leafIdx = -1);
int create_clipnode_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetModel, int targetHull = 0, bool skipEmpty = false, bool empty = false);
// copies a model from the sourceMap into this one
void add_model(Bsp* sourceMap, int modelIdx);
Expand Down Expand Up @@ -389,6 +389,8 @@ class Bsp
std::vector<vec3> get_face_verts(int faceIdx, int limited = INT_MAX);
std::vector<int> get_face_verts_idx(int faceIdx, int limited = INT_MAX);

void fix_all_duplicate_vertices();

bool is_worldspawn_ent(int entIdx);

int get_ent_from_model(int modelIdx);
Expand Down Expand Up @@ -499,6 +501,9 @@ class Bsp
std::vector<Entity*> get_model_ents(int modelIdx);
std::vector<int> get_model_ents_ids(int modelIdx);

vec3 getEntOrigin(Entity* ent);
vec3 getEntOffset(Entity* ent);

void write_csg_polys(int nodeIdx, FILE* fout, int flipPlaneSkip, bool debug);


Expand Down
46 changes: 16 additions & 30 deletions src/bsp/Keyvalue.cpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
#include "Keyvalue.h"
#include "util.h"

const std::regex Keyvalues::kv_regex("\"(.*?)\"\\s*\"(.*?)\"");

Keyvalues::Keyvalues(std::string& line)
{
keys.clear();
values.clear();
std::vector<std::string> allstrings = splitString(line, "\"");
if (allstrings.size() > 1)
{
if (allstrings[0].find('{') != std::string::npos)
{
allstrings.erase(allstrings.begin());
}
while (allstrings.size() >= 2)
{
std::string tmpkey = allstrings[0];
std::string tmpvalue = "";
if (allstrings.size() > 2)
tmpvalue = allstrings[2];
allstrings.erase(allstrings.begin());
allstrings.erase(allstrings.begin());
if (allstrings.size() > 1)
allstrings.erase(allstrings.begin());
if (allstrings.size() > 1)
allstrings.erase(allstrings.begin());
keys.push_back(tmpkey);
values.push_back(tmpvalue);
}
}
line.clear();
if (!allstrings.empty())
{
line = allstrings[allstrings.size() - 1];
}
keys.clear();
values.clear();

std::smatch matches;
std::string remaining_line = line;

while (std::regex_search(remaining_line, matches, kv_regex))
{
keys.push_back(matches[1]);
values.push_back(matches[2]);
remaining_line = matches.suffix().str();
}

line = remaining_line;
}

Keyvalues::Keyvalues(void)
Expand Down
3 changes: 3 additions & 0 deletions src/bsp/Keyvalue.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "util.h"
#include <regex>

class Keyvalues
{
Expand All @@ -11,5 +12,7 @@ class Keyvalues
Keyvalues(const std::string& key, const std::string& value);
Keyvalues(void);
~Keyvalues(void) = default;
private:
static const std::regex kv_regex;
};

118 changes: 117 additions & 1 deletion src/editor/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4516,7 +4516,7 @@ void Gui::drawMenuBar()
ImGui::EndTooltip();
}

if (ImGui::BeginMenu("Porting tools"))
if (ImGui::BeginMenu("Additional tools"))
{
if (ImGui::BeginMenu("Delete OOB Data", !app->isLoading && app->getSelectedMap() && rend))
{
Expand Down Expand Up @@ -4663,6 +4663,122 @@ void Gui::drawMenuBar()
}
IMGUI_TOOLTIP(g, "Create a point entity for use with the culling tool. 2 of these define the bounding box for structure culling operations.\n");




if (ImGui::MenuItem("Make map overlay"))
{
for (int m = map->modelCount - 1; m >= 1; m--)
{
int e = map->get_ent_from_model(m);
if (e >= 0 && !starts_with(map->ents[e]->classname, "func_wa") &&
!starts_with(map->ents[e]->classname, "func_ill"))
{
map->delete_model(m);
}
}

map->remove_faces_by_content(CONTENTS_SKY);
map->remove_faces_by_content(CONTENTS_SOLID);

for (int f = map->faceCount - 1; f >= 0; f--)
{
BSPFACE32 face = map->faces[f];

if (face.iTextureInfo >= 0)
{
BSPTEXTUREINFO texinfo = map->texinfos[face.iTextureInfo];
if (texinfo.iMiptex >= 0)
{
int texOffset = ((int*)map->textures)[texinfo.iMiptex + 1];
if (texOffset >= 0)
{
BSPMIPTEX tex = *((BSPMIPTEX*)(map->textures + texOffset));
std::string texname = toLowerCase(tex.szName);
if (starts_with(texname, "sky"))
{
map->remove_face(f);
}
}
}
}
}

map->remove_unused_model_structures();

for (int i = map->modelCount - 1; i >= 1; i--)
{
int e = map->get_ent_from_model(i);

map->duplicate_model_structures(i);
auto offset = map->ents[e]->origin;
auto verts = map->getModelVertsIds(i);
for (int v : verts)
{
map->verts[v] += offset;
}
map->remove_unused_model_structures();
}

map->remove_unused_model_structures();

map->save_undo_lightmaps();

// MAGIC! :)
map->fix_all_duplicate_vertices();

for (int f = 0; f < map->faceCount; f++)
{
auto verts = map->get_face_verts_idx(f);
vec3 plane_z_normalized = map->getPlaneFromFace(&map->faces[f]).vNormal.normalize();

for (auto v : verts)
{
map->verts[v] += plane_z_normalized * 0.15f;
}
}

map->remove_unused_model_structures();
map->resize_all_lightmaps();

rend->loadLightmaps();
rend->preRenderFaces();

BSPMODEL tmpMdl{};
tmpMdl.iFirstFace = 0;
tmpMdl.nFaces = map->faceCount;
map->get_bounding_box(tmpMdl.nMins, tmpMdl.nMaxs);

tmpMdl.vOrigin = map->models[0].vOrigin;
tmpMdl.nVisLeafs = 0;
tmpMdl.iHeadnodes[0] = tmpMdl.iHeadnodes[1] = tmpMdl.iHeadnodes[2] = tmpMdl.iHeadnodes[3] = -1;
map->replace_lump(LUMP_MODELS, &tmpMdl, sizeof(BSPMODEL));


tmpMdl.iHeadnodes[0] = map->create_node_box(map->models[0].nMins, map->models[0].nMaxs, &map->models[0], true, 0);

map->ents.erase(map->ents.begin() + 1, map->ents.end());
map->update_ent_lump();

map->remove_unused_model_structures(CLEAN_LIGHTMAP | CLEAN_PLANES | CLEAN_NODES | CLEAN_CLIPNODES | CLEAN_MARKSURFACES | CLEAN_FACES | CLEAN_SURFEDGES | CLEAN_TEXINFOS |
CLEAN_EDGES | CLEAN_VERTICES | CLEAN_TEXTURES | CLEAN_VISDATA | CLEAN_MODELS);


BSPLEAF32 tmpLeaf{};
tmpLeaf.iFirstMarkSurface = 0;
tmpLeaf.nMarkSurfaces = map->marksurfCount;
tmpLeaf.nContents = CONTENTS_EMPTY;
tmpLeaf.nVisOffset = -1;
tmpLeaf.nMins = tmpMdl.nMins;
tmpLeaf.nMaxs = tmpMdl.nMaxs;
map->replace_lump(LUMP_LEAVES, &tmpLeaf, sizeof(BSPLEAF32));


rend->pushUndoState("Create map BSP model overlay", EDIT_MODEL_LUMPS);
}

IMGUI_TOOLTIP(g, "Create overlay for every map face.\n");

ImGui::EndMenu();
}

Expand Down
Loading

0 comments on commit 37cbdb9

Please sign in to comment.