Skip to content

Commit

Permalink
Refactor: Replaced superblock_t::bbox with an AABox
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 12, 2012
1 parent f0898e2 commit 2b6accd
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 93 deletions.
5 changes: 3 additions & 2 deletions doomsday/engine/portable/include/bsp_superblock.h
Expand Up @@ -30,6 +30,7 @@
#ifndef LIBDENG_MAP_BSP_SUPERBLOCK
#define LIBDENG_MAP_BSP_SUPERBLOCK

#include "de_platform.h"
#include "bsp_intersection.h"

typedef struct superblock_s {
Expand All @@ -38,8 +39,8 @@ typedef struct superblock_s {

// Coordinates on map for this block, from lower-left corner to
// upper-right corner. Pseudo-inclusive, i.e (x,y) is inside block
// if and only if BOXLEFT <= x < BOXRIGHT and BOXBOTTOM <= y < BOXTOP.
int bbox[4];
// if and only if minX <= x < maxX and minY <= y < maxY.
AABox aaBox;

// Sub-blocks. NULL when empty. [0] has the lower coordinates, and
// [1] has the higher coordinates. Division of a square always
Expand Down
23 changes: 19 additions & 4 deletions doomsday/engine/portable/include/p_maputil.h
Expand Up @@ -62,10 +62,25 @@ int P_PointOnLinedefSide2(double pointX, double pointY,
int P_BoxOnLineSide(const AABoxf* box, const LineDef* ld);
int P_BoxOnLineSide2(float xl, float xh, float yl, float yh,
const LineDef *ld);
int P_BoxOnLineSide3(const int bbox[4], double lineSX,
double lineSY, double lineDX, double lineDY,
double linePerp, double lineLength,
double epsilon);

/**
* Check the spatial relationship between the given box and a partitioning line.
*
* @param bbox Ptr to the box being tested.
* @param lineSX X coordinate of the start of the line.
* @param lineSY Y coordinate of the end of the line.
* @param lineDX X delta of the line (slope).
* @param lineDY Y delta of the line (slope).
* @param linePerp Perpendicular d of the line.
* @param lineLength Length of the line.
* @param epsilon Points within this distance will be considered equal.
*
* @return @c <0= bbox is wholly on the left side.
* @c 0= line intersects bbox.
* @c >0= bbox wholly on the right side.
*/
int P_BoxOnLineSide3(const AABox* aaBox, double lineSX, double lineSY, double lineDX,
double lineDY, double linePerp, double lineLength, double epsilon);

void P_MakeDivline(const LineDef* lineDef, divline_t* divline);

Expand Down
98 changes: 67 additions & 31 deletions doomsday/engine/portable/src/bsp_main.c
Expand Up @@ -43,31 +43,63 @@ void BSP_Register(void)
C_VAR_INT("bsp-factor", &bspFactor, CVF_NO_MAX, 0, 0);
}

static void findMapLimits(GameMap* src, int* bbox)
static void initAABoxFromEditableLineDefVertexes(AABoxf* aaBox, const LineDef* line)
{
uint i;
const double* from = line->L_v1->buildData.pos;
const double* to = line->L_v2->buildData.pos;
aaBox->minX = MIN_OF(from[VX], to[VX]);
aaBox->minY = MIN_OF(from[VY], to[VY]);
aaBox->maxX = MAX_OF(from[VX], to[VX]);
aaBox->maxY = MAX_OF(from[VY], to[VY]);
}

typedef struct {
AABoxf bounds;
boolean initialized;
} findmapboundsparams_t;

static int findMapBoundsIterator(LineDef* line, void* parameters)
{
findmapboundsparams_t* p = (findmapboundsparams_t*) parameters;
AABoxf lineAABox;
assert(p);

M_ClearBox(bbox);
// Do not consider zero-length LineDefs.
if(line->buildData.mlFlags & MLF_ZEROLENGTH) return false; // Continue iteration.

for(i = 0; i < src->numLineDefs; ++i)
initAABoxFromEditableLineDefVertexes(&lineAABox, line);
if(p->initialized)
{
LineDef* l = &src->lineDefs[i];
V2_AddToBox(p->bounds.arvec2, lineAABox.min);
}
else
{
V2_InitBox(p->bounds.arvec2, lineAABox.min);
p->initialized = true;
}
V2_AddToBox(p->bounds.arvec2, lineAABox.max);
return false; // Continue iteration.
}

if(!(l->buildData.mlFlags & MLF_ZEROLENGTH))
static void findMapBounds(GameMap* map, AABoxf* aaBox)
{
assert(map && aaBox);

if(GameMap_LineDefCount(map))
{
findmapboundsparams_t parm;
parm.initialized = false;
GameMap_LineDefIterator(map, findMapBoundsIterator, (void*)&parm);
if(parm.initialized)
{
double x1 = l->v[0]->buildData.pos[VX];
double y1 = l->v[0]->buildData.pos[VY];
double x2 = l->v[1]->buildData.pos[VX];
double y2 = l->v[1]->buildData.pos[VY];
int lX = (int) floor(MIN_OF(x1, x2));
int lY = (int) floor(MIN_OF(y1, y2));
int hX = (int) ceil(MAX_OF(x1, x2));
int hY = (int) ceil(MAX_OF(y1, y2));

M_AddToBox(bbox, lX, lY);
M_AddToBox(bbox, hX, hY);
V2_CopyBox(aaBox->arvec2, parm.bounds.arvec2);
return;
}
}

// Clear.
V2_Set(aaBox->min, DDMAXFLOAT, DDMAXFLOAT);
V2_Set(aaBox->max, DDMINFLOAT, DDMINFLOAT);
}

/**
Expand All @@ -79,29 +111,33 @@ static superblock_t* createInitialHEdges(GameMap* map)
{
uint startTime = Sys_GetRealTime();

uint i;
int bw, bh;
bsp_hedge_t* back, *front;
superblock_t* block;
int mapBounds[4];
AABoxf mapBoundsf;
AABox mapBounds;
int bw, bh;
uint i;

// Find maximal vertexes.
findMapLimits(map, mapBounds);
findMapBounds(map, &mapBoundsf);

mapBounds.minX = (int) floor(mapBoundsf.minX);
mapBounds.minY = (int) floor(mapBoundsf.minY);
mapBounds.maxX = (int) ceil(mapBoundsf.maxX);
mapBounds.maxY = (int) ceil(mapBoundsf.maxY);

VERBOSE2(
Con_Message("Map goes from (%d,%d) to (%d,%d)\n",
mapBounds[BOXLEFT], mapBounds[BOXBOTTOM],
mapBounds[BOXRIGHT], mapBounds[BOXTOP]) );
Con_Message("Map goes from [x:%f, y:%f] -> [x:%f, y:%f]\n",
mapBoundsf.minX, mapBoundsf.minY, mapBoundsf.maxX, mapBoundsf.maxY) );

block = BSP_SuperBlockCreate();
block->aaBox.minX = mapBounds.minX - (mapBounds.minX & 0x7);
block->aaBox.minY = mapBounds.minY - (mapBounds.minY & 0x7);
bw = ((mapBounds.maxX - block->aaBox.minX) / 128) + 1;
bh = ((mapBounds.maxY - block->aaBox.minY) / 128) + 1;

block->bbox[BOXLEFT] = mapBounds[BOXLEFT] - (mapBounds[BOXLEFT] & 0x7);
block->bbox[BOXBOTTOM] = mapBounds[BOXBOTTOM] - (mapBounds[BOXBOTTOM] & 0x7);
bw = ((mapBounds[BOXRIGHT] - block->bbox[BOXLEFT]) / 128) + 1;
bh = ((mapBounds[BOXTOP] - block->bbox[BOXBOTTOM]) / 128) + 1;

block->bbox[BOXRIGHT] = block->bbox[BOXLEFT] + 128 * M_CeilPow2(bw);
block->bbox[BOXTOP] = block->bbox[BOXBOTTOM] + 128 * M_CeilPow2(bh);
block->aaBox.maxX = block->aaBox.minX + 128 * M_CeilPow2(bw);
block->aaBox.maxY = block->aaBox.minY + 128 * M_CeilPow2(bh);

for(i = 0; i < map->numLineDefs; ++i)
{
Expand Down
40 changes: 19 additions & 21 deletions doomsday/engine/portable/src/bsp_node.c
Expand Up @@ -51,18 +51,16 @@ static __inline int pointOnHEdgeSide(double x, double y, const bsp_hedge_t* part
void BSP_AddHEdgeToSuperBlock(superblock_t* block, bsp_hedge_t* hEdge)
{
#define SUPER_IS_LEAF(s) \
((s)->bbox[BOXRIGHT] - (s)->bbox[BOXLEFT] <= 256 && \
(s)->bbox[BOXTOP] - (s)->bbox[BOXBOTTOM] <= 256)
((s)->aaBox.maxX - (s)->aaBox.minX <= 256 && \
(s)->aaBox.maxY - (s)->aaBox.minY <= 256)

for(;;)
{
int p1, p2;
int child;
int midPoint[2];
int p1, p2, child, midPoint[2];
superblock_t* sub;

midPoint[VX] = (block->bbox[BOXLEFT] + block->bbox[BOXRIGHT]) / 2;
midPoint[VY] = (block->bbox[BOXBOTTOM] + block->bbox[BOXTOP]) / 2;
midPoint[VX] = (block->aaBox.minX + block->aaBox.maxX) / 2;
midPoint[VY] = (block->aaBox.minY + block->aaBox.maxY) / 2;

// Update half-edge counts.
if(hEdge->lineDef)
Expand All @@ -77,8 +75,8 @@ void BSP_AddHEdgeToSuperBlock(superblock_t* block, bsp_hedge_t* hEdge)
return;
}

if(block->bbox[BOXRIGHT] - block->bbox[BOXLEFT] >=
block->bbox[BOXTOP] - block->bbox[BOXBOTTOM])
if(block->aaBox.maxX - block->aaBox.minX >=
block->aaBox.maxY - block->aaBox.minY)
{
// Block is wider than it is high, or square.
p1 = hEdge->v[0]->buildData.pos[VX] >= midPoint[VX];
Expand Down Expand Up @@ -113,22 +111,22 @@ void BSP_AddHEdgeToSuperBlock(superblock_t* block, bsp_hedge_t* hEdge)
block->subs[child] = sub = BSP_SuperBlockCreate();
sub->parent = block;

if(block->bbox[BOXRIGHT] - block->bbox[BOXLEFT] >=
block->bbox[BOXTOP] - block->bbox[BOXBOTTOM])
if(block->aaBox.maxX - block->aaBox.minX >=
block->aaBox.maxY - block->aaBox.minY)
{
sub->bbox[BOXLEFT] = (child? midPoint[VX] : block->bbox[BOXLEFT]);
sub->bbox[BOXBOTTOM] = block->bbox[BOXBOTTOM];
sub->aaBox.minX = (child? midPoint[VX] : block->aaBox.minX);
sub->aaBox.minY = block->aaBox.minY;

sub->bbox[BOXRIGHT] = (child? block->bbox[BOXRIGHT] : midPoint[VX]);
sub->bbox[BOXTOP] = block->bbox[BOXTOP];
sub->aaBox.maxX = (child? block->aaBox.maxX : midPoint[VX]);
sub->aaBox.maxY = block->aaBox.maxY;
}
else
{
sub->bbox[BOXLEFT] = block->bbox[BOXLEFT];
sub->bbox[BOXBOTTOM] = (child? midPoint[VY] : block->bbox[BOXBOTTOM]);
sub->aaBox.minX = block->aaBox.minX;
sub->aaBox.minY = (child? midPoint[VY] : block->aaBox.minY);

sub->bbox[BOXRIGHT] = block->bbox[BOXRIGHT];
sub->bbox[BOXTOP] = (child? block->bbox[BOXTOP] : midPoint[VY]);
sub->aaBox.maxX = block->aaBox.maxX;
sub->aaBox.maxY = (child? block->aaBox.maxY : midPoint[VY]);
}
}

Expand Down Expand Up @@ -546,8 +544,8 @@ boolean BuildNodes(superblock_t* hEdgeList, binarytree_t** parent, size_t depth,
hEdgeSet[LEFT] = (superblock_t *) BSP_SuperBlockCreate();

// Copy the bounding box of the edge list to the superblocks.
M_CopyBox(hEdgeSet[LEFT]->bbox, hEdgeList->bbox);
M_CopyBox(hEdgeSet[RIGHT]->bbox, hEdgeList->bbox);
memcpy(&hEdgeSet[LEFT]->aaBox, &hEdgeList->aaBox, sizeof(hEdgeSet[LEFT]->aaBox));
memcpy(&hEdgeSet[RIGHT]->aaBox, &hEdgeList->aaBox, sizeof(hEdgeSet[RIGHT]->aaBox));

// Divide the half-edges into two lists: left & right.
BSP_PartitionHEdges(hEdgeList, &partition, hEdgeSet[RIGHT], hEdgeSet[LEFT], cutList);
Expand Down
4 changes: 2 additions & 2 deletions doomsday/engine/portable/src/bsp_superblock.c
Expand Up @@ -315,8 +315,8 @@ static int evalPartitionWorker(const superblock_t* hEdgeList, bsp_hedge_t* part,
* half-edges within it at once. Only when the partition line intercepts the
* box do we need to go deeper into it.
*/
num = P_BoxOnLineSide3(hEdgeList->bbox, part->pSX, part->pSY, part->pDX, part->pDY,
part->pPerp, part->pLength, DIST_EPSILON);
num = P_BoxOnLineSide3(&hEdgeList->aaBox, part->pSX, part->pSY, part->pDX,
part->pDY, part->pPerp, part->pLength, DIST_EPSILON);

if(num < 0)
{
Expand Down
50 changes: 17 additions & 33 deletions doomsday/engine/portable/src/p_maputil.c
Expand Up @@ -245,37 +245,20 @@ int P_PointOnLinedefSide2(double pointX, double pointY, double lineDX,
return (perp < 0? -1 : +1);
}

/**
* Check the spatial relationship between the given box and a partitioning
* line.
*
* @param bbox Ptr to the box being tested.
* @param lineSX X coordinate of the start of the line.
* @param lineSY Y coordinate of the end of the line.
* @param lineDX X delta of the line (slope).
* @param lineDY Y delta of the line (slope).
* @param linePerp Perpendicular d of the line.
* @param lineLength Length of the line.
* @param epsilon Points within this distance will be considered equal.
*
* @return @c <0= bbox is wholly on the left side.
* @c 0= line intersects bbox.
* @c >0= bbox wholly on the right side.
*/
int P_BoxOnLineSide3(const int bbox[4], double lineSX, double lineSY,
double lineDX, double lineDY, double linePerp,
double lineLength, double epsilon)
int P_BoxOnLineSide3(const AABox* aaBox, double lineSX, double lineSY,
double lineDX, double lineDY, double linePerp, double lineLength, double epsilon)
{
#define IFFY_LEN 4.0
#define IFFY_LEN 4.0

int p1, p2;
double x1 = (double)bbox[BOXLEFT] - IFFY_LEN * 1.5;
double y1 = (double)bbox[BOXBOTTOM] - IFFY_LEN * 1.5;
double x2 = (double)bbox[BOXRIGHT] + IFFY_LEN * 1.5;
double y2 = (double)bbox[BOXTOP] + IFFY_LEN * 1.5;
double x1 = (double)aaBox->minX - IFFY_LEN * 1.5;
double y1 = (double)aaBox->minY - IFFY_LEN * 1.5;
double x2 = (double)aaBox->maxX + IFFY_LEN * 1.5;
double y2 = (double)aaBox->maxY + IFFY_LEN * 1.5;
int p1, p2;

if(FEQUAL(lineDX, 0))
{ // Horizontal.
{
// Horizontal.
p1 = (x1 > lineSX? +1 : -1);
p2 = (x2 > lineSX? +1 : -1);

Expand All @@ -286,7 +269,8 @@ int P_BoxOnLineSide3(const int bbox[4], double lineSX, double lineSY,
}
}
else if(FEQUAL(lineDY, 0))
{ // Vertical.
{
// Vertical.
p1 = (y1 < lineSY? +1 : -1);
p2 = (y2 < lineSY? +1 : -1);

Expand All @@ -297,19 +281,19 @@ int P_BoxOnLineSide3(const int bbox[4], double lineSX, double lineSY,
}
}
else if(lineDX * lineDY > 0)
{ // Positive slope.
{
// Positive slope.
p1 = P_PointOnLinedefSide2(x1, y2, lineDX, lineDY, linePerp, lineLength, epsilon);
p2 = P_PointOnLinedefSide2(x2, y1, lineDX, lineDY, linePerp, lineLength, epsilon);
}
else
{ // Negative slope.
{
// Negative slope.
p1 = P_PointOnLinedefSide2(x1, y1, lineDX, lineDY, linePerp, lineLength, epsilon);
p2 = P_PointOnLinedefSide2(x2, y2, lineDX, lineDY, linePerp, lineLength, epsilon);
}

if(p1 == p2)
return p1;

if(p1 == p2) return p1;
return 0;

#undef IFFY_LEN
Expand Down

0 comments on commit 2b6accd

Please sign in to comment.