mirror of
https://github.com/ZDoom/zdbsp.git
synced 2025-02-11 06:50:40 +00:00
ZDBSP fixes:
- MapSideDef.sector was declared signed but treated as unsigned. - Degenerate (one-dimensional) subsectors could throw away segs when output for GL nodes depending on the seg ordering. SVN r152 (trunk)
This commit is contained in:
parent
65cdd0323e
commit
3128c11fd1
8 changed files with 386 additions and 94 deletions
|
@ -27,7 +27,7 @@ struct MapSideDef
|
|||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
short sector;
|
||||
WORD sector;
|
||||
};
|
||||
|
||||
struct MapLineDef
|
||||
|
|
|
@ -117,7 +117,7 @@ DWORD FNodeBuilder::CreateSubsector (DWORD set, fixed_t bbox[4])
|
|||
|
||||
assert (set != DWORD_MAX);
|
||||
|
||||
#if defined(_DEBUG) || 1
|
||||
#if defined(_DEBUG)// || 1
|
||||
// Check for segs with duplicate start/end vertices
|
||||
DWORD s1, s2;
|
||||
|
||||
|
@ -192,8 +192,14 @@ void FNodeBuilder::CreateSubsectorsForReal ()
|
|||
qsort (&SegList[sub.firstline], sub.numlines, sizeof(int), SortSegs);
|
||||
|
||||
// Convert seg pointers into indices
|
||||
D(printf ("Output subsector %d:\n", Subsectors.Size()));
|
||||
for (size_t i = sub.firstline; i < SegList.Size(); ++i)
|
||||
{
|
||||
D(printf (" Seg %5d (%5d,%5d)-(%5d,%5d)\n", SegList[i].SegPtr - &Segs[0],
|
||||
Vertices[SegList[i].SegPtr->v1].x>>16,
|
||||
Vertices[SegList[i].SegPtr->v1].y>>16,
|
||||
Vertices[SegList[i].SegPtr->v2].x>>16,
|
||||
Vertices[SegList[i].SegPtr->v2].y>>16));
|
||||
SegList[i].SegNum = SegList[i].SegPtr - &Segs[0];
|
||||
}
|
||||
Subsectors.Push (sub);
|
||||
|
|
|
@ -19,11 +19,18 @@
|
|||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include "templates.h"
|
||||
|
||||
#if 0
|
||||
#define D(x) x
|
||||
#else
|
||||
#define D(x) do{}while(0)
|
||||
#endif
|
||||
|
||||
void FNodeBuilder::GetGLNodes (MapNodeEx *&outNodes, int &nodeCount,
|
||||
MapSegGLEx *&outSegs, int &segCount,
|
||||
MapSubsectorEx *&outSubs, int &subCount)
|
||||
|
@ -82,18 +89,31 @@ int FNodeBuilder::CloseSubsector (TArray<MapSegGLEx> &segs, int subsector)
|
|||
double accumx, accumy;
|
||||
fixed_t midx, midy;
|
||||
int i, j, first, max, count, firstVert;
|
||||
bool diffplanes;
|
||||
int firstplane;
|
||||
|
||||
first = Subsectors[subsector].firstline;
|
||||
max = first + Subsectors[subsector].numlines;
|
||||
count = 0;
|
||||
|
||||
accumx = accumy = 0.0;
|
||||
diffplanes = false;
|
||||
firstplane = Segs[SegList[first].SegNum].planenum;
|
||||
|
||||
// Calculate the midpoint of the subsector and also check for degenerate subsectors.
|
||||
// A subsector is degenerate if it exists in only one dimension, which can be
|
||||
// detected when all the segs lie in the same plane. This can happen if you have
|
||||
// outward-facing lines in the void that don't point toward any sector. (Some of the
|
||||
// polyobjects in Hexen are constructed like this.)
|
||||
for (i = first; i < max; ++i)
|
||||
{
|
||||
seg = &Segs[SegList[i].SegNum];
|
||||
accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x);
|
||||
accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y);
|
||||
if (firstplane != seg->planenum)
|
||||
{
|
||||
diffplanes = true;
|
||||
}
|
||||
}
|
||||
|
||||
midx = fixed_t(accumx / (max - first) / 2);
|
||||
|
@ -112,69 +132,228 @@ int FNodeBuilder::CloseSubsector (TArray<MapSegGLEx> &segs, int subsector)
|
|||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
printf ("%d: %5d(%5d,%5d)->%5d(%5d,%5d) - %3.3f\n", j,
|
||||
printf ("%d: %5d(%5d,%5d)->%5d(%5d,%5d) - %3.3f %d,%d\n", j,
|
||||
seg->v1, Vertices[seg->v1].x>>16, Vertices[seg->v1].y>>16,
|
||||
seg->v2, Vertices[seg->v2].x>>16, Vertices[seg->v2].y>>16,
|
||||
double(ang/2)*180/(1<<30));
|
||||
double(ang/2)*180/(1<<30),
|
||||
seg->planenum, seg->planefront);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
angle_t bestdiff = ANGLE_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
int bestj = -1;
|
||||
for (j = first; j < max; ++j)
|
||||
if (diffplanes)
|
||||
{ // A well-behaved subsector. Output the segs sorted by the angle formed by connecting
|
||||
// the subsector's center to their first vertex.
|
||||
|
||||
D(printf("Well behaved subsector\n"));
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
angle_t diff = prevAngle - ang;
|
||||
if (seg->v1 == prev->v2)
|
||||
angle_t bestdiff = ANGLE_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
int bestj = -1;
|
||||
for (j = first; j < max; ++j)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
angle_t diff = prevAngle - ang;
|
||||
if (seg->v1 == prev->v2)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
break;
|
||||
}
|
||||
if (diff < bestdiff && diff > 0)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
seg = bestseg;
|
||||
}
|
||||
if (prev->v2 != seg->v1)
|
||||
{
|
||||
// Add a new miniseg to connect the two segs
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, seg->v1);
|
||||
count++;
|
||||
}
|
||||
#if 0
|
||||
printf ("+%d\n", bestj);
|
||||
#endif
|
||||
prevAngle -= bestdiff;
|
||||
seg->storedseg = PushGLSeg (segs, seg);
|
||||
count++;
|
||||
prev = seg;
|
||||
if (seg->v2 == firstVert)
|
||||
{
|
||||
prev = seg;
|
||||
break;
|
||||
}
|
||||
if (diff < bestdiff && diff > 0)
|
||||
}
|
||||
#if 0
|
||||
printf ("\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // A degenerate subsector. These are handled in three stages:
|
||||
// Stage 1. Proceed in the same direction as the start seg until we
|
||||
// hit the seg furthest from it.
|
||||
// Stage 2. Reverse direction and proceed until we hit the seg
|
||||
// furthest from the start seg.
|
||||
// Stage 3. Reverse direction again and insert segs until we get
|
||||
// to the start seg.
|
||||
// A dot product serves to determine distance from the start seg.
|
||||
|
||||
D(printf("degenerate subsector\n"));
|
||||
seg = &Segs[SegList[first].SegNum];
|
||||
double x1 = Vertices[seg->v1].x;
|
||||
double y1 = Vertices[seg->v1].y;
|
||||
double dx = Vertices[seg->v2].x - x1, dx2;
|
||||
double dy = Vertices[seg->v2].y - y1, dy2;
|
||||
double lastdot = 0, dot;
|
||||
bool firstside = seg->planefront;
|
||||
|
||||
#if 0
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
printf ("Seg %d: dot %g\n", j, dot);
|
||||
}
|
||||
#endif
|
||||
// Stage 1. Go forward.
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = DBL_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, bestseg->v1);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
|
||||
// Stage 2. Go backward.
|
||||
lastdot = DBL_MAX;
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
seg = bestseg;
|
||||
double bestdot = -DBL_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront == firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot > bestdot && dot < lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, bestseg->v1);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
if (prev->v2 != seg->v1)
|
||||
|
||||
// Stage 3. Go forward again.
|
||||
lastdot = -DBL_MAX;
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
// Add a new miniseg to connect the two segs
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, seg->v1);
|
||||
count++;
|
||||
}
|
||||
#if 0
|
||||
printf ("+%d\n", bestj);
|
||||
#endif
|
||||
prevAngle -= bestdiff;
|
||||
seg->storedseg = PushGLSeg (segs, seg);
|
||||
count++;
|
||||
prev = seg;
|
||||
if (seg->v2 == firstVert)
|
||||
{
|
||||
prev = seg;
|
||||
break;
|
||||
double bestdot = 0;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != firstside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, bestseg->v1);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
if (prev->v2 != firstVert)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, firstVert);
|
||||
count++;
|
||||
}
|
||||
#if 0
|
||||
printf ("Output GL subsector %d:\n", subsector);
|
||||
for (i = segs.Size() - count; i < (int)segs.Size(); ++i)
|
||||
{
|
||||
printf (" Seg %5d%c(%5d,%5d)-(%5d,%5d)\n", i,
|
||||
segs[i].linedef == NO_INDEX ? '+' : ' ',
|
||||
Vertices[segs[i].v1].x>>16,
|
||||
Vertices[segs[i].v1].y>>16,
|
||||
Vertices[segs[i].v2].x>>16,
|
||||
Vertices[segs[i].v2].y>>16);
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -124,6 +124,8 @@ void FNodeBuilder::MakeSegsFromSides ()
|
|||
j = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = j;
|
||||
Vertices[seg.v2].segs2 = j;
|
||||
D(printf("Seg %4d: From line %d, side front (%5d,%5d)-(%5d,%5d)\n", j, i, Vertices[seg.v1].x>>16,
|
||||
Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -162,6 +164,8 @@ void FNodeBuilder::MakeSegsFromSides ()
|
|||
Segs[j-1].partner = j;
|
||||
Segs[j].partner = j-1;
|
||||
}
|
||||
D(printf("Seg %4d: From line %d, side back (%5d,%5d)-(%5d,%5d)\n", j, i, Vertices[seg.v1].x>>16,
|
||||
Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16));
|
||||
}
|
||||
else if (share2->linedef != share1->linedef)
|
||||
{
|
||||
|
@ -280,7 +284,7 @@ void FNodeBuilder::GroupSegPlanes ()
|
|||
}
|
||||
}
|
||||
|
||||
D(Printf ("%d planes from %d segs\n", planenum, Segs.Size()));
|
||||
D(printf ("%d planes from %d segs\n", planenum, Segs.Size()));
|
||||
|
||||
planenum = (planenum+7)/8;
|
||||
PlaneChecked.Reserve (planenum);
|
||||
|
|
|
@ -93,8 +93,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,6,0,0
|
||||
PRODUCTVERSION 1,6,0,0
|
||||
FILEVERSION 1,7,0,0
|
||||
PRODUCTVERSION 1,7,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -110,12 +110,12 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "ZDBSP Node Builder"
|
||||
VALUE "FileVersion", "1.6"
|
||||
VALUE "FileVersion", "1.7"
|
||||
VALUE "InternalName", "zdbsp"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2002,2003"
|
||||
VALUE "OriginalFilename", "zdbsp.exe"
|
||||
VALUE "ProductName", "ZDBSP"
|
||||
VALUE "ProductVersion", "1.6"
|
||||
VALUE "ProductVersion", "1.7"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
193
tarray.h
193
tarray.h
|
@ -3,7 +3,7 @@
|
|||
** Templated, automatically resizing array
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2001 Randy Heit
|
||||
** Copyright 1998-2005 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -36,11 +36,28 @@
|
|||
#define __TARRAY_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <new>
|
||||
|
||||
template <class T>
|
||||
class TArray
|
||||
{
|
||||
public:
|
||||
////////
|
||||
// This is a dummy constructor that does nothing. The purpose of this
|
||||
// is so you can create a global TArray in the data segment that gets
|
||||
// used by code before startup without worrying about the constructor
|
||||
// resetting it after it's already been used. You MUST NOT use it for
|
||||
// heap- or stack-allocated TArrays.
|
||||
enum ENoInit
|
||||
{
|
||||
NoInit
|
||||
};
|
||||
TArray (ENoInit dummy)
|
||||
{
|
||||
}
|
||||
////////
|
||||
TArray ()
|
||||
{
|
||||
Most = 0;
|
||||
|
@ -51,7 +68,11 @@ public:
|
|||
{
|
||||
Most = max;
|
||||
Count = 0;
|
||||
Array = new T[max];
|
||||
Array = (T *)malloc (sizeof(T)*max);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
TArray (const TArray<T> &other)
|
||||
{
|
||||
|
@ -63,7 +84,11 @@ public:
|
|||
{
|
||||
if (Array != NULL)
|
||||
{
|
||||
delete[] Array;
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
}
|
||||
free (Array);
|
||||
}
|
||||
DoCopy (other);
|
||||
}
|
||||
|
@ -72,20 +97,25 @@ public:
|
|||
~TArray ()
|
||||
{
|
||||
if (Array)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
}
|
||||
free (Array);
|
||||
Array = NULL;
|
||||
Count = 0;
|
||||
Most = 0;
|
||||
}
|
||||
}
|
||||
T &operator[] (size_t index) const
|
||||
T &operator[] (unsigned int index) const
|
||||
{
|
||||
return Array[index];
|
||||
}
|
||||
size_t Push (const T &item)
|
||||
unsigned int Push (const T &item)
|
||||
{
|
||||
if (Count >= Most)
|
||||
{
|
||||
Most = (Most >= 16) ? Most + Most / 2 : 16;
|
||||
Realloc (Count, Most);
|
||||
}
|
||||
Array[Count] = item;
|
||||
Grow (1);
|
||||
::new((void*)&Array[Count]) T(item);
|
||||
return Count++;
|
||||
}
|
||||
bool Pop (T &item)
|
||||
|
@ -93,26 +123,42 @@ public:
|
|||
if (Count > 0)
|
||||
{
|
||||
item = Array[--Count];
|
||||
Array[Count].~T();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Delete (int index)
|
||||
void Delete (unsigned int index)
|
||||
{
|
||||
if (index < Count-1)
|
||||
memmove (Array + index, Array + index + 1, (Count - index) * sizeof(T));
|
||||
else if (index < Count)
|
||||
Count--;
|
||||
}
|
||||
void Realloc (size_t count, size_t most)
|
||||
{
|
||||
T *copy = new T[most];
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
if (index < Count)
|
||||
{
|
||||
copy[i] = Array[i];
|
||||
Array[index].~T();
|
||||
memmove (&Array[index], &Array[index+1], sizeof(T)*(Count - index - 1));
|
||||
Count--;
|
||||
}
|
||||
}
|
||||
// Inserts an item into the array, shifting elements as needed
|
||||
void Insert (unsigned int index, const T &item)
|
||||
{
|
||||
if (index >= Count)
|
||||
{
|
||||
// Inserting somewhere past the end of the array, so we can
|
||||
// just add it without moving things.
|
||||
Resize (index + 1);
|
||||
::new ((void *)&Array[index]) T(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inserting somewhere in the middle of the array,
|
||||
// so make room for it
|
||||
Resize (Count + 1);
|
||||
|
||||
// Now move items from the index and onward out of the way
|
||||
memmove (&Array[index+1], &Array[index], sizeof(T)*(Count - index - 1));
|
||||
|
||||
// And put the new element in
|
||||
::new ((void *)&Array[index]) T(item);
|
||||
}
|
||||
delete[] Array;
|
||||
Array = copy;
|
||||
}
|
||||
void ShrinkToFit ()
|
||||
{
|
||||
|
@ -129,70 +175,82 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
Realloc (Count, Most);
|
||||
DoResize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow Array to be large enough to hold amount more entries without
|
||||
// further growing.
|
||||
void Grow (size_t amount)
|
||||
void Grow (unsigned int amount)
|
||||
{
|
||||
if (Count + amount > Most)
|
||||
{
|
||||
const size_t choicea = Count + amount;
|
||||
const size_t choiceb = Most + Most/2;
|
||||
const unsigned int choicea = Count + amount;
|
||||
const unsigned int choiceb = Most = (Most >= 16) ? Most + Most / 2 : 16;
|
||||
Most = (choicea > choiceb ? choicea : choiceb);
|
||||
Realloc (Count, Most);
|
||||
DoResize ();
|
||||
}
|
||||
}
|
||||
// Resize Array so that it has exactly amount entries in use.
|
||||
void Resize (size_t amount)
|
||||
void Resize (unsigned int amount)
|
||||
{
|
||||
if (Count < amount)
|
||||
{
|
||||
// Adding new entries
|
||||
Grow (amount - Count);
|
||||
for (unsigned int i = Count; i < amount; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
}
|
||||
else if (Count > amount)
|
||||
else if (Count != amount)
|
||||
{
|
||||
Count = amount;
|
||||
// Deleting old entries
|
||||
DoDelete (amount, Count - 1);
|
||||
}
|
||||
Count = amount;
|
||||
}
|
||||
// Reserves amount entries at the end of the array, but does nothing
|
||||
// with them.
|
||||
size_t Reserve (size_t amount)
|
||||
unsigned int Reserve (unsigned int amount)
|
||||
{
|
||||
if (Count + amount > Most)
|
||||
{
|
||||
Grow (amount);
|
||||
}
|
||||
size_t place = Count;
|
||||
Grow (amount);
|
||||
unsigned int place = Count;
|
||||
Count += amount;
|
||||
return place;
|
||||
}
|
||||
size_t Size () const
|
||||
unsigned int Size () const
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
size_t Max () const
|
||||
unsigned int Max () const
|
||||
{
|
||||
return Most;
|
||||
}
|
||||
void Clear ()
|
||||
{
|
||||
Count = 0;
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
Count = 0;
|
||||
}
|
||||
}
|
||||
private:
|
||||
T *Array;
|
||||
size_t Most;
|
||||
size_t Count;
|
||||
unsigned int Most;
|
||||
unsigned int Count;
|
||||
|
||||
void DoCopy (const TArray<T> &other)
|
||||
{
|
||||
Most = Count = other.Count;
|
||||
if (Count != 0)
|
||||
{
|
||||
Array = new T[Most];
|
||||
for (size_t i = 0; i < Count; ++i)
|
||||
Array = (T *)malloc (sizeof(T)*Most);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
for (unsigned int i = 0; i < Count; ++i)
|
||||
{
|
||||
Array[i] = other.Array[i];
|
||||
}
|
||||
|
@ -202,6 +260,51 @@ private:
|
|||
Array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DoResize ()
|
||||
{
|
||||
size_t allocsize = sizeof(T)*Most;
|
||||
Array = (T *)realloc (Array, allocsize);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void DoDelete (unsigned int first, unsigned int last)
|
||||
{
|
||||
assert (last != ~0u);
|
||||
for (unsigned int i = first; i <= last; ++i)
|
||||
{
|
||||
Array[i].~T();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// An array with accessors that automatically grow the
|
||||
// array as needed. But can still be used as a normal
|
||||
// TArray if needed. Used by ACS world and global arrays.
|
||||
|
||||
template <class T>
|
||||
class TAutoGrowArray : public TArray<T>
|
||||
{
|
||||
public:
|
||||
T GetVal (unsigned int index)
|
||||
{
|
||||
if (index >= this->Size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (*this)[index];
|
||||
}
|
||||
void SetVal (unsigned int index, T val)
|
||||
{
|
||||
if (index >= this->Size())
|
||||
{
|
||||
this->Resize (index + 1);
|
||||
}
|
||||
(*this)[index] = val;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //__TARRAY_H__
|
||||
|
|
2
zdbsp.h
2
zdbsp.h
|
@ -8,7 +8,7 @@
|
|||
#include <limits.h>
|
||||
#include <exception>
|
||||
|
||||
#define ZDBSP_VERSION "1.6"
|
||||
#define ZDBSP_VERSION "1.7"
|
||||
|
||||
enum EBlockmapMode
|
||||
{
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
AdditionalIncludeDirectories="zlib"
|
||||
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\Debug/zdbsp.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
|
|
Loading…
Reference in a new issue