- remove memheap

This commit is contained in:
Magnus Norddahl 2018-11-03 17:12:39 +01:00
parent de8983a382
commit e37ea126ce
12 changed files with 35 additions and 718 deletions

View file

@ -153,7 +153,6 @@ set( SOURCES
src/lightmap/collision.cpp
src/lightmap/halffloat.cpp
src/lightmap/kexlib/binfile.cpp
src/lightmap/kexlib/memheap.cpp
src/lightmap/kexlib/math/angle.cpp
src/lightmap/kexlib/math/bounds.cpp
src/lightmap/kexlib/math/mathlib.cpp
@ -194,7 +193,6 @@ set( HEADERS
src/lightmap/collision.h
src/lightmap/halffloat.h
src/lightmap/kexlib/binfile.h
src/lightmap/kexlib/memheap.h
src/lightmap/kexlib/math/mathlib.h
)

View file

@ -353,7 +353,7 @@ struct FLevel
TArray<int> MeshSurfaces;
std::unique_ptr<TriangleMeshShape> CollisionMesh;
bool *bSkySectors = nullptr;
std::vector<bool> bSkySectors;
TArray<thingLight_t*> thingLights;
TArray<kexLightSurface*> lightSurfaces;

View file

@ -153,7 +153,6 @@ typedef union
#define d_inline
#endif
#include "kexlib/memheap.h"
#include "kexlib/math/mathlib.h"
void Error(const char *error, ...);

View file

@ -33,149 +33,6 @@
#include "lightmap/common.h"
#include "lightmap/kexlib/binfile.h"
kexBinFile::kexBinFile()
{
this->handle = NULL;
this->buffer = NULL;
this->bufferOffset = 0;
this->bOpened = false;
}
kexBinFile::~kexBinFile()
{
Close();
}
bool kexBinFile::Open(const char *file, kexHeapBlock &heapBlock)
{
if ((handle = fopen(file, "rb")))
{
size_t length;
fseek(handle, 0, SEEK_END);
length = ftell(handle);
fseek(handle, 0, SEEK_SET);
buffer = (byte*)Mem_Calloc(length + 1, heapBlock);
if (fread(buffer, 1, length, handle) == length)
{
if (length > 0)
{
bOpened = true;
bufferOffset = 0;
return true;
}
}
Mem_Free(buffer);
buffer = NULL;
fclose(handle);
}
return false;
}
bool kexBinFile::Create(const char *file)
{
if ((handle = fopen(file, "wb")))
{
bOpened = true;
bufferOffset = 0;
return true;
}
return false;
}
void kexBinFile::Close()
{
if (bOpened == false)
{
return;
}
if (handle)
{
fclose(handle);
handle = NULL;
if (buffer)
{
Mem_Free(buffer);
}
}
bOpened = false;
}
bool kexBinFile::Exists(const char *file)
{
FILE *fstream;
fstream = fopen(file, "r");
if (fstream != NULL)
{
fclose(fstream);
return true;
}
#ifdef KEX_WIN32
else
{
// If we can't open because the file is a directory, the
// "file" exists at least!
if (errno == 21)
{
return true;
}
}
#endif
return false;
}
void kexBinFile::Duplicate(const char *newFileName)
{
FILE *f;
if (bOpened == false)
{
return;
}
f = fopen(newFileName, "wb");
if (f == NULL)
{
return;
}
fwrite(buffer, Length(), 1, f);
fclose(f);
}
int kexBinFile::Length()
{
long savedpos;
long length;
if (bOpened == false)
{
return 0;
}
// save the current position in the file
savedpos = ftell(handle);
// jump to the end and find the length
fseek(handle, 0, SEEK_END);
length = ftell(handle);
// go back to the old location
fseek(handle, savedpos, SEEK_SET);
return length;
}
byte kexBinFile::Read8()
{
byte result;
@ -239,14 +96,7 @@ std::string kexBinFile::ReadString()
void kexBinFile::Write8(const byte val)
{
if (bOpened)
{
fwrite(&val, 1, 1, handle);
}
else
{
buffer[bufferOffset] = val;
}
bufferOffset++;
}
@ -297,7 +147,7 @@ int kexBinFile::GetOffsetValue(int id)
byte *kexBinFile::GetOffset(int id, byte *subdata, int *count)
{
byte *data = (subdata == NULL) ? buffer : subdata;
byte *data = (subdata == nullptr) ? buffer : subdata;
bufferOffset = GetOffsetValue(id);
byte *dataOffs = &data[bufferOffset];

View file

@ -33,16 +33,6 @@
class kexBinFile
{
public:
kexBinFile();
~kexBinFile();
bool Open(const char *file, kexHeapBlock &heapBlock = hb_static);
bool Create(const char *file);
void Close();
bool Exists(const char *file);
int Length();
void Duplicate(const char *newFileName);
byte Read8();
short Read16();
int Read32();
@ -58,18 +48,14 @@ public:
void WriteString(const std::string &val);
int GetOffsetValue(int id);
byte *GetOffset(int id, byte *subdata = NULL, int *count = NULL);
byte *GetOffset(int id, byte *subdata = nullptr, int *count = nullptr);
FILE *Handle() const { return handle; }
byte *Buffer() const { return buffer; }
void SetBuffer(byte *ptr) { buffer = ptr; }
byte *BufferAt() const { return &buffer[bufferOffset]; }
bool Opened() const { return bOpened; }
void SetOffset(const int offset) { bufferOffset = offset; }
private:
FILE *handle;
byte *buffer;
unsigned int bufferOffset;
bool bOpened;
byte *buffer = nullptr;
unsigned int bufferOffset = 0;
};

View file

@ -1,403 +0,0 @@
//-----------------------------------------------------------------------------
// 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: Memory Heap Management
//
//-----------------------------------------------------------------------------
#include "lightmap/common.h"
int kexHeap::numHeapBlocks = 0;
int kexHeap::currentHeapBlockID = -1;
kexHeapBlock *kexHeap::currentHeapBlock = NULL;
kexHeapBlock *kexHeap::blockList = NULL;
//
// common heap block types
//
kexHeapBlock hb_static("static", false, NULL, NULL);
kexHeapBlock hb_auto("auto", false, NULL, NULL);
kexHeapBlock hb_file("file", false, NULL, NULL);
kexHeapBlock hb_object("object", false, NULL, NULL);
//
// kexHeapBlock::kexHeapBlock
//
kexHeapBlock::kexHeapBlock(const char *name, bool bGarbageCollect,
blockFunc_t funcFree, blockFunc_t funcGC)
{
this->name = (char*)name;
this->freeFunc = funcFree;
this->gcFunc = funcGC;
this->blocks = NULL;
this->bGC = bGarbageCollect;
this->purgeID = kexHeap::numHeapBlocks++;
// add heap block to main block list
if (kexHeap::blockList)
{
if (kexHeap::blockList->prev)
{
kexHeap::blockList->prev->next = this;
this->prev = kexHeap::blockList->prev;
this->next = NULL;
kexHeap::blockList->prev = this;
}
else
{
kexHeap::blockList->prev = this;
kexHeap::blockList->next = this;
this->prev = kexHeap::blockList;
this->next = NULL;
}
}
else
{
kexHeap::blockList = this;
this->prev = NULL;
this->next = NULL;
}
}
//
// kexHeapBlock::~kexHeapBlock
//
kexHeapBlock::~kexHeapBlock()
{
}
//
// kexHeapBlock::operator[]
//
// Should be used with kexHeap::blockList only
//
kexHeapBlock *kexHeapBlock::operator[](int index)
{
if (kexHeap::currentHeapBlockID == index)
{
return kexHeap::currentHeapBlock;
}
kexHeapBlock *heapBlock = this;
for (int i = 0; i < index; i++)
{
heapBlock = heapBlock->next;
if (heapBlock == NULL)
{
return NULL;
}
}
kexHeap::currentHeapBlockID = index;
kexHeap::currentHeapBlock = heapBlock;
return heapBlock;
}
//
// kexHeap::AddBlock
//
void kexHeap::AddBlock(memBlock *block, kexHeapBlock *heapBlock)
{
block->prev = NULL;
block->next = heapBlock->blocks;
heapBlock->blocks = block;
block->heapBlock = heapBlock;
if (block->next != NULL)
{
block->next->prev = block;
}
}
//
// kexHeap::RemoveBlock
//
void kexHeap::RemoveBlock(memBlock *block)
{
if (block->prev == NULL)
{
block->heapBlock->blocks = block->next;
}
else
{
block->prev->next = block->next;
}
if (block->next != NULL)
{
block->next->prev = block->prev;
}
block->heapBlock = NULL;
}
//
// kexHeap::GetBlock
//
memBlock *kexHeap::GetBlock(void *ptr, const char *file, int line)
{
memBlock* block;
block = (memBlock*)((byte*)ptr - sizeof(memBlock));
if (block->heapTag != kexHeap::HeapTag)
{
Error("kexHeap::GetBlock: found a pointer without heap tag (%s:%d)", file, line);
}
return block;
}
//
// kexHeap::Malloc
//
void *kexHeap::Malloc(int size, kexHeapBlock &heapBlock, const char *file, int line)
{
memBlock *newblock;
assert(size > 0);
newblock = NULL;
if (!(newblock = (memBlock*)malloc(sizeof(memBlock) + size)))
{
Error("kexHeap::Malloc: failed on allocation of %u bytes (%s:%d)", size, file, line);
}
newblock->purgeID = heapBlock.purgeID;
newblock->heapTag = kexHeap::HeapTag;
newblock->size = size;
newblock->ptrRef = NULL;
kexHeap::AddBlock(newblock, &heapBlock);
return ((byte*)newblock) + sizeof(memBlock);
}
//
// kexHeap::Calloc
//
void *kexHeap::Calloc(int size, kexHeapBlock &heapBlock, const char *file, int line)
{
return memset(kexHeap::Malloc(size, heapBlock, file, line), 0, size);
}
//
// kexHeap::Realloc
//
void *kexHeap::Realloc(void *ptr, int size, kexHeapBlock &heapBlock, const char *file, int line)
{
memBlock *block;
memBlock *newblock;
if (!ptr)
{
return kexHeap::Malloc(size, heapBlock, file, line);
}
assert(size >= 0);
if (size == 0)
{
kexHeap::Free(ptr, file, line);
return NULL;
}
block = kexHeap::GetBlock(ptr, file, line);
newblock = NULL;
kexHeap::RemoveBlock(block);
block->next = NULL;
block->prev = NULL;
if (block->ptrRef)
{
*block->ptrRef = NULL;
}
if (!(newblock = (memBlock*)realloc(block, sizeof(memBlock) + size)))
{
Error("kexHeap::Realloc: failed on allocation of %u bytes (%s:%d)", size, file, line);
}
newblock->purgeID = heapBlock.purgeID;
newblock->heapTag = kexHeap::HeapTag;
newblock->size = size;
newblock->ptrRef = NULL;
kexHeap::AddBlock(newblock, &heapBlock);
return ((byte*)newblock) + sizeof(memBlock);
}
//
// kexHeap::Alloca
//
void *kexHeap::Alloca(int size, const char *file, int line)
{
return size == 0 ? NULL : kexHeap::Calloc(size, hb_auto, file, line);
}
//
// kexHeap::Free
//
void kexHeap::Free(void *ptr, const char *file, int line)
{
memBlock* block;
block = kexHeap::GetBlock(ptr, file, line);
if (block->ptrRef)
{
*block->ptrRef = NULL;
}
kexHeap::RemoveBlock(block);
// free back to system
free(block);
}
//
// kexHeap::Purge
//
void kexHeap::Purge(kexHeapBlock &heapBlock, const char *file, int line)
{
memBlock *block;
memBlock *next;
for (block = heapBlock.blocks; block != NULL;)
{
next = block->next;
if (block->heapTag != kexHeap::HeapTag)
{
Error("kexHeap::Purge: Purging without heap tag (%s:%d)", file, line);
}
if (block->ptrRef)
{
*block->ptrRef = NULL;
}
free(block);
block = next;
}
heapBlock.blocks = NULL;
}
//
// kexHeap::SetCacheRef
//
void kexHeap::SetCacheRef(void **ptr, const char *file, int line)
{
kexHeap::GetBlock(*ptr, file, line)->ptrRef = ptr;
}
//
// kexHeap::GarbageCollect
//
void kexHeap::GarbageCollect(const char *file, int line)
{
kexHeap::Purge(hb_auto, file, line);
}
//
// kexHeap::CheckBlocks
//
void kexHeap::CheckBlocks(const char *file, int line)
{
memBlock *block;
memBlock *prev;
kexHeapBlock *heapBlock;
for (heapBlock = kexHeap::blockList; heapBlock; heapBlock = heapBlock->next)
{
prev = NULL;
for (block = heapBlock->blocks; block != NULL; block = block->next)
{
if (block->heapTag != kexHeap::HeapTag)
{
Error("kexHeap::CheckBlocks: found block without heap tag (%s:%d)", file, line);
}
if (block->prev != prev)
{
Error("kexHeap::CheckBlocks: bad link list found (%s:%d)", file, line);
}
prev = block;
}
}
}
//
// kexHeap::Touch
//
void kexHeap::Touch(void *ptr, const char *file, int line)
{
}
//
// kexHeap::Usage
//
int kexHeap::Usage(const kexHeapBlock &heapBlock)
{
int bytes = 0;
memBlock *block;
for (block = heapBlock.blocks; block != NULL; block = block->next)
{
bytes += block->size;
}
return bytes;
}

View file

@ -1,111 +0,0 @@
//-----------------------------------------------------------------------------
// 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
typedef void(*blockFunc_t)(void*);
class kexHeapBlock;
struct memBlock
{
int heapTag;
int purgeID;
int size;
kexHeapBlock *heapBlock;
void **ptrRef;
memBlock *prev;
memBlock *next;
};
class kexHeapBlock
{
public:
kexHeapBlock(const char *name, bool bGarbageCollect,
blockFunc_t funcFree, blockFunc_t funcGC);
~kexHeapBlock();
kexHeapBlock *operator[](int index);
char *name;
memBlock *blocks;
bool bGC;
blockFunc_t freeFunc;
blockFunc_t gcFunc;
int purgeID;
kexHeapBlock *prev;
kexHeapBlock *next;
};
class kexHeap
{
public:
static void *Malloc(int size, kexHeapBlock &heapBlock, const char *file, int line);
static void *Calloc(int size, kexHeapBlock &heapBlock, const char *file, int line);
static void *Realloc(void *ptr, int size, kexHeapBlock &heapBlock, const char *file, int line);
static void *Alloca(int size, const char *file, int line);
static void Free(void *ptr, const char *file, int line);
static void Purge(kexHeapBlock &heapBlock, const char *file, int line);
static void GarbageCollect(const char *file, int line);
static void CheckBlocks(const char *file, int line);
static void Touch(void *ptr, const char *file, int line);
static int Usage(const kexHeapBlock &heapBlock);
static void SetCacheRef(void **ptr, const char *file, int line);
static int numHeapBlocks;
static kexHeapBlock *currentHeapBlock;
static int currentHeapBlockID;
static kexHeapBlock *blockList;
private:
static void AddBlock(memBlock *block, kexHeapBlock *heapBlock);
static void RemoveBlock(memBlock *block);
static memBlock *GetBlock(void *ptr, const char *file, int line);
static const int HeapTag = 0x03151983;
};
extern kexHeapBlock hb_static;
extern kexHeapBlock hb_auto;
extern kexHeapBlock hb_file;
extern kexHeapBlock hb_object;
#define Mem_Malloc(s, hb) (kexHeap::Malloc(s, hb, __FILE__,__LINE__))
#define Mem_Calloc(s, hb) (kexHeap::Calloc(s, hb, __FILE__,__LINE__))
#define Mem_Realloc(p, s, hb) (kexHeap::Realloc(p, s, hb, __FILE__,__LINE__))
#define Mem_Alloca(s) (kexHeap::Alloca(s, __FILE__,__LINE__))
#define Mem_Free(p) (kexHeap::Free(p, __FILE__,__LINE__))
#define Mem_Purge(hb) (kexHeap::Purge(hb, __FILE__,__LINE__))
#define Mem_GC() (kexHeap::GarbageCollect(__FILE__,__LINE__))
#define Mem_CheckBlocks() (kexHeap::CheckBlocks(__FILE__,__LINE__))
#define Mem_Touch(p) (kexHeap::Touch(p, __FILE__,__LINE__))
#define Mem_CacheRef(p) (kexHeap::SetCacheRef(p, __FILE__,__LINE__))
#define Mem_AllocStatic(s) (Mem_Calloc(s, hb_static))
#define Mem_Strdup(s, hb) (strcpy((char*)Mem_Malloc(strlen(s)+1, hb), s))
#define Mem_Strdupa(s) (strcpy((char*)Mem_Alloca(strlen(s)+1), s))

View file

@ -49,14 +49,13 @@ const kexVec3 kexLightmapBuilder::gridSize(64, 64, 128);
kexLightmapBuilder::kexLightmapBuilder()
{
this->textureWidth = 128;
this->textureHeight = 128;
this->allocBlocks = NULL;
this->numTextures = 0;
this->samples = 16;
this->extraSamples = 2;
this->ambience = 0.0f;
this->tracedTexels = 0;
textureWidth = 128;
textureHeight = 128;
numTextures = 0;
samples = 16;
extraSamples = 2;
ambience = 0.0f;
tracedTexels = 0;
}
kexLightmapBuilder::~kexLightmapBuilder()
@ -67,12 +66,10 @@ void kexLightmapBuilder::NewTexture()
{
numTextures++;
allocBlocks = (int**)Mem_Realloc(allocBlocks, sizeof(int*) * numTextures, hb_static);
allocBlocks[numTextures - 1] = (int*)Mem_Calloc(sizeof(int) * textureWidth, hb_static);
allocBlocks.push_back(new int[textureWidth]);
memset(allocBlocks.back(), 0, sizeof(int) * textureWidth);
memset(allocBlocks[numTextures - 1], 0, sizeof(int) * textureWidth);
uint16_t *texture = (uint16_t*)Mem_Calloc((textureWidth * textureHeight) * 3 * 2, hb_static);
uint16_t *texture = new uint16_t[textureWidth * textureHeight * 3];
textures.push_back(texture);
}
@ -87,7 +84,7 @@ bool kexLightmapBuilder::MakeRoomForBlock(const int width, const int height, int
*num = -1;
if (allocBlocks == NULL)
if (allocBlocks.empty())
{
return false;
}
@ -383,8 +380,7 @@ void kexLightmapBuilder::BuildSurfaceParams(surface_t *surface)
height = textureHeight;
}
surface->lightmapCoords = (float*)Mem_Calloc(sizeof(float) *
surface->numVerts * 2, hb_static);
surface->lightmapCoords = new float[surface->numVerts * 2];
surface->textureCoords[0] = tCoords[0];
surface->textureCoords[1] = tCoords[1];
@ -697,6 +693,7 @@ void kexLightmapBuilder::AddLightmapLump(FWadWriter &wadFile)
zout.Write(buffer.data(), lumpFile.BufferAt() - lumpFile.Buffer());
}
/*
void kexLightmapBuilder::WriteTexturesToTGA()
{
kexBinFile file;
@ -723,6 +720,7 @@ void kexLightmapBuilder::WriteTexturesToTGA()
file.Close();
}
}
*/
void kexLightmapBuilder::WriteMeshToOBJ()
{

View file

@ -45,7 +45,7 @@ public:
void TraceSurface(surface_t *surface);
void CreateLightmaps(FLevel &doomMap);
void LightSurface(const int surfid);
void WriteTexturesToTGA();
//void WriteTexturesToTGA();
void WriteMeshToOBJ();
void AddLightmapLump(FWadWriter &wadFile);
@ -65,7 +65,7 @@ private:
FLevel *map;
std::vector<uint16_t*> textures;
int **allocBlocks;
std::vector<int*> allocBlocks;
int numTextures;
int extraSamples;
int tracedTexels;

View file

@ -46,7 +46,7 @@ void FLevel::CheckSkySectors()
{
char name[9];
bSkySectors = (bool*)Mem_Calloc(sizeof(bool) * Sectors.Size(), hb_static);
bSkySectors.resize(Sectors.Size());
for (int i = 0; i < (int)Sectors.Size(); ++i)
{

View file

@ -78,9 +78,9 @@ static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
{
if (side->bottomtexture[0] != '-')
{
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
surf = new surface_t();
surf->numVerts = 4;
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
surf->verts.resize(4);
surf->verts[0].x = surf->verts[2].x = v1.x;
surf->verts[0].y = surf->verts[2].y = v1.y;
@ -120,9 +120,9 @@ static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
if (side->toptexture[0] != '-' || bSky)
{
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
surf = new surface_t();
surf->numVerts = 4;
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
surf->verts.resize(4);
surf->verts[0].x = surf->verts[2].x = v1.x;
surf->verts[0].y = surf->verts[2].y = v1.y;
@ -150,9 +150,9 @@ static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
// middle seg
if (back == NULL)
{
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
surf = new surface_t();
surf->numVerts = 4;
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
surf->verts.resize(4);
surf->verts[0].x = surf->verts[2].x = v1.x;
surf->verts[0].y = surf->verts[2].y = v1.y;
@ -205,9 +205,9 @@ static void CreateSubsectorSurfaces(FLevel &doomMap)
if (sector->controlsector)
continue;
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
surf = new surface_t();
surf->numVerts = sub->numlines;
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static);
surf->verts.resize(surf->numVerts);
// floor verts
for (j = 0; j < surf->numVerts; j++)
@ -226,9 +226,9 @@ static void CreateSubsectorSurfaces(FLevel &doomMap)
surfaces.push_back(surf);
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
surf = new surface_t();
surf->numVerts = sub->numlines;
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static);
surf->verts.resize(surf->numVerts);
if (doomMap.bSkySectors[sector - &doomMap.Sectors[0]])
{
@ -275,7 +275,7 @@ static bool IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2
void CreateSurfaces(FLevel &doomMap)
{
for (size_t i = 0; i < surfaces.size(); i++)
Mem_Free(surfaces[i]);
delete surfaces[i];
surfaces = {};
for (unsigned int i = 0; i < doomMap.Sectors.Size(); i++)

View file

@ -55,7 +55,7 @@ struct surface_t
kexVec3 textureCoords[2];
kexBBox bounds;
int numVerts;
kexVec3 *verts;
std::vector<kexVec3> verts;
float *lightmapCoords;
surfaceType_t type;
int typeIndex;