Permalink
Browse files

qbsp: MakeFaceEdges: accelerate with a hash table to avoid slow O(n^2…

…) search for edges
  • Loading branch information...
1 parent 59bb786 commit 28e460be9a849c76b37c72290f2cb338e677d277 @ericwa committed Apr 26, 2015
Showing with 54 additions and 4 deletions.
  1. +54 −4 qbsp/surfaces.c
View
@@ -151,6 +151,13 @@ static int cStartEdge;
static hashvert_t *hashverts[NUM_HASH];
static vec3_t hash_min, hash_scale;
+typedef struct hashedge_s {
+ unsigned i;
+ struct hashedge_s *next;
+} hashedge_t;
+
+static hashedge_t *hashedges[NUM_HASH];
+
static void
InitHash(void)
{
@@ -179,6 +186,35 @@ InitHash(void)
hash_scale[2] = (vec_t)newsize[1];
hvert_p = pHashverts;
+
+ /* edges hash table */
+ for (i=0; i<NUM_HASH; i++) {
+ hashedge_t *he;
+ for (he = hashedges[i]; he; )
+ {
+ hashedge_t *to_free = he;
+ he = he->next;
+ FreeMem(to_free, OTHER, sizeof(hashedge_t));
+ }
+ }
+ memset(hashedges, 0, sizeof(hashedges));
+}
+
+static unsigned
+HashEdge(unsigned v1, unsigned v2)
+{
+ return (v1 + v2) % NUM_HASH;
+}
+
+static void
+AddHashEdge(unsigned v1, unsigned v2, unsigned i)
+{
+ hashedge_t *he = AllocMem(OTHER, sizeof(hashedge_t), true);
+ unsigned slot = HashEdge(v1, v2);
+
+ he->i = i;
+ he->next = hashedges[slot];
+ hashedges[slot] = he;
}
static unsigned
@@ -262,17 +298,23 @@ GetEdge(mapentity_t *entity, const vec3_t p1, const vec3_t p2,
struct lumpdata *edges = &entity->lumps[LUMP_EDGES];
int v1, v2;
int i;
+ unsigned edge_hash_key;
+ hashedge_t *he;
if (!face->contents[0])
Error("Face with 0 contents (%s)", __func__);
v1 = GetVertex(entity, p1);
v2 = GetVertex(entity, p2);
+ edge_hash_key = HashEdge(v1, v2);
+
if (options.BSPVersion == BSPVERSION) {
- bsp29_dedge_t *edge = edges->data;
+ bsp29_dedge_t *edge;
- for (i = 0; i < edges->index; i++, edge++) {
+ for (he = hashedges[edge_hash_key]; he; he = he->next) {
+ i = he->i;
+ edge = (bsp29_dedge_t *)edges->data + i;
if (v1 == edge->v[1] && v2 == edge->v[0]
&& pEdgeFaces1[i] == NULL
&& pEdgeFaces0[i]->contents[0] == face->contents[0]) {
@@ -282,14 +324,18 @@ GetEdge(mapentity_t *entity, const vec3_t p1, const vec3_t p2,
}
/* emit an edge */
+ i = edges->index;
+ edge = (bsp29_dedge_t *)edges->data + i;
if (edges->index >= edges->count)
Error("Internal error: didn't allocate enough edges?");
edge->v[0] = v1;
edge->v[1] = v2;
} else {
- bsp2_dedge_t *edge = edges->data;
+ bsp2_dedge_t *edge = (bsp2_dedge_t *)edges->data;
- for (i = 0; i < edges->index; i++, edge++) {
+ for (he = hashedges[edge_hash_key]; he; he = he->next) {
+ i = he->i;
+ edge = (bsp2_dedge_t *)edges->data + i;
if (v1 == edge->v[1] && v2 == edge->v[0]
&& pEdgeFaces1[i] == NULL
&& pEdgeFaces0[i]->contents[0] == face->contents[0]) {
@@ -299,12 +345,16 @@ GetEdge(mapentity_t *entity, const vec3_t p1, const vec3_t p2,
}
/* emit an edge */
+ i = edges->index;
+ edge = (bsp2_dedge_t *)edges->data + i;
if (edges->index >= edges->count)
Error("Internal error: didn't allocate enough edges?");
edge->v[0] = v1;
edge->v[1] = v2;
}
+ AddHashEdge(v1, v2, edges->index);
+
edges->index++;
map.cTotal[LUMP_EDGES]++;
pEdgeFaces0[i] = face;

0 comments on commit 28e460b

Please sign in to comment.