Skip to content

Commit 37cbdb9

Browse files
HotFix missing origin! Bugfixes! ! Added new featu
HotFix missing origin! Bugfixes! ! Added new feature : generate map overlay (for example for special effects)
1 parent 8562559 commit 37cbdb9

File tree

8 files changed

+242
-75
lines changed

8 files changed

+242
-75
lines changed

src/bsp/Bsp.cpp

+84-4
Original file line numberDiff line numberDiff line change
@@ -4535,7 +4535,7 @@ void Bsp::update_ent_lump(bool stripNodes)
45354535

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

64626462
void Bsp::print_model_hull(int modelIdx, int hull_number)
64636463
{
6464-
if (modelIdx < 0 || modelIdx > bsp_header.lump[LUMP_MODELS].nLength / (int)sizeof(BSPMODEL))
6464+
if (modelIdx < 0 || modelIdx >= modelCount)
64656465
{
64666466
print_log(PRINT_RED | PRINT_INTENSITY, get_localized_string(LANG_1024), modelIdx);
64676467
return;
@@ -8581,7 +8581,7 @@ int Bsp::create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetMod
85818581
{
85828582
int sharedSolidLeaf = 0;
85838583
int anyEmptyLeaf = leafIdx;
8584-
if (anyEmptyLeaf == 0)
8584+
if (anyEmptyLeaf == -1)
85858585
{
85868586
for (int i = 0; i < leafCount; i++)
85878587
{
@@ -8591,7 +8591,7 @@ int Bsp::create_node_box(const vec3& mins, const vec3& maxs, BSPMODEL* targetMod
85918591
break;
85928592
}
85938593
}
8594-
if (anyEmptyLeaf == 0)
8594+
if (anyEmptyLeaf == -1)
85958595
{
85968596
anyEmptyLeaf = create_leaf(CONTENTS_EMPTY);
85978597
targetModel->nVisLeafs += 1;
@@ -14803,6 +14803,67 @@ bool Bsp::is_texture_with_pal(int textureid)
1480314803
return is_texture_has_pal;
1480414804
}
1480514805

14806+
void Bsp::fix_all_duplicate_vertices()
14807+
{
14808+
std::set<int> verts_usage;
14809+
std::set<int> edges_usage;
14810+
14811+
for (int faceIdx = 0; faceIdx < faceCount; faceIdx++)
14812+
{
14813+
BSPFACE32 face = faces[faceIdx];
14814+
14815+
for (int e = face.iFirstEdge; e < face.iFirstEdge + face.nEdges; e++)
14816+
{
14817+
int edgeIdx = surfedges[e];
14818+
BSPEDGE32& edge = edges[abs(edgeIdx)];
14819+
14820+
if (edges_usage.count(abs(edgeIdx)))
14821+
{
14822+
int newedge_id = create_edge();
14823+
14824+
if (edgeIdx >= 0)
14825+
{
14826+
edgeIdx = newedge_id;
14827+
}
14828+
else
14829+
{
14830+
edgeIdx = -newedge_id;
14831+
}
14832+
14833+
BSPEDGE32& newedge = edges[newedge_id];
14834+
newedge = edge;
14835+
14836+
int v1 = create_vert();
14837+
verts[v1] = verts[edge.iVertex[0]];
14838+
newedge.iVertex[0] = v1;
14839+
14840+
int v2 = create_vert();
14841+
verts[v2] = verts[edge.iVertex[1]];
14842+
newedge.iVertex[1] = v1;
14843+
}
14844+
else
14845+
{
14846+
int vert1 = edge.iVertex[0];
14847+
int vert2 = edge.iVertex[1];
14848+
14849+
if (verts_usage.count(vert1) || verts_usage.count(vert2))
14850+
{
14851+
int v1 = create_vert();
14852+
verts[v1] = verts[vert1];
14853+
edge.iVertex[0] = v1;
14854+
int v2 = create_vert();
14855+
verts[v2] = verts[vert2];
14856+
edge.iVertex[1] = v2;
14857+
}
14858+
14859+
edges_usage.insert(abs(edgeIdx));
14860+
verts_usage.insert(vert2);
14861+
verts_usage.insert(vert1);
14862+
}
14863+
}
14864+
}
14865+
}
14866+
1480614867
void Bsp::face_fix_duplicate_edges_index(int faceIdx)
1480714868
{
1480814869
if (faceIdx < 0 || faceIdx >= faceCount)
@@ -15071,4 +15132,23 @@ int Bsp::AddTriggerTexture()
1507115132
{
1507215133
//print_log(get_localized_string(LANG_0295));
1507315134
return add_texture("aaatrigger", aaatriggerTex->get_data(), aaatriggerTex->width, aaatriggerTex->height);
15135+
}
15136+
15137+
vec3 Bsp::getEntOrigin(Entity* ent)
15138+
{
15139+
vec3 origin = ent->origin;
15140+
return origin + getEntOffset(ent);
15141+
}
15142+
15143+
vec3 Bsp::getEntOffset(Entity* ent)
15144+
{
15145+
if (ent->isBspModel())
15146+
{
15147+
int mdl = ent->getBspModelIdx();
15148+
if (mdl >= 0 && mdl < modelCount)
15149+
{
15150+
return get_model_center(mdl);
15151+
}
15152+
}
15153+
return vec3();
1507415154
}

src/bsp/Bsp.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ class Bsp
322322
void create_solid_nodes(Solid& solid, BSPMODEL* targetModel);
323323
// returns index of the solid node
324324

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

392+
void fix_all_duplicate_vertices();
393+
392394
bool is_worldspawn_ent(int entIdx);
393395

394396
int get_ent_from_model(int modelIdx);
@@ -499,6 +501,9 @@ class Bsp
499501
std::vector<Entity*> get_model_ents(int modelIdx);
500502
std::vector<int> get_model_ents_ids(int modelIdx);
501503

504+
vec3 getEntOrigin(Entity* ent);
505+
vec3 getEntOffset(Entity* ent);
506+
502507
void write_csg_polys(int nodeIdx, FILE* fout, int flipPlaneSkip, bool debug);
503508

504509

src/bsp/Keyvalue.cpp

+16-30
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,24 @@
11
#include "Keyvalue.h"
22
#include "util.h"
33

4+
const std::regex Keyvalues::kv_regex("\"(.*?)\"\\s*\"(.*?)\"");
5+
46
Keyvalues::Keyvalues(std::string& line)
57
{
6-
keys.clear();
7-
values.clear();
8-
std::vector<std::string> allstrings = splitString(line, "\"");
9-
if (allstrings.size() > 1)
10-
{
11-
if (allstrings[0].find('{') != std::string::npos)
12-
{
13-
allstrings.erase(allstrings.begin());
14-
}
15-
while (allstrings.size() >= 2)
16-
{
17-
std::string tmpkey = allstrings[0];
18-
std::string tmpvalue = "";
19-
if (allstrings.size() > 2)
20-
tmpvalue = allstrings[2];
21-
allstrings.erase(allstrings.begin());
22-
allstrings.erase(allstrings.begin());
23-
if (allstrings.size() > 1)
24-
allstrings.erase(allstrings.begin());
25-
if (allstrings.size() > 1)
26-
allstrings.erase(allstrings.begin());
27-
keys.push_back(tmpkey);
28-
values.push_back(tmpvalue);
29-
}
30-
}
31-
line.clear();
32-
if (!allstrings.empty())
33-
{
34-
line = allstrings[allstrings.size() - 1];
35-
}
8+
keys.clear();
9+
values.clear();
10+
11+
std::smatch matches;
12+
std::string remaining_line = line;
13+
14+
while (std::regex_search(remaining_line, matches, kv_regex))
15+
{
16+
keys.push_back(matches[1]);
17+
values.push_back(matches[2]);
18+
remaining_line = matches.suffix().str();
19+
}
20+
21+
line = remaining_line;
3622
}
3723

3824
Keyvalues::Keyvalues(void)

src/bsp/Keyvalue.h

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include "util.h"
3+
#include <regex>
34

45
class Keyvalues
56
{
@@ -11,5 +12,7 @@ class Keyvalues
1112
Keyvalues(const std::string& key, const std::string& value);
1213
Keyvalues(void);
1314
~Keyvalues(void) = default;
15+
private:
16+
static const std::regex kv_regex;
1417
};
1518

src/editor/Gui.cpp

+117-1
Original file line numberDiff line numberDiff line change
@@ -4516,7 +4516,7 @@ void Gui::drawMenuBar()
45164516
ImGui::EndTooltip();
45174517
}
45184518

4519-
if (ImGui::BeginMenu("Porting tools"))
4519+
if (ImGui::BeginMenu("Additional tools"))
45204520
{
45214521
if (ImGui::BeginMenu("Delete OOB Data", !app->isLoading && app->getSelectedMap() && rend))
45224522
{
@@ -4663,6 +4663,122 @@ void Gui::drawMenuBar()
46634663
}
46644664
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");
46654665

4666+
4667+
4668+
4669+
if (ImGui::MenuItem("Make map overlay"))
4670+
{
4671+
for (int m = map->modelCount - 1; m >= 1; m--)
4672+
{
4673+
int e = map->get_ent_from_model(m);
4674+
if (e >= 0 && !starts_with(map->ents[e]->classname, "func_wa") &&
4675+
!starts_with(map->ents[e]->classname, "func_ill"))
4676+
{
4677+
map->delete_model(m);
4678+
}
4679+
}
4680+
4681+
map->remove_faces_by_content(CONTENTS_SKY);
4682+
map->remove_faces_by_content(CONTENTS_SOLID);
4683+
4684+
for (int f = map->faceCount - 1; f >= 0; f--)
4685+
{
4686+
BSPFACE32 face = map->faces[f];
4687+
4688+
if (face.iTextureInfo >= 0)
4689+
{
4690+
BSPTEXTUREINFO texinfo = map->texinfos[face.iTextureInfo];
4691+
if (texinfo.iMiptex >= 0)
4692+
{
4693+
int texOffset = ((int*)map->textures)[texinfo.iMiptex + 1];
4694+
if (texOffset >= 0)
4695+
{
4696+
BSPMIPTEX tex = *((BSPMIPTEX*)(map->textures + texOffset));
4697+
std::string texname = toLowerCase(tex.szName);
4698+
if (starts_with(texname, "sky"))
4699+
{
4700+
map->remove_face(f);
4701+
}
4702+
}
4703+
}
4704+
}
4705+
}
4706+
4707+
map->remove_unused_model_structures();
4708+
4709+
for (int i = map->modelCount - 1; i >= 1; i--)
4710+
{
4711+
int e = map->get_ent_from_model(i);
4712+
4713+
map->duplicate_model_structures(i);
4714+
auto offset = map->ents[e]->origin;
4715+
auto verts = map->getModelVertsIds(i);
4716+
for (int v : verts)
4717+
{
4718+
map->verts[v] += offset;
4719+
}
4720+
map->remove_unused_model_structures();
4721+
}
4722+
4723+
map->remove_unused_model_structures();
4724+
4725+
map->save_undo_lightmaps();
4726+
4727+
// MAGIC! :)
4728+
map->fix_all_duplicate_vertices();
4729+
4730+
for (int f = 0; f < map->faceCount; f++)
4731+
{
4732+
auto verts = map->get_face_verts_idx(f);
4733+
vec3 plane_z_normalized = map->getPlaneFromFace(&map->faces[f]).vNormal.normalize();
4734+
4735+
for (auto v : verts)
4736+
{
4737+
map->verts[v] += plane_z_normalized * 0.15f;
4738+
}
4739+
}
4740+
4741+
map->remove_unused_model_structures();
4742+
map->resize_all_lightmaps();
4743+
4744+
rend->loadLightmaps();
4745+
rend->preRenderFaces();
4746+
4747+
BSPMODEL tmpMdl{};
4748+
tmpMdl.iFirstFace = 0;
4749+
tmpMdl.nFaces = map->faceCount;
4750+
map->get_bounding_box(tmpMdl.nMins, tmpMdl.nMaxs);
4751+
4752+
tmpMdl.vOrigin = map->models[0].vOrigin;
4753+
tmpMdl.nVisLeafs = 0;
4754+
tmpMdl.iHeadnodes[0] = tmpMdl.iHeadnodes[1] = tmpMdl.iHeadnodes[2] = tmpMdl.iHeadnodes[3] = -1;
4755+
map->replace_lump(LUMP_MODELS, &tmpMdl, sizeof(BSPMODEL));
4756+
4757+
4758+
tmpMdl.iHeadnodes[0] = map->create_node_box(map->models[0].nMins, map->models[0].nMaxs, &map->models[0], true, 0);
4759+
4760+
map->ents.erase(map->ents.begin() + 1, map->ents.end());
4761+
map->update_ent_lump();
4762+
4763+
map->remove_unused_model_structures(CLEAN_LIGHTMAP | CLEAN_PLANES | CLEAN_NODES | CLEAN_CLIPNODES | CLEAN_MARKSURFACES | CLEAN_FACES | CLEAN_SURFEDGES | CLEAN_TEXINFOS |
4764+
CLEAN_EDGES | CLEAN_VERTICES | CLEAN_TEXTURES | CLEAN_VISDATA | CLEAN_MODELS);
4765+
4766+
4767+
BSPLEAF32 tmpLeaf{};
4768+
tmpLeaf.iFirstMarkSurface = 0;
4769+
tmpLeaf.nMarkSurfaces = map->marksurfCount;
4770+
tmpLeaf.nContents = CONTENTS_EMPTY;
4771+
tmpLeaf.nVisOffset = -1;
4772+
tmpLeaf.nMins = tmpMdl.nMins;
4773+
tmpLeaf.nMaxs = tmpMdl.nMaxs;
4774+
map->replace_lump(LUMP_LEAVES, &tmpLeaf, sizeof(BSPLEAF32));
4775+
4776+
4777+
rend->pushUndoState("Create map BSP model overlay", EDIT_MODEL_LUMPS);
4778+
}
4779+
4780+
IMGUI_TOOLTIP(g, "Create overlay for every map face.\n");
4781+
46664782
ImGui::EndMenu();
46674783
}
46684784

0 commit comments

Comments
 (0)