From 484737bb66cc927a4fc7e3aac2c91073c0d859e6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 27 Oct 2018 11:34:18 +0200 Subject: [PATCH] - add back support for writing a level --- src/level/level.cpp | 1038 +++++++++++++++++++++++++++++++++++--- src/level/level.h | 92 +++- src/level/level_udmf.cpp | 227 ++++++++- src/main.cpp | 31 +- 4 files changed, 1275 insertions(+), 113 deletions(-) diff --git a/src/level/level.cpp b/src/level/level.cpp index 5b0156e..8673680 100644 --- a/src/level/level.cpp +++ b/src/level/level.cpp @@ -24,8 +24,6 @@ extern void ShowView (FLevel *level); -int SSELevel = 2; - enum { // Thing numbers used in Hexen maps @@ -47,6 +45,7 @@ FLevel::FLevel () FLevel::~FLevel () { + CleanupThingLights(); if (Vertices) delete[] Vertices; if (Subsectors) delete[] Subsectors; if (Segs) delete[] Segs; @@ -60,7 +59,7 @@ FLevel::~FLevel () if (OrgSectorMap) delete[] OrgSectorMap; } -FLevelLoader::FLevelLoader (FWadReader &inwad, int lump) +FProcessor::FProcessor (FWadReader &inwad, int lump) : Wad (inwad), Lump (lump) { @@ -103,7 +102,7 @@ FLevelLoader::FLevelLoader (FWadReader &inwad, int lump) } } -void FLevelLoader::LoadThings () +void FProcessor::LoadThings () { int NumThings; @@ -156,7 +155,7 @@ void FLevelLoader::LoadThings () } } -void FLevelLoader::LoadLines () +void FProcessor::LoadLines () { int NumLines; @@ -210,7 +209,7 @@ void FLevelLoader::LoadLines () } } -void FLevelLoader::LoadVertices () +void FProcessor::LoadVertices () { MapVertex *verts; ReadMapLump (Wad, "VERTEXES", Lump, verts, Level.NumVertices); @@ -225,7 +224,7 @@ void FLevelLoader::LoadVertices () } } -void FLevelLoader::LoadSides () +void FProcessor::LoadSides () { MapSideDef *Sides; int NumSides; @@ -246,7 +245,7 @@ void FLevelLoader::LoadSides () delete [] Sides; } -void FLevelLoader::LoadSectors () +void FProcessor::LoadSectors () { MapSector *Sectors; int NumSectors; @@ -455,7 +454,7 @@ void FLevel::RemoveExtraSectors () delete[] remap; } -void FLevelLoader::GetPolySpots () +void FProcessor::GetPolySpots () { if (Extended && CheckPolyobjs) { @@ -508,62 +507,160 @@ void FLevelLoader::GetPolySpots () } } -void FLevelLoader::BuildNodes() +void FProcessor::BuildNodes() { - if (Level.NumLines() == 0 || Level.NumSides() == 0 || Level.NumSectors() == 0 || Level.NumVertices == 0) - return; + NodesBuilt = true; - std::unique_ptr builder; + FNodeBuilder *builder = NULL; - builder.reset(new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), true/*BuildGLNodes*/)); - - delete[] Level.Vertices; - builder->GetVertices (Level.Vertices, Level.NumVertices); - - //if (ConformNodes) + // ZDoom's UDMF spec requires compressed GL nodes. + // No other UDMF spec has defined anything regarding nodes yet. + if (isUDMF) { - // When the nodes are "conformed", the normal and GL nodes use the same - // basic information. This creates normal nodes that are less "good" than - // possible, but it makes it easier to compare the two sets of nodes to - // determine the correctness of the GL nodes. - builder->GetNodes (Level.Nodes, Level.NumNodes, - Level.Segs, Level.NumSegs, - Level.Subsectors, Level.NumSubsectors); - builder->GetVertices (Level.GLVertices, Level.NumGLVertices); - builder->GetGLNodes (Level.GLNodes, Level.NumGLNodes, - Level.GLSegs, Level.NumGLSegs, - Level.GLSubsectors, Level.NumGLSubsectors); + BuildGLNodes = true; + ConformNodes = false; + GLOnly = true; + CompressGLNodes = true; } - /*else - { - if (BuildGLNodes) - { - builder->GetVertices (Level.GLVertices, Level.NumGLVertices); - builder->GetGLNodes (Level.GLNodes, Level.NumGLNodes, - Level.GLSegs, Level.NumGLSegs, - Level.GLSubsectors, Level.NumGLSubsectors); + try + { + if (HaveSSE2) + { + SSELevel = 2; + } + else if (HaveSSE1) + { + SSELevel = 1; + } + else + { + SSELevel = 0; + } + builder = new FNodeBuilder(Level, PolyStarts, PolyAnchors, Wad.LumpName(Lump), BuildGLNodes); + if (builder == NULL) + { + throw std::runtime_error(" Not enough memory to build nodes!"); + } + + delete[] Level.Vertices; + builder->GetVertices(Level.Vertices, Level.NumVertices); + + if (ConformNodes) + { + // When the nodes are "conformed", the normal and GL nodes use the same + // basic information. This creates normal nodes that are less "good" than + // possible, but it makes it easier to compare the two sets of nodes to + // determine the correctness of the GL nodes. + builder->GetNodes(Level.Nodes, Level.NumNodes, Level.Segs, Level.NumSegs, Level.Subsectors, Level.NumSubsectors); + builder->GetVertices(Level.GLVertices, Level.NumGLVertices); + builder->GetGLNodes(Level.GLNodes, Level.NumGLNodes, Level.GLSegs, Level.NumGLSegs, Level.GLSubsectors, Level.NumGLSubsectors); + } + else + { + if (BuildGLNodes) + { + builder->GetVertices(Level.GLVertices, Level.NumGLVertices); + builder->GetGLNodes(Level.GLNodes, Level.NumGLNodes, Level.GLSegs, Level.NumGLSegs, Level.GLSubsectors, Level.NumGLSubsectors); + + if (!GLOnly) + { + // Now repeat the process to obtain regular nodes + delete builder; + builder = new FNodeBuilder(Level, PolyStarts, PolyAnchors, Wad.LumpName(Lump), false); + if (builder == NULL) + { + throw std::runtime_error(" Not enough memory to build regular nodes!"); + } + delete[] Level.Vertices; + builder->GetVertices(Level.Vertices, Level.NumVertices); + } + } if (!GLOnly) { - // Now repeat the process to obtain regular nodes - builder.reset(); - builder.reset(new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), false)); - if (builder == nullptr) - { - throw std::runtime_error(" Not enough memory to build regular nodes!"); - } - delete[] Level.Vertices; - builder->GetVertices (Level.Vertices, Level.NumVertices); + builder->GetNodes(Level.Nodes, Level.NumNodes, Level.Segs, Level.NumSegs, Level.Subsectors, Level.NumSubsectors); } } - if (!GLOnly) + delete builder; + builder = NULL; + } + catch (...) + { + if (builder != NULL) { - builder->GetNodes (Level.Nodes, Level.NumNodes, - Level.Segs, Level.NumSegs, - Level.Subsectors, Level.NumSubsectors); + delete builder; } - }*/ - builder.reset(); + throw; + } +} + +void FProcessor::BuildLightmaps(const char *configFile) +{ + Level.ParseConfigFile(configFile); + Level.SetupDlight(); + Surface_AllocateFromMap(Level); + Level.CreateLights(); + + LMBuilder.CreateLightmaps(Level); + + LMBuilder.WriteTexturesToTGA(); + LMBuilder.WriteMeshToOBJ(); + + LightmapsBuilt = true; +} + +void FProcessor::Write (FWadWriter &out) +{ + if (Level.NumLines() == 0 || Level.NumSides() == 0 || Level.NumSectors() == 0 || Level.NumVertices == 0) + { + if (!isUDMF) + { + // Map is empty, so just copy it as-is + out.CopyLump (Wad, Lump); + out.CopyLump (Wad, Wad.FindMapLump ("THINGS", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("LINEDEFS", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("SIDEDEFS", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("VERTEXES", Lump)); + out.CreateLabel ("SEGS"); + out.CreateLabel ("SSECTORS"); + out.CreateLabel ("NODES"); + out.CopyLump (Wad, Wad.FindMapLump ("SECTORS", Lump)); + out.CreateLabel ("REJECT"); + out.CreateLabel ("BLOCKMAP"); + if (Extended) + { + out.CopyLump (Wad, Wad.FindMapLump ("BEHAVIOR", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("SCRIPTS", Lump)); + } + } + else + { + for(int i=Lump; stricmp(Wad.LumpName(i), "ENDMAP") && i < Wad.NumLumps(); i++) + { + out.CopyLump(Wad, i); + } + out.CreateLabel("ENDMAP"); + } + return; + } + + bool compress, compressGL, gl5 = false; + +#ifdef BLOCK_TEST + int size; + BYTE *blockmap; + ReadLump (Wad, Wad.FindMapLump ("BLOCKMAP", Lump), blockmap, size); + if (blockmap) + { + FILE *f = fopen ("blockmap.lmp", "wb"); + if (f) + { + fwrite (blockmap, 1, size, f); + fclose (f); + } + delete[] blockmap; + } +#endif if (!isUDMF) { @@ -573,7 +670,7 @@ void FLevelLoader::BuildNodes() memcpy (Level.Blockmap, blocks, Level.BlockmapSize*sizeof(WORD)); Level.RejectSize = (Level.NumSectors()*Level.NumSectors() + 7) / 8; - Level.Reject = nullptr; + Level.Reject = NULL; switch (RejectMode) { @@ -594,7 +691,7 @@ void FLevelLoader::BuildNodes() { // If the reject is the wrong size, don't use it. delete[] Level.Reject; - Level.Reject = nullptr; + Level.Reject = NULL; if (Level.RejectSize != 0) { // Do not warn about 0-length rejects printf (" REJECT is the wrong size, so it will be removed.\n"); @@ -623,18 +720,112 @@ void FLevelLoader::BuildNodes() } } - if (ShowMap) + if (!isUDMF) { -#ifndef NO_MAP_VIEWER - ShowView (&Level); -#else - puts (" This version of ZDRay was not compiled with the viewer enabled."); -#endif + + if (Level.GLNodes != NULL ) + { + gl5 = V5GLNodes || + (Level.NumGLVertices > 32767) || + (Level.NumGLSegs > 65534) || + (Level.NumGLNodes > 32767) || + (Level.NumGLSubsectors > 32767); + compressGL = CompressGLNodes || (Level.NumVertices > 32767); + } + else + { + compressGL = false; + } + + // If the GL nodes are compressed, then the regular nodes must also be compressed. + compress = CompressNodes || compressGL || + (Level.NumVertices > 65535) || + (Level.NumSegs > 65535) || + (Level.NumSubsectors > 32767) || + (Level.NumNodes > 32767); + + out.CopyLump (Wad, Lump); + out.CopyLump (Wad, Wad.FindMapLump ("THINGS", Lump)); + WriteLines (out); + WriteSides (out); + WriteVertices (out, compress || GLOnly ? Level.NumOrgVerts : Level.NumVertices); + if (NodesBuilt) + { + if (!compress) + { + if (!GLOnly) + { + WriteSegs (out); + WriteSSectors (out); + WriteNodes (out); + } + else + { + out.CreateLabel ("SEGS"); + out.CreateLabel ("SSECTORS"); + out.CreateLabel ("NODES"); + } + } + else + { + out.CreateLabel ("SEGS"); + if (compressGL) + { + if (ForceCompression) WriteGLBSPZ (out, "SSECTORS"); + else WriteGLBSPX (out, "SSECTORS"); + } + else + { + out.CreateLabel ("SSECTORS"); + } + if (!GLOnly) + { + if (ForceCompression) WriteBSPZ (out, "NODES"); + else WriteBSPX (out, "NODES"); + } + else + { + out.CreateLabel ("NODES"); + } + } + } + else + { + out.CopyLump (Wad, Wad.FindMapLump ("SEGS", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("SSECTORS", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("NODES", Lump)); + } + WriteSectors (out); + WriteReject (out); + WriteBlockmap (out); + if (Extended) + { + out.CopyLump (Wad, Wad.FindMapLump ("BEHAVIOR", Lump)); + out.CopyLump (Wad, Wad.FindMapLump ("SCRIPTS", Lump)); + } + if (Level.GLNodes != NULL && !compressGL) + { + char glname[9]; + glname[0] = 'G'; + glname[1] = 'L'; + glname[2] = '_'; + glname[8] = 0; + strncpy (glname+3, Wad.LumpName (Lump), 5); + out.CreateLabel (glname); + WriteGLVertices (out, gl5); + WriteGLSegs (out, gl5); + WriteGLSSect (out, gl5); + WriteGLNodes (out, gl5); + } + } + else + { + WriteUDMF(out); } } // -BYTE *FLevelLoader::FixReject (const BYTE *oldreject) +BYTE *FProcessor::FixReject (const BYTE *oldreject) { int x, y, ox, oy, pnum, opnum; int rejectSize = (Level.NumSectors()*Level.NumSectors() + 7) / 8; @@ -660,11 +851,11 @@ BYTE *FLevelLoader::FixReject (const BYTE *oldreject) return newreject; } -MapNodeEx *FLevelLoader::NodesToEx (const MapNode *nodes, int count) +MapNodeEx *FProcessor::NodesToEx (const MapNode *nodes, int count) { if (count == 0) { - return nullptr; + return NULL; } MapNodeEx *Nodes = new MapNodeEx[Level.NumNodes]; @@ -695,11 +886,11 @@ MapNodeEx *FLevelLoader::NodesToEx (const MapNode *nodes, int count) return Nodes; } -MapSubsectorEx *FLevelLoader::SubsectorsToEx (const MapSubsector *ssec, int count) +MapSubsectorEx *FProcessor::SubsectorsToEx (const MapSubsector *ssec, int count) { if (count == 0) { - return nullptr; + return NULL; } MapSubsectorEx *out = new MapSubsectorEx[Level.NumSubsectors]; @@ -714,11 +905,11 @@ MapSubsectorEx *FLevelLoader::SubsectorsToEx (const MapSubsector *ssec, int coun return out; } -MapSegGLEx *FLevelLoader::SegGLsToEx (const MapSegGL *segs, int count) +MapSegGLEx *FProcessor::SegGLsToEx (const MapSegGL *segs, int count) { if (count == 0) { - return nullptr; + return NULL; } MapSegGLEx *out = new MapSegGLEx[count]; @@ -736,7 +927,716 @@ MapSegGLEx *FLevelLoader::SegGLsToEx (const MapSegGL *segs, int count) return out; } -bool FLevelLoader::CheckForFracSplitters(const MapNodeEx *nodes, int numnodes) +void FProcessor::WriteVertices (FWadWriter &out, int count) +{ + int i; + WideVertex *vertdata = Level.Vertices; + + short *verts = new short[count * 2]; + + for (i = 0; i < count; ++i) + { + verts[i*2] = LittleShort(vertdata[i].x >> FRACBITS); + verts[i*2+1] = LittleShort(vertdata[i].y >> FRACBITS); + } + out.WriteLump ("VERTEXES", verts, sizeof(*verts)*count*2); + delete[] verts; + + if (count >= 32768) + { + printf (" VERTEXES is past the normal limit. (%d vertices)\n", count); + } +} + +void FProcessor::WriteLines (FWadWriter &out) +{ + int i; + + if (Extended) + { + MapLineDef2 *Lines = new MapLineDef2[Level.NumLines()]; + for (i = 0; i < Level.NumLines(); ++i) + { + Lines[i].special = Level.Lines[i].special; + Lines[i].args[0] = Level.Lines[i].args[0]; + Lines[i].args[1] = Level.Lines[i].args[1]; + Lines[i].args[2] = Level.Lines[i].args[2]; + Lines[i].args[3] = Level.Lines[i].args[3]; + Lines[i].args[4] = Level.Lines[i].args[4]; + Lines[i].v1 = LittleShort(WORD(Level.Lines[i].v1)); + Lines[i].v2 = LittleShort(WORD(Level.Lines[i].v2)); + Lines[i].flags = LittleShort(WORD(Level.Lines[i].flags)); + Lines[i].sidenum[0] = LittleShort(WORD(Level.Lines[i].sidenum[0])); + Lines[i].sidenum[1] = LittleShort(WORD(Level.Lines[i].sidenum[1])); + } + out.WriteLump ("LINEDEFS", Lines, Level.NumLines()*sizeof(*Lines)); + delete[] Lines; + } + else + { + MapLineDef *ld = new MapLineDef[Level.NumLines()]; + + for (i = 0; i < Level.NumLines(); ++i) + { + ld[i].v1 = LittleShort(WORD(Level.Lines[i].v1)); + ld[i].v2 = LittleShort(WORD(Level.Lines[i].v2)); + ld[i].flags = LittleShort(WORD(Level.Lines[i].flags)); + ld[i].sidenum[0] = LittleShort(WORD(Level.Lines[i].sidenum[0])); + ld[i].sidenum[1] = LittleShort(WORD(Level.Lines[i].sidenum[1])); + ld[i].special = LittleShort(WORD(Level.Lines[i].args[0])); + ld[i].tag = LittleShort(WORD(Level.Lines[i].args[1])); + } + out.WriteLump ("LINEDEFS", ld, Level.NumLines()*sizeof(*ld)); + delete[] ld; + } +} + +void FProcessor::WriteSides (FWadWriter &out) +{ + int i; + MapSideDef *Sides = new MapSideDef[Level.NumSides()]; + + for (i = 0; i < Level.NumSides(); ++i) + { + Sides[i].textureoffset = Level.Sides[i].textureoffset; + Sides[i].rowoffset = Level.Sides[i].rowoffset; + memcpy(Sides[i].toptexture, Level.Sides[i].toptexture, 8); + memcpy(Sides[i].bottomtexture, Level.Sides[i].bottomtexture, 8); + memcpy(Sides[i].midtexture, Level.Sides[i].midtexture, 8); + Sides[i].sector = LittleShort(Level.Sides[i].sector); + } + out.WriteLump ("SIDEDEFS", Sides, Level.NumSides()*sizeof(*Sides)); + delete[] Sides; +} + +void FProcessor::WriteSectors (FWadWriter &out) +{ + int i; + MapSector *Sectors = new MapSector[Level.NumSectors()]; + + for (i = 0; i < Level.NumSectors(); ++i) + { + Sectors[i] = Level.Sectors[i].data; + } + + out.WriteLump ("SECTORS", Sectors, Level.NumSectors()*sizeof(*Sectors)); +} + +void FProcessor::WriteSegs (FWadWriter &out) +{ + int i; + MapSeg *segdata; + + assert(Level.NumVertices < 65536); + + segdata = new MapSeg[Level.NumSegs]; + + for (i = 0; i < Level.NumSegs; ++i) + { + segdata[i].v1 = LittleShort(WORD(Level.Segs[i].v1)); + segdata[i].v2 = LittleShort(WORD(Level.Segs[i].v2)); + segdata[i].angle = LittleShort(Level.Segs[i].angle); + segdata[i].linedef = LittleShort(Level.Segs[i].linedef); + segdata[i].side = LittleShort(Level.Segs[i].side); + segdata[i].offset = LittleShort(Level.Segs[i].offset); + } + out.WriteLump ("SEGS", segdata, sizeof(*segdata)*Level.NumSegs); + + if (Level.NumSegs >= 65536) + { + printf (" SEGS is too big for any port. (%d segs)\n", Level.NumSegs); + } + else if (Level.NumSegs >= 32768) + { + printf (" SEGS is too big for vanilla Doom and some ports. (%d segs)\n", Level.NumSegs); + } +} + +void FProcessor::WriteSSectors (FWadWriter &out) const +{ + WriteSSectors2 (out, "SSECTORS", Level.Subsectors, Level.NumSubsectors); +} + +void FProcessor::WriteSSectors2 (FWadWriter &out, const char *name, const MapSubsectorEx *subs, int count) const +{ + int i; + MapSubsector *ssec; + + ssec = new MapSubsector[count]; + + for (i = 0; i < count; ++i) + { + ssec[i].firstline = LittleShort((WORD)subs[i].firstline); + ssec[i].numlines = LittleShort((WORD)subs[i].numlines); + } + out.WriteLump (name, ssec, sizeof(*ssec)*count); + delete[] ssec; + + if (count >= 65536) + { + printf (" %s is too big. (%d subsectors)\n", name, count); + } +} + +void FProcessor::WriteSSectors5 (FWadWriter &out, const char *name, const MapSubsectorEx *subs, int count) const +{ + int i; + MapSubsectorEx *ssec; + + ssec = new MapSubsectorEx[count]; + + for (i = 0; i < count; ++i) + { + ssec[i].firstline = LittleLong(subs[i].firstline); + ssec[i].numlines = LittleLong(subs[i].numlines); + } + out.WriteLump (name, ssec, sizeof(*ssec)*count); + delete[] ssec; +} + +void FProcessor::WriteNodes (FWadWriter &out) const +{ + WriteNodes2 (out, "NODES", Level.Nodes, Level.NumNodes); +} + +void FProcessor::WriteNodes2 (FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const +{ + int i, j; + short *onodes, *nodes; + + nodes = onodes = new short[count * sizeof(MapNode)/2]; + + for (i = 0; i < count; ++i) + { + nodes[0] = LittleShort(zaNodes[i].x >> 16); + nodes[1] = LittleShort(zaNodes[i].y >> 16); + nodes[2] = LittleShort(zaNodes[i].dx >> 16); + nodes[3] = LittleShort(zaNodes[i].dy >> 16); + nodes += 4; + const short *inodes = (short *)&zaNodes[i].bbox[0][0]; + for (j = 0; j < 2*4; ++j) + { + nodes[j] = LittleShort(inodes[j]); + } + nodes += j; + for (j = 0; j < 2; ++j) + { + DWORD child = zaNodes[i].children[j]; + if (child & NFX_SUBSECTOR) + { + *nodes++ = LittleShort(WORD(child - (NFX_SUBSECTOR + NF_SUBSECTOR))); + } + else + { + *nodes++ = LittleShort((WORD)child); + } + } + } + out.WriteLump (name, onodes, count * sizeof(MapNode)); + delete[] onodes; + + if (count >= 32768) + { + printf (" %s is too big. (%d nodes)\n", name, count); + } +} + +void FProcessor::WriteNodes5 (FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const +{ + int i, j; + MapNodeExO *const nodes = new MapNodeExO[count * sizeof(MapNodeEx)]; + + for (i = 0; i < count; ++i) + { + const short *inodes = &zaNodes[i].bbox[0][0]; + short *coord = &nodes[i].bbox[0][0]; + for (j = 0; j < 2*4; ++j) + { + coord[j] = LittleShort(inodes[j]); + } + nodes[i].x = LittleShort(zaNodes[i].x >> 16); + nodes[i].y = LittleShort(zaNodes[i].y >> 16); + nodes[i].dx = LittleShort(zaNodes[i].dx >> 16); + nodes[i].dy = LittleShort(zaNodes[i].dy >> 16); + for (j = 0; j < 2; ++j) + { + nodes[i].children[j] = LittleLong(zaNodes[i].children[j]); + } + } + out.WriteLump (name, nodes, count * sizeof(MapNodeEx)); + delete[] nodes; +} + +void FProcessor::WriteBlockmap (FWadWriter &out) +{ + if (BlockmapMode == EBM_Create0) + { + out.CreateLabel ("BLOCKMAP"); + return; + } + + size_t i, count; + WORD *blocks; + + count = Level.BlockmapSize; + blocks = Level.Blockmap; + + for (i = 0; i < count; ++i) + { + blocks[i] = LittleShort(blocks[i]); + } + out.WriteLump ("BLOCKMAP", blocks, int(sizeof(*blocks)*count)); + +#ifdef BLOCK_TEST + FILE *f = fopen ("blockmap.lm2", "wb"); + if (f) + { + fwrite (blocks, count, sizeof(*blocks), f); + fclose (f); + } +#endif + + for (i = 0; i < count; ++i) + { + blocks[i] = LittleShort(blocks[i]); + } + + if (count >= 65536) + { + printf (" BLOCKMAP is so big that ports will have to recreate it.\n" + " Vanilla Doom cannot handle it at all. If this map is for ZDoom 2+,\n" + " you should use the -b switch to save space in the wad.\n"); + } + else if (count >= 32768) + { + printf (" BLOCKMAP is too big for vanilla Doom.\n"); + } +} + +void FProcessor::WriteReject (FWadWriter &out) +{ + if (RejectMode == ERM_Create0 || Level.Reject == NULL) + { + out.CreateLabel ("REJECT"); + } + else + { + out.WriteLump ("REJECT", Level.Reject, Level.RejectSize); + } +} + +void FProcessor::WriteGLVertices (FWadWriter &out, bool v5) +{ + int i, count = (Level.NumGLVertices - Level.NumOrgVerts); + WideVertex *vertdata = Level.GLVertices + Level.NumOrgVerts; + + fixed_t *verts = new fixed_t[count*2+1]; + char *magic = (char *)verts; + magic[0] = 'g'; + magic[1] = 'N'; + magic[2] = 'd'; + magic[3] = v5 ? '5' : '2'; + + for (i = 0; i < count; ++i) + { + verts[i*2+1] = LittleShort(vertdata[i].x); + verts[i*2+2] = LittleShort(vertdata[i].y); + } + out.WriteLump ("GL_VERT", verts, sizeof(*verts)*(count*2+1)); + delete[] verts; + + if (count > 65536) + { + printf (" GL_VERT is too big. (%d GL vertices)\n", count/2); + } +} + +void FProcessor::WriteGLSegs (FWadWriter &out, bool v5) +{ + if (v5) + { + WriteGLSegs5 (out); + return; + } + int i, count; + MapSegGL *segdata; + + count = Level.NumGLSegs; + segdata = new MapSegGL[count]; + + for (i = 0; i < count; ++i) + { + if (Level.GLSegs[i].v1 < (DWORD)Level.NumOrgVerts) + { + segdata[i].v1 = LittleShort((WORD)Level.GLSegs[i].v1); + } + else + { + segdata[i].v1 = LittleShort(0x8000 | (WORD)(Level.GLSegs[i].v1 - Level.NumOrgVerts)); + } + if (Level.GLSegs[i].v2 < (DWORD)Level.NumOrgVerts) + { + segdata[i].v2 = (WORD)LittleShort(Level.GLSegs[i].v2); + } + else + { + segdata[i].v2 = LittleShort(0x8000 | (WORD)(Level.GLSegs[i].v2 - Level.NumOrgVerts)); + } + segdata[i].linedef = LittleShort((WORD)Level.GLSegs[i].linedef); + segdata[i].side = LittleShort(Level.GLSegs[i].side); + segdata[i].partner = LittleShort((WORD)Level.GLSegs[i].partner); + } + out.WriteLump ("GL_SEGS", segdata, sizeof(MapSegGL)*count); + delete[] segdata; + + if (count >= 65536) + { + printf (" GL_SEGS is too big for any port. (%d GL segs)\n", count); + } + else if (count >= 32768) + { + printf (" GL_SEGS is too big for some ports. (%d GL segs)\n", count); + } +} + +void FProcessor::WriteGLSegs5 (FWadWriter &out) +{ + int i, count; + MapSegGLEx *segdata; + + count = Level.NumGLSegs; + segdata = new MapSegGLEx[count]; + + for (i = 0; i < count; ++i) + { + if (Level.GLSegs[i].v1 < (DWORD)Level.NumOrgVerts) + { + segdata[i].v1 = LittleLong(Level.GLSegs[i].v1); + } + else + { + segdata[i].v1 = LittleLong(0x80000000u | ((int)Level.GLSegs[i].v1 - Level.NumOrgVerts)); + } + if (Level.GLSegs[i].v2 < (DWORD)Level.NumOrgVerts) + { + segdata[i].v2 = LittleLong(Level.GLSegs[i].v2); + } + else + { + segdata[i].v2 = LittleLong(0x80000000u | ((int)Level.GLSegs[i].v2 - Level.NumOrgVerts)); + } + segdata[i].linedef = LittleShort(Level.GLSegs[i].linedef); + segdata[i].side = LittleShort(Level.GLSegs[i].side); + segdata[i].partner = LittleLong(Level.GLSegs[i].partner); + } + out.WriteLump ("GL_SEGS", segdata, sizeof(MapSegGLEx)*count); + delete[] segdata; +} + +void FProcessor::WriteGLSSect (FWadWriter &out, bool v5) +{ + if (!v5) + { + WriteSSectors2 (out, "GL_SSECT", Level.GLSubsectors, Level.NumGLSubsectors); + } + else + { + WriteSSectors5 (out, "GL_SSECT", Level.GLSubsectors, Level.NumGLSubsectors); + } +} + +void FProcessor::WriteGLNodes (FWadWriter &out, bool v5) +{ + if (!v5) + { + WriteNodes2 (out, "GL_NODES", Level.GLNodes, Level.NumGLNodes); + } + else + { + WriteNodes5 (out, "GL_NODES", Level.GLNodes, Level.NumGLNodes); + } +} + +void FProcessor::WriteBSPZ (FWadWriter &out, const char *label) +{ + ZLibOut zout (out); + + if (!CompressNodes) + { + printf (" Nodes are so big that compression has been forced.\n"); + } + + out.StartWritingLump (label); + out.AddToLump ("ZNOD", 4); + WriteVerticesZ (zout, &Level.Vertices[Level.NumOrgVerts], Level.NumOrgVerts, Level.NumVertices - Level.NumOrgVerts); + WriteSubsectorsZ (zout, Level.Subsectors, Level.NumSubsectors); + WriteSegsZ (zout, Level.Segs, Level.NumSegs); + WriteNodesZ (zout, Level.Nodes, Level.NumNodes, 1); +} + +void FProcessor::WriteGLBSPZ (FWadWriter &out, const char *label) +{ + ZLibOut zout (out); + bool fracsplitters = CheckForFracSplitters(Level.GLNodes, Level.NumGLNodes); + int nodever; + + if (!CompressGLNodes) + { + printf (" GL Nodes are so big that compression has been forced.\n"); + } + + out.StartWritingLump (label); + if (fracsplitters) + { + out.AddToLump ("ZGL3", 4); + nodever = 3; + } + else if (Level.NumLines() < 65535) + { + out.AddToLump ("ZGLN", 4); + nodever = 1; + } + else + { + out.AddToLump ("ZGL2", 4); + nodever = 2; + } + WriteVerticesZ (zout, &Level.GLVertices[Level.NumOrgVerts], Level.NumOrgVerts, Level.NumGLVertices - Level.NumOrgVerts); + WriteSubsectorsZ (zout, Level.GLSubsectors, Level.NumGLSubsectors); + WriteGLSegsZ (zout, Level.GLSegs, Level.NumGLSegs, nodever); + WriteNodesZ (zout, Level.GLNodes, Level.NumGLNodes, nodever); +} + +void FProcessor::WriteVerticesZ (ZLibOut &out, const WideVertex *verts, int orgverts, int newverts) +{ + out << (DWORD)orgverts << (DWORD)newverts; + + for (int i = 0; i < newverts; ++i) + { + out << verts[i].x << verts[i].y; + } +} + +void FProcessor::WriteSubsectorsZ (ZLibOut &out, const MapSubsectorEx *subs, int numsubs) +{ + out << (DWORD)numsubs; + + for (int i = 0; i < numsubs; ++i) + { + out << (DWORD)subs[i].numlines; + } +} + +void FProcessor::WriteSegsZ (ZLibOut &out, const MapSegEx *segs, int numsegs) +{ + out << (DWORD)numsegs; + + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].v2 + << (WORD)segs[i].linedef + << (BYTE)segs[i].side; + } +} + +void FProcessor::WriteGLSegsZ (ZLibOut &out, const MapSegGLEx *segs, int numsegs, int nodever) +{ + out << (DWORD)numsegs; + + if (nodever < 2) + { + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].partner + << (WORD)segs[i].linedef + << (BYTE)segs[i].side; + } + } + else + { + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].partner + << (DWORD)segs[i].linedef + << (BYTE)segs[i].side; + } + } +} + +void FProcessor::WriteNodesZ (ZLibOut &out, const MapNodeEx *nodes, int numnodes, int nodever) +{ + out << (DWORD)numnodes; + + for (int i = 0; i < numnodes; ++i) + { + if (nodever < 3) + { + out << (SWORD)(nodes[i].x >> 16) + << (SWORD)(nodes[i].y >> 16) + << (SWORD)(nodes[i].dx >> 16) + << (SWORD)(nodes[i].dy >> 16); + } + else + { + out << (DWORD)nodes[i].x + << (DWORD)nodes[i].y + << (DWORD)nodes[i].dx + << (DWORD)nodes[i].dy; + } + for (int j = 0; j < 2; ++j) + { + for (int k = 0; k < 4; ++k) + { + out << (SWORD)nodes[i].bbox[j][k]; + } + } + out << (DWORD)nodes[i].children[0] + << (DWORD)nodes[i].children[1]; + } +} + +void FProcessor::WriteBSPX (FWadWriter &out, const char *label) +{ + if (!CompressNodes) + { + printf (" Nodes are so big that extended format has been forced.\n"); + } + + out.StartWritingLump (label); + out.AddToLump ("XNOD", 4); + WriteVerticesX (out, &Level.Vertices[Level.NumOrgVerts], Level.NumOrgVerts, Level.NumVertices - Level.NumOrgVerts); + WriteSubsectorsX (out, Level.Subsectors, Level.NumSubsectors); + WriteSegsX (out, Level.Segs, Level.NumSegs); + WriteNodesX (out, Level.Nodes, Level.NumNodes, 1); +} + +void FProcessor::WriteGLBSPX (FWadWriter &out, const char *label) +{ + bool fracsplitters = CheckForFracSplitters(Level.GLNodes, Level.NumGLNodes); + int nodever; + + if (!CompressGLNodes) + { + printf (" GL Nodes are so big that extended format has been forced.\n"); + } + + out.StartWritingLump (label); + if (fracsplitters) + { + out.AddToLump ("XGL3", 4); + nodever = 3; + } + else if (Level.NumLines() < 65535) + { + out.AddToLump ("XGLN", 4); + nodever = 1; + } + else + { + out.AddToLump ("XGL2", 4); + nodever = 2; + } + WriteVerticesX (out, &Level.GLVertices[Level.NumOrgVerts], Level.NumOrgVerts, Level.NumGLVertices - Level.NumOrgVerts); + WriteSubsectorsX (out, Level.GLSubsectors, Level.NumGLSubsectors); + WriteGLSegsX (out, Level.GLSegs, Level.NumGLSegs, nodever); + WriteNodesX (out, Level.GLNodes, Level.NumGLNodes, nodever); +} + +void FProcessor::WriteVerticesX (FWadWriter &out, const WideVertex *verts, int orgverts, int newverts) +{ + out << (DWORD)orgverts << (DWORD)newverts; + + for (int i = 0; i < newverts; ++i) + { + out << verts[i].x << verts[i].y; + } +} + +void FProcessor::WriteSubsectorsX (FWadWriter &out, const MapSubsectorEx *subs, int numsubs) +{ + out << (DWORD)numsubs; + + for (int i = 0; i < numsubs; ++i) + { + out << (DWORD)subs[i].numlines; + } +} + +void FProcessor::WriteSegsX (FWadWriter &out, const MapSegEx *segs, int numsegs) +{ + out << (DWORD)numsegs; + + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].v2 + << (WORD)segs[i].linedef + << (BYTE)segs[i].side; + } +} + +void FProcessor::WriteGLSegsX (FWadWriter &out, const MapSegGLEx *segs, int numsegs, int nodever) +{ + out << (DWORD)numsegs; + + if (nodever < 2) + { + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].partner + << (WORD)segs[i].linedef + << (BYTE)segs[i].side; + } + } + else + { + for (int i = 0; i < numsegs; ++i) + { + out << (DWORD)segs[i].v1 + << (DWORD)segs[i].partner + << (DWORD)segs[i].linedef + << (BYTE)segs[i].side; + } + } +} + +void FProcessor::WriteNodesX (FWadWriter &out, const MapNodeEx *nodes, int numnodes, int nodever) +{ + out << (DWORD)numnodes; + + for (int i = 0; i < numnodes; ++i) + { + if (nodever < 3) + { + out << (SWORD)(nodes[i].x >> 16) + << (SWORD)(nodes[i].y >> 16) + << (SWORD)(nodes[i].dx >> 16) + << (SWORD)(nodes[i].dy >> 16); + } + else + { + out << (DWORD)nodes[i].x + << (DWORD)nodes[i].y + << (DWORD)nodes[i].dx + << (DWORD)nodes[i].dy; + } + for (int j = 0; j < 2; ++j) + { + for (int k = 0; k < 4; ++k) + { + out << (SWORD)nodes[i].bbox[j][k]; + } + } + out << (DWORD)nodes[i].children[0] + << (DWORD)nodes[i].children[1]; + } +} + +bool FProcessor::CheckForFracSplitters(const MapNodeEx *nodes, int numnodes) { for (int i = 0; i < numnodes; ++i) { diff --git a/src/level/level.h b/src/level/level.h index a765e2a..1a444ca 100644 --- a/src/level/level.h +++ b/src/level/level.h @@ -7,20 +7,21 @@ #include "framework/tarray.h" #include "nodebuilder/nodebuild.h" #include "blockmapbuilder/blockmapbuilder.h" +#include "lightmap/lightmap.h" #include class ZLibOut { public: - ZLibOut (FWadWriter &out); - ~ZLibOut (); + ZLibOut(FWadWriter &out); + ~ZLibOut(); ZLibOut &operator << (BYTE); ZLibOut &operator << (WORD); ZLibOut &operator << (SWORD); ZLibOut &operator << (DWORD); ZLibOut &operator << (fixed_t); - void Write (BYTE *data, int len); + void Write(BYTE *data, int len); private: enum { BUFFER_SIZE = 8192 }; @@ -31,31 +32,70 @@ private: FWadWriter &Out; }; -class FLevelLoader +class FProcessor { public: - FLevelLoader (FWadReader &inwad, int lump); + FProcessor(FWadReader &inwad, int lump); - void BuildNodes (); - - FLevel Level; + void BuildNodes(); + void BuildLightmaps(const char *configFile); + void Write(FWadWriter &out); private: void LoadUDMF(); - void LoadThings (); - void LoadLines (); - void LoadVertices (); - void LoadSides (); - void LoadSectors (); - void GetPolySpots (); + void LoadThings(); + void LoadLines(); + void LoadVertices(); + void LoadSides(); + void LoadSectors(); + void GetPolySpots(); - MapNodeEx *NodesToEx (const MapNode *nodes, int count); - MapSubsectorEx *SubsectorsToEx (const MapSubsector *ssec, int count); - MapSegGLEx *SegGLsToEx (const MapSegGL *segs, int count); + MapNodeEx *NodesToEx(const MapNode *nodes, int count); + MapSubsectorEx *SubsectorsToEx(const MapSubsector *ssec, int count); + MapSegGLEx *SegGLsToEx(const MapSegGL *segs, int count); - BYTE *FixReject (const BYTE *oldreject); + BYTE *FixReject(const BYTE *oldreject); bool CheckForFracSplitters(const MapNodeEx *nodes, int count); + void WriteLines(FWadWriter &out); + void WriteVertices(FWadWriter &out, int count); + void WriteSectors(FWadWriter &out); + void WriteSides(FWadWriter &out); + void WriteSegs(FWadWriter &out); + void WriteSSectors(FWadWriter &out) const; + void WriteNodes(FWadWriter &out) const; + void WriteBlockmap(FWadWriter &out); + void WriteReject(FWadWriter &out); + + void WriteGLVertices(FWadWriter &out, bool v5); + void WriteGLSegs(FWadWriter &out, bool v5); + void WriteGLSegs5(FWadWriter &out); + void WriteGLSSect(FWadWriter &out, bool v5); + void WriteGLNodes(FWadWriter &out, bool v5); + + void WriteBSPZ(FWadWriter &out, const char *label); + void WriteGLBSPZ(FWadWriter &out, const char *label); + + void WriteVerticesZ(ZLibOut &out, const WideVertex *verts, int orgverts, int newverts); + void WriteSubsectorsZ(ZLibOut &out, const MapSubsectorEx *subs, int numsubs); + void WriteSegsZ(ZLibOut &out, const MapSegEx *segs, int numsegs); + void WriteGLSegsZ(ZLibOut &out, const MapSegGLEx *segs, int numsegs, int nodever); + void WriteNodesZ(ZLibOut &out, const MapNodeEx *nodes, int numnodes, int nodever); + + void WriteBSPX(FWadWriter &out, const char *label); + void WriteGLBSPX(FWadWriter &out, const char *label); + + void WriteVerticesX(FWadWriter &out, const WideVertex *verts, int orgverts, int newverts); + void WriteSubsectorsX(FWadWriter &out, const MapSubsectorEx *subs, int numsubs); + void WriteSegsX(FWadWriter &out, const MapSegEx *segs, int numsegs); + void WriteGLSegsX(FWadWriter &out, const MapSegGLEx *segs, int numsegs, int nodever); + void WriteNodesX(FWadWriter &out, const MapNodeEx *nodes, int numnodes, int nodever); + + void WriteNodes2(FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const; + void WriteSSectors2(FWadWriter &out, const char *name, const MapSubsectorEx *zaSubs, int count) const; + void WriteNodes5(FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const; + void WriteSSectors5(FWadWriter &out, const char *name, const MapSubsectorEx *zaSubs, int count) const; + const char *ParseKey(const char *&value); bool CheckKey(const char *&key, const char *&value); void ParseThing(IntThing *th); @@ -66,6 +106,18 @@ private: void ParseMapProperties(); void ParseTextMap(int lump); + void WriteProps(FWadWriter &out, TArray &props); + void WriteIntProp(FWadWriter &out, const char *key, int value); + void WriteThingUDMF(FWadWriter &out, IntThing *th, int num); + void WriteLinedefUDMF(FWadWriter &out, IntLineDef *ld, int num); + void WriteSidedefUDMF(FWadWriter &out, IntSideDef *sd, int num); + void WriteSectorUDMF(FWadWriter &out, IntSector *sec, int num); + void WriteVertexUDMF(FWadWriter &out, IntVertex *vt, int num); + void WriteTextMap(FWadWriter &out); + void WriteUDMF(FWadWriter &out); + + FLevel Level; + TArray PolyStarts; TArray PolyAnchors; @@ -74,4 +126,8 @@ private: FWadReader &Wad; int Lump; + + bool NodesBuilt = false; + bool LightmapsBuilt = false; + kexLightmapBuilder LMBuilder; }; diff --git a/src/level/level_udmf.cpp b/src/level/level_udmf.cpp index 7521b4b..fbf86d3 100644 --- a/src/level/level_udmf.cpp +++ b/src/level/level_udmf.cpp @@ -73,7 +73,7 @@ StringBuffer stbuf; // //=========================================================================== -const char *FLevelLoader::ParseKey(const char *&value) +const char *FProcessor::ParseKey(const char *&value) { SC_MustGetString(); const char *key = stbuf.Copy(sc_String); @@ -90,7 +90,7 @@ const char *FLevelLoader::ParseKey(const char *&value) return key; } -bool FLevelLoader::CheckKey(const char *&key, const char *&value) +bool FProcessor::CheckKey(const char *&key, const char *&value) { SC_SavePos(); SC_MustGetString(); @@ -138,7 +138,7 @@ fixed_t CheckFixed(const char *key) // //=========================================================================== -void FLevelLoader::ParseThing(IntThing *th) +void FProcessor::ParseThing(IntThing *th) { SC_MustGetStringName("{"); while (!SC_CheckString("}")) @@ -178,7 +178,7 @@ void FLevelLoader::ParseThing(IntThing *th) // //=========================================================================== -void FLevelLoader::ParseLinedef(IntLineDef *ld) +void FProcessor::ParseLinedef(IntLineDef *ld) { SC_MustGetStringName("{"); ld->v1 = ld->v2 = ld->sidenum[0] = ld->sidenum[1] = NO_INDEX; @@ -229,7 +229,7 @@ void FLevelLoader::ParseLinedef(IntLineDef *ld) // //=========================================================================== -void FLevelLoader::ParseSidedef(IntSideDef *sd) +void FProcessor::ParseSidedef(IntSideDef *sd) { SC_MustGetStringName("{"); sd->sector = NO_INDEX; @@ -256,7 +256,7 @@ void FLevelLoader::ParseSidedef(IntSideDef *sd) // //=========================================================================== -void FLevelLoader::ParseSector(IntSector *sec) +void FProcessor::ParseSector(IntSector *sec) { SC_MustGetStringName("{"); while (!SC_CheckString("}")) @@ -279,7 +279,7 @@ void FLevelLoader::ParseSector(IntSector *sec) // //=========================================================================== -void FLevelLoader::ParseVertex(WideVertex *vt, IntVertex *vtp) +void FProcessor::ParseVertex(WideVertex *vt, IntVertex *vtp) { vt->x = vt->y = 0; SC_MustGetStringName("{"); @@ -310,7 +310,7 @@ void FLevelLoader::ParseVertex(WideVertex *vt, IntVertex *vtp) // //=========================================================================== -void FLevelLoader::ParseMapProperties() +void FProcessor::ParseMapProperties() { const char *key, *value; @@ -337,7 +337,7 @@ void FLevelLoader::ParseMapProperties() // //=========================================================================== -void FLevelLoader::ParseTextMap(int lump) +void FProcessor::ParseTextMap(int lump) { char *buffer; int buffersize; @@ -393,7 +393,214 @@ void FLevelLoader::ParseTextMap(int lump) // //=========================================================================== -void FLevelLoader::LoadUDMF() +void FProcessor::LoadUDMF() { ParseTextMap(Lump+1); } + +//=========================================================================== +// +// writes a property list +// +//=========================================================================== + +void FProcessor::WriteProps(FWadWriter &out, TArray &props) +{ + for(unsigned i=0; i< props.Size(); i++) + { + out.AddToLump(props[i].key, (int)strlen(props[i].key)); + out.AddToLump(" = ", 3); + out.AddToLump(props[i].value, (int)strlen(props[i].value)); + out.AddToLump(";\n", 2); + } +} + +//=========================================================================== +// +// writes an integer property +// +//=========================================================================== + +void FProcessor::WriteIntProp(FWadWriter &out, const char *key, int value) +{ + char buffer[20]; + + out.AddToLump(key, (int)strlen(key)); + out.AddToLump(" = ", 3); + sprintf(buffer, "%d;\n", value); + out.AddToLump(buffer, (int)strlen(buffer)); +} + +//=========================================================================== +// +// writes a UDMF thing +// +//=========================================================================== + +void FProcessor::WriteThingUDMF(FWadWriter &out, IntThing *th, int num) +{ + out.AddToLump("thing", 5); + if (WriteComments) + { + char buffer[32]; + int len = sprintf(buffer, " // %d", num); + out.AddToLump(buffer, len); + } + out.AddToLump("\n{\n", 3); + WriteProps(out, th->props); + out.AddToLump("}\n\n", 3); +} + +//=========================================================================== +// +// writes a UDMF linedef +// +//=========================================================================== + +void FProcessor::WriteLinedefUDMF(FWadWriter &out, IntLineDef *ld, int num) +{ + out.AddToLump("linedef", 7); + if (WriteComments) + { + char buffer[32]; + int len = sprintf(buffer, " // %d", num); + out.AddToLump(buffer, len); + } + out.AddToLump("\n{\n", 3); + WriteIntProp(out, "v1", ld->v1); + WriteIntProp(out, "v2", ld->v2); + if (ld->sidenum[0] != NO_INDEX) WriteIntProp(out, "sidefront", ld->sidenum[0]); + if (ld->sidenum[1] != NO_INDEX) WriteIntProp(out, "sideback", ld->sidenum[1]); + WriteProps(out, ld->props); + out.AddToLump("}\n\n", 3); +} + +//=========================================================================== +// +// writes a UDMF sidedef +// +//=========================================================================== + +void FProcessor::WriteSidedefUDMF(FWadWriter &out, IntSideDef *sd, int num) +{ + out.AddToLump("sidedef", 7); + if (WriteComments) + { + char buffer[32]; + int len = sprintf(buffer, " // %d", num); + out.AddToLump(buffer, len); + } + out.AddToLump("\n{\n", 3); + WriteIntProp(out, "sector", sd->sector); + WriteProps(out, sd->props); + out.AddToLump("}\n\n", 3); +} + +//=========================================================================== +// +// writes a UDMF sector +// +//=========================================================================== + +void FProcessor::WriteSectorUDMF(FWadWriter &out, IntSector *sec, int num) +{ + out.AddToLump("sector", 6); + if (WriteComments) + { + char buffer[32]; + int len = sprintf(buffer, " // %d", num); + out.AddToLump(buffer, len); + } + out.AddToLump("\n{\n", 3); + WriteProps(out, sec->props); + out.AddToLump("}\n\n", 3); +} + +//=========================================================================== +// +// writes a UDMF vertex +// +//=========================================================================== + +void FProcessor::WriteVertexUDMF(FWadWriter &out, IntVertex *vt, int num) +{ + out.AddToLump("vertex", 6); + if (WriteComments) + { + char buffer[32]; + int len = sprintf(buffer, " // %d", num); + out.AddToLump(buffer, len); + } + out.AddToLump("\n{\n", 3); + WriteProps(out, vt->props); + out.AddToLump("}\n\n", 3); +} + +//=========================================================================== +// +// writes a UDMF text map +// +//=========================================================================== + +void FProcessor::WriteTextMap(FWadWriter &out) +{ + out.StartWritingLump("TEXTMAP"); + WriteProps(out, Level.props); + for(int i = 0; i < Level.NumThings(); i++) + { + WriteThingUDMF(out, &Level.Things[i], i); + } + + for(int i = 0; i < Level.NumOrgVerts; i++) + { + WideVertex *vt = &Level.Vertices[i]; + if (vt->index <= 0) + { + // not valid! + throw std::runtime_error("Invalid vertex data."); + } + WriteVertexUDMF(out, &Level.VertexProps[vt->index-1], i); + } + + for(int i = 0; i < Level.NumLines(); i++) + { + WriteLinedefUDMF(out, &Level.Lines[i], i); + } + + for(int i = 0; i < Level.NumSides(); i++) + { + WriteSidedefUDMF(out, &Level.Sides[i], i); + } + + for(int i = 0; i < Level.NumSectors(); i++) + { + WriteSectorUDMF(out, &Level.Sectors[i], i); + } +} + +//=========================================================================== +// +// writes an UDMF map +// +//=========================================================================== + +void FProcessor::WriteUDMF(FWadWriter &out) +{ + out.CopyLump (Wad, Lump); + WriteTextMap(out); + if (ForceCompression) WriteGLBSPZ (out, "ZNODES"); + else WriteGLBSPX (out, "ZNODES"); + + // copy everything except existing nodes, blockmap and reject + for(int i=Lump+2; stricmp(Wad.LumpName(i), "ENDMAP") && i < Wad.NumLumps(); i++) + { + const char *lumpname = Wad.LumpName(i); + if (stricmp(lumpname, "ZNODES") && + stricmp(lumpname, "BLOCKMAP") && + stricmp(lumpname, "REJECT")) + { + out.CopyLump(Wad, i); + } + } + out.CreateLabel("ENDMAP"); +} diff --git a/src/main.cpp b/src/main.cpp index 096847e..c6136fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,6 @@ #include "framework/zdray.h" #include "wad/wad.h" #include "level/level.h" -#include "lightmap/lightmap.h" static void ParseArgs(int argc, char **argv); static void ShowUsage(); @@ -19,6 +18,18 @@ const char *OutName = "zdray.bin"; bool ShowMap = false; bool ShowWarnings = false; +bool BuildGLNodes = true; +bool ConformNodes = false; +bool GLOnly = true; +bool CompressNodes = true; +bool CompressGLNodes = true; +bool ForceCompression = true; +bool V5GLNodes = true; +bool HaveSSE1 = true; +bool HaveSSE2 = true; +int SSELevel = 2; +bool WriteComments = true; + // Constants that used to be args in zdbsp bool NoPrune = false; EBlockmapMode BlockmapMode = EBM_Rebuild; @@ -68,21 +79,9 @@ int main(int argc, char **argv) { if (inwad.IsMap(lump) && (!Map || stricmp(inwad.LumpName(lump), Map) == 0)) { - FLevelLoader loader(inwad, lump); - loader.BuildNodes(); - - loader.Level.ParseConfigFile("lightconfig.txt"); - loader.Level.SetupDlight(); - Surface_AllocateFromMap(loader.Level); - loader.Level.CreateLights(); - - kexLightmapBuilder builder; - builder.CreateLightmaps(loader.Level); - builder.WriteTexturesToTGA(); - - builder.WriteMeshToOBJ(); - - loader.Level.CleanupThingLights(); + FProcessor processor(inwad, lump); + processor.BuildNodes(); + processor.BuildLightmaps("lightconfig.txt"); lump = inwad.LumpAfterMap(lump); }