00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "bsp.h"
00029
00030 #define INTEGRAL_EPSILON 0.01
00031 #define POINT_EPSILON 0.5
00032 #define OFF_EPSILON 0.5
00033
00034 static int c_merge, c_subdivide, c_totalverts, c_uniqueverts, c_degenerate, c_tjunctions, c_faceoverflows, c_facecollapse, c_badstartverts, c_faces;
00035
00036 #define MAX_SUPERVERTS 512
00037 static int superverts[MAX_SUPERVERTS];
00038 static int numsuperverts;
00039
00040 static const face_t *edgefaces[MAX_MAP_EDGES][2];
00041 int firstmodeledge = 1;
00042
00043 static vec3_t edge_dir;
00044 static vec3_t edge_start;
00045
00046 static int num_edge_verts;
00047 static int edge_verts[MAX_MAP_VERTS];
00048
00049 #define HASH_SIZE 64
00050
00051 static int vertexchain[MAX_MAP_VERTS];
00052 static int hashverts[HASH_SIZE * HASH_SIZE];
00053
00057 static unsigned HashVec (const vec3_t vec)
00058 {
00059 const int x = (4096 + (int)(vec[0] + 0.5)) >> 7;
00060 const int y = (4096 + (int)(vec[1] + 0.5)) >> 7;
00061
00062 if (x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE)
00063 Sys_Error("HashVec: point outside valid range");
00064
00065 return y * HASH_SIZE + x;
00066 }
00067
00072 static int GetVertexnum (const vec3_t in)
00073 {
00074 int h, i, vnum;
00075 vec3_t vert;
00076
00077 c_totalverts++;
00078
00079 for (i = 0; i < 3; i++) {
00080 if (fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
00081 vert[i] = Q_rint(in[i]);
00082 else
00083 vert[i] = in[i];
00084 }
00085
00086 h = HashVec(vert);
00087
00088 for (vnum = hashverts[h]; vnum; vnum = vertexchain[vnum]) {
00089 const float *p = curTile->vertexes[vnum].point;
00090 if (fabs(p[0] - vert[0]) < POINT_EPSILON
00091 && fabs(p[1] - vert[1]) < POINT_EPSILON
00092 && fabs(p[2] - vert[2]) < POINT_EPSILON)
00093 return vnum;
00094 }
00095
00096
00097 if (curTile->numvertexes == MAX_MAP_VERTS)
00098 Sys_Error("numvertexes == MAX_MAP_VERTS");
00099
00100 curTile->vertexes[curTile->numvertexes].point[0] = vert[0];
00101 curTile->vertexes[curTile->numvertexes].point[1] = vert[1];
00102 curTile->vertexes[curTile->numvertexes].point[2] = vert[2];
00103
00104 vertexchain[curTile->numvertexes] = hashverts[h];
00105 hashverts[h] = curTile->numvertexes;
00106
00107 c_uniqueverts++;
00108
00109 curTile->numvertexes++;
00110 curTile->numnormals++;
00111
00112 return curTile->numvertexes - 1;
00113 }
00114
00115 static face_t *AllocFace (void)
00116 {
00117 c_faces++;
00118
00119 return Mem_Alloc(sizeof(face_t));
00120 }
00121
00122 static face_t *NewFaceFromFace (const face_t *f)
00123 {
00124 face_t *newf;
00125
00126 newf = AllocFace();
00127 *newf = *f;
00128 newf->merged = NULL;
00129 newf->split[0] = newf->split[1] = NULL;
00130 newf->w = NULL;
00131 return newf;
00132 }
00133
00134 void FreeFace (face_t *f)
00135 {
00136 if (f->w)
00137 FreeWinding(f->w);
00138 Mem_Free(f);
00139 c_faces--;
00140 }
00141
00153 static void FaceFromSuperverts (node_t *node, face_t *f, int base)
00154 {
00155 face_t *newf;
00156 int i, remaining;
00157
00158 remaining = numsuperverts;
00159
00160 while (remaining > MAXEDGES) {
00161 c_faceoverflows++;
00162
00163 newf = f->split[0] = NewFaceFromFace(f);
00164 newf = f->split[0];
00165 newf->next = node->faces;
00166 node->faces = newf;
00167
00168 newf->numpoints = MAXEDGES;
00169 for (i = 0; i < MAXEDGES; i++)
00170 newf->vertexnums[i] = superverts[(i + base) % numsuperverts];
00171
00172 f->split[1] = NewFaceFromFace(f);
00173 f = f->split[1];
00174 f->next = node->faces;
00175 node->faces = f;
00176
00177 remaining -= (MAXEDGES - 2);
00178 base = (base + MAXEDGES - 1) % numsuperverts;
00179 }
00180
00181
00182 f->numpoints = remaining;
00183 for (i = 0; i < remaining; i++)
00184 f->vertexnums[i] = superverts[(i + base) % numsuperverts];
00185 }
00186
00187 static void EmitFaceVertexes (node_t *node, face_t *f)
00188 {
00189 winding_t *w;
00190 int i;
00191
00192 if (f->merged || f->split[0] || f->split[1])
00193 return;
00194
00195 w = f->w;
00196 for (i = 0; i < w->numpoints; i++) {
00197
00198 if (config.noweld) {
00199 if (curTile->numvertexes == MAX_MAP_VERTS)
00200 Sys_Error("MAX_MAP_VERTS (%i)", curTile->numvertexes);
00201 superverts[i] = curTile->numvertexes;
00202 VectorCopy(w->p[i], curTile->vertexes[curTile->numvertexes].point);
00203 curTile->numvertexes++;
00204 curTile->numnormals++;
00205 c_uniqueverts++;
00206 c_totalverts++;
00207 } else
00208 superverts[i] = GetVertexnum(w->p[i]);
00209 }
00210 numsuperverts = w->numpoints;
00211
00212
00213 FaceFromSuperverts(node, f, 0);
00214 }
00215
00216 static void EmitVertexes_r (node_t *node)
00217 {
00218 int i;
00219 face_t *f;
00220
00221 if (node->planenum == PLANENUM_LEAF)
00222 return;
00223
00224 for (f = node->faces; f; f = f->next)
00225 EmitFaceVertexes(node, f);
00226
00227 for (i = 0; i < 2; i++)
00228 EmitVertexes_r(node->children[i]);
00229 }
00230
00231
00235 static void FindEdgeVerts (const vec3_t v1, const vec3_t v2)
00236 {
00237 int x1, x2, y1, y2, t;
00238 int x, y, vnum;
00239
00240 x1 = (MAX_WORLD_WIDTH + (int)(v1[0] + 0.5)) >> 7;
00241 y1 = (MAX_WORLD_WIDTH + (int)(v1[1] + 0.5)) >> 7;
00242 x2 = (MAX_WORLD_WIDTH + (int)(v2[0] + 0.5)) >> 7;
00243 y2 = (MAX_WORLD_WIDTH + (int)(v2[1] + 0.5)) >> 7;
00244
00245 if (x1 > x2) {
00246 t = x1;
00247 x1 = x2;
00248 x2 = t;
00249 }
00250 if (y1 > y2) {
00251 t = y1;
00252 y1 = y2;
00253 y2 = t;
00254 }
00255 num_edge_verts = 0;
00256 for (x = x1; x <= x2; x++)
00257 for (y = y1; y <= y2; y++)
00258 for (vnum = hashverts[y * HASH_SIZE + x]; vnum; vnum = vertexchain[vnum])
00259 edge_verts[num_edge_verts++] = vnum;
00260 }
00261
00265 static void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
00266 {
00267 int k;
00268 vec_t dist, error;
00269 vec3_t delta, exact, off, p;
00270
00271 if (p1 == p2) {
00272 c_degenerate++;
00273 return;
00274 }
00275
00276 for (k = startvert; k < num_edge_verts; k++) {
00277 const int j = edge_verts[k];
00278 if (j == p1 || j == p2)
00279 continue;
00280
00281 VectorCopy(curTile->vertexes[j].point, p);
00282
00283 VectorSubtract(p, edge_start, delta);
00284 dist = DotProduct(delta, edge_dir);
00285 if (dist <= start || dist >= end)
00286 continue;
00287 VectorMA(edge_start, dist, edge_dir, exact);
00288 VectorSubtract(p, exact, off);
00289 error = VectorLength(off);
00290
00291 if (fabs(error) > OFF_EPSILON)
00292 continue;
00293
00294
00295 c_tjunctions++;
00296 TestEdge(start, dist, p1, j, k + 1);
00297 TestEdge(dist, end, j, p2, k + 1);
00298 return;
00299 }
00300
00301
00302 if (numsuperverts >= MAX_SUPERVERTS)
00303 Sys_Error("MAX_SUPERVERTS (%i)", numsuperverts);
00304 superverts[numsuperverts] = p1;
00305 numsuperverts++;
00306 }
00307
00308 static void FixFaceEdges (node_t *node, face_t *f)
00309 {
00310 int i, base;
00311 vec3_t e2;
00312 vec_t len;
00313 int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
00314
00315 if (f->merged || f->split[0] || f->split[1])
00316 return;
00317
00318 numsuperverts = 0;
00319
00320 for (i = 0; i < f->numpoints; i++) {
00321 const int p1 = f->vertexnums[i];
00322 const int p2 = f->vertexnums[(i + 1) % f->numpoints];
00323
00324 VectorCopy(curTile->vertexes[p1].point, edge_start);
00325 VectorCopy(curTile->vertexes[p2].point, e2);
00326
00327 FindEdgeVerts(edge_start, e2);
00328
00329 VectorSubtract(e2, edge_start, edge_dir);
00330 len = VectorNormalize(edge_dir);
00331
00332 start[i] = numsuperverts;
00333 TestEdge(0, len, p1, p2, 0);
00334
00335 count[i] = numsuperverts - start[i];
00336 }
00337
00338
00339 if (numsuperverts < 3) {
00340 f->numpoints = 0;
00341 c_facecollapse++;
00342 return;
00343 }
00344
00345
00346
00347
00348 for (i = 0; i < f->numpoints; i++) {
00349 if (count[i] == 1 && count[(i + f->numpoints - 1) % f->numpoints] == 1)
00350 break;
00351 }
00352 if (i == f->numpoints) {
00353 c_badstartverts++;
00354 base = 0;
00355 } else {
00356
00357 base = start[i];
00358 }
00359
00360
00361 FaceFromSuperverts(node, f, base);
00362 }
00363
00364 static void FixEdges_r (node_t *node)
00365 {
00366 int i;
00367 face_t *f;
00368
00369 if (node->planenum == PLANENUM_LEAF)
00370 return;
00371
00372 for (f = node->faces; f; f = f->next)
00373 FixFaceEdges(node, f);
00374
00375 for (i = 0; i < 2; i++)
00376 FixEdges_r(node->children[i]);
00377 }
00378
00383 void FixTjuncs (node_t *headnode)
00384 {
00385
00386 Verb_Printf(VERB_EXTRA, "---- snap verts ----\n");
00387 memset(hashverts, 0, sizeof(hashverts));
00388 c_totalverts = 0;
00389 c_uniqueverts = 0;
00390 c_faceoverflows = 0;
00391 EmitVertexes_r(headnode);
00392 Verb_Printf(VERB_EXTRA, "%i unique from %i\n", c_uniqueverts, c_totalverts);
00393
00394
00395 Verb_Printf(VERB_EXTRA, "---- tjunc ----\n");
00396 c_degenerate = 0;
00397 c_facecollapse = 0;
00398 c_tjunctions = 0;
00399 if (!config.notjunc)
00400 FixEdges_r(headnode);
00401 Verb_Printf(VERB_EXTRA, "%5i edges degenerated\n", c_degenerate);
00402 Verb_Printf(VERB_EXTRA, "%5i faces degenerated\n", c_facecollapse);
00403 Verb_Printf(VERB_EXTRA, "%5i edges added by tjunctions\n", c_tjunctions);
00404 Verb_Printf(VERB_EXTRA, "%5i faces added by tjunctions\n", c_faceoverflows);
00405 Verb_Printf(VERB_EXTRA, "%5i bad start verts\n", c_badstartverts);
00406 }
00407
00412 int GetEdge (int v1, int v2, const face_t *f)
00413 {
00414 dBspEdge_t *edge;
00415
00416 if (!config.noshare) {
00417 int i;
00418 for (i = firstmodeledge; i < curTile->numedges; i++) {
00419 edge = &curTile->edges[i];
00420 if (v1 == edge->v[1] && v2 == edge->v[0]
00421 && edgefaces[i][0]->contentFlags == f->contentFlags) {
00422 if (edgefaces[i][1])
00423 continue;
00424 edgefaces[i][1] = f;
00425 return -i;
00426 }
00427 }
00428 }
00429
00430
00431 if (curTile->numedges >= MAX_MAP_EDGES)
00432 Sys_Error("numedges >= MAX_MAP_EDGES (%i)", curTile->numedges);
00433 edge = &curTile->edges[curTile->numedges];
00434 edge->v[0] = v1;
00435 edge->v[1] = v2;
00436 edgefaces[curTile->numedges][0] = f;
00437 curTile->numedges++;
00438
00439 return curTile->numedges - 1;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 #define CONTINUOUS_EPSILON 0.001
00449
00456 static winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, const vec3_t planenormal)
00457 {
00458 vec_t *p1, *p2, *back;
00459 winding_t *newf;
00460 int i, j, k, l;
00461 vec3_t normal, delta;
00462 vec_t dot;
00463 qboolean keep1, keep2;
00464
00465 p1 = p2 = NULL;
00466 j = 0;
00467
00468
00469 for (i = 0; i < f1->numpoints; i++) {
00470 p1 = f1->p[i];
00471 p2 = f1->p[(i + 1) % f1->numpoints];
00472 for (j = 0; j < f2->numpoints; j++) {
00473 const vec_t *p3 = f2->p[j];
00474 const vec_t *p4 = f2->p[(j + 1) % f2->numpoints];
00475 for (k = 0; k < 3; k++) {
00476 if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
00477 break;
00478 if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
00479 break;
00480 }
00481 if (k == 3)
00482 break;
00483 }
00484 if (j < f2->numpoints)
00485 break;
00486 }
00487
00488
00489 if (i == f1->numpoints)
00490 return NULL;
00491
00492
00493
00494 back = f1->p[(i + f1->numpoints - 1) % f1->numpoints];
00495 VectorSubtract(p1, back, delta);
00496 CrossProduct(planenormal, delta, normal);
00497 VectorNormalize(normal);
00498
00499 back = f2->p[(j + 2) % f2->numpoints];
00500 VectorSubtract(back, p1, delta);
00501 dot = DotProduct(delta, normal);
00502
00503 if (dot > CONTINUOUS_EPSILON)
00504 return NULL;
00505 keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00506
00507 back = f1->p[(i + 2) % f1->numpoints];
00508 VectorSubtract(back, p2, delta);
00509 CrossProduct(planenormal, delta, normal);
00510 VectorNormalize(normal);
00511
00512 back = f2->p[(j + f2->numpoints - 1) % f2->numpoints];
00513 VectorSubtract(back, p2, delta);
00514 dot = DotProduct(delta, normal);
00515
00516 if (dot > CONTINUOUS_EPSILON)
00517 return NULL;
00518 keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00519
00520
00521 newf = AllocWinding(f1->numpoints + f2->numpoints);
00522
00523
00524 for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) {
00525 if (k == (i + 1) % f1->numpoints && !keep2)
00526 continue;
00527
00528 VectorCopy(f1->p[k], newf->p[newf->numpoints]);
00529 newf->numpoints++;
00530 }
00531
00532
00533 for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) {
00534 if (l == (j + 1) % f2->numpoints && !keep1)
00535 continue;
00536 VectorCopy(f2->p[l], newf->p[newf->numpoints]);
00537 newf->numpoints++;
00538 }
00539
00540 return newf;
00541 }
00542
00550 static face_t *TryMerge (face_t *f1, face_t *f2, const vec3_t planenormal)
00551 {
00552 face_t *newf;
00553 winding_t *nw;
00554
00555 if (!f1->w || !f2->w)
00556 return NULL;
00557 if (f1->texinfo != f2->texinfo)
00558 return NULL;
00559 if (f1->planenum != f2->planenum)
00560 return NULL;
00561 if (f1->contentFlags != f2->contentFlags)
00562 return NULL;
00563
00564 nw = TryMergeWinding(f1->w, f2->w, planenormal);
00565 if (!nw)
00566 return NULL;
00567
00568 c_merge++;
00569 newf = NewFaceFromFace(f1);
00570 newf->w = nw;
00571
00572 f1->merged = newf;
00573 f2->merged = newf;
00574
00575 return newf;
00576 }
00577
00578 static void MergeNodeFaces (node_t *node)
00579 {
00580 face_t *f1, *f2, *end;
00581 face_t *merged;
00582 const plane_t *plane = &mapplanes[node->planenum];
00583
00584 for (f1 = node->faces; f1; f1 = f1->next) {
00585 if (f1->merged || f1->split[0] || f1->split[1])
00586 continue;
00587 for (f2 = node->faces; f2 != f1; f2 = f2->next) {
00588 if (f2->merged || f2->split[0] || f2->split[1])
00589 continue;
00590 merged = TryMerge(f1, f2, plane->normal);
00591 if (!merged)
00592 continue;
00593
00594
00595
00596 for (end = node->faces; end->next; end = end->next);
00597
00598 merged->next = NULL;
00599 end->next = merged;
00600 break;
00601 }
00602 }
00603 }
00604
00605
00606
00610 static void SubdivideFace (node_t *node, face_t *f)
00611 {
00612 int axis, i;
00613 const dBspTexinfo_t *tex;
00614 vec3_t temp;
00615 vec_t dist;
00616
00617 if (f->merged)
00618 return;
00619
00620
00621 tex = &curTile->texinfo[f->texinfo];
00622 if (tex->surfaceFlags & SURF_WARP)
00623 return;
00624
00625 for (axis = 0; axis < 2; axis++) {
00626 while (1) {
00627 const winding_t *w = f->w;
00628 winding_t *frontw, *backw;
00629 float mins = 999999;
00630 float maxs = -999999;
00631 vec_t v;
00632
00633 VectorCopy(tex->vecs[axis], temp);
00634 for (i = 0; i < w->numpoints; i++) {
00635 v = DotProduct(w->p[i], temp);
00636 if (v < mins)
00637 mins = v;
00638 if (v > maxs)
00639 maxs = v;
00640 }
00641
00642
00643 if (maxs - mins <= config.subdivideSize)
00644 break;
00645
00646
00647 c_subdivide++;
00648
00649 v = VectorNormalize(temp);
00650
00651 dist = (mins + config.subdivideSize - 16) / v;
00652
00653 ClipWindingEpsilon(w, temp, dist, ON_EPSILON, &frontw, &backw);
00654 if (!frontw || !backw)
00655 Sys_Error("SubdivideFace: didn't split the polygon (texture: '%s')",
00656 tex->texture);
00657
00658 f->split[0] = NewFaceFromFace(f);
00659 f->split[0]->w = frontw;
00660 f->split[0]->next = node->faces;
00661 node->faces = f->split[0];
00662
00663 f->split[1] = NewFaceFromFace(f);
00664 f->split[1]->w = backw;
00665 f->split[1]->next = node->faces;
00666 node->faces = f->split[1];
00667
00668 SubdivideFace(node, f->split[0]);
00669 SubdivideFace(node, f->split[1]);
00670 return;
00671 }
00672 }
00673 }
00674
00675 static void SubdivideNodeFaces (node_t *node)
00676 {
00677 face_t *f;
00678
00679 for (f = node->faces; f; f = f->next)
00680 SubdivideFace(node, f);
00681 }
00682
00683 static int c_nodefaces;
00684
00685 static face_t *FaceFromPortal (portal_t *p, int pside)
00686 {
00687 face_t *f;
00688 side_t *side = p->side;
00689
00690
00691 if (!side)
00692 return NULL;
00693
00694
00695 if (side->surfaceFlags & SURF_NODRAW)
00696 return NULL;
00697
00698 f = AllocFace();
00699
00700 f->texinfo = side->texinfo;
00701 f->planenum = (side->planenum & ~1) | pside;
00702 f->portal = p;
00703
00704 if ((p->nodes[pside]->contentFlags & CONTENTS_WINDOW)
00705 && VisibleContents(p->nodes[!pside]->contentFlags ^ p->nodes[pside]->contentFlags) == CONTENTS_WINDOW)
00706 return NULL;
00707
00708
00709 if (!config.nobackclip && mapplanes[f->planenum].normal[2] < -0.9) {
00710
00711
00712 const entity_t *e = &entities[side->brush->entitynum];
00713 if (strcmp(ValueForKey(e, "classname"), "func_rotating")) {
00714 if (!(curTile->texinfo[f->texinfo].surfaceFlags & SURF_LIGHT)) {
00715
00716
00717
00718 return NULL;
00719 }
00720 }
00721 }
00722
00723 if (pside) {
00724 f->w = ReverseWinding(p->winding);
00725 f->contentFlags = p->nodes[1]->contentFlags;
00726 } else {
00727 f->w = CopyWinding(p->winding);
00728 f->contentFlags = p->nodes[0]->contentFlags;
00729 }
00730 return f;
00731 }
00732
00733
00741 static void MakeFaces_r (node_t *node)
00742 {
00743 portal_t *p;
00744
00745
00746 if (node->planenum != PLANENUM_LEAF) {
00747 MakeFaces_r(node->children[0]);
00748 MakeFaces_r(node->children[1]);
00749
00750
00751 if (!config.nomerge)
00752 MergeNodeFaces(node);
00753 if (!config.nosubdiv)
00754 SubdivideNodeFaces(node);
00755
00756 return;
00757 }
00758
00759
00760 if (node->contentFlags & CONTENTS_SOLID)
00761 return;
00762
00763
00764 for (p = node->portals; p;) {
00765 const int pside = (p->nodes[1] == node);
00766
00767 p->face[pside] = FaceFromPortal(p, pside);
00768 if (p->face[pside]) {
00769 c_nodefaces++;
00770 p->face[pside]->next = p->onnode->faces;
00771 p->onnode->faces = p->face[pside];
00772 }
00773 p = p->next[pside];
00774 }
00775 }
00776
00777 void MakeFaces (node_t *node)
00778 {
00779 Verb_Printf(VERB_EXTRA, "--- MakeFaces ---\n");
00780 c_merge = 0;
00781 c_subdivide = 0;
00782 c_nodefaces = 0;
00783
00784 MakeFaces_r(node);
00785
00786 Verb_Printf(VERB_EXTRA, "%5i makefaces\n", c_nodefaces);
00787 Verb_Printf(VERB_EXTRA, "%5i merged\n", c_merge);
00788 Verb_Printf(VERB_EXTRA, "%5i subdivided\n", c_subdivide);
00789 }