Skip to content

Commit

Permalink
BSP Builder|Refactor: Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 14, 2012
1 parent 00a74fc commit c56240a
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 58 deletions.
5 changes: 3 additions & 2 deletions doomsday/engine/portable/include/bsp_intersection.h
Expand Up @@ -36,13 +36,14 @@ struct superblock_s;
typedef struct hplanepartition_s {
double x, y;
double dX, dY;
double length;

LineDef* lineDef; // Not NULL if partition originated from a linedef.
LineDef* sourceLineDef;

double pSX, pSY;
double pDX, pDY;
double pPara, pPerp;
double pLength;
} HPlanePartition;

typedef struct hplaneintercept_s HPlaneIntercept;
Expand Down Expand Up @@ -89,7 +90,7 @@ void HPlaneIntercept_Print(HPlane* hPlane);
#endif

void BSP_InitHPlaneInterceptAllocator(void);
void BSP_ShutdownIntersectionAllocator(void);
void BSP_ShutdownHPlaneInterceptAllocator(void);

/**
* @todo the following functions do not belong in this module.
Expand Down
18 changes: 12 additions & 6 deletions doomsday/engine/portable/include/bsp_main.h
Expand Up @@ -62,11 +62,15 @@ typedef double angle_g;
struct hplane_s;
struct superblock_s;
struct hplanepartition_s;
struct hplaneintercept_s;
struct bsp_hedge_s;

/**
* An "intercept" remembers the vertex that touches a BS partition line (especially
* a new vertex that is created at a twin-edge split).
* Plain-old-data structure containing additional information for a half-edge
* half-plane intercept point where the geometry intersects (an incident vertex
* can be found here (or at there will be upon insertion.)).
*
* There is always a corresponding HPlaneIntercept in the owning HPlane.
*/
typedef struct hedgeintercept_s {
// Vertex in question.
Expand Down Expand Up @@ -99,14 +103,16 @@ void Bsp_PrintHEdgeIntercept(HEdgeIntercept* intercept);
#endif

/**
* Search the given list for an intersection, if found; return it.
* Search the given list for an intercept, if found; return it.
*
* @param list The list to be searched.
* @param vert Ptr to the intersection vertex to look for.
* @param vert Ptr to the vertex to look for.
*
* @return Ptr to the found intersection, else @c NULL;
* @return Ptr to the found intercept, else @c NULL;
*/
HEdgeIntercept* Bsp_HEdgeInterceptByVertex(struct hplane_s* hPlane, Vertex* v);
struct hplaneintercept_s* Bsp_HPlaneInterceptByVertex(struct hplane_s* hPlane, Vertex* vertex);

HEdgeIntercept* Bsp_HEdgeInterceptByVertex(struct hplane_s* hPlane, Vertex* vertex);

/**
* Analyze the intersection list, and add any needed minihedges to the given half-edge lists
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/portable/src/bsp_intersection.c
Expand Up @@ -394,7 +394,7 @@ void BSP_InitHPlaneInterceptAllocator(void)
}
}

void BSP_ShutdownIntersectionAllocator(void)
void BSP_ShutdownHPlaneInterceptAllocator(void)
{
if(usedIntercepts)
{
Expand Down
19 changes: 13 additions & 6 deletions doomsday/engine/portable/src/bsp_main.c
Expand Up @@ -333,7 +333,7 @@ boolean BSP_Build(GameMap* map, Vertex*** vertexes, uint* numVertexes)

// Free temporary storage.
BSP_ShutdownHEdgeAllocator();
BSP_ShutdownIntersectionAllocator();
BSP_ShutdownHPlaneInterceptAllocator();
BSP_ShutdownSuperBlockAllocator();

// How much time did we spend?
Expand All @@ -344,23 +344,23 @@ boolean BSP_Build(GameMap* map, Vertex*** vertexes, uint* numVertexes)

typedef struct {
Vertex* vertex;
HEdgeIntercept* found;
HPlaneIntercept* found;
} findintersectionforvertexworkerparams_t;

static int findIntersectionForVertexWorker(HPlaneIntercept* bi, void* parameters)
static int findIntersectionForVertexWorker(HPlaneIntercept* hpi, void* parameters)
{
HEdgeIntercept* inter = (HEdgeIntercept*) HPlaneIntercept_UserData(bi);
HEdgeIntercept* inter = (HEdgeIntercept*) HPlaneIntercept_UserData(hpi);
findintersectionforvertexworkerparams_t* p = (findintersectionforvertexworkerparams_t*) parameters;
assert(p);
if(inter->vertex == p->vertex)
{
p->found = inter;
p->found = hpi;
return true; // Stop iteration.
}
return false; // Continue iteration.
}

HEdgeIntercept* Bsp_HEdgeInterceptByVertex(HPlane* intersections, Vertex* vertex)
HPlaneIntercept* Bsp_HPlaneInterceptByVertex(HPlane* intersections, Vertex* vertex)
{
findintersectionforvertexworkerparams_t parm;

Expand All @@ -372,6 +372,13 @@ HEdgeIntercept* Bsp_HEdgeInterceptByVertex(HPlane* intersections, Vertex* vertex
return parm.found;
}

HEdgeIntercept* Bsp_HEdgeInterceptByVertex(struct hplane_s* hPlane, Vertex* vertex)
{
HPlaneIntercept* hpi = Bsp_HPlaneInterceptByVertex(hPlane, vertex);
if(!hpi) return NULL; // Not found.
return (HEdgeIntercept*) HPlaneIntercept_UserData(hpi);
}

void Bsp_BuildHEdgesBetweenIntersections(HPlane* hPlane,
HEdgeIntercept* start, HEdgeIntercept* end, bsp_hedge_t** right, bsp_hedge_t** left)
{
Expand Down
104 changes: 61 additions & 43 deletions doomsday/engine/portable/src/bsp_node.c
Expand Up @@ -724,100 +724,118 @@ boolean Bsp_ChoosePartition(SuperBlock* hEdgeList, size_t depth, HPlane* partiti
part->pSY = best->pSY;
part->pPara = best->pPara;
part->pPerp = best->pPerp;
part->length = best->pLength;
part->pLength = best->pLength;
return true;
}

//DEBUG_Message(("Bsp_ChoosePartition: No best found!\n"));
return false;
}

static void makeIntersection(HPlane* hPlane, Vertex* vert, boolean selfRef)
static boolean lineDefHasSelfRef(LineDef* lineDef)
{
HEdgeIntercept* inter = Bsp_HEdgeInterceptByVertex(hPlane, vert);
return !!(lineDef->buildData.mlFlags & MLF_SELFREF);
}

if(!inter)
{
const HPlanePartition* part = HPlane_Partition(hPlane);
double distance = M_ParallelDist(part->pDX, part->pDY, part->pPara, part->length,
vert->buildData.pos[VX], vert->buildData.pos[VY]);
static HPlaneIntercept* Bsp_MakeHPlaneIntersection(HPlane* hPlane, bsp_hedge_t* hEdge, int leftSide)
{
HEdgeIntercept* hEdgeIntercept;
const HPlanePartition* part;
HPlaneIntercept* inter;
Vertex* vertex;
double distance;
assert(hPlane && hEdge);

// Already present on this edge?
vertex = hEdge->v[leftSide?1:0];
inter = Bsp_HPlaneInterceptByVertex(hPlane, vertex);
if(inter) return inter;

inter = Bsp_NewHEdgeIntercept(vert, part, selfRef);
HPlane_NewIntercept2(hPlane, distance, inter);
}
part = HPlane_Partition(hPlane);
distance = M_ParallelDist(part->pDX, part->pDY, part->pPara, part->pLength,
vertex->buildData.pos[VX], vertex->buildData.pos[VY]);

hEdgeIntercept = Bsp_NewHEdgeIntercept(vertex, part, (hEdge->lineDef && lineDefHasSelfRef(hEdge->lineDef)));
return HPlane_NewIntercept2(hPlane, distance, hEdgeIntercept);
}

static HPlaneIntercept* makeIntersection(HPlane* hPlane, bsp_hedge_t* hEdge, int leftSide)
{
if(!hPlane || !hEdge)
Con_Error("Bsp_MakeHPlaneIntersection: Invalid arguments.");
return Bsp_MakeHPlaneIntersection(hPlane, hEdge, leftSide);
}

/**
* Calculate the intersection location between the current half-edge and the partition.
* Takes advantage of some common situations like horizontal and vertical lines to
* choose a 'nicer' intersection point.
*/
static __inline void calcIntersection(bsp_hedge_t* cur, const HPlanePartition* part,
static __inline void calcIntersection(bsp_hedge_t* hEdge, const HPlanePartition* part,
double perpC, double perpD, double* x, double* y)
{
double ds;

// Horizontal partition against vertical half-edge.
if(part->pDY == 0 && cur->pDX == 0)
if(part->pDY == 0 && hEdge->pDX == 0)
{
*x = cur->pSX;
*x = hEdge->pSX;
*y = part->pSY;
return;
}

// Vertical partition against horizontal half-edge.
if(part->pDX == 0 && cur->pDY == 0)
if(part->pDX == 0 && hEdge->pDY == 0)
{
*x = part->pSX;
*y = cur->pSY;
*y = hEdge->pSY;
return;
}

// 0 = start, 1 = end.
ds = perpC / (perpC - perpD);

if(cur->pDX == 0)
*x = cur->pSX;
if(hEdge->pDX == 0)
*x = hEdge->pSX;
else
*x = cur->pSX + (cur->pDX * ds);
*x = hEdge->pSX + (hEdge->pDX * ds);

if(cur->pDY == 0)
*y = cur->pSY;
if(hEdge->pDY == 0)
*y = hEdge->pSY;
else
*y = cur->pSY + (cur->pDY * ds);
*y = hEdge->pSY + (hEdge->pDY * ds);
}

void BSP_DivideOneHEdge(bsp_hedge_t* cur, HPlane* hPlane, SuperBlock* rightList,
void BSP_DivideOneHEdge(bsp_hedge_t* hEdge, HPlane* hPlane, SuperBlock* rightList,
SuperBlock* leftList)
{
const HPlanePartition* part = HPlane_Partition(hPlane);
bsp_hedge_t* newHEdge;
double x, y;
double a, b;
boolean selfRef = (cur->lineDef? (cur->lineDef->buildData.mlFlags & MLF_SELFREF) : false);

// Get state of lines' relation to each other.
a = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->length, cur->pSX, cur->pSY);
b = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->length, cur->pEX, cur->pEY);
a = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->pLength, hEdge->pSX, hEdge->pSY);
b = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->pLength, hEdge->pEX, hEdge->pEY);

if(cur->sourceLineDef == part->sourceLineDef)
if(hEdge->sourceLineDef == part->sourceLineDef)
a = b = 0;

// Check for being on the same line.
if(fabs(a) <= DIST_EPSILON && fabs(b) <= DIST_EPSILON)
{
makeIntersection(hPlane, cur->v[0], selfRef);
makeIntersection(hPlane, cur->v[1], selfRef);
makeIntersection(hPlane, hEdge, RIGHT);
makeIntersection(hPlane, hEdge, LEFT);

// This hedge runs along the same line as the partition. Check whether it goes in
// the same direction or the opposite.
if(cur->pDX * part->pDX + cur->pDY * part->pDY < 0)
if(hEdge->pDX * part->pDX + hEdge->pDY * part->pDY < 0)
{
SuperBlock_HEdgePush(leftList, cur);
SuperBlock_HEdgePush(leftList, hEdge);
}
else
{
SuperBlock_HEdgePush(rightList, cur);
SuperBlock_HEdgePush(rightList, hEdge);
}

return;
Expand All @@ -827,41 +845,41 @@ void BSP_DivideOneHEdge(bsp_hedge_t* cur, HPlane* hPlane, SuperBlock* rightList,
if(a > -DIST_EPSILON && b > -DIST_EPSILON)
{
if(a < DIST_EPSILON)
makeIntersection(hPlane, cur->v[0], selfRef);
makeIntersection(hPlane, hEdge, RIGHT);
else if(b < DIST_EPSILON)
makeIntersection(hPlane, cur->v[1], selfRef);
makeIntersection(hPlane, hEdge, LEFT);

SuperBlock_HEdgePush(rightList, cur);
SuperBlock_HEdgePush(rightList, hEdge);
return;
}

// Check for left side.
if(a < DIST_EPSILON && b < DIST_EPSILON)
{
if(a > -DIST_EPSILON)
makeIntersection(hPlane, cur->v[0], selfRef);
makeIntersection(hPlane, hEdge, RIGHT);
else if(b > -DIST_EPSILON)
makeIntersection(hPlane, cur->v[1], selfRef);
makeIntersection(hPlane, hEdge, LEFT);

SuperBlock_HEdgePush(leftList, cur);
SuperBlock_HEdgePush(leftList, hEdge);
return;
}

// When we reach here, we have a and b non-zero and opposite sign, hence this edge
// will be split by the partition line.

calcIntersection(cur, part, a, b, &x, &y);
newHEdge = BSP_HEdge_Split(cur, x, y);
makeIntersection(hPlane, cur->v[1], selfRef);
calcIntersection(hEdge, part, a, b, &x, &y);
newHEdge = BSP_HEdge_Split(hEdge, x, y);
makeIntersection(hPlane, hEdge, LEFT);

if(a < 0)
{
SuperBlock_HEdgePush(leftList, cur);
SuperBlock_HEdgePush(leftList, hEdge);
SuperBlock_HEdgePush(rightList, newHEdge);
}
else
{
SuperBlock_HEdgePush(rightList, cur);
SuperBlock_HEdgePush(rightList, hEdge);
SuperBlock_HEdgePush(leftList, newHEdge);
}
}
Expand Down

0 comments on commit c56240a

Please sign in to comment.