engine: reject mbf21 and shit24 wads. there is no way to know if it is safe to ignore...
[k8vavoom.git] / source / maploader / mapload_nodes_zd.cpp
blob09af9c39f9397b654b07f8e60da70240c1c9608d
1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
12 //**
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
16 //**
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
21 //**
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
24 //**
25 //**************************************************************************
26 //**
27 //** Build nodes using zdbsp.
28 //**
29 //**************************************************************************
30 #include "../gamedefs.h"
31 #include "../text.h"
33 #include "../bsp/zdbsp/nodebuild.h"
36 static inline int toFix (double val) { return (int)(val*(1<<16)); }
37 static inline float fromFix (int val) { return (float)((double)val/(double)(1<<16)); }
40 //==========================================================================
42 // UploadSectorsZD
44 //==========================================================================
45 static void UploadSectorsZD (VLevel *Level, ZDBSP::FLevel &zlvl) {
46 for (auto &&it : Level->allSectorsIdx()) {
47 ZDBSP::IntSector zsec;
48 zsec.data.special = it.value()->special;
49 zsec.data.tag = it.value()->sectorTag;
50 zsec.origindex = it.index();
51 zlvl.Sectors.Push(zsec);
56 //==========================================================================
58 // UploadSidedefsZD
60 //==========================================================================
61 static void UploadSidedefsZD (VLevel *Level, ZDBSP::FLevel &zlvl) {
62 for (auto &&it : Level->allSidesIdx()) {
63 ZDBSP::IntSideDef zside;
64 zside.sector = (!it.value()->Sector ? ZDBSP::NO_INDEX : (int)(ptrdiff_t)(it.value()->Sector-Level->Sectors));
65 zside.origindex = it.index();
66 zlvl.Sides.Push(zside);
71 //==========================================================================
73 // UploadLinedefsZD
75 //==========================================================================
76 static void UploadLinedefsZD (VLevel *Level, ZDBSP::FLevel &zlvl) {
77 int vcount = 0;
78 TArray<int> vmap; // index: in `Level->Vertexes`; value: in zlvl
79 vmap.setLength(Level->NumVertexes);
80 for (int f = 0; f < vmap.length(); ++f) vmap[f] = -1;
82 for (auto &&it : Level->allLinesIdx()) {
83 const line_t *pSrc = it.value();
84 int lv1idx = (int)(ptrdiff_t)(pSrc->v1-Level->Vertexes);
85 int lv2idx = (int)(ptrdiff_t)(pSrc->v2-Level->Vertexes);
86 if (lv1idx < 0 || lv2idx < 0 || lv1idx >= Level->NumVertexes || lv2idx >= Level->NumVertexes) Sys_Error("invalid linedef vertexes");
87 if (vmap[lv1idx] < 0) vmap[lv1idx] = vcount++;
88 if (vmap[lv2idx] < 0) vmap[lv2idx] = vcount++;
91 vassert(vcount);
92 if (vcount != Level->NumVertexes) GCon->Logf("ZDBSP: dropped %d vertices out of %d", Level->NumVertexes-vcount, Level->NumVertexes);
93 //GCon->Logf("ZDBSP: old vertex count is %d, new vertex count is %d", Level->NumVertexes, vcount);
95 // copy used vertices
96 zlvl.Vertices = new ZDBSP::WideVertex[vcount];
97 zlvl.NumVertices = vcount;
98 for (auto &&it : Level->allVerticesIdx()) {
99 int didx = vmap[it.index()];
100 if (didx >= 0) {
101 vassert(didx < vcount);
102 ZDBSP::WideVertex *zv = &zlvl.Vertices[didx];
103 zv->x = toFix(it.value()->x);
104 zv->y = toFix(it.value()->y);
105 zv->index = didx;
109 for (auto &&it : Level->allLinesIdx()) {
110 const line_t *pSrc = it.value();
111 if (!pSrc->v1 || !pSrc->v2) Sys_Error("linedef without vertexes");
113 ZDBSP::IntLineDef zline;
114 zline.origindex = it.index();
115 zline.flags = pSrc->flags;
116 zline.special = pSrc->special;
117 zline.args[0] = pSrc->arg1;
118 zline.args[1] = pSrc->arg2;
119 zline.args[2] = pSrc->arg3;
120 zline.args[3] = pSrc->arg4;
121 zline.args[4] = pSrc->arg5;
122 zline.sidenum[0] = (pSrc->sidenum[0] >= 0 ? pSrc->sidenum[0] : ZDBSP::NO_INDEX);
123 zline.sidenum[1] = (pSrc->sidenum[1] >= 0 ? pSrc->sidenum[1] : ZDBSP::NO_INDEX);
125 int lv1idx = (int)(ptrdiff_t)(pSrc->v1-Level->Vertexes);
126 int lv2idx = (int)(ptrdiff_t)(pSrc->v2-Level->Vertexes);
127 if (lv1idx < 0 || lv2idx < 0 || lv1idx >= Level->NumVertexes || lv2idx >= Level->NumVertexes) Sys_Error("invalid linedef vertexes");
128 vassert(vmap[lv1idx] >= 0);
129 vassert(vmap[lv2idx] >= 0);
130 zline.v1 = vmap[lv1idx];
131 zline.v2 = vmap[lv2idx];
133 zlvl.Lines.Push(zline);
138 //==========================================================================
140 // UploadThingsZD
142 //==========================================================================
143 static void UploadThingsZD (VLevel *Level, ZDBSP::FLevel &zlvl) {
144 for (auto &&it : Level->allThingsIdx()) {
145 const mthing_t *pSrc = it.value();
146 ZDBSP::IntThing thing;
147 thing.thingid = pSrc->tid;
148 thing.x = toFix((double)pSrc->x);
149 thing.y = toFix((double)pSrc->y);
150 thing.z = 0; //???
151 thing.angle = pSrc->angle;
152 thing.type = pSrc->type;
153 thing.flags = pSrc->options;
154 thing.special = pSrc->special;
155 thing.args[0] = pSrc->args[1-1];
156 thing.args[1] = pSrc->args[2-1];
157 thing.args[2] = pSrc->args[3-1];
158 thing.args[3] = pSrc->args[4-1];
159 thing.args[4] = pSrc->args[5-1];
160 zlvl.Things.Push(thing);
165 //==========================================================================
167 // CopyNodeZD
169 //==========================================================================
170 static void CopyNodeZD (int NodeIndex, const ZDBSP::MapNodeEx &SrcNode, node_t *Node) {
171 TVec org = TVec(fromFix(SrcNode.x), fromFix(SrcNode.y));
172 TVec dir = TVec(fromFix(SrcNode.dx), fromFix(SrcNode.dy));
173 // check if `Length()` and `SetPointDirXY()` are happy
174 if (dir.isZero2D()) {
175 GCon->Logf("ZDBSP: invalid BSP node #%d (zero direction)", NodeIndex);
176 dir.x = 0.001f;
178 Node->SetPointDirXY(org, dir);
180 // those things are used to emulate buggy vanilla "point in subsector" code
181 // they aren't used for anything else, so precision loss doesn't really matter
182 // they are in 16.16 fixed point format
183 Node->sx = SrcNode.x;
184 Node->sy = SrcNode.y;
185 Node->dx = SrcNode.dx;
186 Node->dy = SrcNode.dy;
188 Node->bbox[0][0] = SrcNode.bbox[0][ZDBSP::BOXLEFT]; // minx
189 Node->bbox[0][1] = SrcNode.bbox[0][ZDBSP::BOXBOTTOM]; // miny
190 Node->bbox[0][2] = -32768.0f;
191 Node->bbox[0][3] = SrcNode.bbox[0][ZDBSP::BOXRIGHT]; // maxx
192 Node->bbox[0][4] = SrcNode.bbox[0][ZDBSP::BOXTOP]; // maxy
193 Node->bbox[0][5] = 32768.0f;
195 Node->bbox[1][0] = SrcNode.bbox[1][ZDBSP::BOXLEFT]; // minx
196 Node->bbox[1][1] = SrcNode.bbox[1][ZDBSP::BOXBOTTOM]; // miny
197 Node->bbox[1][2] = -32768.0f;
198 Node->bbox[1][3] = SrcNode.bbox[1][ZDBSP::BOXRIGHT]; // maxx
199 Node->bbox[1][4] = SrcNode.bbox[1][ZDBSP::BOXTOP]; // maxy
200 Node->bbox[1][5] = 32768.0f;
202 Node->children[0] = SrcNode.children[0];
203 Node->children[1] = SrcNode.children[1];
207 //==========================================================================
209 // ZDProgress
211 // total==-1: complete
213 //==========================================================================
214 void ZDProgress (int curr, int total) {
215 //GCon->Logf("BSP: %d/%d", curr, total);
216 #ifdef CLIENT
217 if (total <= 0) {
218 R_PBarUpdate("BSP", 42, 42, true); // final update
219 } else {
220 R_PBarUpdate("BSP", curr, total);
222 #endif
226 //==========================================================================
228 // VLevel::BuildNodesZD
230 //==========================================================================
231 void VLevel::BuildNodesZD () {
232 ZDBSP::FLevel zlvl;
234 // set up map data from loaded data
235 UploadSectorsZD(this, zlvl);
236 UploadSidedefsZD(this, zlvl);
237 UploadLinedefsZD(this, zlvl);
238 UploadThingsZD(this, zlvl);
241 zlvl.RemoveExtraLines();
242 zlvl.RemoveExtraSides();
243 zlvl.RemoveExtraSectors();
246 zlvl.FindMapBounds();
248 auto nb = new ZDBSP::FNodeBuilder(zlvl, *MapName);
250 ZDBSP::WideVertex *newverts = nullptr;
251 int newvertsCount = 0;
252 nb->GetVertices(newverts, newvertsCount);
254 ZDBSP::MapNodeEx *nodes = nullptr;
255 int nodeCount = 0;
256 ZDBSP::MapSegGLEx *segs = nullptr;
257 int segCount = 0;
258 ZDBSP::MapSubsectorEx *ssecs = nullptr;
259 int subCount = 0;
260 nb->GetGLNodes(nodes, nodeCount, segs, segCount, ssecs, subCount);
262 delete nb;
264 GCon->Logf("added %d vertices; created %d nodes, %d segs, and %d subsectors", newvertsCount-NumVertexes, nodeCount, segCount, subCount);
266 // copy vertices
268 delete[] Vertexes;
270 NumVertexes = newvertsCount;
271 Vertexes = new TVec[newvertsCount];
272 memset((void *)Vertexes, 0, sizeof(TVec)*newvertsCount);
274 for (int vidx = 0; vidx < newvertsCount; ++vidx) {
275 Vertexes[vidx] = TVec(fromFix(newverts[vidx].x), fromFix(newverts[vidx].y), 0);
278 delete[] newverts;
281 // fix linedefs
282 vassert(NumLines == (int)zlvl.Lines.Size());
283 for (size_t f = 0; f < zlvl.Lines.Size(); ++f) {
284 const ZDBSP::IntLineDef &zline = zlvl.Lines[f];
285 line_t *nl = &Lines[f];
286 nl->v1 = &Vertexes[zline.v1];
287 nl->v2 = &Vertexes[zline.v2];
290 // copy subsectors
292 NumSubsectors = subCount;
293 delete[] Subsectors;
294 Subsectors = new subsector_t[subCount];
295 memset((void *)Subsectors, 0, sizeof(subsector_t)*subCount);
296 subsector_t *destss = &Subsectors[0];
297 for (int i = 0; i < subCount; ++i, ++destss) {
298 ZDBSP::MapSubsectorEx &srcss = ssecs[i];
299 destss->numlines = srcss.numlines;
300 destss->firstline = srcss.firstline;
302 delete[] ssecs;
305 // copy segs
307 NumSegs = segCount;
308 delete[] Segs;
309 Segs = new seg_t[segCount+NumLines*2+1];
310 memset((void *)Segs, 0, sizeof(seg_t)*(segCount+NumLines*2+1));
312 seg_t *destseg = &Segs[0];
313 for (int i = 0; i < segCount; ++i, ++destseg) {
314 const ZDBSP::MapSegGLEx &zseg = segs[i];
316 if (zseg.v1 == zseg.v2) {
317 GCon->Logf(NAME_Error, "ZDBSP: seg #%d has same vertices (%d)", i, (int)zseg.v1);
320 destseg->v1 = &Vertexes[zseg.v1];
321 destseg->v2 = &Vertexes[zseg.v2];
323 if (zseg.side != 0 && zseg.side != 1) Sys_Error("ZDBSP: invalid seg #%d side (%d)", i, zseg.side);
324 destseg->side = zseg.side;
326 if (zseg.linedef != ZDBSP::NO_INDEX) {
327 if ((int)zseg.linedef < 0 || (int)zseg.linedef >= NumLines) Sys_Error("ZDBSP: invalid seg #%d linedef (%d), max is %d", i, (int)zseg.linedef, NumLines-1);
328 destseg->linedef = &Lines[zseg.linedef];
331 destseg->partner = (zseg.partner == ZDBSP::NO_INDEX ? nullptr : &Segs[zseg.partner]);
333 delete[] segs;
336 // copy nodes
338 NumNodes = nodeCount;
339 delete[] Nodes;
340 Nodes = new node_t[NumNodes+1];
341 memset((void *)Nodes, 0, sizeof(node_t)*(NumNodes+1));
342 for (int f = 0; f < nodeCount; ++f) CopyNodeZD(f, nodes[f], &Nodes[f]);
343 delete[] nodes;
346 // clear blockmap (just in case), so it will be recreated by the engine
347 delete[] BlockMapLump;
348 BlockMapLump = nullptr;
349 BlockMapLumpSize = 0;