mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-02-03 13:11:04 +00:00
- fix race condition crash
- rewrote kexWorker to use std::function - added --threads, --samples, --size command line arguments - changed the default threading to be what the processor supports (64 threads on my Threadripper, muhahaha!)
This commit is contained in:
parent
6459b10724
commit
81a70d7c96
6 changed files with 343 additions and 515 deletions
|
@ -22,6 +22,9 @@
|
||||||
//#include "rejectbuilder.h"
|
//#include "rejectbuilder.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
extern int LMDims;
|
||||||
|
extern int Samples;
|
||||||
|
|
||||||
extern void ShowView (FLevel *level);
|
extern void ShowView (FLevel *level);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -597,9 +600,9 @@ void FProcessor::BuildNodes()
|
||||||
void FProcessor::BuildLightmaps(const char *configFile)
|
void FProcessor::BuildLightmaps(const char *configFile)
|
||||||
{
|
{
|
||||||
LMBuilder.ambience = 0.0f;
|
LMBuilder.ambience = 0.0f;
|
||||||
LMBuilder.samples = 8;
|
LMBuilder.samples = Samples;
|
||||||
LMBuilder.textureWidth = LIGHTMAP_MAX_SIZE;
|
LMBuilder.textureWidth = LMDims;
|
||||||
LMBuilder.textureHeight = LIGHTMAP_MAX_SIZE;
|
LMBuilder.textureHeight = LMDims;
|
||||||
|
|
||||||
Level.ParseConfigFile(configFile);
|
Level.ParseConfigFile(configFile);
|
||||||
Level.SetupDlight();
|
Level.SetupDlight();
|
||||||
|
|
|
@ -42,30 +42,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
kexWorker lightmapWorker;
|
|
||||||
|
|
||||||
const kexVec3 kexLightmapBuilder::gridSize(64, 64, 128);
|
const kexVec3 kexLightmapBuilder::gridSize(64, 64, 128);
|
||||||
|
|
||||||
//
|
|
||||||
// LightmapWorkerFunc
|
|
||||||
//
|
|
||||||
|
|
||||||
static void LightmapWorkerFunc(void *data, int id)
|
|
||||||
{
|
|
||||||
kexLightmapBuilder *builder = static_cast<kexLightmapBuilder*>(data);
|
|
||||||
builder->LightSurface(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// LightGridWorkerFunc
|
|
||||||
//
|
|
||||||
|
|
||||||
static void LightGridWorkerFunc(void *data, int id)
|
|
||||||
{
|
|
||||||
kexLightmapBuilder *builder = static_cast<kexLightmapBuilder*>(data);
|
|
||||||
builder->LightGrid(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// kexLightmapBuilder::kexLightmapBuilder
|
// kexLightmapBuilder::kexLightmapBuilder
|
||||||
//
|
//
|
||||||
|
@ -536,23 +514,25 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
int width = surface->lightmapDims[0];
|
int width = surface->lightmapDims[0];
|
||||||
int height = surface->lightmapDims[1];
|
int height = surface->lightmapDims[1];
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
// now that we know the width and height of this block, see if we got
|
// now that we know the width and height of this block, see if we got
|
||||||
// room for it in the light map texture. if not, then we must allocate
|
// room for it in the light map texture. if not, then we must allocate
|
||||||
// a new texture
|
// a new texture
|
||||||
if(!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
|
if(!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
|
||||||
{
|
{
|
||||||
// allocate a new texture for this block
|
// allocate a new texture for this block
|
||||||
lightmapWorker.LockMutex();
|
|
||||||
NewTexture();
|
NewTexture();
|
||||||
lightmapWorker.UnlockMutex();
|
|
||||||
|
|
||||||
if(!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
|
if(!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
|
||||||
{
|
{
|
||||||
Error("Lightmap allocation failed\n");
|
Error("Lightmap allocation failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
// calculate texture coordinates
|
// calculate texture coordinates
|
||||||
for(i = 0; i < surface->numVerts; i++)
|
for(i = 0; i < surface->numVerts; i++)
|
||||||
{
|
{
|
||||||
|
@ -567,9 +547,9 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
surface->lightmapOffs[1] = y;
|
surface->lightmapOffs[1] = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
lightmapWorker.LockMutex();
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
currentTexture = textures[surface->lightmapNum];
|
currentTexture = textures[surface->lightmapNum];
|
||||||
lightmapWorker.UnlockMutex();
|
lock.unlock();
|
||||||
|
|
||||||
// store results to lightmap texture
|
// store results to lightmap texture
|
||||||
for(i = 0; i < sampleHeight; i++)
|
for(i = 0; i < sampleHeight; i++)
|
||||||
|
@ -581,9 +561,9 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
surface->lightmapOffs[0]) * 3);
|
surface->lightmapOffs[0]) * 3);
|
||||||
|
|
||||||
// convert RGB to bytes
|
// convert RGB to bytes
|
||||||
rgb[0] = (byte)(colorSamples[i][j][0] * 255);
|
rgb[0] = (uint32_t)(colorSamples[i][j][0] * 255 + 0.5f);
|
||||||
rgb[1] = (byte)(colorSamples[i][j][1] * 255);
|
rgb[1] = (uint32_t)(colorSamples[i][j][1] * 255 + 0.5f);
|
||||||
rgb[2] = (byte)(colorSamples[i][j][2] * 255);
|
rgb[2] = (uint32_t)(colorSamples[i][j][2] * 255 + 0.5f);
|
||||||
|
|
||||||
currentTexture[offs + j * 3 + 0] = rgb[0];
|
currentTexture[offs + j * 3 + 0] = rgb[0];
|
||||||
currentTexture[offs + j * 3 + 1] = rgb[1];
|
currentTexture[offs + j * 3 + 1] = rgb[1];
|
||||||
|
@ -611,12 +591,12 @@ void kexLightmapBuilder::LightSurface(const int surfid)
|
||||||
BuildSurfaceParams(surfaces[surfid]);
|
BuildSurfaceParams(surfaces[surfid]);
|
||||||
TraceSurface(surfaces[surfid]);
|
TraceSurface(surfaces[surfid]);
|
||||||
|
|
||||||
lightmapWorker.LockMutex();
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
remaining = (float)processed / (float)numsurfs;
|
remaining = (float)processed / (float)numsurfs;
|
||||||
processed++;
|
processed++;
|
||||||
|
|
||||||
printf("%i%c surfaces done\r", (int)(remaining * 100.0f), '%');
|
printf("%i%c surfaces done\r", (int)(remaining * 100.0f), '%');
|
||||||
lightmapWorker.UnlockMutex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -822,11 +802,11 @@ void kexLightmapBuilder::LightGrid(const int gridid)
|
||||||
|
|
||||||
kexMath::Clamp(gridMap[gridid].color, 0, 1);
|
kexMath::Clamp(gridMap[gridid].color, 0, 1);
|
||||||
|
|
||||||
lightmapWorker.LockMutex();
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
remaining = (float)processed / (float)numLightGrids;
|
remaining = (float)processed / (float)numLightGrids;
|
||||||
|
|
||||||
printf("%i%c cells done\r", (int)(remaining * 100.0f), '%');
|
printf("%i%c cells done\r", (int)(remaining * 100.0f), '%');
|
||||||
lightmapWorker.UnlockMutex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -841,15 +821,12 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
||||||
CreateLightGrid();
|
CreateLightGrid();
|
||||||
|
|
||||||
printf("------------- Tracing surfaces -------------\n");
|
printf("------------- Tracing surfaces -------------\n");
|
||||||
lightmapWorker.RunThreads(surfaces.Length(), this, LightmapWorkerFunc);
|
|
||||||
|
|
||||||
while(!lightmapWorker.FinishedAllJobs())
|
kexWorker::RunJob(surfaces.Length(), [=](int id) {
|
||||||
{
|
LightSurface(id);
|
||||||
Delay(1000);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
printf("Texels traced: %i \n\n", tracedTexels);
|
printf("Texels traced: %i \n\n", tracedTexels);
|
||||||
lightmapWorker.Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -895,12 +872,9 @@ void kexLightmapBuilder::CreateLightGrid()
|
||||||
(int)(gridBlock.x * gridBlock.y), hb_static);
|
(int)(gridBlock.x * gridBlock.y), hb_static);
|
||||||
|
|
||||||
// process all grid cells
|
// process all grid cells
|
||||||
lightmapWorker.RunThreads(count, this, LightGridWorkerFunc);
|
kexWorker::RunJob(count, [=](int id) {
|
||||||
|
LightGrid(id);
|
||||||
while(!lightmapWorker.FinishedAllJobs())
|
});
|
||||||
{
|
|
||||||
Delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nGrid cells: %i\n\n", count);
|
printf("\nGrid cells: %i\n\n", count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "surfaces.h"
|
#include "surfaces.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#define LIGHTMAP_MAX_SIZE 1024
|
#define LIGHTMAP_MAX_SIZE 1024
|
||||||
|
|
||||||
|
@ -87,4 +88,6 @@ private:
|
||||||
kexBBox worldGrid;
|
kexBBox worldGrid;
|
||||||
kexBBox gridBound;
|
kexBBox gridBound;
|
||||||
kexVec3 gridBlock;
|
kexVec3 gridBlock;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,407 +1,36 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Note: this is a modified version of dlight. It is not the original software.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
|
||||||
// svkaiser@gmail.com
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would be
|
|
||||||
// appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
// misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// DESCRIPTION: Worker Threads
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "worker.h"
|
#include "worker.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
int kexWorker::maxWorkThreads = MAX_THREADS;
|
extern int NumThreads;
|
||||||
|
|
||||||
//
|
void kexWorker::RunJob(int count, std::function<void(int)> callback)
|
||||||
// WorkThread
|
|
||||||
//
|
|
||||||
|
|
||||||
void *WorkThread(void *p)
|
|
||||||
{
|
{
|
||||||
jobFuncArgs_t *args = (jobFuncArgs_t*)p;
|
int numThreads = NumThreads;
|
||||||
kexWorker *worker = args->worker;
|
if (numThreads <= 0)
|
||||||
|
numThreads = std::thread::hardware_concurrency();
|
||||||
|
if (numThreads <= 0)
|
||||||
|
numThreads = 4;
|
||||||
|
|
||||||
while(1)
|
numThreads = std::min(numThreads, count);
|
||||||
{
|
|
||||||
int jobid;
|
|
||||||
|
|
||||||
worker->LockMutex();
|
std::vector<std::thread> threads;
|
||||||
|
for (int threadIndex = 0; threadIndex < numThreads; threadIndex++)
|
||||||
|
{
|
||||||
|
threads.push_back(std::thread([=]() {
|
||||||
|
|
||||||
if(worker->FinishedAllJobs())
|
int start = threadIndex * count / numThreads;
|
||||||
{
|
int end = std::min((threadIndex + 1) * count / numThreads, count);
|
||||||
worker->UnlockMutex();
|
for (int i = start; i < end; i++)
|
||||||
break;
|
{
|
||||||
}
|
callback(i);
|
||||||
|
}
|
||||||
|
|
||||||
jobid = worker->DispatchJob();
|
}));
|
||||||
worker->UnlockMutex();
|
}
|
||||||
|
|
||||||
worker->RunJob(args->data, jobid);
|
for (int i = 0; i < numThreads; i++)
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::kexWorker
|
|
||||||
//
|
|
||||||
|
|
||||||
kexWorker::kexWorker()
|
|
||||||
{
|
|
||||||
this->numWorkLoad = 0;
|
|
||||||
this->jobsWorked = 0;
|
|
||||||
this->job = NULL;
|
|
||||||
|
|
||||||
memset(this->jobArgs, 0, sizeof(this->jobArgs));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::~kexWorker
|
|
||||||
//
|
|
||||||
|
|
||||||
kexWorker::~kexWorker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::LockMutex
|
|
||||||
//
|
|
||||||
|
|
||||||
void kexWorker::LockMutex()
|
|
||||||
{
|
|
||||||
mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::UnlockMutex
|
|
||||||
//
|
|
||||||
|
|
||||||
void kexWorker::UnlockMutex()
|
|
||||||
{
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::Destroy
|
|
||||||
//
|
|
||||||
|
|
||||||
void kexWorker::Destroy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// kexWorker::RunThreads
|
|
||||||
//
|
|
||||||
|
|
||||||
void kexWorker::RunThreads(const int count, void *data, jobFunc_t jobFunc)
|
|
||||||
{
|
|
||||||
job = jobFunc;
|
|
||||||
numWorkLoad = count;
|
|
||||||
jobsWorked = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < kexWorker::maxWorkThreads; ++i)
|
|
||||||
{
|
|
||||||
jobArgs[i].worker = this;
|
|
||||||
jobArgs[i].jobID = i;
|
|
||||||
jobArgs[i].data = data;
|
|
||||||
|
|
||||||
threads[i] = std::thread([=]() { WorkThread(&jobArgs[i]); });
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < kexWorker::maxWorkThreads; ++i)
|
|
||||||
{
|
|
||||||
threads[i].join();
|
threads[i].join();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Stuff from old main.cpp
|
|
||||||
|
|
||||||
void Error(const char *error, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
|
|
||||||
va_start(argptr, error);
|
|
||||||
vprintf(error, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
printf("\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Va(const char *str, ...)
|
|
||||||
{
|
|
||||||
va_list v;
|
|
||||||
static char vastr[1024];
|
|
||||||
|
|
||||||
va_start(v, str);
|
|
||||||
vsprintf(vastr, str, v);
|
|
||||||
va_end(v);
|
|
||||||
|
|
||||||
return vastr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delay(int ms)
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// GetSeconds
|
|
||||||
//
|
|
||||||
|
|
||||||
const int64_t GetSeconds()
|
|
||||||
{
|
|
||||||
return time(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Main
|
|
||||||
//
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
kexWadFile wadFile;
|
|
||||||
kexWadFile outWadFile;
|
|
||||||
FLevel doomMap;
|
|
||||||
lump_t *lmLump;
|
|
||||||
kexArray<int> ignoreLumps;
|
|
||||||
kexLightmapBuilder builder;
|
|
||||||
kexStr configFile("strife_sve.cfg");
|
|
||||||
bool bWriteTGA;
|
|
||||||
int map = 1;
|
|
||||||
int arg = 1;
|
|
||||||
|
|
||||||
printf("DLight (c) 2013-2014 Samuel Villarreal\n\n");
|
|
||||||
|
|
||||||
if (argc < 1 || argv[1] == NULL)
|
|
||||||
{
|
|
||||||
printf("Usage: dlight [options] [wadfile]\n");
|
|
||||||
printf("Use -help for list of options\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
basePath = argv[0];
|
|
||||||
basePath.StripFile();
|
|
||||||
|
|
||||||
bWriteTGA = false;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (!strcmp(argv[arg], "-help"))
|
|
||||||
{
|
|
||||||
printf("Options:\n");
|
|
||||||
printf("-help: displays all known options\n");
|
|
||||||
printf("-map: process lightmap for MAP##\n");
|
|
||||||
printf("-samples: set texel sampling size (lowest = higher quaility but\n");
|
|
||||||
printf(" slow compile time) must be in powers of two\n");
|
|
||||||
printf("-ambience: set global ambience value for lightmaps (0.0 - 1.0)\n");
|
|
||||||
printf("-size: lightmap texture dimentions for width and height\n");
|
|
||||||
printf(" must be in powers of two (1, 2, 4, 8, 16, etc)\n");
|
|
||||||
printf("-threads: set total number of threads (1 min, 128 max)\n");
|
|
||||||
printf("-config: specify a config file to parse (default: strife_sve.cfg)\n");
|
|
||||||
printf("-writetga: dumps lightmaps to targa (.TGA) files\n");
|
|
||||||
arg++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-map"))
|
|
||||||
{
|
|
||||||
if (argv[arg + 1] == NULL)
|
|
||||||
{
|
|
||||||
Error("Specify map number for -map\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
map = atoi(argv[++arg]);
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-samples"))
|
|
||||||
{
|
|
||||||
if (argv[arg + 1] == NULL)
|
|
||||||
{
|
|
||||||
Error("Specify value for -samples\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.samples = atoi(argv[++arg]);
|
|
||||||
if (builder.samples <= 0)
|
|
||||||
{
|
|
||||||
builder.samples = 1;
|
|
||||||
}
|
|
||||||
if (builder.samples > 128)
|
|
||||||
{
|
|
||||||
builder.samples = 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.samples = kexMath::RoundPowerOfTwo(builder.samples);
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-ambience"))
|
|
||||||
{
|
|
||||||
if (argv[arg + 1] == NULL)
|
|
||||||
{
|
|
||||||
Error("Specify value for -ambience\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.ambience = (float)atof(argv[++arg]);
|
|
||||||
if (builder.ambience < 0)
|
|
||||||
{
|
|
||||||
builder.ambience = 0;
|
|
||||||
}
|
|
||||||
if (builder.ambience > 1)
|
|
||||||
{
|
|
||||||
builder.ambience = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-size"))
|
|
||||||
{
|
|
||||||
int lmDims;
|
|
||||||
|
|
||||||
if (argv[arg + 1] == NULL)
|
|
||||||
{
|
|
||||||
Error("Specify value for -size\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lmDims = atoi(argv[++arg]);
|
|
||||||
if (lmDims <= 0)
|
|
||||||
{
|
|
||||||
lmDims = 1;
|
|
||||||
}
|
|
||||||
if (lmDims > LIGHTMAP_MAX_SIZE)
|
|
||||||
{
|
|
||||||
lmDims = LIGHTMAP_MAX_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
lmDims = kexMath::RoundPowerOfTwo(lmDims);
|
|
||||||
|
|
||||||
builder.textureWidth = lmDims;
|
|
||||||
builder.textureHeight = lmDims;
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-threads"))
|
|
||||||
{
|
|
||||||
kexWorker::maxWorkThreads = atoi(argv[++arg]);
|
|
||||||
kexMath::Clamp(kexWorker::maxWorkThreads, 1, MAX_THREADS);
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-config"))
|
|
||||||
{
|
|
||||||
configFile = argv[++arg];
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[arg], "-writetga"))
|
|
||||||
{
|
|
||||||
bWriteTGA = true;
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv[arg] == NULL)
|
|
||||||
{
|
|
||||||
printf("Usage: dlight [options] [wadfile]\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wadFile.Open(argv[arg]))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// concat the base path to light def file if there is none
|
|
||||||
if (configFile.IndexOf("\\") == -1 && configFile.IndexOf("/") == -1)
|
|
||||||
{
|
|
||||||
configFile = basePath + configFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
int starttime = (int)GetSeconds();
|
|
||||||
|
|
||||||
printf("---------------- Parsing config file ----------------\n\n");
|
|
||||||
doomMap.ParseConfigFile(configFile.c_str());
|
|
||||||
|
|
||||||
printf("------------- Building level structures -------------\n\n");
|
|
||||||
wadFile.SetCurrentMap(map);
|
|
||||||
doomMap.BuildMapFromWad(wadFile);
|
|
||||||
|
|
||||||
printf("----------- Allocating surfaces from level ----------\n\n");
|
|
||||||
Surface_AllocateFromMap(doomMap);
|
|
||||||
|
|
||||||
printf("---------------- Allocating lights ----------------\n\n");
|
|
||||||
doomMap.CreateLights();
|
|
||||||
|
|
||||||
printf("---------------- Creating lightmaps ---------------\n\n");
|
|
||||||
builder.CreateLightmaps(doomMap);
|
|
||||||
doomMap.CleanupThingLights();
|
|
||||||
|
|
||||||
if (bWriteTGA)
|
|
||||||
{
|
|
||||||
builder.WriteTexturesToTGA();
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("------------------ Rebuilding wad ----------------\n\n");
|
|
||||||
wadFile.CreateBackup();
|
|
||||||
|
|
||||||
lmLump = wadFile.GetLumpFromName(Va("LM_MAP%02d", wadFile.currentmap));
|
|
||||||
|
|
||||||
if (lmLump)
|
|
||||||
{
|
|
||||||
int lumpnum = lmLump - wadFile.lumps;
|
|
||||||
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_LABEL);
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_CELLS);
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_SUN);
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_SURFS);
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_TXCRD);
|
|
||||||
ignoreLumps.Push(lumpnum + ML_LM_LMAPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
outWadFile.InitForWrite();
|
|
||||||
outWadFile.CopyLumpsFromWadFile(wadFile, ignoreLumps);
|
|
||||||
outWadFile.AddLump(Va("LM_MAP%02d", wadFile.currentmap), 0, NULL);
|
|
||||||
|
|
||||||
builder.AddLightGridLump(outWadFile);
|
|
||||||
builder.AddLightmapLumps(outWadFile);
|
|
||||||
|
|
||||||
printf("------------- Writing %s -------------\n\n", wadFile.wadName.c_str());
|
|
||||||
outWadFile.Write(wadFile.wadName);
|
|
||||||
outWadFile.Close();
|
|
||||||
wadFile.Close();
|
|
||||||
|
|
||||||
printf("----------------- Shutting down -----------------\n\n");
|
|
||||||
Mem_Purge(hb_static);
|
|
||||||
|
|
||||||
int proctime = (int)GetSeconds() - starttime;
|
|
||||||
printf("\nBuild time: %d:%02d:%02d\n",
|
|
||||||
proctime / 3600, (proctime / 60) % 60, proctime % 60);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,75 +1,10 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Note: this is a modified version of dlight. It is not the original software.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
|
||||||
// svkaiser@gmail.com
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would be
|
|
||||||
// appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
// misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <thread>
|
#include <functional>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
// There's a race condition in the code that causes it to sometimes fail if using multiple threads
|
|
||||||
//#define MAX_THREADS 128
|
|
||||||
#define MAX_THREADS 1
|
|
||||||
|
|
||||||
class kexWorker;
|
|
||||||
|
|
||||||
typedef void(*jobFunc_t)(void*, int);
|
|
||||||
|
|
||||||
struct jobFuncArgs_t
|
|
||||||
{
|
|
||||||
kexWorker *worker;
|
|
||||||
void *data;
|
|
||||||
int jobID;
|
|
||||||
};
|
|
||||||
|
|
||||||
class kexWorker
|
class kexWorker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
kexWorker();
|
static void RunJob(int count, std::function<void(int i)> callback);
|
||||||
~kexWorker();
|
|
||||||
|
|
||||||
void RunThreads(const int count, void *data, jobFunc_t jobFunc);
|
|
||||||
void LockMutex();
|
|
||||||
void UnlockMutex();
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
bool FinishedAllJobs() { return jobsWorked == numWorkLoad; }
|
|
||||||
int DispatchJob() { int j = jobsWorked; jobsWorked++; return j; }
|
|
||||||
void RunJob(void *data, const int jobID) { job(data, jobID); }
|
|
||||||
|
|
||||||
jobFuncArgs_t *Args(const int id) { return &jobArgs[id]; }
|
|
||||||
const int JobsWorked() const { return jobsWorked; }
|
|
||||||
|
|
||||||
static int maxWorkThreads;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::thread threads[MAX_THREADS];
|
|
||||||
jobFuncArgs_t jobArgs[MAX_THREADS];
|
|
||||||
std::mutex mutex;
|
|
||||||
jobFunc_t job;
|
|
||||||
int jobsWorked;
|
|
||||||
int numWorkLoad;
|
|
||||||
};
|
};
|
||||||
|
|
292
src/main.cpp
292
src/main.cpp
|
@ -53,6 +53,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "framework/zdray.h"
|
#include "framework/zdray.h"
|
||||||
#include "wad/wad.h"
|
#include "wad/wad.h"
|
||||||
|
@ -113,6 +114,9 @@ bool GLOnly = true;// false;
|
||||||
bool V5GLNodes = false;
|
bool V5GLNodes = false;
|
||||||
bool HaveSSE1, HaveSSE2;
|
bool HaveSSE1, HaveSSE2;
|
||||||
int SSELevel;
|
int SSELevel;
|
||||||
|
int NumThreads = 0;
|
||||||
|
int LMDims = LIGHTMAP_MAX_SIZE;
|
||||||
|
int Samples = 8;
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
@ -148,6 +152,9 @@ static option long_opts[] =
|
||||||
{"no-sse", no_argument, 0, 1002},
|
{"no-sse", no_argument, 0, 1002},
|
||||||
{"no-sse2", no_argument, 0, 1003},
|
{"no-sse2", no_argument, 0, 1003},
|
||||||
{"comments", no_argument, 0, 'c'},
|
{"comments", no_argument, 0, 'c'},
|
||||||
|
{"threads", required_argument, 0, 'j'},
|
||||||
|
{"samples", required_argument, 0, 'Q'},
|
||||||
|
{"size", required_argument, 0, 'S'},
|
||||||
{0,0,0,0}
|
{0,0,0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -426,6 +433,21 @@ static void ParseArgs(int argc, char **argv)
|
||||||
case 1003: // Disable only SSE2 ClassifyLine routine
|
case 1003: // Disable only SSE2 ClassifyLine routine
|
||||||
HaveSSE2 = false;
|
HaveSSE2 = false;
|
||||||
break;
|
break;
|
||||||
|
case 'j':
|
||||||
|
NumThreads = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
Samples = atoi(optarg);
|
||||||
|
if (Samples <= 0) Samples = 1;
|
||||||
|
if (Samples > 128) Samples = 128;
|
||||||
|
Samples = kexMath::RoundPowerOfTwo(Samples);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
LMDims = atoi(optarg);
|
||||||
|
if (LMDims <= 0) LMDims = 1;
|
||||||
|
if (LMDims > LIGHTMAP_MAX_SIZE) LMDims = LIGHTMAP_MAX_SIZE;
|
||||||
|
LMDims = kexMath::RoundPowerOfTwo(LMDims);
|
||||||
|
break;
|
||||||
case 1000:
|
case 1000:
|
||||||
ShowUsage();
|
ShowUsage();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -466,6 +488,11 @@ static void ShowUsage()
|
||||||
" -s, --split-cost=NNN Cost for splitting segs (default %d)\n"
|
" -s, --split-cost=NNN Cost for splitting segs (default %d)\n"
|
||||||
" -d, --diagonal-cost=NNN Cost for avoiding diagonal splitters (default %d)\n"
|
" -d, --diagonal-cost=NNN Cost for avoiding diagonal splitters (default %d)\n"
|
||||||
" -P, --no-polyobjs Do not check for polyobject subsector splits\n"
|
" -P, --no-polyobjs Do not check for polyobject subsector splits\n"
|
||||||
|
" -j, --threads=NNN Number of threads used for raytracing (default %d)\n"
|
||||||
|
" -Q, --samples=NNN Set texel sampling size (lowest = higher quaility but\n"
|
||||||
|
" slow compile time) must be in powers of two\n"
|
||||||
|
" -S, --size=NNN lightmap texture dimensions for width and height\n"
|
||||||
|
" must be in powers of two (1, 2, 4, 8, 16, etc)\n"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
" -v, --view View the nodes\n"
|
" -v, --view View the nodes\n"
|
||||||
#endif
|
#endif
|
||||||
|
@ -481,6 +508,7 @@ static void ShowUsage()
|
||||||
, MaxSegs /* Partition size */
|
, MaxSegs /* Partition size */
|
||||||
, SplitCost
|
, SplitCost
|
||||||
, AAPreference
|
, AAPreference
|
||||||
|
, (int)std::thread::hardware_concurrency()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,10 +706,6 @@ static void CheckSSE()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Warn
|
|
||||||
//
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void Warn(const char *format, ...)
|
void Warn(const char *format, ...)
|
||||||
|
@ -697,3 +721,263 @@ void Warn(const char *format, ...)
|
||||||
vprintf(format, marker);
|
vprintf(format, marker);
|
||||||
va_end(marker);
|
va_end(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Error(const char *error, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start(argptr, error);
|
||||||
|
vprintf(error, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
printf("\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Va(const char *str, ...)
|
||||||
|
{
|
||||||
|
va_list v;
|
||||||
|
static char vastr[1024];
|
||||||
|
|
||||||
|
va_start(v, str);
|
||||||
|
vsprintf(vastr, str, v);
|
||||||
|
va_end(v);
|
||||||
|
|
||||||
|
return vastr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delay(int ms)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t GetSeconds()
|
||||||
|
{
|
||||||
|
return time(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // Old dlight main function
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
kexWadFile wadFile;
|
||||||
|
kexWadFile outWadFile;
|
||||||
|
FLevel doomMap;
|
||||||
|
lump_t *lmLump;
|
||||||
|
kexArray<int> ignoreLumps;
|
||||||
|
kexLightmapBuilder builder;
|
||||||
|
kexStr configFile("strife_sve.cfg");
|
||||||
|
bool bWriteTGA;
|
||||||
|
int map = 1;
|
||||||
|
int arg = 1;
|
||||||
|
|
||||||
|
printf("DLight (c) 2013-2014 Samuel Villarreal\n\n");
|
||||||
|
|
||||||
|
if (argc < 1 || argv[1] == NULL)
|
||||||
|
{
|
||||||
|
printf("Usage: dlight [options] [wadfile]\n");
|
||||||
|
printf("Use -help for list of options\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
basePath = argv[0];
|
||||||
|
basePath.StripFile();
|
||||||
|
|
||||||
|
bWriteTGA = false;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (!strcmp(argv[arg], "-help"))
|
||||||
|
{
|
||||||
|
printf("Options:\n");
|
||||||
|
printf("-help: displays all known options\n");
|
||||||
|
printf("-map: process lightmap for MAP##\n");
|
||||||
|
printf("-samples: set texel sampling size (lowest = higher quaility but\n");
|
||||||
|
printf(" slow compile time) must be in powers of two\n");
|
||||||
|
printf("-ambience: set global ambience value for lightmaps (0.0 - 1.0)\n");
|
||||||
|
printf("-size: lightmap texture dimentions for width and height\n");
|
||||||
|
printf(" must be in powers of two (1, 2, 4, 8, 16, etc)\n");
|
||||||
|
printf("-threads: set total number of threads (1 min, 128 max)\n");
|
||||||
|
printf("-config: specify a config file to parse (default: strife_sve.cfg)\n");
|
||||||
|
printf("-writetga: dumps lightmaps to targa (.TGA) files\n");
|
||||||
|
arg++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-map"))
|
||||||
|
{
|
||||||
|
if (argv[arg + 1] == NULL)
|
||||||
|
{
|
||||||
|
Error("Specify map number for -map\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
map = atoi(argv[++arg]);
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-samples"))
|
||||||
|
{
|
||||||
|
if (argv[arg + 1] == NULL)
|
||||||
|
{
|
||||||
|
Error("Specify value for -samples\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.samples = atoi(argv[++arg]);
|
||||||
|
if (builder.samples <= 0)
|
||||||
|
{
|
||||||
|
builder.samples = 1;
|
||||||
|
}
|
||||||
|
if (builder.samples > 128)
|
||||||
|
{
|
||||||
|
builder.samples = 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.samples = kexMath::RoundPowerOfTwo(builder.samples);
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-ambience"))
|
||||||
|
{
|
||||||
|
if (argv[arg + 1] == NULL)
|
||||||
|
{
|
||||||
|
Error("Specify value for -ambience\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.ambience = (float)atof(argv[++arg]);
|
||||||
|
if (builder.ambience < 0)
|
||||||
|
{
|
||||||
|
builder.ambience = 0;
|
||||||
|
}
|
||||||
|
if (builder.ambience > 1)
|
||||||
|
{
|
||||||
|
builder.ambience = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-size"))
|
||||||
|
{
|
||||||
|
int lmDims;
|
||||||
|
|
||||||
|
if (argv[arg + 1] == NULL)
|
||||||
|
{
|
||||||
|
Error("Specify value for -size\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lmDims = atoi(argv[++arg]);
|
||||||
|
if (lmDims <= 0)
|
||||||
|
{
|
||||||
|
lmDims = 1;
|
||||||
|
}
|
||||||
|
if (lmDims > LIGHTMAP_MAX_SIZE)
|
||||||
|
{
|
||||||
|
lmDims = LIGHTMAP_MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lmDims = kexMath::RoundPowerOfTwo(lmDims);
|
||||||
|
|
||||||
|
builder.textureWidth = lmDims;
|
||||||
|
builder.textureHeight = lmDims;
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-threads"))
|
||||||
|
{
|
||||||
|
kexWorker::maxWorkThreads = atoi(argv[++arg]);
|
||||||
|
kexMath::Clamp(kexWorker::maxWorkThreads, 1, MAX_THREADS);
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-config"))
|
||||||
|
{
|
||||||
|
configFile = argv[++arg];
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "-writetga"))
|
||||||
|
{
|
||||||
|
bWriteTGA = true;
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[arg] == NULL)
|
||||||
|
{
|
||||||
|
printf("Usage: dlight [options] [wadfile]\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wadFile.Open(argv[arg]))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// concat the base path to light def file if there is none
|
||||||
|
if (configFile.IndexOf("\\") == -1 && configFile.IndexOf("/") == -1)
|
||||||
|
{
|
||||||
|
configFile = basePath + configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
int starttime = (int)GetSeconds();
|
||||||
|
|
||||||
|
printf("---------------- Parsing config file ----------------\n\n");
|
||||||
|
doomMap.ParseConfigFile(configFile.c_str());
|
||||||
|
|
||||||
|
printf("------------- Building level structures -------------\n\n");
|
||||||
|
wadFile.SetCurrentMap(map);
|
||||||
|
doomMap.BuildMapFromWad(wadFile);
|
||||||
|
|
||||||
|
printf("----------- Allocating surfaces from level ----------\n\n");
|
||||||
|
Surface_AllocateFromMap(doomMap);
|
||||||
|
|
||||||
|
printf("---------------- Allocating lights ----------------\n\n");
|
||||||
|
doomMap.CreateLights();
|
||||||
|
|
||||||
|
printf("---------------- Creating lightmaps ---------------\n\n");
|
||||||
|
builder.CreateLightmaps(doomMap);
|
||||||
|
doomMap.CleanupThingLights();
|
||||||
|
|
||||||
|
if (bWriteTGA)
|
||||||
|
{
|
||||||
|
builder.WriteTexturesToTGA();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("------------------ Rebuilding wad ----------------\n\n");
|
||||||
|
wadFile.CreateBackup();
|
||||||
|
|
||||||
|
lmLump = wadFile.GetLumpFromName(Va("LM_MAP%02d", wadFile.currentmap));
|
||||||
|
|
||||||
|
if (lmLump)
|
||||||
|
{
|
||||||
|
int lumpnum = lmLump - wadFile.lumps;
|
||||||
|
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_LABEL);
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_CELLS);
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_SUN);
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_SURFS);
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_TXCRD);
|
||||||
|
ignoreLumps.Push(lumpnum + ML_LM_LMAPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
outWadFile.InitForWrite();
|
||||||
|
outWadFile.CopyLumpsFromWadFile(wadFile, ignoreLumps);
|
||||||
|
outWadFile.AddLump(Va("LM_MAP%02d", wadFile.currentmap), 0, NULL);
|
||||||
|
|
||||||
|
builder.AddLightGridLump(outWadFile);
|
||||||
|
builder.AddLightmapLumps(outWadFile);
|
||||||
|
|
||||||
|
printf("------------- Writing %s -------------\n\n", wadFile.wadName.c_str());
|
||||||
|
outWadFile.Write(wadFile.wadName);
|
||||||
|
outWadFile.Close();
|
||||||
|
wadFile.Close();
|
||||||
|
|
||||||
|
printf("----------------- Shutting down -----------------\n\n");
|
||||||
|
Mem_Purge(hb_static);
|
||||||
|
|
||||||
|
int proctime = (int)GetSeconds() - starttime;
|
||||||
|
printf("\nBuild time: %d:%02d:%02d\n",
|
||||||
|
proctime / 3600, (proctime / 60) % 60, proctime % 60);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue