mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- added support for loading DeepBSP's V4 nodes.
- disabled writing the nodes with the dumpmap command. ZDoom doesn't need the nodes to load a map and this only worked if the original map had standard nodes but trying to write out nodes loaded from any other format would have caused broken data. SVN r2285 (trunk)
This commit is contained in:
parent
64fe29bf0e
commit
da99577cbf
3 changed files with 126 additions and 31 deletions
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
// Some global defines, that configure the game.
|
// Some global defines, that configure the game.
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
|
#include "m_swap.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Map level types.
|
// Map level types.
|
||||||
|
@ -220,6 +221,13 @@ struct mapsubsector_t
|
||||||
WORD firstseg; // index of first one, segs are stored sequentially
|
WORD firstseg; // index of first one, segs are stored sequentially
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
struct mapsubsector4_t
|
||||||
|
{
|
||||||
|
WORD numsegs;
|
||||||
|
DWORD firstseg; // index of first one, segs are stored sequentially
|
||||||
|
};
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
// LineSeg, generated by splitting LineDefs
|
// LineSeg, generated by splitting LineDefs
|
||||||
// using partition lines selected by BSP builder.
|
// using partition lines selected by BSP builder.
|
||||||
|
@ -231,6 +239,22 @@ struct mapseg_t
|
||||||
WORD linedef;
|
WORD linedef;
|
||||||
SWORD side;
|
SWORD side;
|
||||||
SWORD offset;
|
SWORD offset;
|
||||||
|
|
||||||
|
int V1() { return LittleShort(v1); }
|
||||||
|
int V2() { return LittleShort(v2); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mapseg4_t
|
||||||
|
{
|
||||||
|
SDWORD v1;
|
||||||
|
SDWORD v2;
|
||||||
|
SWORD angle;
|
||||||
|
WORD linedef;
|
||||||
|
SWORD side;
|
||||||
|
SWORD offset;
|
||||||
|
|
||||||
|
int V1() { return LittleLong(v1); }
|
||||||
|
int V2() { return LittleLong(v2); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,18 +262,40 @@ struct mapseg_t
|
||||||
// BSP node structure.
|
// BSP node structure.
|
||||||
|
|
||||||
// Indicate a leaf.
|
// Indicate a leaf.
|
||||||
#define NF_SUBSECTOR 0x8000
|
|
||||||
|
|
||||||
struct mapnode_t
|
struct mapnode_t
|
||||||
{
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NF_SUBSECTOR = 0x8000,
|
||||||
|
NF_LUMPOFFSET = 0
|
||||||
|
};
|
||||||
SWORD x,y,dx,dy; // partition line
|
SWORD x,y,dx,dy; // partition line
|
||||||
SWORD bbox[2][4]; // bounding box for each child
|
SWORD bbox[2][4]; // bounding box for each child
|
||||||
// If NF_SUBSECTOR is or'ed in, it's a subsector,
|
// If NF_SUBSECTOR is or'ed in, it's a subsector,
|
||||||
// else it's a node of another subtree.
|
// else it's a node of another subtree.
|
||||||
WORD children[2];
|
WORD children[2];
|
||||||
|
|
||||||
|
DWORD Child(int num) { return LittleShort(children[num]); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct mapnode4_t
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NF_SUBSECTOR = 0x80000000,
|
||||||
|
NF_LUMPOFFSET = 8
|
||||||
|
};
|
||||||
|
SWORD x,y,dx,dy; // partition line
|
||||||
|
SWORD bbox[2][4]; // bounding box for each child
|
||||||
|
// If NF_SUBSECTOR is or'ed in, it's a subsector,
|
||||||
|
// else it's a node of another subtree.
|
||||||
|
DWORD children[2];
|
||||||
|
|
||||||
|
DWORD Child(int num) { return LittleLong(children[num]); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Thing definition, position, orientation and type,
|
// Thing definition, position, orientation and type,
|
||||||
|
|
|
@ -1029,6 +1029,22 @@ static void P_LoadZNodes (FileReader &dalump, DWORD id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// P_CheckV4Nodes
|
||||||
|
// http://www.sbsoftware.com/files/DeePBSPV4specs.txt
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
static bool P_CheckV4Nodes(MapData *map)
|
||||||
|
{
|
||||||
|
char header[8];
|
||||||
|
|
||||||
|
map->Read(ML_NODES, header, 8);
|
||||||
|
return !memcmp(header, "xNd4\0\0\0\0", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// P_LoadSegs
|
// P_LoadSegs
|
||||||
|
@ -1037,6 +1053,7 @@ static void P_LoadZNodes (FileReader &dalump, DWORD id)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
template<class segtype>
|
||||||
void P_LoadSegs (MapData * map)
|
void P_LoadSegs (MapData * map)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1053,7 +1070,7 @@ void P_LoadSegs (MapData * map)
|
||||||
|
|
||||||
memset (vertchanged,0,numvertexes); // phares 10/4/98
|
memset (vertchanged,0,numvertexes); // phares 10/4/98
|
||||||
|
|
||||||
numsegs = lumplen / sizeof(mapseg_t);
|
numsegs = lumplen / sizeof(segtype);
|
||||||
|
|
||||||
if (numsegs == 0)
|
if (numsegs == 0)
|
||||||
{
|
{
|
||||||
|
@ -1086,13 +1103,13 @@ void P_LoadSegs (MapData * map)
|
||||||
for (i = 0; i < numsegs; i++)
|
for (i = 0; i < numsegs; i++)
|
||||||
{
|
{
|
||||||
seg_t *li = segs + i;
|
seg_t *li = segs + i;
|
||||||
mapseg_t *ml = (mapseg_t *) data + i;
|
segtype *ml = ((segtype *) data) + i;
|
||||||
|
|
||||||
int side, linedef;
|
int side, linedef;
|
||||||
line_t *ldef;
|
line_t *ldef;
|
||||||
|
|
||||||
vnum1 = LittleShort(ml->v1);
|
vnum1 = ml->V1();
|
||||||
vnum2 = LittleShort(ml->v2);
|
vnum2 = ml->V2();
|
||||||
|
|
||||||
if (vnum1 >= numvertexes || vnum2 >= numvertexes)
|
if (vnum1 >= numvertexes || vnum2 >= numvertexes)
|
||||||
{
|
{
|
||||||
|
@ -1222,12 +1239,13 @@ void P_LoadSegs (MapData * map)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
template<class subsectortype, class segtype>
|
||||||
void P_LoadSubsectors (MapData * map)
|
void P_LoadSubsectors (MapData * map)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
DWORD maxseg = map->Size(ML_SEGS) / sizeof(mapseg_t);
|
DWORD maxseg = map->Size(ML_SEGS) / sizeof(segtype);
|
||||||
|
|
||||||
numsubsectors = map->MapLumps[ML_SSECTORS].Size / sizeof(mapsubsector_t);
|
numsubsectors = map->MapLumps[ML_SSECTORS].Size / sizeof(subsectortype);
|
||||||
|
|
||||||
if (numsubsectors == 0 || maxseg == 0 )
|
if (numsubsectors == 0 || maxseg == 0 )
|
||||||
{
|
{
|
||||||
|
@ -1244,11 +1262,11 @@ void P_LoadSubsectors (MapData * map)
|
||||||
|
|
||||||
for (i = 0; i < numsubsectors; i++)
|
for (i = 0; i < numsubsectors; i++)
|
||||||
{
|
{
|
||||||
WORD numsegs, firstseg;
|
subsectortype subd;
|
||||||
|
|
||||||
(*map->file) >> numsegs >> firstseg;
|
(*map->file) >> subd.numsegs >> subd.firstseg;
|
||||||
|
|
||||||
if (numsegs == 0)
|
if (subd.numsegs == 0)
|
||||||
{
|
{
|
||||||
Printf ("Subsector %i is empty.\n", i);
|
Printf ("Subsector %i is empty.\n", i);
|
||||||
delete[] subsectors;
|
delete[] subsectors;
|
||||||
|
@ -1257,8 +1275,8 @@ void P_LoadSubsectors (MapData * map)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subsectors[i].numlines = numsegs;
|
subsectors[i].numlines = subd.numsegs;
|
||||||
subsectors[i].firstline = firstseg;
|
subsectors[i].firstline = subd.firstseg;
|
||||||
|
|
||||||
if (subsectors[i].firstline >= maxseg)
|
if (subsectors[i].firstline >= maxseg)
|
||||||
{
|
{
|
||||||
|
@ -1390,6 +1408,7 @@ void P_LoadSectors (MapData * map)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
template<class nodetype, class subsectortype>
|
||||||
void P_LoadNodes (MapData * map)
|
void P_LoadNodes (MapData * map)
|
||||||
{
|
{
|
||||||
FMemLump data;
|
FMemLump data;
|
||||||
|
@ -1397,13 +1416,13 @@ void P_LoadNodes (MapData * map)
|
||||||
int j;
|
int j;
|
||||||
int k;
|
int k;
|
||||||
char *mnp;
|
char *mnp;
|
||||||
mapnode_t *mn;
|
nodetype *mn;
|
||||||
node_t* no;
|
node_t* no;
|
||||||
WORD* used;
|
WORD* used;
|
||||||
int lumplen = map->Size(ML_NODES);
|
int lumplen = map->Size(ML_NODES);
|
||||||
int maxss = map->Size(ML_SSECTORS) / sizeof(mapsubsector_t);
|
int maxss = map->Size(ML_SSECTORS) / sizeof(subsectortype);
|
||||||
|
|
||||||
numnodes = lumplen / sizeof(mapnode_t);
|
numnodes = (lumplen - nodetype::NF_LUMPOFFSET) / sizeof(nodetype);
|
||||||
|
|
||||||
if ((numnodes == 0 && maxss != 1) || maxss == 0)
|
if ((numnodes == 0 && maxss != 1) || maxss == 0)
|
||||||
{
|
{
|
||||||
|
@ -1416,8 +1435,8 @@ void P_LoadNodes (MapData * map)
|
||||||
memset (used, 0, sizeof(WORD)*numnodes);
|
memset (used, 0, sizeof(WORD)*numnodes);
|
||||||
|
|
||||||
mnp = new char[lumplen];
|
mnp = new char[lumplen];
|
||||||
mn = (mapnode_t*)mnp;
|
mn = (nodetype*)(mnp + nodetype::NF_LUMPOFFSET);
|
||||||
map->Read(ML_NODES, mn);
|
map->Read(ML_NODES, mnp);
|
||||||
no = nodes;
|
no = nodes;
|
||||||
|
|
||||||
for (i = 0; i < numnodes; i++, no++, mn++)
|
for (i = 0; i < numnodes; i++, no++, mn++)
|
||||||
|
@ -1428,10 +1447,10 @@ void P_LoadNodes (MapData * map)
|
||||||
no->dy = LittleShort(mn->dy)<<FRACBITS;
|
no->dy = LittleShort(mn->dy)<<FRACBITS;
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
WORD child = LittleShort(mn->children[j]);
|
int child = mn->Child(j);
|
||||||
if (child & NF_SUBSECTOR)
|
if (child & nodetype::NF_SUBSECTOR)
|
||||||
{
|
{
|
||||||
child &= ~NF_SUBSECTOR;
|
child &= ~nodetype::NF_SUBSECTOR;
|
||||||
if (child >= maxss)
|
if (child >= maxss)
|
||||||
{
|
{
|
||||||
Printf ("BSP node %d references invalid subsector %d.\n"
|
Printf ("BSP node %d references invalid subsector %d.\n"
|
||||||
|
@ -3589,19 +3608,36 @@ void P_SetupLevel (char *lumpname, int position)
|
||||||
// If all 3 node related lumps are empty there's no need to output a message.
|
// If all 3 node related lumps are empty there's no need to output a message.
|
||||||
// This just means that the map has no nodes and the engine is supposed to build them.
|
// This just means that the map has no nodes and the engine is supposed to build them.
|
||||||
if (map->Size(ML_SEGS) != 0 || map->Size(ML_SSECTORS) != 0 || map->Size(ML_NODES) != 0)
|
if (map->Size(ML_SEGS) != 0 || map->Size(ML_SSECTORS) != 0 || map->Size(ML_NODES) != 0)
|
||||||
|
{
|
||||||
|
if (!P_CheckV4Nodes(map))
|
||||||
{
|
{
|
||||||
times[7].Clock();
|
times[7].Clock();
|
||||||
P_LoadSubsectors (map);
|
P_LoadSubsectors<mapsubsector_t, mapseg_t> (map);
|
||||||
times[7].Unclock();
|
times[7].Unclock();
|
||||||
|
|
||||||
times[8].Clock();
|
times[8].Clock();
|
||||||
if (!ForceNodeBuild) P_LoadNodes (map);
|
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t> (map);
|
||||||
times[8].Unclock();
|
times[8].Unclock();
|
||||||
|
|
||||||
times[9].Clock();
|
times[9].Clock();
|
||||||
if (!ForceNodeBuild) P_LoadSegs (map);
|
if (!ForceNodeBuild) P_LoadSegs<mapseg_t> (map);
|
||||||
times[9].Unclock();
|
times[9].Unclock();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
times[7].Clock();
|
||||||
|
P_LoadSubsectors<mapsubsector4_t, mapseg4_t> (map);
|
||||||
|
times[7].Unclock();
|
||||||
|
|
||||||
|
times[8].Clock();
|
||||||
|
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t> (map);
|
||||||
|
times[8].Unclock();
|
||||||
|
|
||||||
|
times[9].Clock();
|
||||||
|
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t> (map);
|
||||||
|
times[9].Unclock();
|
||||||
|
}
|
||||||
|
}
|
||||||
else ForceNodeBuild = true;
|
else ForceNodeBuild = true;
|
||||||
}
|
}
|
||||||
else ForceNodeBuild = true;
|
else ForceNodeBuild = true;
|
||||||
|
|
|
@ -172,8 +172,10 @@ static int WriteVERTEXES (FILE *file)
|
||||||
return numvertexes * sizeof(mv);
|
return numvertexes * sizeof(mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int WriteSEGS (FILE *file)
|
static int WriteSEGS (FILE *file)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
mapseg_t ms;
|
mapseg_t ms;
|
||||||
|
|
||||||
ms.offset = 0; // unused by ZDoom, so just leave it 0
|
ms.offset = 0; // unused by ZDoom, so just leave it 0
|
||||||
|
@ -190,10 +192,14 @@ static int WriteSEGS (FILE *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return numsegs * sizeof(ms);
|
return numsegs * sizeof(ms);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteSSECTORS (FILE *file)
|
static int WriteSSECTORS (FILE *file)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
mapsubsector_t mss;
|
mapsubsector_t mss;
|
||||||
|
|
||||||
for (int i = 0; i < numsubsectors; ++i)
|
for (int i = 0; i < numsubsectors; ++i)
|
||||||
|
@ -203,10 +209,14 @@ static int WriteSSECTORS (FILE *file)
|
||||||
fwrite (&mss, sizeof(mss), 1, file);
|
fwrite (&mss, sizeof(mss), 1, file);
|
||||||
}
|
}
|
||||||
return numsubsectors * sizeof(mss);
|
return numsubsectors * sizeof(mss);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteNODES (FILE *file)
|
static int WriteNODES (FILE *file)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
mapnode_t mn;
|
mapnode_t mn;
|
||||||
|
|
||||||
for (int i = 0; i < numnodes; ++i)
|
for (int i = 0; i < numnodes; ++i)
|
||||||
|
@ -224,7 +234,7 @@ static int WriteNODES (FILE *file)
|
||||||
WORD child;
|
WORD child;
|
||||||
if ((size_t)nodes[i].children[j] & 1)
|
if ((size_t)nodes[i].children[j] & 1)
|
||||||
{
|
{
|
||||||
child = NF_SUBSECTOR | WORD((subsector_t *)((BYTE *)nodes[i].children[j] - 1) - subsectors);
|
child = mapnode_t::NF_SUBSECTOR | WORD((subsector_t *)((BYTE *)nodes[i].children[j] - 1) - subsectors);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -235,6 +245,9 @@ static int WriteNODES (FILE *file)
|
||||||
fwrite (&mn, sizeof(mn), 1, file);
|
fwrite (&mn, sizeof(mn), 1, file);
|
||||||
}
|
}
|
||||||
return numnodes * sizeof(mn);
|
return numnodes * sizeof(mn);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteSECTORS (FILE *file)
|
static int WriteSECTORS (FILE *file)
|
||||||
|
|
Loading…
Reference in a new issue