map_q2.c (30781B)
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 //=========================================================================== 24 // ANSI, Area Navigational System Interface 25 // AAS, Area Awareness System 26 //=========================================================================== 27 28 #include "qbsp.h" 29 #include "l_mem.h" 30 #include "../botlib/aasfile.h" //aas_bbox_t 31 #include "aas_store.h" //AAS_MAX_BBOXES 32 #include "aas_cfg.h" 33 #include "aas_map.h" //AAS_CreateMapBrushes 34 #include "l_bsp_q2.h" 35 36 37 #ifdef ME 38 39 #define NODESTACKSIZE 1024 40 41 int nodestack[NODESTACKSIZE]; 42 int *nodestackptr; 43 int nodestacksize = 0; 44 int brushmodelnumbers[MAX_MAPFILE_BRUSHES]; 45 int dbrushleafnums[MAX_MAPFILE_BRUSHES]; 46 int dplanes2mapplanes[MAX_MAPFILE_PLANES]; 47 48 #endif //ME 49 50 //==================================================================== 51 52 //=========================================================================== 53 // 54 // Parameter: - 55 // Returns: - 56 // Changes Globals: - 57 //=========================================================================== 58 void Q2_CreateMapTexinfo(void) 59 { 60 int i; 61 62 for (i = 0; i < numtexinfo; i++) 63 { 64 memcpy(map_texinfo[i].vecs, texinfo[i].vecs, sizeof(float) * 2 * 4); 65 map_texinfo[i].flags = texinfo[i].flags; 66 map_texinfo[i].value = texinfo[i].value; 67 strcpy(map_texinfo[i].texture, texinfo[i].texture); 68 map_texinfo[i].nexttexinfo = 0; 69 } //end for 70 } //end of the function Q2_CreateMapTexinfo 71 72 /* 73 =========== 74 Q2_BrushContents 75 =========== 76 */ 77 int Q2_BrushContents (mapbrush_t *b) 78 { 79 int contents; 80 side_t *s; 81 int i; 82 int trans; 83 84 s = &b->original_sides[0]; 85 contents = s->contents; 86 trans = texinfo[s->texinfo].flags; 87 for (i = 1; i < b->numsides; i++, s++) 88 { 89 s = &b->original_sides[i]; 90 trans |= texinfo[s->texinfo].flags; 91 if (s->contents != contents) 92 { 93 Log_Print("Entity %i, Brush %i: mixed face contents\n" 94 , b->entitynum, b->brushnum); 95 Log_Print("texture name = %s\n", texinfo[s->texinfo].texture); 96 break; 97 } 98 } 99 100 // if any side is translucent, mark the contents 101 // and change solid to window 102 if ( trans & (SURF_TRANS33|SURF_TRANS66) ) 103 { 104 contents |= CONTENTS_Q2TRANSLUCENT; 105 if (contents & CONTENTS_SOLID) 106 { 107 contents &= ~CONTENTS_SOLID; 108 contents |= CONTENTS_WINDOW; 109 } 110 } 111 112 return contents; 113 } 114 115 #ifdef ME 116 117 #define BBOX_NORMAL_EPSILON 0.0001 118 119 //=========================================================================== 120 // 121 // Parameter: - 122 // Returns: - 123 // Changes Globals: - 124 //=========================================================================== 125 void MakeAreaPortalBrush(mapbrush_t *brush) 126 { 127 int sn; 128 side_t *s; 129 130 brush->contents = CONTENTS_AREAPORTAL; 131 132 for (sn = 0; sn < brush->numsides; sn++) 133 { 134 s = brush->original_sides + sn; 135 //make sure the surfaces are not hint or skip 136 s->surf &= ~(SURF_HINT|SURF_SKIP); 137 // 138 s->texinfo = 0; 139 s->contents = CONTENTS_AREAPORTAL; 140 } //end for 141 } //end of the function MakeAreaPortalBrush 142 //=========================================================================== 143 // 144 // Parameter: - 145 // Returns: - 146 // Changes Globals: - 147 //=========================================================================== 148 void DPlanes2MapPlanes(void) 149 { 150 int i; 151 152 for (i = 0; i < numplanes; i++) 153 { 154 dplanes2mapplanes[i] = FindFloatPlane(dplanes[i].normal, dplanes[i].dist); 155 } //end for 156 } //end of the function DPlanes2MapPlanes 157 //=========================================================================== 158 // 159 // Parameter: - 160 // Returns: - 161 // Changes Globals: - 162 //=========================================================================== 163 void MarkVisibleBrushSides(mapbrush_t *brush) 164 { 165 int n, i, planenum; 166 side_t *side; 167 dface_t *face; 168 // 169 for (n = 0; n < brush->numsides; n++) 170 { 171 side = brush->original_sides + n; 172 //if this side is a bevel or the leaf number of the brush is unknown 173 if ((side->flags & SFL_BEVEL) || brush->leafnum < 0) 174 { 175 //this side is a valid splitter 176 side->flags |= SFL_VISIBLE; 177 continue; 178 } //end if 179 //assum this side will not be used as a splitter 180 side->flags &= ~SFL_VISIBLE; 181 //check if the side plane is used by a visible face 182 for (i = 0; i < numfaces; i++) 183 { 184 face = &dfaces[i]; 185 planenum = dplanes2mapplanes[face->planenum]; 186 if ((planenum & ~1) == (side->planenum & ~1)) 187 { 188 //this side is a valid splitter 189 side->flags |= SFL_VISIBLE; 190 } //end if 191 } //end for 192 } //end for 193 } //end of the function MarkVisibleBrushSides 194 195 #endif //ME 196 197 /* 198 ================= 199 Q2_ParseBrush 200 ================= 201 */ 202 void Q2_ParseBrush (script_t *script, entity_t *mapent) 203 { 204 mapbrush_t *b; 205 int i, j, k; 206 int mt; 207 side_t *side, *s2; 208 int planenum; 209 brush_texture_t td; 210 int planepts[3][3]; 211 token_t token; 212 213 if (nummapbrushes >= MAX_MAPFILE_BRUSHES) 214 Error ("nummapbrushes == MAX_MAPFILE_BRUSHES"); 215 216 b = &mapbrushes[nummapbrushes]; 217 b->original_sides = &brushsides[nummapbrushsides]; 218 b->entitynum = num_entities-1; 219 b->brushnum = nummapbrushes - mapent->firstbrush; 220 b->leafnum = -1; 221 222 do 223 { 224 if (!PS_ReadToken(script, &token)) 225 break; 226 if (!strcmp(token.string, "}") ) 227 break; 228 229 //IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could 230 // lead to out of bound indexing of the arrays 231 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES) 232 Error ("MAX_MAPFILE_BRUSHSIDES"); 233 side = &brushsides[nummapbrushsides]; 234 235 //read the three point plane definition 236 for (i = 0; i < 3; i++) 237 { 238 if (i != 0) PS_ExpectTokenString(script, "("); 239 for (j = 0; j < 3; j++) 240 { 241 PS_ExpectAnyToken(script, &token); 242 planepts[i][j] = atof(token.string); 243 } //end for 244 PS_ExpectTokenString(script, ")"); 245 } //end for 246 247 // 248 //read the texturedef 249 // 250 PS_ExpectAnyToken(script, &token); 251 strcpy(td.name, token.string); 252 253 PS_ExpectAnyToken(script, &token); 254 td.shift[0] = atol(token.string); 255 PS_ExpectAnyToken(script, &token); 256 td.shift[1] = atol(token.string); 257 PS_ExpectAnyToken(script, &token); 258 td.rotate = atol(token.string); 259 PS_ExpectAnyToken(script, &token); 260 td.scale[0] = atof(token.string); 261 PS_ExpectAnyToken(script, &token); 262 td.scale[1] = atof(token.string); 263 264 //find default flags and values 265 mt = FindMiptex (td.name); 266 td.flags = textureref[mt].flags; 267 td.value = textureref[mt].value; 268 side->contents = textureref[mt].contents; 269 side->surf = td.flags = textureref[mt].flags; 270 271 //check if there's a number available 272 if (PS_CheckTokenType(script, TT_NUMBER, 0, &token)) 273 { 274 side->contents = token.intvalue; 275 PS_ExpectTokenType(script, TT_NUMBER, 0, &token); 276 side->surf = td.flags = token.intvalue; 277 PS_ExpectTokenType(script, TT_NUMBER, 0, &token); 278 td.value = token.intvalue; 279 } 280 281 // translucent objects are automatically classified as detail 282 if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) 283 side->contents |= CONTENTS_DETAIL; 284 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 285 side->contents |= CONTENTS_DETAIL; 286 if (fulldetail) 287 side->contents &= ~CONTENTS_DETAIL; 288 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 289 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) 290 side->contents |= CONTENTS_SOLID; 291 292 // hints and skips are never detail, and have no content 293 if (side->surf & (SURF_HINT|SURF_SKIP) ) 294 { 295 side->contents = 0; 296 side->surf &= ~CONTENTS_DETAIL; 297 } 298 299 #ifdef ME 300 //for creating AAS... this side is textured 301 side->flags |= SFL_TEXTURED; 302 #endif //ME 303 // 304 // find the plane number 305 // 306 planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]); 307 if (planenum == -1) 308 { 309 Log_Print("Entity %i, Brush %i: plane with no normal\n" 310 , b->entitynum, b->brushnum); 311 continue; 312 } 313 314 // 315 // see if the plane has been used already 316 // 317 for (k=0 ; k<b->numsides ; k++) 318 { 319 s2 = b->original_sides + k; 320 if (s2->planenum == planenum) 321 { 322 Log_Print("Entity %i, Brush %i: duplicate plane\n" 323 , b->entitynum, b->brushnum); 324 break; 325 } 326 if ( s2->planenum == (planenum^1) ) 327 { 328 Log_Print("Entity %i, Brush %i: mirrored plane\n" 329 , b->entitynum, b->brushnum); 330 break; 331 } 332 } 333 if (k != b->numsides) 334 continue; // duplicated 335 336 // 337 // keep this side 338 // 339 340 side = b->original_sides + b->numsides; 341 side->planenum = planenum; 342 side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], 343 &td, vec3_origin); 344 345 // save the td off in case there is an origin brush and we 346 // have to recalculate the texinfo 347 side_brushtextures[nummapbrushsides] = td; 348 349 nummapbrushsides++; 350 b->numsides++; 351 } while (1); 352 353 // get the content for the entire brush 354 b->contents = Q2_BrushContents (b); 355 356 #ifdef ME 357 if (BrushExists(b)) 358 { 359 c_squattbrushes++; 360 b->numsides = 0; 361 return; 362 } //end if 363 364 if (create_aas) 365 { 366 //create AAS brushes, and add brush bevels 367 AAS_CreateMapBrushes(b, mapent, true); 368 //NOTE: if we return here then duplicate plane errors occur for the non world entities 369 return; 370 } //end if 371 #endif //ME 372 373 // allow detail brushes to be removed 374 if (nodetail && (b->contents & CONTENTS_DETAIL) ) 375 { 376 b->numsides = 0; 377 return; 378 } 379 380 // allow water brushes to be removed 381 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) 382 { 383 b->numsides = 0; 384 return; 385 } 386 387 // create windings for sides and bounds for brush 388 MakeBrushWindings (b); 389 390 // brushes that will not be visible at all will never be 391 // used as bsp splitters 392 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 393 { 394 c_clipbrushes++; 395 for (i=0 ; i<b->numsides ; i++) 396 b->original_sides[i].texinfo = TEXINFO_NODE; 397 } 398 399 // 400 // origin brushes are removed, but they set 401 // the rotation origin for the rest of the brushes 402 // in the entity. After the entire entity is parsed, 403 // the planenums and texinfos will be adjusted for 404 // the origin brush 405 // 406 if (b->contents & CONTENTS_ORIGIN) 407 { 408 char string[32]; 409 vec3_t origin; 410 411 if (num_entities == 1) 412 { 413 Error ("Entity %i, Brush %i: origin brushes not allowed in world" 414 , b->entitynum, b->brushnum); 415 return; 416 } 417 418 VectorAdd (b->mins, b->maxs, origin); 419 VectorScale (origin, 0.5, origin); 420 421 sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); 422 SetKeyValue (&entities[b->entitynum], "origin", string); 423 424 VectorCopy (origin, entities[b->entitynum].origin); 425 426 // don't keep this brush 427 b->numsides = 0; 428 429 return; 430 } 431 432 AddBrushBevels(b); 433 434 nummapbrushes++; 435 mapent->numbrushes++; 436 } 437 438 /* 439 ================ 440 Q2_MoveBrushesToWorld 441 442 Takes all of the brushes from the current entity and 443 adds them to the world's brush list. 444 445 Used by func_group and func_areaportal 446 ================ 447 */ 448 void Q2_MoveBrushesToWorld (entity_t *mapent) 449 { 450 int newbrushes; 451 int worldbrushes; 452 mapbrush_t *temp; 453 int i; 454 455 // this is pretty gross, because the brushes are expected to be 456 // in linear order for each entity 457 458 newbrushes = mapent->numbrushes; 459 worldbrushes = entities[0].numbrushes; 460 461 temp = GetMemory(newbrushes*sizeof(mapbrush_t)); 462 memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t)); 463 464 #if 0 // let them keep their original brush numbers 465 for (i=0 ; i<newbrushes ; i++) 466 temp[i].entitynum = 0; 467 #endif 468 469 // make space to move the brushes (overlapped copy) 470 memmove (mapbrushes + worldbrushes + newbrushes, 471 mapbrushes + worldbrushes, 472 sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) ); 473 474 // copy the new brushes down 475 memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes); 476 477 // fix up indexes 478 entities[0].numbrushes += newbrushes; 479 for (i=1 ; i<num_entities ; i++) 480 entities[i].firstbrush += newbrushes; 481 FreeMemory(temp); 482 483 mapent->numbrushes = 0; 484 } 485 486 /* 487 ================ 488 Q2_ParseMapEntity 489 ================ 490 */ 491 qboolean Q2_ParseMapEntity(script_t *script) 492 { 493 entity_t *mapent; 494 epair_t *e; 495 side_t *s; 496 int i, j; 497 int startbrush, startsides; 498 vec_t newdist; 499 mapbrush_t *b; 500 token_t token; 501 502 if (!PS_ReadToken(script, &token)) return false; 503 504 if (strcmp(token.string, "{") ) 505 Error ("ParseEntity: { not found"); 506 507 if (num_entities == MAX_MAP_ENTITIES) 508 Error ("num_entities == MAX_MAP_ENTITIES"); 509 510 startbrush = nummapbrushes; 511 startsides = nummapbrushsides; 512 513 mapent = &entities[num_entities]; 514 num_entities++; 515 memset (mapent, 0, sizeof(*mapent)); 516 mapent->firstbrush = nummapbrushes; 517 mapent->numbrushes = 0; 518 // mapent->portalareas[0] = -1; 519 // mapent->portalareas[1] = -1; 520 521 do 522 { 523 if (!PS_ReadToken(script, &token)) 524 { 525 Error("ParseEntity: EOF without closing brace"); 526 } //end if 527 if (!strcmp(token.string, "}")) break; 528 if (!strcmp(token.string, "{")) 529 { 530 Q2_ParseBrush(script, mapent); 531 } //end if 532 else 533 { 534 PS_UnreadLastToken(script); 535 e = ParseEpair(script); 536 e->next = mapent->epairs; 537 mapent->epairs = e; 538 } //end else 539 } while(1); 540 541 GetVectorForKey(mapent, "origin", mapent->origin); 542 543 // 544 // if there was an origin brush, offset all of the planes and texinfo 545 // 546 if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) 547 { 548 for (i=0 ; i<mapent->numbrushes ; i++) 549 { 550 b = &mapbrushes[mapent->firstbrush + i]; 551 for (j=0 ; j<b->numsides ; j++) 552 { 553 s = &b->original_sides[j]; 554 newdist = mapplanes[s->planenum].dist - 555 DotProduct (mapplanes[s->planenum].normal, mapent->origin); 556 s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); 557 s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum], 558 &side_brushtextures[s-brushsides], mapent->origin); 559 } 560 MakeBrushWindings (b); 561 } 562 } 563 564 // group entities are just for editor convenience 565 // toss all brushes into the world entity 566 if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) 567 { 568 Q2_MoveBrushesToWorld (mapent); 569 mapent->numbrushes = 0; 570 return true; 571 } 572 573 // areaportal entities move their brushes, but don't eliminate 574 // the entity 575 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) 576 { 577 char str[128]; 578 579 if (mapent->numbrushes != 1) 580 Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1); 581 582 b = &mapbrushes[nummapbrushes-1]; 583 b->contents = CONTENTS_AREAPORTAL; 584 c_areaportals++; 585 mapent->areaportalnum = c_areaportals; 586 // set the portal number as "style" 587 sprintf (str, "%i", c_areaportals); 588 SetKeyValue (mapent, "style", str); 589 Q2_MoveBrushesToWorld (mapent); 590 return true; 591 } 592 593 return true; 594 } 595 596 //=================================================================== 597 598 /* 599 ================ 600 LoadMapFile 601 ================ 602 */ 603 void Q2_LoadMapFile(char *filename) 604 { 605 int i; 606 script_t *script; 607 608 Log_Print("-- Q2_LoadMapFile --\n"); 609 #ifdef ME 610 //loaded map type 611 loadedmaptype = MAPTYPE_QUAKE2; 612 //reset the map loading 613 ResetMapLoading(); 614 #endif //ME 615 616 script = LoadScriptFile(filename); 617 if (!script) 618 { 619 Log_Print("couldn't open %s\n", filename); 620 return; 621 } //end if 622 //white spaces and escape characters inside a string are not allowed 623 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES | 624 SCFL_NOSTRINGESCAPECHARS | 625 SCFL_PRIMITIVE); 626 627 nummapbrushsides = 0; 628 num_entities = 0; 629 630 while (Q2_ParseMapEntity(script)) 631 { 632 } 633 634 ClearBounds (map_mins, map_maxs); 635 for (i=0 ; i<entities[0].numbrushes ; i++) 636 { 637 if (mapbrushes[i].mins[0] > 4096) 638 continue; // no valid points 639 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs); 640 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs); 641 } //end for 642 643 PrintMapInfo(); 644 645 //free the script 646 FreeScript(script); 647 // TestExpandBrushes (); 648 // 649 Q2_CreateMapTexinfo(); 650 } //end of the function Q2_LoadMapFile 651 652 #ifdef ME //Begin MAP loading from BSP file 653 //=========================================================================== 654 // 655 // Parameter: - 656 // Returns: - 657 // Changes Globals: - 658 //=========================================================================== 659 void Q2_SetLeafBrushesModelNumbers(int leafnum, int modelnum) 660 { 661 int i, brushnum; 662 dleaf_t *leaf; 663 664 leaf = &dleafs[leafnum]; 665 for (i = 0; i < leaf->numleafbrushes; i++) 666 { 667 brushnum = dleafbrushes[leaf->firstleafbrush + i]; 668 brushmodelnumbers[brushnum] = modelnum; 669 dbrushleafnums[brushnum] = leafnum; 670 } //end for 671 } //end of the function Q2_SetLeafBrushesModelNumbers 672 //=========================================================================== 673 // 674 // Parameter: - 675 // Returns: - 676 // Changes Globals: - 677 //=========================================================================== 678 void Q2_InitNodeStack(void) 679 { 680 nodestackptr = nodestack; 681 nodestacksize = 0; 682 } //end of the function Q2_InitNodeStack 683 //=========================================================================== 684 // 685 // Parameter: - 686 // Returns: - 687 // Changes Globals: - 688 //=========================================================================== 689 void Q2_PushNodeStack(int num) 690 { 691 *nodestackptr = num; 692 nodestackptr++; 693 nodestacksize++; 694 // 695 if (nodestackptr >= &nodestack[NODESTACKSIZE]) 696 { 697 Error("Q2_PushNodeStack: stack overflow\n"); 698 } //end if 699 } //end of the function Q2_PushNodeStack 700 //=========================================================================== 701 // 702 // Parameter: - 703 // Returns: - 704 // Changes Globals: - 705 //=========================================================================== 706 int Q2_PopNodeStack(void) 707 { 708 //if the stack is empty 709 if (nodestackptr <= nodestack) return -1; 710 //decrease stack pointer 711 nodestackptr--; 712 nodestacksize--; 713 //return the top value from the stack 714 return *nodestackptr; 715 } //end of the function Q2_PopNodeStack 716 //=========================================================================== 717 // 718 // Parameter: - 719 // Returns: - 720 // Changes Globals: - 721 //=========================================================================== 722 void Q2_SetBrushModelNumbers(entity_t *mapent) 723 { 724 int n, pn; 725 int leafnum; 726 727 // 728 Q2_InitNodeStack(); 729 //head node (root) of the bsp tree 730 n = dmodels[mapent->modelnum].headnode; 731 pn = 0; 732 733 do 734 { 735 //if we are in a leaf (negative node number) 736 if (n < 0) 737 { 738 //number of the leaf 739 leafnum = (-n) - 1; 740 //set the brush numbers 741 Q2_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum); 742 //walk back into the tree to find a second child to continue with 743 for (pn = Q2_PopNodeStack(); pn >= 0; n = pn, pn = Q2_PopNodeStack()) 744 { 745 //if we took the first child at the parent node 746 if (dnodes[pn].children[0] == n) break; 747 } //end for 748 //if the stack wasn't empty (if not processed whole tree) 749 if (pn >= 0) 750 { 751 //push the parent node again 752 Q2_PushNodeStack(pn); 753 //we proceed with the second child of the parent node 754 n = dnodes[pn].children[1]; 755 } //end if 756 } //end if 757 else 758 { 759 //push the current node onto the stack 760 Q2_PushNodeStack(n); 761 //walk forward into the tree to the first child 762 n = dnodes[n].children[0]; 763 } //end else 764 } while(pn >= 0); 765 } //end of the function Q2_SetBrushModelNumbers 766 //=========================================================================== 767 // 768 // Parameter: - 769 // Returns: - 770 // Changes Globals: - 771 //=========================================================================== 772 void Q2_BSPBrushToMapBrush(dbrush_t *bspbrush, entity_t *mapent) 773 { 774 mapbrush_t *b; 775 int i, k, n; 776 side_t *side, *s2; 777 int planenum; 778 dbrushside_t *bspbrushside; 779 dplane_t *bspplane; 780 781 if (nummapbrushes >= MAX_MAPFILE_BRUSHES) 782 Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES"); 783 784 b = &mapbrushes[nummapbrushes]; 785 b->original_sides = &brushsides[nummapbrushsides]; 786 b->entitynum = mapent-entities; 787 b->brushnum = nummapbrushes - mapent->firstbrush; 788 b->leafnum = dbrushleafnums[bspbrush - dbrushes]; 789 790 for (n = 0; n < bspbrush->numsides; n++) 791 { 792 //pointer to the bsp brush side 793 bspbrushside = &dbrushsides[bspbrush->firstside + n]; 794 795 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES) 796 { 797 Error ("MAX_MAPFILE_BRUSHSIDES"); 798 } //end if 799 //pointer to the map brush side 800 side = &brushsides[nummapbrushsides]; 801 //if the BSP brush side is textured 802 if (brushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED; 803 else side->flags &= ~SFL_TEXTURED; 804 //ME: can get side contents and surf directly from BSP file 805 side->contents = bspbrush->contents; 806 //if the texinfo is TEXINFO_NODE 807 if (bspbrushside->texinfo < 0) side->surf = 0; 808 else side->surf = texinfo[bspbrushside->texinfo].flags; 809 810 // translucent objects are automatically classified as detail 811 if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) 812 side->contents |= CONTENTS_DETAIL; 813 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 814 side->contents |= CONTENTS_DETAIL; 815 if (fulldetail) 816 side->contents &= ~CONTENTS_DETAIL; 817 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 818 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) 819 side->contents |= CONTENTS_SOLID; 820 821 // hints and skips are never detail, and have no content 822 if (side->surf & (SURF_HINT|SURF_SKIP) ) 823 { 824 side->contents = 0; 825 side->surf &= ~CONTENTS_DETAIL; 826 } 827 828 //ME: get a plane for this side 829 bspplane = &dplanes[bspbrushside->planenum]; 830 planenum = FindFloatPlane(bspplane->normal, bspplane->dist); 831 // 832 // see if the plane has been used already 833 // 834 //ME: this really shouldn't happen!!! 835 //ME: otherwise the bsp file is corrupted?? 836 //ME: still it seems to happen, maybe Johny Boy's 837 //ME: brush bevel adding is crappy ? 838 for (k = 0; k < b->numsides; k++) 839 { 840 s2 = b->original_sides + k; 841 // if (DotProduct (mapplanes[s2->planenum].normal, mapplanes[planenum].normal) > 0.999 842 // && fabs(mapplanes[s2->planenum].dist - mapplanes[planenum].dist) < 0.01 ) 843 844 if (s2->planenum == planenum) 845 { 846 Log_Print("Entity %i, Brush %i: duplicate plane\n" 847 , b->entitynum, b->brushnum); 848 break; 849 } 850 if ( s2->planenum == (planenum^1) ) 851 { 852 Log_Print("Entity %i, Brush %i: mirrored plane\n" 853 , b->entitynum, b->brushnum); 854 break; 855 } 856 } 857 if (k != b->numsides) 858 continue; // duplicated 859 860 // 861 // keep this side 862 // 863 //ME: reset pointer to side, why? hell I dunno (pointer is set above already) 864 side = b->original_sides + b->numsides; 865 //ME: store the plane number 866 side->planenum = planenum; 867 //ME: texinfo is already stored when bsp is loaded 868 //NOTE: check for TEXINFO_NODE, otherwise crash in Q2_BrushContents 869 if (bspbrushside->texinfo < 0) side->texinfo = 0; 870 else side->texinfo = bspbrushside->texinfo; 871 872 // save the td off in case there is an origin brush and we 873 // have to recalculate the texinfo 874 // ME: don't need to recalculate because it's already done 875 // (for non-world entities) in the BSP file 876 // side_brushtextures[nummapbrushsides] = td; 877 878 nummapbrushsides++; 879 b->numsides++; 880 } //end for 881 882 // get the content for the entire brush 883 b->contents = bspbrush->contents; 884 Q2_BrushContents(b); 885 886 if (BrushExists(b)) 887 { 888 c_squattbrushes++; 889 b->numsides = 0; 890 return; 891 } //end if 892 893 //if we're creating AAS 894 if (create_aas) 895 { 896 //create the AAS brushes from this brush, don't add brush bevels 897 AAS_CreateMapBrushes(b, mapent, false); 898 return; 899 } //end if 900 901 // allow detail brushes to be removed 902 if (nodetail && (b->contents & CONTENTS_DETAIL) ) 903 { 904 b->numsides = 0; 905 return; 906 } //end if 907 908 // allow water brushes to be removed 909 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) 910 { 911 b->numsides = 0; 912 return; 913 } //end if 914 915 // create windings for sides and bounds for brush 916 MakeBrushWindings(b); 917 918 //mark brushes without winding or with a tiny window as bevels 919 MarkBrushBevels(b); 920 921 // brushes that will not be visible at all will never be 922 // used as bsp splitters 923 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 924 { 925 c_clipbrushes++; 926 for (i = 0; i < b->numsides; i++) 927 b->original_sides[i].texinfo = TEXINFO_NODE; 928 } //end for 929 930 // 931 // origin brushes are removed, but they set 932 // the rotation origin for the rest of the brushes 933 // in the entity. After the entire entity is parsed, 934 // the planenums and texinfos will be adjusted for 935 // the origin brush 936 // 937 //ME: not needed because the entities in the BSP file already 938 // have an origin set 939 // if (b->contents & CONTENTS_ORIGIN) 940 // { 941 // char string[32]; 942 // vec3_t origin; 943 // 944 // if (num_entities == 1) 945 // { 946 // Error ("Entity %i, Brush %i: origin brushes not allowed in world" 947 // , b->entitynum, b->brushnum); 948 // return; 949 // } 950 // 951 // VectorAdd (b->mins, b->maxs, origin); 952 // VectorScale (origin, 0.5, origin); 953 // 954 // sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); 955 // SetKeyValue (&entities[b->entitynum], "origin", string); 956 // 957 // VectorCopy (origin, entities[b->entitynum].origin); 958 // 959 // // don't keep this brush 960 // b->numsides = 0; 961 // 962 // return; 963 // } 964 965 //ME: the bsp brushes already have bevels, so we won't try to 966 // add them again (especially since Johny Boy's bevel adding might 967 // be crappy) 968 // AddBrushBevels(b); 969 970 nummapbrushes++; 971 mapent->numbrushes++; 972 } //end of the function Q2_BSPBrushToMapBrush 973 //=========================================================================== 974 //=========================================================================== 975 void Q2_ParseBSPBrushes(entity_t *mapent) 976 { 977 int i; 978 979 //give all the brushes that belong to this entity the number of the 980 //BSP model used by this entity 981 Q2_SetBrushModelNumbers(mapent); 982 //now parse all the brushes with the correct mapent->modelnum 983 for (i = 0; i < numbrushes; i++) 984 { 985 if (brushmodelnumbers[i] == mapent->modelnum) 986 { 987 Q2_BSPBrushToMapBrush(&dbrushes[i], mapent); 988 } //end if 989 } //end for 990 } //end of the function Q2_ParseBSPBrushes 991 //=========================================================================== 992 //=========================================================================== 993 qboolean Q2_ParseBSPEntity(int entnum) 994 { 995 entity_t *mapent; 996 char *model; 997 int startbrush, startsides; 998 999 startbrush = nummapbrushes; 1000 startsides = nummapbrushsides; 1001 1002 mapent = &entities[entnum];//num_entities]; 1003 mapent->firstbrush = nummapbrushes; 1004 mapent->numbrushes = 0; 1005 mapent->modelnum = -1; //-1 = no model 1006 1007 model = ValueForKey(mapent, "model"); 1008 if (model && strlen(model)) 1009 { 1010 if (*model != '*') 1011 { 1012 Error("Q2_ParseBSPEntity: model number without leading *"); 1013 } //end if 1014 //get the model number of this entity (skip the leading *) 1015 mapent->modelnum = atoi(&model[1]); 1016 } //end if 1017 1018 GetVectorForKey(mapent, "origin", mapent->origin); 1019 1020 //if this is the world entity it has model number zero 1021 //the world entity has no model key 1022 if (!strcmp("worldspawn", ValueForKey(mapent, "classname"))) 1023 { 1024 mapent->modelnum = 0; 1025 } //end if 1026 //if the map entity has a BSP model (a modelnum of -1 is used for 1027 //entities that aren't using a BSP model) 1028 if (mapent->modelnum >= 0) 1029 { 1030 //parse the bsp brushes 1031 Q2_ParseBSPBrushes(mapent); 1032 } //end if 1033 // 1034 //the origin of the entity is already taken into account 1035 // 1036 //func_group entities can't be in the bsp file 1037 // 1038 //check out the func_areaportal entities 1039 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) 1040 { 1041 c_areaportals++; 1042 mapent->areaportalnum = c_areaportals; 1043 return true; 1044 } //end if 1045 return true; 1046 } //end of the function Q2_ParseBSPEntity 1047 //=========================================================================== 1048 // 1049 // Parameter: - 1050 // Returns: - 1051 // Changes Globals: - 1052 //=========================================================================== 1053 void Q2_LoadMapFromBSP(char *filename, int offset, int length) 1054 { 1055 int i; 1056 1057 Log_Print("-- Q2_LoadMapFromBSP --\n"); 1058 //loaded map type 1059 loadedmaptype = MAPTYPE_QUAKE2; 1060 1061 Log_Print("Loading map from %s...\n", filename); 1062 //load the bsp file 1063 Q2_LoadBSPFile(filename, offset, length); 1064 1065 //create an index from bsp planes to map planes 1066 //DPlanes2MapPlanes(); 1067 //clear brush model numbers 1068 for (i = 0; i < MAX_MAPFILE_BRUSHES; i++) 1069 brushmodelnumbers[i] = -1; 1070 1071 nummapbrushsides = 0; 1072 num_entities = 0; 1073 1074 Q2_ParseEntities(); 1075 // 1076 for (i = 0; i < num_entities; i++) 1077 { 1078 Q2_ParseBSPEntity(i); 1079 } //end for 1080 1081 //get the map mins and maxs from the world model 1082 ClearBounds(map_mins, map_maxs); 1083 for (i = 0; i < entities[0].numbrushes; i++) 1084 { 1085 if (mapbrushes[i].mins[0] > 4096) 1086 continue; //no valid points 1087 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs); 1088 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs); 1089 } //end for 1090 1091 PrintMapInfo(); 1092 // 1093 Q2_CreateMapTexinfo(); 1094 } //end of the function Q2_LoadMapFromBSP 1095 1096 void Q2_ResetMapLoading(void) 1097 { 1098 //reset for map loading from bsp 1099 memset(nodestack, 0, NODESTACKSIZE * sizeof(int)); 1100 nodestackptr = NULL; 1101 nodestacksize = 0; 1102 memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int)); 1103 } //end of the function Q2_ResetMapLoading 1104 1105 //End MAP loading from BSP file 1106 #endif //ME 1107 1108 //==================================================================== 1109 1110 /* 1111 ================ 1112 TestExpandBrushes 1113 1114 Expands all the brush planes and saves a new map out 1115 ================ 1116 */ 1117 void TestExpandBrushes (void) 1118 { 1119 FILE *f; 1120 side_t *s; 1121 int i, j, bn; 1122 winding_t *w; 1123 char *name = "expanded.map"; 1124 mapbrush_t *brush; 1125 vec_t dist; 1126 1127 Log_Print("writing %s\n", name); 1128 f = fopen (name, "wb"); 1129 if (!f) 1130 Error ("Can't write %s\n", name); 1131 1132 fprintf (f, "{\n\"classname\" \"worldspawn\"\n"); 1133 1134 for (bn=0 ; bn<nummapbrushes ; bn++) 1135 { 1136 brush = &mapbrushes[bn]; 1137 fprintf (f, "{\n"); 1138 for (i=0 ; i<brush->numsides ; i++) 1139 { 1140 s = brush->original_sides + i; 1141 dist = mapplanes[s->planenum].dist; 1142 for (j=0 ; j<3 ; j++) 1143 dist += fabs( 16 * mapplanes[s->planenum].normal[j] ); 1144 1145 w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist); 1146 1147 fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]); 1148 fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]); 1149 fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]); 1150 1151 fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture); 1152 FreeWinding (w); 1153 } 1154 fprintf (f, "}\n"); 1155 } 1156 fprintf (f, "}\n"); 1157 1158 fclose (f); 1159 1160 Error ("can't proceed after expanding brushes"); 1161 } //end of the function TestExpandBrushes 1162