1 //**************************************************************************
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
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.
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.
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/>.
25 //**************************************************************************
27 //** Build nodes using zdbsp.
29 //**************************************************************************
30 #include "../gamedefs.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 //==========================================================================
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 //==========================================================================
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 //==========================================================================
75 //==========================================================================
76 static void UploadLinedefsZD (VLevel
*Level
, ZDBSP::FLevel
&zlvl
) {
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
++;
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);
96 zlvl
.Vertices
= new ZDBSP::WideVertex
[vcount
];
97 zlvl
.NumVertices
= vcount
;
98 for (auto &&it
: Level
->allVerticesIdx()) {
99 int didx
= vmap
[it
.index()];
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
);
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 //==========================================================================
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
);
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 //==========================================================================
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
);
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 //==========================================================================
211 // total==-1: complete
213 //==========================================================================
214 void ZDProgress (int curr
, int total
) {
215 //GCon->Logf("BSP: %d/%d", curr, total);
218 R_PBarUpdate("BSP", 42, 42, true); // final update
220 R_PBarUpdate("BSP", curr
, total
);
226 //==========================================================================
228 // VLevel::BuildNodesZD
230 //==========================================================================
231 void VLevel::BuildNodesZD () {
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;
256 ZDBSP::MapSegGLEx
*segs
= nullptr;
258 ZDBSP::MapSubsectorEx
*ssecs
= nullptr;
260 nb
->GetGLNodes(nodes
, nodeCount
, segs
, segCount
, ssecs
, subCount
);
264 GCon
->Logf("added %d vertices; created %d nodes, %d segs, and %d subsectors", newvertsCount
-NumVertexes
, nodeCount
, segCount
, subCount
);
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);
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
];
292 NumSubsectors
= subCount
;
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
;
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
]);
338 NumNodes
= nodeCount
;
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
]);
346 // clear blockmap (just in case), so it will be recreated by the engine
347 delete[] BlockMapLump
;
348 BlockMapLump
= nullptr;
349 BlockMapLumpSize
= 0;