tetrahedron.c (42552B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 #include "qbsp.h" 24 #include "l_mem.h" 25 #include "../botlib/aasfile.h" 26 #include "aas_store.h" 27 #include "aas_cfg.h" 28 #include "aas_file.h" 29 30 // 31 // creating tetrahedrons from a arbitrary world bounded by triangles 32 // 33 // a triangle has 3 corners and 3 edges 34 // a tetrahedron is build out of 4 triangles 35 // a tetrahedron has 6 edges 36 // we start with a world bounded by triangles, a side of a triangle facing 37 // towards the oudside of the world is marked as part of tetrahedron -1 38 // 39 // a tetrahedron is defined by two non-coplanar triangles with a shared edge 40 // 41 // a tetrahedron is defined by one triangle and a vertex not in the triangle plane 42 // 43 // if all triangles using a specific vertex have tetrahedrons 44 // at both sides then this vertex will never be part of a new tetrahedron 45 // 46 // if all triangles using a specific edge have tetrahedrons 47 // at both sides then this vertex will never be part of a new tetrahedron 48 // 49 // each triangle can only be shared by two tetrahedrons 50 // when all triangles have tetrahedrons at both sides then we're done 51 // 52 // if we cannot create any new tetrahedrons and there is at least one triangle 53 // which has a tetrahedron only at one side then the world leaks 54 // 55 56 #define Sign(x) (x < 0 ? 1 : 0) 57 58 #define MAX_TH_VERTEXES 128000 59 #define MAX_TH_PLANES 128000 60 #define MAX_TH_EDGES 512000 61 #define MAX_TH_TRIANGLES 51200 62 #define MAX_TH_TETRAHEDRONS 12800 63 64 #define PLANEHASH_SIZE 1024 65 #define EDGEHASH_SIZE 1024 66 #define TRIANGLEHASH_SIZE 1024 67 #define VERTEXHASH_SHIFT 7 68 #define VERTEXHASH_SIZE ((MAX_MAP_BOUNDS>>(VERTEXHASH_SHIFT-1))+1) //was 64 69 70 #define NORMAL_EPSILON 0.0001 71 #define DIST_EPSILON 0.1 72 #define VERTEX_EPSILON 0.01 73 #define INTEGRAL_EPSILON 0.01 74 75 76 //plane 77 typedef struct th_plane_s 78 { 79 vec3_t normal; 80 float dist; 81 int type; 82 int signbits; 83 struct th_plane_s *hashnext; //next plane in hash 84 } th_plane_t; 85 86 //vertex 87 typedef struct th_vertex_s 88 { 89 vec3_t v; 90 int usercount; //2x the number of to be processed 91 //triangles using this vertex 92 struct th_vertex_s *hashnext; //next vertex in hash 93 } th_vertex_t; 94 95 //edge 96 typedef struct th_edge_s 97 { 98 int v[2]; //vertex indexes 99 int usercount; //number of to be processed 100 //triangles using this edge 101 struct th_edge_s *hashnext; //next edge in hash 102 } th_edge_t; 103 104 //triangle 105 typedef struct th_triangle_s 106 { 107 int edges[3]; //negative if edge is flipped 108 th_plane_t planes[3]; //triangle bounding planes 109 int planenum; //plane the triangle is in 110 int front; //tetrahedron at the front 111 int back; //tetrahedron at the back 112 vec3_t mins, maxs; //triangle bounding box 113 struct th_triangle_s *prev, *next; //links in linked triangle lists 114 struct th_triangle_s *hashnext; //next triangle in hash 115 } th_triangle_t; 116 117 //tetrahedron 118 typedef struct th_tetrahedron_s 119 { 120 int triangles[4]; //negative if at backside of triangle 121 float volume; //tetrahedron volume 122 } th_tetrahedron_t; 123 124 typedef struct th_s 125 { 126 //vertexes 127 int numvertexes; 128 th_vertex_t *vertexes; 129 th_vertex_t *vertexhash[VERTEXHASH_SIZE * VERTEXHASH_SIZE]; 130 //planes 131 int numplanes; 132 th_plane_t *planes; 133 th_plane_t *planehash[PLANEHASH_SIZE]; 134 //edges 135 int numedges; 136 th_edge_t *edges; 137 th_edge_t *edgehash[EDGEHASH_SIZE]; 138 //triangles 139 int numtriangles; 140 th_triangle_t *triangles; 141 th_triangle_t *trianglehash[TRIANGLEHASH_SIZE]; 142 //tetrahedrons 143 int numtetrahedrons; 144 th_tetrahedron_t *tetrahedrons; 145 } th_t; 146 147 th_t thworld; 148 149 //=========================================================================== 150 // 151 // Parameter: - 152 // Returns: - 153 // Changes Globals: - 154 //=========================================================================== 155 void TH_InitMaxTH(void) 156 { 157 //get memory for the tetrahedron data 158 thworld.vertexes = (th_vertex_t *) GetClearedMemory(MAX_TH_VERTEXES * sizeof(th_vertex_t)); 159 thworld.planes = (th_plane_t *) GetClearedMemory(MAX_TH_PLANES * sizeof(th_plane_t)); 160 thworld.edges = (th_edge_t *) GetClearedMemory(MAX_TH_EDGES * sizeof(th_edge_t)); 161 thworld.triangles = (th_triangle_t *) GetClearedMemory(MAX_TH_TRIANGLES * sizeof(th_triangle_t)); 162 thworld.tetrahedrons = (th_tetrahedron_t *) GetClearedMemory(MAX_TH_TETRAHEDRONS * sizeof(th_tetrahedron_t)); 163 //reset the hash tables 164 memset(thworld.vertexhash, 0, VERTEXHASH_SIZE * sizeof(th_vertex_t *)); 165 memset(thworld.planehash, 0, PLANEHASH_SIZE * sizeof(th_plane_t *)); 166 memset(thworld.edgehash, 0, EDGEHASH_SIZE * sizeof(th_edge_t *)); 167 memset(thworld.trianglehash, 0, TRIANGLEHASH_SIZE * sizeof(th_triangle_t *)); 168 } //end of the function TH_InitMaxTH 169 //=========================================================================== 170 // 171 // Parameter: - 172 // Returns: - 173 // Changes Globals: - 174 //=========================================================================== 175 void TH_FreeMaxTH(void) 176 { 177 if (thworld.vertexes) FreeMemory(thworld.vertexes); 178 thworld.vertexes = NULL; 179 thworld.numvertexes = 0; 180 if (thworld.planes) FreeMemory(thworld.planes); 181 thworld.planes = NULL; 182 thworld.numplanes = 0; 183 if (thworld.edges) FreeMemory(thworld.edges); 184 thworld.edges = NULL; 185 thworld.numedges = 0; 186 if (thworld.triangles) FreeMemory(thworld.triangles); 187 thworld.triangles = NULL; 188 thworld.numtriangles = 0; 189 if (thworld.tetrahedrons) FreeMemory(thworld.tetrahedrons); 190 thworld.tetrahedrons = NULL; 191 thworld.numtetrahedrons = 0; 192 } //end of the function TH_FreeMaxTH 193 //=========================================================================== 194 // 195 // Parameter: - 196 // Returns: - 197 // Changes Globals: - 198 //=========================================================================== 199 float TH_TriangleArea(th_triangle_t *tri) 200 { 201 return 0; 202 } //end of the function TH_TriangleArea 203 //=========================================================================== 204 // 205 // Parameter: - 206 // Returns: - 207 // Changes Globals: - 208 //=========================================================================== 209 float TH_TetrahedronVolume(th_tetrahedron_t *tetrahedron) 210 { 211 int edgenum, verts[3], i, j, v2; 212 float volume, d; 213 th_triangle_t *tri, *tri2; 214 th_plane_t *plane; 215 216 tri = &thworld.triangles[abs(tetrahedron->triangles[0])]; 217 for (i = 0; i < 3; i++) 218 { 219 edgenum = tri->edges[i]; 220 if (edgenum < 0) verts[i] = thworld.edges[abs(edgenum)].v[1]; 221 else verts[i] = thworld.edges[edgenum].v[0]; 222 } //end for 223 // 224 tri2 = &thworld.triangles[abs(tetrahedron->triangles[1])]; 225 for (j = 0; j < 3; j++) 226 { 227 edgenum = tri2->edges[i]; 228 if (edgenum < 0) v2 = thworld.edges[abs(edgenum)].v[1]; 229 else v2 = thworld.edges[edgenum].v[0]; 230 if (v2 != verts[0] && 231 v2 != verts[1] && 232 v2 != verts[2]) break; 233 } //end for 234 235 plane = &thworld.planes[tri->planenum]; 236 d = -(DotProduct (thworld.vertexes[v2].v, plane->normal) - plane->dist); 237 volume = TH_TriangleArea(tri) * d / 3; 238 return volume; 239 } //end of the function TH_TetrahedronVolume 240 //=========================================================================== 241 // 242 // Parameter: - 243 // Returns: - 244 // Changes Globals: - 245 //=========================================================================== 246 int TH_PlaneSignBits(vec3_t normal) 247 { 248 int i, signbits; 249 250 signbits = 0; 251 for (i = 2; i >= 0; i--) 252 { 253 signbits = (signbits << 1) + Sign(normal[i]); 254 } //end for 255 return signbits; 256 } //end of the function TH_PlaneSignBits 257 //=========================================================================== 258 // 259 // Parameter: - 260 // Returns: - 261 // Changes Globals: - 262 //=========================================================================== 263 int TH_PlaneTypeForNormal(vec3_t normal) 264 { 265 vec_t ax, ay, az; 266 267 // NOTE: should these have an epsilon around 1.0? 268 if (normal[0] == 1.0 || normal[0] == -1.0) 269 return PLANE_X; 270 if (normal[1] == 1.0 || normal[1] == -1.0) 271 return PLANE_Y; 272 if (normal[2] == 1.0 || normal[2] == -1.0) 273 return PLANE_Z; 274 275 ax = fabs(normal[0]); 276 ay = fabs(normal[1]); 277 az = fabs(normal[2]); 278 279 if (ax >= ay && ax >= az) 280 return PLANE_ANYX; 281 if (ay >= ax && ay >= az) 282 return PLANE_ANYY; 283 return PLANE_ANYZ; 284 } //end of the function TH_PlaneTypeForNormal 285 //=========================================================================== 286 // 287 // Parameter: - 288 // Returns: - 289 // Changes Globals: - 290 //=========================================================================== 291 qboolean TH_PlaneEqual(th_plane_t *p, vec3_t normal, vec_t dist) 292 { 293 if ( 294 fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON 295 && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON 296 && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON 297 && fabs(p->dist - dist) < DIST_EPSILON ) 298 return true; 299 return false; 300 } //end of the function TH_PlaneEqual 301 //=========================================================================== 302 // 303 // Parameter: - 304 // Returns: - 305 // Changes Globals: - 306 //=========================================================================== 307 void TH_AddPlaneToHash(th_plane_t *p) 308 { 309 int hash; 310 311 hash = (int)fabs(p->dist) / 8; 312 hash &= (PLANEHASH_SIZE-1); 313 314 p->hashnext = thworld.planehash[hash]; 315 thworld.planehash[hash] = p; 316 } //end of the function TH_AddPlaneToHash 317 //=========================================================================== 318 // 319 // Parameter: - 320 // Returns: - 321 // Changes Globals: - 322 //=========================================================================== 323 int TH_CreateFloatPlane(vec3_t normal, vec_t dist) 324 { 325 th_plane_t *p, temp; 326 327 if (VectorLength(normal) < 0.5) 328 Error ("FloatPlane: bad normal"); 329 // create a new plane 330 if (thworld.numplanes+2 > MAX_TH_PLANES) 331 Error ("MAX_TH_PLANES"); 332 333 p = &thworld.planes[thworld.numplanes]; 334 VectorCopy (normal, p->normal); 335 p->dist = dist; 336 p->type = (p+1)->type = TH_PlaneTypeForNormal (p->normal); 337 p->signbits = TH_PlaneSignBits(p->normal); 338 339 VectorSubtract (vec3_origin, normal, (p+1)->normal); 340 (p+1)->dist = -dist; 341 (p+1)->signbits = TH_PlaneSignBits((p+1)->normal); 342 343 thworld.numplanes += 2; 344 345 // allways put axial planes facing positive first 346 if (p->type < 3) 347 { 348 if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0) 349 { 350 // flip order 351 temp = *p; 352 *p = *(p+1); 353 *(p+1) = temp; 354 355 TH_AddPlaneToHash(p); 356 TH_AddPlaneToHash(p+1); 357 return thworld.numplanes - 1; 358 } //end if 359 } //end if 360 361 TH_AddPlaneToHash(p); 362 TH_AddPlaneToHash(p+1); 363 return thworld.numplanes - 2; 364 } //end of the function TH_CreateFloatPlane 365 //=========================================================================== 366 // 367 // Parameter: - 368 // Returns: - 369 // Changes Globals: - 370 //=========================================================================== 371 void TH_SnapVector(vec3_t normal) 372 { 373 int i; 374 375 for (i = 0; i < 3; i++) 376 { 377 if ( fabs(normal[i] - 1) < NORMAL_EPSILON ) 378 { 379 VectorClear (normal); 380 normal[i] = 1; 381 break; 382 } //end if 383 if ( fabs(normal[i] - -1) < NORMAL_EPSILON ) 384 { 385 VectorClear (normal); 386 normal[i] = -1; 387 break; 388 } //end if 389 } //end for 390 } //end of the function TH_SnapVector 391 //=========================================================================== 392 // 393 // Parameter: - 394 // Returns: - 395 // Changes Globals: - 396 //=========================================================================== 397 void TH_SnapPlane(vec3_t normal, vec_t *dist) 398 { 399 TH_SnapVector(normal); 400 401 if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON) 402 *dist = Q_rint(*dist); 403 } //end of the function TH_SnapPlane 404 //=========================================================================== 405 // 406 // Parameter: - 407 // Returns: - 408 // Changes Globals: - 409 //=========================================================================== 410 int TH_FindFloatPlane(vec3_t normal, vec_t dist) 411 { 412 int i; 413 th_plane_t *p; 414 int hash, h; 415 416 TH_SnapPlane (normal, &dist); 417 hash = (int)fabs(dist) / 8; 418 hash &= (PLANEHASH_SIZE-1); 419 420 // search the border bins as well 421 for (i = -1; i <= 1; i++) 422 { 423 h = (hash+i)&(PLANEHASH_SIZE-1); 424 for (p = thworld.planehash[h]; p; p = p->hashnext) 425 { 426 if (TH_PlaneEqual(p, normal, dist)) 427 { 428 return p - thworld.planes; 429 } //end if 430 } //end for 431 } //end for 432 return TH_CreateFloatPlane(normal, dist); 433 } //end of the function TH_FindFloatPlane 434 //=========================================================================== 435 // 436 // Parameter: - 437 // Returns: - 438 // Changes Globals: - 439 //=========================================================================== 440 int TH_PlaneFromPoints(int v1, int v2, int v3) 441 { 442 vec3_t t1, t2, normal; 443 vec_t dist; 444 float *p0, *p1, *p2; 445 446 p0 = thworld.vertexes[v1].v; 447 p1 = thworld.vertexes[v2].v; 448 p2 = thworld.vertexes[v3].v; 449 450 VectorSubtract(p0, p1, t1); 451 VectorSubtract(p2, p1, t2); 452 CrossProduct(t1, t2, normal); 453 VectorNormalize(normal); 454 455 dist = DotProduct(p0, normal); 456 457 return TH_FindFloatPlane(normal, dist); 458 } //end of the function TH_PlaneFromPoints 459 //=========================================================================== 460 // 461 // Parameter: - 462 // Returns: - 463 // Changes Globals: - 464 //=========================================================================== 465 void TH_AddEdgeUser(int edgenum) 466 { 467 th_edge_t *edge; 468 469 edge = &thworld.edges[abs(edgenum)]; 470 //increase edge user count 471 edge->usercount++; 472 //increase vertex user count as well 473 thworld.vertexes[edge->v[0]].usercount++; 474 thworld.vertexes[edge->v[1]].usercount++; 475 } //end of the function TH_AddEdgeUser 476 //=========================================================================== 477 // 478 // Parameter: - 479 // Returns: - 480 // Changes Globals: - 481 //=========================================================================== 482 void TH_RemoveEdgeUser(int edgenum) 483 { 484 th_edge_t *edge; 485 486 edge = &thworld.edges[abs(edgenum)]; 487 //decrease edge user count 488 edge->usercount--; 489 //decrease vertex user count as well 490 thworld.vertexes[edge->v[0]].usercount--; 491 thworld.vertexes[edge->v[1]].usercount--; 492 } //end of the function TH_RemoveEdgeUser 493 //=========================================================================== 494 // 495 // Parameter: - 496 // Returns: - 497 // Changes Globals: - 498 //=========================================================================== 499 void TH_FreeTriangleEdges(th_triangle_t *tri) 500 { 501 int i; 502 503 for (i = 0; i < 3; i++) 504 { 505 TH_RemoveEdgeUser(abs(tri->edges[i])); 506 } //end for 507 } //end of the function TH_FreeTriangleEdges 508 //=========================================================================== 509 // 510 // Parameter: - 511 // Returns: - 512 // Changes Globals: - 513 //=========================================================================== 514 unsigned TH_HashVec(vec3_t vec) 515 { 516 int x, y; 517 518 x = (MAX_MAP_BOUNDS + (int)(vec[0]+0.5)) >> VERTEXHASH_SHIFT; 519 y = (MAX_MAP_BOUNDS + (int)(vec[1]+0.5)) >> VERTEXHASH_SHIFT; 520 521 if (x < 0 || x >= VERTEXHASH_SIZE || y < 0 || y >= VERTEXHASH_SIZE) 522 Error("HashVec: point %f %f %f outside valid range", vec[0], vec[1], vec[2]); 523 524 return y*VERTEXHASH_SIZE + x; 525 } //end of the function TH_HashVec 526 //=========================================================================== 527 // 528 // Parameter: - 529 // Returns: - 530 // Changes Globals: - 531 //=========================================================================== 532 int TH_FindVertex(vec3_t v) 533 { 534 int i, h; 535 th_vertex_t *vertex; 536 vec3_t vert; 537 538 for (i = 0; i < 3; i++) 539 { 540 if ( fabs(v[i] - Q_rint(v[i])) < INTEGRAL_EPSILON) 541 vert[i] = Q_rint(v[i]); 542 else 543 vert[i] = v[i]; 544 } //end for 545 546 h = TH_HashVec(vert); 547 548 for (vertex = thworld.vertexhash[h]; vertex; vertex = vertex->hashnext) 549 { 550 if (fabs(vertex->v[0] - vert[0]) < VERTEX_EPSILON && 551 fabs(vertex->v[1] - vert[1]) < VERTEX_EPSILON && 552 fabs(vertex->v[2] - vert[2]) < VERTEX_EPSILON) 553 { 554 return vertex - thworld.vertexes; 555 } //end if 556 } //end for 557 return 0; 558 } //end of the function TH_FindVertex 559 //=========================================================================== 560 // 561 // Parameter: - 562 // Returns: - 563 // Changes Globals: - 564 //=========================================================================== 565 void TH_AddVertexToHash(th_vertex_t *vertex) 566 { 567 int hashvalue; 568 569 hashvalue = TH_HashVec(vertex->v); 570 vertex->hashnext = thworld.vertexhash[hashvalue]; 571 thworld.vertexhash[hashvalue] = vertex; 572 } //end of the function TH_AddVertexToHash 573 //=========================================================================== 574 // 575 // Parameter: - 576 // Returns: - 577 // Changes Globals: - 578 //=========================================================================== 579 int TH_CreateVertex(vec3_t v) 580 { 581 if (thworld.numvertexes == 0) thworld.numvertexes = 1; 582 if (thworld.numvertexes >= MAX_TH_VERTEXES) 583 Error("MAX_TH_VERTEXES"); 584 VectorCopy(v, thworld.vertexes[thworld.numvertexes].v); 585 thworld.vertexes[thworld.numvertexes].usercount = 0; 586 TH_AddVertexToHash(&thworld.vertexes[thworld.numvertexes]); 587 thworld.numvertexes++; 588 return thworld.numvertexes-1; 589 } //end of the function TH_CreateVertex 590 //=========================================================================== 591 // 592 // Parameter: - 593 // Returns: - 594 // Changes Globals: - 595 //=========================================================================== 596 int TH_FindOrCreateVertex(vec3_t v) 597 { 598 int vertexnum; 599 600 vertexnum = TH_FindVertex(v); 601 if (!vertexnum) vertexnum = TH_CreateVertex(v); 602 return vertexnum; 603 } //end of the function TH_FindOrCreateVertex 604 //=========================================================================== 605 // 606 // Parameter: - 607 // Returns: - 608 // Changes Globals: - 609 //=========================================================================== 610 int TH_FindEdge(int v1, int v2) 611 { 612 int hashvalue; 613 th_edge_t *edge; 614 615 hashvalue = (v1 + v2) & (EDGEHASH_SIZE-1); 616 617 for (edge = thworld.edgehash[hashvalue]; edge; edge = edge->hashnext) 618 { 619 if (edge->v[0] == v1 && edge->v[1] == v2) return edge - thworld.edges; 620 if (edge->v[1] == v1 && edge->v[0] == v2) return -(edge - thworld.edges); 621 } //end for 622 return 0; 623 } //end of the function TH_FindEdge 624 //=========================================================================== 625 // 626 // Parameter: - 627 // Returns: - 628 // Changes Globals: - 629 //=========================================================================== 630 void TH_AddEdgeToHash(th_edge_t *edge) 631 { 632 int hashvalue; 633 634 hashvalue = (edge->v[0] + edge->v[1]) & (EDGEHASH_SIZE-1); 635 edge->hashnext = thworld.edgehash[hashvalue]; 636 thworld.edgehash[hashvalue] = edge; 637 } //end of the function TH_AddEdgeToHash 638 //=========================================================================== 639 // 640 // Parameter: - 641 // Returns: - 642 // Changes Globals: - 643 //=========================================================================== 644 int TH_CreateEdge(int v1, int v2) 645 { 646 th_edge_t *edge; 647 648 if (thworld.numedges == 0) thworld.numedges = 1; 649 if (thworld.numedges >= MAX_TH_EDGES) 650 Error("MAX_TH_EDGES"); 651 edge = &thworld.edges[thworld.numedges++]; 652 edge->v[0] = v1; 653 edge->v[1] = v2; 654 TH_AddEdgeToHash(edge); 655 return thworld.numedges-1; 656 } //end of the function TH_CreateEdge 657 //=========================================================================== 658 // 659 // Parameter: - 660 // Returns: - 661 // Changes Globals: - 662 //=========================================================================== 663 int TH_FindOrCreateEdge(int v1, int v2) 664 { 665 int edgenum; 666 667 edgenum = TH_FindEdge(v1, v2); 668 if (!edgenum) edgenum = TH_CreateEdge(v1, v2); 669 return edgenum; 670 } //end of the function TH_FindOrCreateEdge 671 //=========================================================================== 672 // 673 // Parameter: - 674 // Returns: - 675 // Changes Globals: - 676 //=========================================================================== 677 int TH_FindTriangle(int verts[3]) 678 { 679 int i, hashvalue, edges[3]; 680 th_triangle_t *tri; 681 682 for (i = 0; i < 3; i++) 683 { 684 edges[i] = TH_FindEdge(verts[i], verts[(i+1)%3]); 685 if (!edges[i]) return false; 686 } //end for 687 hashvalue = (abs(edges[0]) + abs(edges[1]) + abs(edges[2])) & (TRIANGLEHASH_SIZE-1); 688 for (tri = thworld.trianglehash[hashvalue]; tri; tri = tri->next) 689 { 690 for (i = 0; i < 3; i++) 691 { 692 if (abs(tri->edges[i]) != abs(edges[0]) && 693 abs(tri->edges[i]) != abs(edges[1]) && 694 abs(tri->edges[i]) != abs(edges[2])) break; 695 } //end for 696 if (i >= 3) return tri - thworld.triangles; 697 } //end for 698 return 0; 699 } //end of the function TH_FindTriangle 700 //=========================================================================== 701 // 702 // Parameter: - 703 // Returns: - 704 // Changes Globals: - 705 //=========================================================================== 706 void TH_AddTriangleToHash(th_triangle_t *tri) 707 { 708 int hashvalue; 709 710 hashvalue = (abs(tri->edges[0]) + abs(tri->edges[1]) + abs(tri->edges[2])) & (TRIANGLEHASH_SIZE-1); 711 tri->hashnext = thworld.trianglehash[hashvalue]; 712 thworld.trianglehash[hashvalue] = tri; 713 } //end of the function TH_AddTriangleToHash 714 //=========================================================================== 715 // 716 // Parameter: - 717 // Returns: - 718 // Changes Globals: - 719 //=========================================================================== 720 void TH_CreateTrianglePlanes(int verts[3], th_plane_t *triplane, th_plane_t *planes) 721 { 722 int i; 723 vec3_t dir; 724 725 for (i = 0; i < 3; i++) 726 { 727 VectorSubtract(thworld.vertexes[verts[(i+1)%3]].v, thworld.vertexes[verts[i]].v, dir); 728 CrossProduct(dir, triplane->normal, planes[i].normal); 729 VectorNormalize(planes[i].normal); 730 planes[i].dist = DotProduct(thworld.vertexes[verts[i]].v, planes[i].normal); 731 } //end for 732 } //end of the function TH_CreateTrianglePlanes 733 //=========================================================================== 734 // 735 // Parameter: - 736 // Returns: - 737 // Changes Globals: - 738 //=========================================================================== 739 int TH_CreateTriangle(int verts[3]) 740 { 741 th_triangle_t *tri; 742 int i; 743 744 if (thworld.numtriangles == 0) thworld.numtriangles = 1; 745 if (thworld.numtriangles >= MAX_TH_TRIANGLES) 746 Error("MAX_TH_TRIANGLES"); 747 tri = &thworld.triangles[thworld.numtriangles++]; 748 for (i = 0; i < 3; i++) 749 { 750 tri->edges[i] = TH_FindOrCreateEdge(verts[i], verts[(i+1)%3]); 751 TH_AddEdgeUser(abs(tri->edges[i])); 752 } //end for 753 tri->front = 0; 754 tri->back = 0; 755 tri->planenum = TH_PlaneFromPoints(verts[0], verts[1], verts[2]); 756 tri->prev = NULL; 757 tri->next = NULL; 758 tri->hashnext = NULL; 759 TH_CreateTrianglePlanes(verts, &thworld.planes[tri->planenum], tri->planes); 760 TH_AddTriangleToHash(tri); 761 ClearBounds(tri->mins, tri->maxs); 762 for (i = 0; i < 3; i++) 763 { 764 AddPointToBounds(thworld.vertexes[verts[i]].v, tri->mins, tri->maxs); 765 } //end for 766 return thworld.numtriangles-1; 767 } //end of the function TH_CreateTriangle 768 //=========================================================================== 769 // 770 // Parameter: - 771 // Returns: - 772 // Changes Globals: - 773 //=========================================================================== 774 int TH_CreateTetrahedron(int triangles[4]) 775 { 776 th_tetrahedron_t *tetrahedron; 777 int i; 778 779 if (thworld.numtetrahedrons == 0) thworld.numtetrahedrons = 1; 780 if (thworld.numtetrahedrons >= MAX_TH_TETRAHEDRONS) 781 Error("MAX_TH_TETRAHEDRONS"); 782 tetrahedron = &thworld.tetrahedrons[thworld.numtetrahedrons++]; 783 for (i = 0; i < 4; i++) 784 { 785 tetrahedron->triangles[i] = triangles[i]; 786 if (thworld.triangles[abs(triangles[i])].front) 787 { 788 thworld.triangles[abs(triangles[i])].back = thworld.numtetrahedrons-1; 789 } //end if 790 else 791 { 792 thworld.triangles[abs(triangles[i])].front = thworld.numtetrahedrons-1; 793 } //end else 794 } //end for 795 tetrahedron->volume = 0; 796 return thworld.numtetrahedrons-1; 797 } //end of the function TH_CreateTetrahedron 798 //=========================================================================== 799 // 800 // Parameter: - 801 // Returns: - 802 // Changes Globals: - 803 //=========================================================================== 804 int TH_IntersectTrianglePlanes(int v1, int v2, th_plane_t *triplane, th_plane_t *planes) 805 { 806 float *p1, *p2, front, back, frac, d; 807 int i, side, lastside; 808 vec3_t mid; 809 810 p1 = thworld.vertexes[v1].v; 811 p2 = thworld.vertexes[v2].v; 812 813 front = DotProduct(p1, triplane->normal) - triplane->dist; 814 back = DotProduct(p2, triplane->normal) - triplane->dist; 815 //if both points at the same side of the plane 816 if (front < 0.1 && back < 0.1) return false; 817 if (front > -0.1 && back > -0.1) return false; 818 // 819 frac = front/(front-back); 820 mid[0] = p1[0] + (p2[0] - p1[0]) * frac; 821 mid[1] = p1[1] + (p2[1] - p1[1]) * frac; 822 mid[2] = p1[2] + (p2[2] - p1[2]) * frac; 823 //if the mid point is at the same side of all the tri bounding planes 824 lastside = 0; 825 for (i = 0; i < 3; i++) 826 { 827 d = DotProduct(mid, planes[i].normal) - planes[i].dist; 828 side = d < 0; 829 if (i && side != lastside) return false; 830 lastside = side; 831 } //end for 832 return true; 833 } //end of the function TH_IntersectTrianglePlanes 834 //=========================================================================== 835 // 836 // Parameter: - 837 // Returns: - 838 // Changes Globals: - 839 //=========================================================================== 840 int TH_OutsideBoundingBox(int v1, int v2, vec3_t mins, vec3_t maxs) 841 { 842 float *p1, *p2; 843 int i; 844 845 p1 = thworld.vertexes[v1].v; 846 p2 = thworld.vertexes[v2].v; 847 //if both points are at the outer side of one of the bounding box planes 848 for (i = 0; i < 3; i++) 849 { 850 if (p1[i] < mins[i] && p2[i] < mins[i]) return true; 851 if (p1[i] > maxs[i] && p2[i] > maxs[i]) return true; 852 } //end for 853 return false; 854 } //end of the function TH_OutsideBoundingBox 855 //=========================================================================== 856 // 857 // Parameter: - 858 // Returns: - 859 // Changes Globals: - 860 //=========================================================================== 861 int TH_TryEdge(int v1, int v2) 862 { 863 int i, j, v; 864 th_plane_t *plane; 865 th_triangle_t *tri; 866 867 //if the edge already exists it must be valid 868 if (TH_FindEdge(v1, v2)) return true; 869 //test the edge with all existing triangles 870 for (i = 1; i < thworld.numtriangles; i++) 871 { 872 tri = &thworld.triangles[i]; 873 //if triangle is enclosed by two tetrahedrons we don't have to test it 874 //because the edge always has to go through another triangle of those 875 //tetrahedrons first to reach the enclosed triangle 876 if (tri->front && tri->back) continue; 877 //if the edges is totally outside the triangle bounding box 878 if (TH_OutsideBoundingBox(v1, v2, tri->mins, tri->maxs)) continue; 879 //if one of the edge vertexes is used by this triangle 880 for (j = 0; j < 3; j++) 881 { 882 v = thworld.edges[abs(tri->edges[j])].v[tri->edges[j] < 0]; 883 if (v == v1 || v == v2) break; 884 } //end for 885 if (j < 3) continue; 886 //get the triangle plane 887 plane = &thworld.planes[tri->planenum]; 888 //if the edge intersects with a triangle then it's not valid 889 if (TH_IntersectTrianglePlanes(v1, v2, plane, tri->planes)) return false; 890 } //end for 891 return true; 892 } //end of the function TH_TryEdge 893 //=========================================================================== 894 // 895 // Parameter: - 896 // Returns: - 897 // Changes Globals: - 898 //=========================================================================== 899 int TH_TryTriangle(int verts[3]) 900 { 901 th_plane_t planes[3], triplane; 902 vec3_t t1, t2; 903 float *p0, *p1, *p2; 904 int i, j; 905 906 p0 = thworld.vertexes[verts[0]].v; 907 p1 = thworld.vertexes[verts[1]].v; 908 p2 = thworld.vertexes[verts[2]].v; 909 910 VectorSubtract(p0, p1, t1); 911 VectorSubtract(p2, p1, t2); 912 CrossProduct(t1, t2, triplane.normal); 913 VectorNormalize(triplane.normal); 914 triplane.dist = DotProduct(p0, triplane.normal); 915 // 916 TH_CreateTrianglePlanes(verts, &triplane, planes); 917 //test if any existing edge intersects with this triangle 918 for (i = 1; i < thworld.numedges; i++) 919 { 920 //if the edge is only used by triangles with tetrahedrons at both sides 921 if (!thworld.edges[i].usercount) continue; 922 //if one of the triangle vertexes is used by this edge 923 for (j = 0; j < 3; j++) 924 { 925 if (verts[j] == thworld.edges[j].v[0] || 926 verts[j] == thworld.edges[j].v[1]) break; 927 } //end for 928 if (j < 3) continue; 929 //if this edge intersects with the triangle 930 if (TH_IntersectTrianglePlanes(thworld.edges[i].v[0], thworld.edges[i].v[1], &triplane, planes)) return false; 931 } //end for 932 return true; 933 } //end of the function TH_TryTriangle 934 //=========================================================================== 935 // 936 // Parameter: - 937 // Returns: - 938 // Changes Globals: - 939 //=========================================================================== 940 void TH_AddTriangleToList(th_triangle_t **trianglelist, th_triangle_t *tri) 941 { 942 tri->prev = NULL; 943 tri->next = *trianglelist; 944 if (*trianglelist) (*trianglelist)->prev = tri; 945 *trianglelist = tri; 946 } //end of the function TH_AddTriangleToList 947 //=========================================================================== 948 // 949 // Parameter: - 950 // Returns: - 951 // Changes Globals: - 952 //=========================================================================== 953 void TH_RemoveTriangleFromList(th_triangle_t **trianglelist, th_triangle_t *tri) 954 { 955 if (tri->next) tri->next->prev = tri->prev; 956 if (tri->prev) tri->prev->next = tri->next; 957 else *trianglelist = tri->next; 958 } //end of the function TH_RemoveTriangleFromList 959 //=========================================================================== 960 // 961 // Parameter: - 962 // Returns: - 963 // Changes Globals: - 964 //=========================================================================== 965 int TH_FindTetrahedron1(th_triangle_t *tri, int *triangles) 966 { 967 int i, j, edgenum, side, v1, v2, v3, v4; 968 int verts1[3], verts2[3]; 969 th_triangle_t *tri2; 970 971 //find another triangle with a shared edge 972 for (tri2 = tri->next; tri2; tri2 = tri2->next) 973 { 974 //if the triangles are in the same plane 975 if ((tri->planenum & ~1) == (tri2->planenum & ~1)) continue; 976 //try to find a shared edge 977 for (i = 0; i < 3; i++) 978 { 979 edgenum = abs(tri->edges[i]); 980 for (j = 0; j < 3; j++) 981 { 982 if (edgenum == abs(tri2->edges[j])) break; 983 } //end for 984 if (j < 3) break; 985 } //end for 986 //if the triangles have a shared edge 987 if (i < 3) 988 { 989 edgenum = tri->edges[(i+1)%3]; 990 if (edgenum < 0) v1 = thworld.edges[abs(edgenum)].v[0]; 991 else v1 = thworld.edges[edgenum].v[1]; 992 edgenum = tri2->edges[(j+1)%3]; 993 if (edgenum < 0) v2 = thworld.edges[abs(edgenum)].v[0]; 994 else v2 = thworld.edges[edgenum].v[1]; 995 //try the new edge 996 if (TH_TryEdge(v1, v2)) 997 { 998 edgenum = tri->edges[i]; 999 side = edgenum < 0; 1000 //get the vertexes of the shared edge 1001 v3 = thworld.edges[abs(edgenum)].v[side]; 1002 v4 = thworld.edges[abs(edgenum)].v[!side]; 1003 //try the two new triangles 1004 verts1[0] = v1; 1005 verts1[1] = v2; 1006 verts1[2] = v3; 1007 triangles[2] = TH_FindTriangle(verts1); 1008 if (triangles[2] || TH_TryTriangle(verts1)) 1009 { 1010 verts2[0] = v2; 1011 verts2[1] = v1; 1012 verts2[2] = v4; 1013 triangles[3] = TH_FindTriangle(verts2); 1014 if (triangles[3] || TH_TryTriangle(verts2)) 1015 { 1016 triangles[0] = tri - thworld.triangles; 1017 triangles[1] = tri2 - thworld.triangles; 1018 if (!triangles[2]) triangles[2] = TH_CreateTriangle(verts1); 1019 if (!triangles[3]) triangles[3] = TH_CreateTriangle(verts2); 1020 return true; 1021 } //end if 1022 } //end if 1023 } //end if 1024 } //end if 1025 } //end for 1026 return false; 1027 } //end of the function TH_FindTetrahedron 1028 //=========================================================================== 1029 // 1030 // Parameter: - 1031 // Returns: - 1032 // Changes Globals: - 1033 //=========================================================================== 1034 int TH_FindTetrahedron2(th_triangle_t *tri, int *triangles) 1035 { 1036 int i, edgenum, v1, verts[3], triverts[3]; 1037 float d; 1038 th_plane_t *plane; 1039 1040 //get the verts of this triangle 1041 for (i = 0; i < 3; i++) 1042 { 1043 edgenum = tri->edges[i]; 1044 if (edgenum < 0) verts[i] = thworld.edges[abs(edgenum)].v[1]; 1045 else verts[i] = thworld.edges[edgenum].v[0]; 1046 } //end for 1047 // 1048 plane = &thworld.planes[tri->planenum]; 1049 for (v1 = 0; v1 < thworld.numvertexes; v1++) 1050 { 1051 //if the vertex is only used by triangles with tetrahedrons at both sides 1052 if (!thworld.vertexes[v1].usercount) continue; 1053 //check if the vertex is not coplanar with the triangle 1054 d = DotProduct(thworld.vertexes[v1].v, plane->normal) - plane->dist; 1055 if (fabs(d) < 1) continue; 1056 //check if we can create edges from the triangle towards this new vertex 1057 for (i = 0; i < 3; i++) 1058 { 1059 if (v1 == verts[i]) break; 1060 if (!TH_TryEdge(v1, verts[i])) break; 1061 } //end for 1062 if (i < 3) continue; 1063 //check if the triangles are valid 1064 for (i = 0; i < 3; i++) 1065 { 1066 triverts[0] = v1; 1067 triverts[1] = verts[i]; 1068 triverts[2] = verts[(i+1)%3]; 1069 //if the triangle already exists then it is valid 1070 triangles[i] = TH_FindTriangle(triverts); 1071 if (!triangles[i]) 1072 { 1073 if (!TH_TryTriangle(triverts)) break; 1074 } //end if 1075 } //end for 1076 if (i < 3) continue; 1077 //create the tetrahedron triangles using the new vertex 1078 for (i = 0; i < 3; i++) 1079 { 1080 if (!triangles[i]) 1081 { 1082 triverts[0] = v1; 1083 triverts[1] = verts[i]; 1084 triverts[2] = verts[(i+1)%3]; 1085 triangles[i] = TH_CreateTriangle(triverts); 1086 } //end if 1087 } //end for 1088 //add the existing triangle 1089 triangles[3] = tri - thworld.triangles; 1090 // 1091 return true; 1092 } //end for 1093 return false; 1094 } //end of the function TH_FindTetrahedron2 1095 //=========================================================================== 1096 // 1097 // Parameter: - 1098 // Returns: - 1099 // Changes Globals: - 1100 //=========================================================================== 1101 void TH_TetrahedralDecomposition(th_triangle_t *triangles) 1102 { 1103 int i, thtriangles[4], numtriangles; 1104 th_triangle_t *donetriangles, *tri; 1105 1106 donetriangles = NULL; 1107 1108 /* 1109 numtriangles = 0; 1110 qprintf("%6d triangles", numtriangles); 1111 for (tri = triangles; tri; tri = triangles) 1112 { 1113 qprintf("\r%6d", numtriangles++); 1114 if (!TH_FindTetrahedron1(tri, thtriangles)) 1115 { 1116 // if (!TH_FindTetrahedron2(tri, thtriangles)) 1117 { 1118 // Error("triangle without tetrahedron"); 1119 TH_RemoveTriangleFromList(&triangles, tri); 1120 continue; 1121 } //end if 1122 } //end if 1123 //create a tetrahedron from the triangles 1124 TH_CreateTetrahedron(thtriangles); 1125 // 1126 for (i = 0; i < 4; i++) 1127 { 1128 if (thworld.triangles[abs(thtriangles[i])].front && 1129 thworld.triangles[abs(thtriangles[i])].back) 1130 { 1131 TH_RemoveTriangleFromList(&triangles, &thworld.triangles[abs(thtriangles[i])]); 1132 TH_AddTriangleToList(&donetriangles, &thworld.triangles[abs(thtriangles[i])]); 1133 TH_FreeTriangleEdges(&thworld.triangles[abs(thtriangles[i])]); 1134 } //end if 1135 else 1136 { 1137 TH_AddTriangleToList(&triangles, &thworld.triangles[abs(thtriangles[i])]); 1138 } //end else 1139 } //end for 1140 } //end for*/ 1141 qprintf("%6d tetrahedrons", thworld.numtetrahedrons); 1142 do 1143 { 1144 do 1145 { 1146 numtriangles = 0; 1147 for (i = 1; i < thworld.numtriangles; i++) 1148 { 1149 tri = &thworld.triangles[i]; 1150 if (tri->front && tri->back) continue; 1151 //qprintf("\r%6d", numtriangles++); 1152 if (!TH_FindTetrahedron1(tri, thtriangles)) 1153 { 1154 // if (!TH_FindTetrahedron2(tri, thtriangles)) 1155 { 1156 continue; 1157 } //end if 1158 } //end if 1159 numtriangles++; 1160 //create a tetrahedron from the triangles 1161 TH_CreateTetrahedron(thtriangles); 1162 qprintf("\r%6d", thworld.numtetrahedrons); 1163 } //end for 1164 } while(numtriangles); 1165 for (i = 1; i < thworld.numtriangles; i++) 1166 { 1167 tri = &thworld.triangles[i]; 1168 if (tri->front && tri->back) continue; 1169 //qprintf("\r%6d", numtriangles++); 1170 // if (!TH_FindTetrahedron1(tri, thtriangles)) 1171 { 1172 if (!TH_FindTetrahedron2(tri, thtriangles)) 1173 { 1174 continue; 1175 } //end if 1176 } //end if 1177 numtriangles++; 1178 //create a tetrahedron from the triangles 1179 TH_CreateTetrahedron(thtriangles); 1180 qprintf("\r%6d", thworld.numtetrahedrons); 1181 } //end for 1182 } while(numtriangles); 1183 // 1184 numtriangles = 0; 1185 for (i = 1; i < thworld.numtriangles; i++) 1186 { 1187 tri = &thworld.triangles[i]; 1188 if (!tri->front && !tri->back) numtriangles++; 1189 } //end for 1190 Log_Print("\r%6d triangles with front only\n", numtriangles); 1191 Log_Print("\r%6d tetrahedrons\n", thworld.numtetrahedrons-1); 1192 } //end of the function TH_TetrahedralDecomposition 1193 //=========================================================================== 1194 // 1195 // Parameter: - 1196 // Returns: - 1197 // Changes Globals: - 1198 //=========================================================================== 1199 void TH_AASFaceVertex(aas_face_t *face, int index, vec3_t vertex) 1200 { 1201 int edgenum, side; 1202 1203 edgenum = aasworld.edgeindex[face->firstedge + index]; 1204 side = edgenum < 0; 1205 VectorCopy(aasworld.vertexes[aasworld.edges[abs(edgenum)].v[side]], vertex); 1206 } //end of the function TH_AASFaceVertex 1207 //=========================================================================== 1208 // 1209 // Parameter: - 1210 // Returns: - 1211 // Changes Globals: - 1212 //=========================================================================== 1213 int TH_Colinear(float *v0, float *v1, float *v2) 1214 { 1215 vec3_t t1, t2, vcross; 1216 float d; 1217 1218 VectorSubtract(v1, v0, t1); 1219 VectorSubtract(v2, v0, t2); 1220 CrossProduct (t1, t2, vcross); 1221 d = VectorLength( vcross ); 1222 1223 // if cross product is zero point is colinear 1224 if (d < 10) 1225 { 1226 return true; 1227 } //end if 1228 return false; 1229 } //end of the function TH_Colinear 1230 //=========================================================================== 1231 // 1232 // Parameter: - 1233 // Returns: - 1234 // Changes Globals: - 1235 //=========================================================================== 1236 void TH_FaceCenter(aas_face_t *face, vec3_t center) 1237 { 1238 int i, edgenum, side; 1239 aas_edge_t *edge; 1240 1241 VectorClear(center); 1242 for (i = 0; i < face->numedges; i++) 1243 { 1244 edgenum = abs(aasworld.edgeindex[face->firstedge + i]); 1245 side = edgenum < 0; 1246 edge = &aasworld.edges[abs(edgenum)]; 1247 VectorAdd(aasworld.vertexes[edge->v[side]], center, center); 1248 } //end for 1249 VectorScale(center, 1.0 / face->numedges, center); 1250 } //end of the function TH_FaceCenter 1251 //=========================================================================== 1252 // 1253 // Parameter: - 1254 // Returns: - 1255 // Changes Globals: - 1256 //=========================================================================== 1257 th_triangle_t *TH_CreateAASFaceTriangles(aas_face_t *face) 1258 { 1259 int i, first, verts[3], trinum; 1260 vec3_t p0, p1, p2, p3, p4, center; 1261 th_triangle_t *tri, *triangles; 1262 1263 triangles = NULL; 1264 //find three points that are not colinear 1265 for (i = 0; i < face->numedges; i++) 1266 { 1267 TH_AASFaceVertex(face, (face->numedges + i-2)%face->numedges, p0); 1268 TH_AASFaceVertex(face, (face->numedges + i-1)%face->numedges, p1); 1269 TH_AASFaceVertex(face, (i )%face->numedges, p2); 1270 if (TH_Colinear(p2, p0, p1)) continue; 1271 TH_AASFaceVertex(face, (i+1)%face->numedges, p3); 1272 TH_AASFaceVertex(face, (i+2)%face->numedges, p4); 1273 if (TH_Colinear(p2, p3, p4)) continue; 1274 break; 1275 } //end for 1276 //if there are three points that are not colinear 1277 if (i < face->numedges) 1278 { 1279 //normal triangulation 1280 first = i; //left and right most point of three non-colinear points 1281 TH_AASFaceVertex(face, first, p0); 1282 verts[0] = TH_FindOrCreateVertex(p0); 1283 for (i = 1; i < face->numedges-1; i++) 1284 { 1285 TH_AASFaceVertex(face, (first+i )%face->numedges, p1); 1286 TH_AASFaceVertex(face, (first+i+1)%face->numedges, p2); 1287 verts[1] = TH_FindOrCreateVertex(p1); 1288 verts[2] = TH_FindOrCreateVertex(p2); 1289 trinum = TH_CreateTriangle(verts); 1290 tri = &thworld.triangles[trinum]; 1291 tri->front = -1; 1292 TH_AddTriangleToList(&triangles, tri); 1293 } //end for 1294 } //end if 1295 else 1296 { 1297 //fan triangulation 1298 TH_FaceCenter(face, center); 1299 // 1300 verts[0] = TH_FindOrCreateVertex(center); 1301 for (i = 0; i < face->numedges; i++) 1302 { 1303 TH_AASFaceVertex(face, (i )%face->numedges, p1); 1304 TH_AASFaceVertex(face, (i+1)%face->numedges, p2); 1305 if (TH_Colinear(center, p1, p2)) continue; 1306 verts[1] = TH_FindOrCreateVertex(p1); 1307 verts[2] = TH_FindOrCreateVertex(p2); 1308 trinum = TH_CreateTriangle(verts); 1309 tri = &thworld.triangles[trinum]; 1310 tri->front = -1; 1311 TH_AddTriangleToList(&triangles, tri); 1312 } //end for 1313 } //end else 1314 return triangles; 1315 } //end of the function TH_CreateAASFaceTriangles 1316 //=========================================================================== 1317 // 1318 // Parameter: - 1319 // Returns: - 1320 // Changes Globals: - 1321 //=========================================================================== 1322 th_triangle_t *TH_AASToTriangleMesh(void) 1323 { 1324 int i, j, facenum, otherareanum; 1325 aas_face_t *face; 1326 th_triangle_t *tri, *nexttri, *triangles; 1327 1328 triangles = NULL; 1329 for (i = 1; i < aasworld.numareas; i++) 1330 { 1331 //if (!(aasworld.areasettings[i].presencetype & PRESENCE_NORMAL)) continue; 1332 for (j = 0; j < aasworld.areas[i].numfaces; j++) 1333 { 1334 facenum = abs(aasworld.faceindex[aasworld.areas[i].firstface + j]); 1335 face = &aasworld.faces[facenum]; 1336 //only convert solid faces into triangles 1337 if (!(face->faceflags & FACE_SOLID)) 1338 { 1339 /* 1340 if (face->frontarea == i) otherareanum = face->backarea; 1341 else otherareanum = face->frontarea; 1342 if (aasworld.areasettings[otherareanum].presencetype & PRESENCE_NORMAL) continue; 1343 */ 1344 continue; 1345 } //end if 1346 // 1347 tri = TH_CreateAASFaceTriangles(face); 1348 for (; tri; tri = nexttri) 1349 { 1350 nexttri = tri->next; 1351 TH_AddTriangleToList(&triangles, tri); 1352 } //end for 1353 } //end if 1354 } //end for 1355 return triangles; 1356 } //end of the function TH_AASToTriangleMesh 1357 //=========================================================================== 1358 // 1359 // Parameter: - 1360 // Returns: - 1361 // Changes Globals: - 1362 //=========================================================================== 1363 void TH_AASToTetrahedrons(char *filename) 1364 { 1365 th_triangle_t *triangles, *tri, *lasttri; 1366 int cnt; 1367 1368 if (!AAS_LoadAASFile(filename, 0, 0)) 1369 Error("couldn't load %s\n", filename); 1370 1371 // 1372 TH_InitMaxTH(); 1373 //create a triangle mesh from the solid faces in the AAS file 1374 triangles = TH_AASToTriangleMesh(); 1375 // 1376 cnt = 0; 1377 lasttri = NULL; 1378 for (tri = triangles; tri; tri = tri->next) 1379 { 1380 cnt++; 1381 if (tri->prev != lasttri) Log_Print("BAH\n"); 1382 lasttri = tri; 1383 } //end for 1384 Log_Print("%6d triangles\n", cnt); 1385 //create a tetrahedral decomposition of the world bounded by triangles 1386 TH_TetrahedralDecomposition(triangles); 1387 // 1388 TH_FreeMaxTH(); 1389 } //end of the function TH_AASToTetrahedrons