00001 /* 00002 =========================================================================== 00003 Copyright (C) 1999-2005 Id Software, Inc. 00004 00005 This file is part of Quake III Arena source code. 00006 00007 Quake III Arena source code is free software; you can redistribute it 00008 and/or modify it under the terms of the GNU General Public License as 00009 published by the Free Software Foundation; either version 2 of the License, 00010 or (at your option) any later version. 00011 00012 Quake III Arena source code is distributed in the hope that it will be 00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with Foobar; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 =========================================================================== 00021 */ 00022 //----------------------------------------------------------------------------- 00023 // 00024 // $Logfile:: /MissionPack/code/bspc/map_sin.c $ 00025 00026 #include "qbsp.h" 00027 #include "l_bsp_sin.h" 00028 #include "aas_map.h" //AAS_CreateMapBrushes 00029 00030 00031 //==================================================================== 00032 00033 00034 /* 00035 =========== 00036 Sin_BrushContents 00037 =========== 00038 */ 00039 00040 int Sin_BrushContents(mapbrush_t *b) 00041 { 00042 int contents; 00043 side_t *s; 00044 int i; 00045 #ifdef SIN 00046 float trans = 0; 00047 #else 00048 int trans; 00049 #endif 00050 00051 s = &b->original_sides[0]; 00052 contents = s->contents; 00053 00054 #ifdef SIN 00055 trans = sin_texinfo[s->texinfo].translucence; 00056 #else 00057 trans = texinfo[s->texinfo].flags; 00058 #endif 00059 for (i=1 ; i<b->numsides ; i++, s++) 00060 { 00061 s = &b->original_sides[i]; 00062 #ifdef SIN 00063 trans += sin_texinfo[s->texinfo].translucence; 00064 #else 00065 trans |= texinfo[s->texinfo].flags; 00066 #endif 00067 if (s->contents != contents) 00068 { 00069 #ifdef SIN 00070 if ( 00071 ( s->contents & CONTENTS_DETAIL && !(contents & CONTENTS_DETAIL) ) || 00072 ( !(s->contents & CONTENTS_DETAIL) && contents & CONTENTS_DETAIL ) 00073 ) 00074 { 00075 s->contents |= CONTENTS_DETAIL; 00076 contents |= CONTENTS_DETAIL; 00077 continue; 00078 } 00079 #endif 00080 printf ("Entity %i, Brush %i: mixed face contents\n" 00081 , b->entitynum, b->brushnum); 00082 break; 00083 } 00084 } 00085 00086 00087 #ifdef SIN 00088 if (contents & CONTENTS_FENCE) 00089 { 00090 // contents |= CONTENTS_TRANSLUCENT; 00091 contents |= CONTENTS_DETAIL; 00092 contents |= CONTENTS_DUMMYFENCE; 00093 contents &= ~CONTENTS_SOLID; 00094 contents &= ~CONTENTS_FENCE; 00095 contents |= CONTENTS_WINDOW; 00096 } 00097 #endif 00098 00099 // if any side is translucent, mark the contents 00100 // and change solid to window 00101 #ifdef SIN 00102 if ( trans > 0 ) 00103 #else 00104 if ( trans & (SURF_TRANS33|SURF_TRANS66) ) 00105 #endif 00106 { 00107 contents |= CONTENTS_Q2TRANSLUCENT; 00108 if (contents & CONTENTS_SOLID) 00109 { 00110 contents &= ~CONTENTS_SOLID; 00111 contents |= CONTENTS_WINDOW; 00112 } 00113 } 00114 00115 return contents; 00116 } //*/ 00117 00118 00119 //============================================================================ 00120 00121 00122 00123 /* 00124 ================= 00125 ParseBrush 00126 ================= 00127 * / 00128 void ParseBrush (entity_t *mapent) 00129 { 00130 mapbrush_t *b; 00131 int i,j, k; 00132 int mt; 00133 side_t *side, *s2; 00134 int planenum; 00135 brush_texture_t td; 00136 #ifdef SIN 00137 textureref_t newref; 00138 #endif 00139 int planepts[3][3]; 00140 00141 if (nummapbrushes == MAX_MAP_BRUSHES) 00142 Error ("nummapbrushes == MAX_MAP_BRUSHES"); 00143 00144 b = &mapbrushes[nummapbrushes]; 00145 b->original_sides = &brushsides[nummapbrushsides]; 00146 b->entitynum = num_entities-1; 00147 b->brushnum = nummapbrushes - mapent->firstbrush; 00148 00149 do 00150 { 00151 if (!GetToken (true)) 00152 break; 00153 if (!strcmp (token, "}") ) 00154 break; 00155 00156 if (nummapbrushsides == MAX_MAP_BRUSHSIDES) 00157 Error ("MAX_MAP_BRUSHSIDES"); 00158 side = &brushsides[nummapbrushsides]; 00159 00160 // read the three point plane definition 00161 for (i=0 ; i<3 ; i++) 00162 { 00163 if (i != 0) 00164 GetToken (true); 00165 if (strcmp (token, "(") ) 00166 Error ("parsing brush"); 00167 00168 for (j=0 ; j<3 ; j++) 00169 { 00170 GetToken (false); 00171 planepts[i][j] = atoi(token); 00172 } 00173 00174 GetToken (false); 00175 if (strcmp (token, ")") ) 00176 Error ("parsing brush"); 00177 00178 } 00179 00180 00181 // 00182 // read the texturedef 00183 // 00184 GetToken (false); 00185 strcpy (td.name, token); 00186 00187 GetToken (false); 00188 td.shift[0] = atoi(token); 00189 GetToken (false); 00190 td.shift[1] = atoi(token); 00191 GetToken (false); 00192 #ifdef SIN 00193 td.rotate = atof(token); 00194 #else 00195 td.rotate = atoi(token); 00196 #endif 00197 GetToken (false); 00198 td.scale[0] = atof(token); 00199 GetToken (false); 00200 td.scale[1] = atof(token); 00201 00202 // find default flags and values 00203 mt = FindMiptex (td.name); 00204 #ifdef SIN 00205 // clear out the masks on newref 00206 memset(&newref,0,sizeof(newref)); 00207 // copy over the name 00208 strcpy( newref.name, td.name ); 00209 00210 ParseSurfaceInfo( &newref ); 00211 MergeRefs( &bsp_textureref[mt], &newref, &td.tref ); 00212 side->contents = td.tref.contents; 00213 side->surf = td.tref.flags; 00214 #else 00215 td.flags = textureref[mt].flags; 00216 td.value = textureref[mt].value; 00217 side->contents = textureref[mt].contents; 00218 side->surf = td.flags = textureref[mt].flags; 00219 00220 if (TokenAvailable()) 00221 { 00222 GetToken (false); 00223 side->contents = atoi(token); 00224 GetToken (false); 00225 side->surf = td.flags = atoi(token); 00226 GetToken (false); 00227 td.value = atoi(token); 00228 } 00229 #endif 00230 00231 // translucent objects are automatically classified as detail 00232 #ifdef SIN 00233 if ( td.tref.translucence > 0 ) 00234 #else 00235 if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) 00236 #endif 00237 side->contents |= CONTENTS_DETAIL; 00238 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 00239 side->contents |= CONTENTS_DETAIL; 00240 if (fulldetail) 00241 side->contents &= ~CONTENTS_DETAIL; 00242 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 00243 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) 00244 side->contents |= CONTENTS_SOLID; 00245 00246 // hints and skips are never detail, and have no content 00247 if (side->surf & (SURF_HINT|SURF_SKIP) ) 00248 { 00249 side->contents = 0; 00250 #ifndef SIN // I think this is a bug of some kind 00251 side->surf &= ~CONTENTS_DETAIL; 00252 #endif 00253 } 00254 00255 // 00256 // find the plane number 00257 // 00258 planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]); 00259 if (planenum == -1) 00260 { 00261 printf ("Entity %i, Brush %i: plane with no normal\n" 00262 , b->entitynum, b->brushnum); 00263 continue; 00264 } 00265 00266 // 00267 // see if the plane has been used already 00268 // 00269 for (k=0 ; k<b->numsides ; k++) 00270 { 00271 s2 = b->original_sides + k; 00272 if (s2->planenum == planenum) 00273 { 00274 printf ("Entity %i, Brush %i: duplicate plane\n" 00275 , b->entitynum, b->brushnum); 00276 break; 00277 } 00278 if ( s2->planenum == (planenum^1) ) 00279 { 00280 printf ("Entity %i, Brush %i: mirrored plane\n" 00281 , b->entitynum, b->brushnum); 00282 break; 00283 } 00284 } 00285 if (k != b->numsides) 00286 continue; // duplicated 00287 00288 // 00289 // keep this side 00290 // 00291 00292 side = b->original_sides + b->numsides; 00293 side->planenum = planenum; 00294 #ifdef SIN 00295 side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], 00296 &td, vec3_origin, &newref); 00297 // 00298 // save off lightinfo 00299 // 00300 side->lightinfo = LightinfoForBrushTexture ( &td ); 00301 #else 00302 side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], 00303 &td, vec3_origin); 00304 00305 #endif 00306 00307 // save the td off in case there is an origin brush and we 00308 // have to recalculate the texinfo 00309 side_brushtextures[nummapbrushsides] = td; 00310 #ifdef SIN 00311 // save off the merged tref for animating textures 00312 side_newrefs[nummapbrushsides] = newref; 00313 #endif 00314 00315 nummapbrushsides++; 00316 b->numsides++; 00317 } while (1); 00318 00319 // get the content for the entire brush 00320 b->contents = Sin_BrushContents (b); 00321 00322 // allow detail brushes to be removed 00323 if (nodetail && (b->contents & CONTENTS_DETAIL) ) 00324 { 00325 b->numsides = 0; 00326 return; 00327 } 00328 00329 // allow water brushes to be removed 00330 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) 00331 { 00332 b->numsides = 0; 00333 return; 00334 } 00335 00336 // create windings for sides and bounds for brush 00337 MakeBrushWindings (b); 00338 00339 // brushes that will not be visible at all will never be 00340 // used as bsp splitters 00341 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 00342 { 00343 c_clipbrushes++; 00344 for (i=0 ; i<b->numsides ; i++) 00345 b->original_sides[i].texinfo = TEXINFO_NODE; 00346 } 00347 00348 // 00349 // origin brushes are removed, but they set 00350 // the rotation origin for the rest of the brushes 00351 // in the entity. After the entire entity is parsed, 00352 // the planenums and texinfos will be adjusted for 00353 // the origin brush 00354 // 00355 if (b->contents & CONTENTS_ORIGIN) 00356 { 00357 char string[32]; 00358 vec3_t origin; 00359 00360 if (num_entities == 1) 00361 { 00362 Error ("Entity %i, Brush %i: origin brushes not allowed in world" 00363 , b->entitynum, b->brushnum); 00364 return; 00365 } 00366 00367 VectorAdd (b->mins, b->maxs, origin); 00368 VectorScale (origin, 0.5, origin); 00369 00370 sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); 00371 SetKeyValue (&entities[b->entitynum], "origin", string); 00372 00373 VectorCopy (origin, entities[b->entitynum].origin); 00374 00375 // don't keep this brush 00376 b->numsides = 0; 00377 00378 return; 00379 } 00380 00381 AddBrushBevels (b); 00382 00383 nummapbrushes++; 00384 mapent->numbrushes++; 00385 } //*/ 00386 00387 /* 00388 ================ 00389 MoveBrushesToWorld 00390 00391 Takes all of the brushes from the current entity and 00392 adds them to the world's brush list. 00393 00394 Used by func_group and func_areaportal 00395 ================ 00396 * / 00397 void MoveBrushesToWorld (entity_t *mapent) 00398 { 00399 int newbrushes; 00400 int worldbrushes; 00401 mapbrush_t *temp; 00402 int i; 00403 00404 // this is pretty gross, because the brushes are expected to be 00405 // in linear order for each entity 00406 00407 newbrushes = mapent->numbrushes; 00408 worldbrushes = entities[0].numbrushes; 00409 00410 temp = malloc(newbrushes*sizeof(mapbrush_t)); 00411 memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t)); 00412 00413 #if 0 // let them keep their original brush numbers 00414 for (i=0 ; i<newbrushes ; i++) 00415 temp[i].entitynum = 0; 00416 #endif 00417 00418 // make space to move the brushes (overlapped copy) 00419 memmove (mapbrushes + worldbrushes + newbrushes, 00420 mapbrushes + worldbrushes, 00421 sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) ); 00422 00423 // copy the new brushes down 00424 memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes); 00425 00426 // fix up indexes 00427 entities[0].numbrushes += newbrushes; 00428 for (i=1 ; i<num_entities ; i++) 00429 entities[i].firstbrush += newbrushes; 00430 free (temp); 00431 00432 mapent->numbrushes = 0; 00433 } //*/ 00434 00435 /* 00436 ================ 00437 ParseMapEntity 00438 ================ 00439 * / 00440 qboolean Sin_ParseMapEntity (void) 00441 { 00442 entity_t *mapent; 00443 epair_t *e; 00444 side_t *s; 00445 int i, j; 00446 int startbrush, startsides; 00447 vec_t newdist; 00448 mapbrush_t *b; 00449 00450 if (!GetToken (true)) 00451 return false; 00452 00453 if (strcmp (token, "{") ) 00454 Error ("ParseEntity: { not found"); 00455 00456 if (num_entities == MAX_MAP_ENTITIES) 00457 Error ("num_entities == MAX_MAP_ENTITIES"); 00458 00459 startbrush = nummapbrushes; 00460 startsides = nummapbrushsides; 00461 00462 mapent = &entities[num_entities]; 00463 num_entities++; 00464 memset (mapent, 0, sizeof(*mapent)); 00465 mapent->firstbrush = nummapbrushes; 00466 mapent->numbrushes = 0; 00467 // mapent->portalareas[0] = -1; 00468 // mapent->portalareas[1] = -1; 00469 00470 do 00471 { 00472 if (!GetToken (true)) 00473 Error ("ParseEntity: EOF without closing brace"); 00474 if (!strcmp (token, "}") ) 00475 break; 00476 if (!strcmp (token, "{") ) 00477 ParseBrush (mapent); 00478 else 00479 { 00480 e = ParseEpair (); 00481 #ifdef SIN 00482 //HACK HACK HACK 00483 // MED Gotta do this here 00484 if ( !stricmp(e->key, "surfacefile") ) 00485 { 00486 if (!surfacefile[0]) 00487 { 00488 strcpy( surfacefile, e->value ); 00489 } 00490 printf ("--- ParseSurfaceFile ---\n"); 00491 printf ("Surface script: %s\n", surfacefile); 00492 if (!ParseSurfaceFile(surfacefile)) 00493 { 00494 Error ("Script file not found: %s\n", surfacefile); 00495 } 00496 } 00497 #endif 00498 e->next = mapent->epairs; 00499 mapent->epairs = e; 00500 } 00501 } while (1); 00502 00503 #ifdef SIN 00504 if (!(strlen(ValueForKey(mapent, "origin"))) && ((num_entities-1) != 0)) 00505 { 00506 mapbrush_t *brush; 00507 vec3_t origin; 00508 char string[32]; 00509 vec3_t mins, maxs; 00510 int start, end; 00511 // Calculate bounds 00512 00513 start = mapent->firstbrush; 00514 end = start + mapent->numbrushes; 00515 ClearBounds (mins, maxs); 00516 00517 for (j=start ; j<end ; j++) 00518 { 00519 brush = &mapbrushes[j]; 00520 if (!brush->numsides) 00521 continue; // not a real brush (origin brush) - shouldn't happen 00522 AddPointToBounds (brush->mins, mins, maxs); 00523 AddPointToBounds (brush->maxs, mins, maxs); 00524 } 00525 00526 // Set the origin to be the centroid of the entity. 00527 VectorAdd ( mins, maxs, origin); 00528 VectorScale( origin, 0.5f, origin ); 00529 00530 sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); 00531 SetKeyValue ( mapent, "origin", string); 00532 // qprintf("Setting origin to %s\n",string); 00533 } 00534 #endif 00535 00536 GetVectorForKey (mapent, "origin", mapent->origin); 00537 00538 #ifdef SIN 00539 if ( 00540 (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) || 00541 (!strcmp ("func_group", ValueForKey (mapent, "classname"))) || 00542 (!strcmp ("detail", ValueForKey (mapent, "classname")) && !entitydetails) 00543 ) 00544 { 00545 VectorClear( mapent->origin ); 00546 } 00547 #endif 00548 00549 // 00550 // if there was an origin brush, offset all of the planes and texinfo 00551 // 00552 if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) 00553 { 00554 for (i=0 ; i<mapent->numbrushes ; i++) 00555 { 00556 b = &mapbrushes[mapent->firstbrush + i]; 00557 for (j=0 ; j<b->numsides ; j++) 00558 { 00559 s = &b->original_sides[j]; 00560 newdist = mapplanes[s->planenum].dist - 00561 DotProduct (mapplanes[s->planenum].normal, mapent->origin); 00562 s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); 00563 #ifdef SIN 00564 s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum], 00565 &side_brushtextures[s-brushsides], mapent->origin, &side_newrefs[s-brushsides]); 00566 // 00567 // save off lightinfo 00568 // 00569 s->lightinfo = LightinfoForBrushTexture ( &side_brushtextures[s-brushsides] ); 00570 #else 00571 s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum], 00572 &side_brushtextures[s-brushsides], mapent->origin); 00573 #endif 00574 } 00575 MakeBrushWindings (b); 00576 } 00577 } 00578 00579 // group entities are just for editor convenience 00580 // toss all brushes into the world entity 00581 if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) 00582 { 00583 MoveBrushesToWorld (mapent); 00584 mapent->numbrushes = 0; 00585 mapent->wasdetail = true; 00586 FreeValueKeys( mapent ); 00587 return true; 00588 } 00589 #ifdef SIN 00590 // detail entities are just for editor convenience 00591 // toss all brushes into the world entity as detail brushes 00592 if (!strcmp ("detail", ValueForKey (mapent, "classname")) && !entitydetails) 00593 { 00594 for (i=0 ; i<mapent->numbrushes ; i++) 00595 { 00596 int j; 00597 side_t * s; 00598 b = &mapbrushes[mapent->firstbrush + i]; 00599 if (nodetail) 00600 { 00601 b->numsides = 0; 00602 continue; 00603 } 00604 if (!fulldetail) 00605 { 00606 // set the contents for the entire brush 00607 b->contents |= CONTENTS_DETAIL; 00608 // set the contents in the sides as well 00609 for (j=0, s=b->original_sides ; j<b->numsides ; j++,s++) 00610 { 00611 s->contents |= CONTENTS_DETAIL; 00612 } 00613 } 00614 else 00615 { 00616 // set the contents for the entire brush 00617 b->contents |= CONTENTS_SOLID; 00618 // set the contents in the sides as well 00619 for (j=0, s=b->original_sides ; j<b->numsides ; j++,s++) 00620 { 00621 s->contents |= CONTENTS_SOLID; 00622 } 00623 } 00624 } 00625 MoveBrushesToWorld (mapent); 00626 mapent->wasdetail = true; 00627 FreeValueKeys( mapent ); 00628 // kill off the entity 00629 // num_entities--; 00630 return true; 00631 } 00632 #endif 00633 00634 // areaportal entities move their brushes, but don't eliminate 00635 // the entity 00636 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) 00637 { 00638 char str[128]; 00639 00640 if (mapent->numbrushes != 1) 00641 Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1); 00642 00643 b = &mapbrushes[nummapbrushes-1]; 00644 b->contents = CONTENTS_AREAPORTAL; 00645 c_areaportals++; 00646 mapent->areaportalnum = c_areaportals; 00647 // set the portal number as "style" 00648 sprintf (str, "%i", c_areaportals); 00649 SetKeyValue (mapent, "style", str); 00650 MoveBrushesToWorld (mapent); 00651 return true; 00652 } 00653 00654 return true; 00655 } //end of the function Sin_ParseMapEntity */ 00656 00657 //=================================================================== 00658 00659 /* 00660 ================ 00661 LoadMapFile 00662 ================ 00663 * / 00664 void Sin_LoadMapFile (char *filename) 00665 { 00666 int i; 00667 #ifdef SIN 00668 int num_detailsides=0; 00669 int num_detailbrushes=0; 00670 int num_worldsides=0; 00671 int num_worldbrushes=0; 00672 int j,k; 00673 #endif 00674 00675 qprintf ("--- LoadMapFile ---\n"); 00676 00677 LoadScriptFile (filename); 00678 00679 nummapbrushsides = 0; 00680 num_entities = 0; 00681 00682 while (ParseMapEntity ()) 00683 { 00684 } 00685 00686 ClearBounds (map_mins, map_maxs); 00687 for (i=0 ; i<entities[0].numbrushes ; i++) 00688 { 00689 if (mapbrushes[i].mins[0] > 4096) 00690 continue; // no valid points 00691 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs); 00692 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs); 00693 } 00694 #ifdef SIN 00695 for (j=0; j<num_entities; j++) 00696 { 00697 for (i=0 ; i<entities[j].numbrushes ; i++) 00698 { 00699 side_t * s; 00700 mapbrush_t *b; 00701 b = &mapbrushes[entities[j].firstbrush + i]; 00702 if (b->numsides && b->contents & CONTENTS_DETAIL) 00703 num_detailbrushes++; 00704 else if (b->numsides) 00705 num_worldbrushes++; 00706 for (k=0, s=b->original_sides ; k<b->numsides ; k++,s++) 00707 { 00708 if (s->contents & CONTENTS_DETAIL) 00709 num_detailsides++; 00710 else 00711 num_worldsides++; 00712 } 00713 } 00714 } 00715 #endif 00716 00717 qprintf ("%5i brushes\n", nummapbrushes); 00718 qprintf ("%5i clipbrushes\n", c_clipbrushes); 00719 qprintf ("%5i total sides\n", nummapbrushsides); 00720 qprintf ("%5i boxbevels\n", c_boxbevels); 00721 qprintf ("%5i edgebevels\n", c_edgebevels); 00722 qprintf ("%5i entities\n", num_entities); 00723 qprintf ("%5i planes\n", nummapplanes); 00724 qprintf ("%5i areaportals\n", c_areaportals); 00725 qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2], 00726 map_maxs[0],map_maxs[1],map_maxs[2]); 00727 #ifdef SIN 00728 qprintf ("%5i detailbrushes\n", num_detailbrushes); 00729 qprintf ("%5i worldbrushes\n", num_worldbrushes); 00730 qprintf ("%5i detailsides\n", num_detailsides); 00731 qprintf ("%5i worldsides\n", num_worldsides); 00732 #endif 00733 00734 } //end of the function Sin_LoadMap */ 00735 00736 00737 #ifdef ME //Begin MAP loading from BSP file 00738 //=========================================================================== 00739 // 00740 // Parameter: - 00741 // Returns: - 00742 // Changes Globals: - 00743 //=========================================================================== 00744 void Sin_CreateMapTexinfo(void) 00745 { 00746 int i; 00747 vec_t defaultvec[4] = {1, 0, 0, 0}; 00748 00749 memcpy(map_texinfo[0].vecs[0], defaultvec, sizeof(defaultvec)); 00750 memcpy(map_texinfo[0].vecs[1], defaultvec, sizeof(defaultvec)); 00751 map_texinfo[0].flags = 0; 00752 map_texinfo[0].value = 0; 00753 strcpy(map_texinfo[0].texture, "generic/misc/red"); //no texture 00754 map_texinfo[0].nexttexinfo = -1; 00755 for (i = 1; i < sin_numtexinfo; i++) 00756 { 00757 memcpy(map_texinfo[i].vecs, sin_texinfo[i].vecs, sizeof(float) * 2 * 4); 00758 map_texinfo[i].flags = sin_texinfo[i].flags; 00759 map_texinfo[i].value = 0; 00760 strcpy(map_texinfo[i].texture, sin_texinfo[i].texture); 00761 map_texinfo[i].nexttexinfo = -1; 00762 } //end for 00763 } //end of the function Sin_CreateMapTexinfo 00764 //=========================================================================== 00765 // 00766 // Parameter: - 00767 // Returns: - 00768 // Changes Globals: - 00769 //=========================================================================== 00770 void Sin_SetLeafBrushesModelNumbers(int leafnum, int modelnum) 00771 { 00772 int i, brushnum; 00773 sin_dleaf_t *leaf; 00774 00775 leaf = &sin_dleafs[leafnum]; 00776 for (i = 0; i < leaf->numleafbrushes; i++) 00777 { 00778 brushnum = sin_dleafbrushes[leaf->firstleafbrush + i]; 00779 brushmodelnumbers[brushnum] = modelnum; 00780 dbrushleafnums[brushnum] = leafnum; 00781 } //end for 00782 } //end of the function Sin_SetLeafBrushesModelNumbers 00783 //=========================================================================== 00784 // 00785 // Parameter: - 00786 // Returns: - 00787 // Changes Globals: - 00788 //=========================================================================== 00789 void Sin_InitNodeStack(void) 00790 { 00791 nodestackptr = nodestack; 00792 nodestacksize = 0; 00793 } //end of the function Sin_InitNodeStack 00794 //=========================================================================== 00795 // 00796 // Parameter: - 00797 // Returns: - 00798 // Changes Globals: - 00799 //=========================================================================== 00800 void Sin_PushNodeStack(int num) 00801 { 00802 *nodestackptr = num; 00803 nodestackptr++; 00804 nodestacksize++; 00805 // 00806 if (nodestackptr >= &nodestack[NODESTACKSIZE]) 00807 { 00808 Error("Sin_PushNodeStack: stack overflow\n"); 00809 } //end if 00810 } //end of the function Sin_PushNodeStack 00811 //=========================================================================== 00812 // 00813 // Parameter: - 00814 // Returns: - 00815 // Changes Globals: - 00816 //=========================================================================== 00817 int Sin_PopNodeStack(void) 00818 { 00819 //if the stack is empty 00820 if (nodestackptr <= nodestack) return -1; 00821 //decrease stack pointer 00822 nodestackptr--; 00823 nodestacksize--; 00824 //return the top value from the stack 00825 return *nodestackptr; 00826 } //end of the function Sin_PopNodeStack 00827 //=========================================================================== 00828 // 00829 // Parameter: - 00830 // Returns: - 00831 // Changes Globals: - 00832 //=========================================================================== 00833 void Sin_SetBrushModelNumbers(entity_t *mapent) 00834 { 00835 int n, pn; 00836 int leafnum; 00837 00838 // 00839 Sin_InitNodeStack(); 00840 //head node (root) of the bsp tree 00841 n = sin_dmodels[mapent->modelnum].headnode; 00842 pn = 0; 00843 00844 do 00845 { 00846 //if we are in a leaf (negative node number) 00847 if (n < 0) 00848 { 00849 //number of the leaf 00850 leafnum = (-n) - 1; 00851 //set the brush numbers 00852 Sin_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum); 00853 //walk back into the tree to find a second child to continue with 00854 for (pn = Sin_PopNodeStack(); pn >= 0; n = pn, pn = Sin_PopNodeStack()) 00855 { 00856 //if we took the first child at the parent node 00857 if (sin_dnodes[pn].children[0] == n) break; 00858 } //end for 00859 //if the stack wasn't empty (if not processed whole tree) 00860 if (pn >= 0) 00861 { 00862 //push the parent node again 00863 Sin_PushNodeStack(pn); 00864 //we proceed with the second child of the parent node 00865 n = sin_dnodes[pn].children[1]; 00866 } //end if 00867 } //end if 00868 else 00869 { 00870 //push the current node onto the stack 00871 Sin_PushNodeStack(n); 00872 //walk forward into the tree to the first child 00873 n = sin_dnodes[n].children[0]; 00874 } //end else 00875 } while(pn >= 0); 00876 } //end of the function Sin_SetBrushModelNumbers 00877 //=========================================================================== 00878 // 00879 // Parameter: - 00880 // Returns: - 00881 // Changes Globals: - 00882 //=========================================================================== 00883 void Sin_BSPBrushToMapBrush(sin_dbrush_t *bspbrush, entity_t *mapent) 00884 { 00885 mapbrush_t *b; 00886 int i, k, n; 00887 side_t *side, *s2; 00888 int planenum; 00889 sin_dbrushside_t *bspbrushside; 00890 sin_dplane_t *bspplane; 00891 00892 if (nummapbrushes >= MAX_MAPFILE_BRUSHES) 00893 Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES"); 00894 00895 b = &mapbrushes[nummapbrushes]; 00896 b->original_sides = &brushsides[nummapbrushsides]; 00897 b->entitynum = mapent-entities; 00898 b->brushnum = nummapbrushes - mapent->firstbrush; 00899 b->leafnum = dbrushleafnums[bspbrush - sin_dbrushes]; 00900 00901 for (n = 0; n < bspbrush->numsides; n++) 00902 { 00903 //pointer to the bsp brush side 00904 bspbrushside = &sin_dbrushsides[bspbrush->firstside + n]; 00905 00906 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES) 00907 { 00908 Error ("MAX_MAPFILE_BRUSHSIDES"); 00909 } //end if 00910 //pointer to the map brush side 00911 side = &brushsides[nummapbrushsides]; 00912 //if the BSP brush side is textured 00913 if (sin_dbrushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED; 00914 else side->flags &= ~SFL_TEXTURED; 00915 //ME: can get side contents and surf directly from BSP file 00916 side->contents = bspbrush->contents; 00917 //if the texinfo is TEXINFO_NODE 00918 if (bspbrushside->texinfo < 0) side->surf = 0; 00919 else side->surf = sin_texinfo[bspbrushside->texinfo].flags; 00920 00921 // translucent objects are automatically classified as detail 00922 if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) 00923 side->contents |= CONTENTS_DETAIL; 00924 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 00925 side->contents |= CONTENTS_DETAIL; 00926 if (fulldetail) 00927 side->contents &= ~CONTENTS_DETAIL; 00928 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 00929 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) 00930 side->contents |= CONTENTS_SOLID; 00931 00932 // hints and skips are never detail, and have no content 00933 if (side->surf & (SURF_HINT|SURF_SKIP) ) 00934 { 00935 side->contents = 0; 00936 side->surf &= ~CONTENTS_DETAIL; 00937 } 00938 00939 //ME: get a plane for this side 00940 bspplane = &sin_dplanes[bspbrushside->planenum]; 00941 planenum = FindFloatPlane(bspplane->normal, bspplane->dist); 00942 // 00943 // see if the plane has been used already 00944 // 00945 //ME: this really shouldn't happen!!! 00946 //ME: otherwise the bsp file is corrupted?? 00947 //ME: still it seems to happen, maybe Johny Boy's 00948 //ME: brush bevel adding is crappy ? 00949 for (k = 0; k < b->numsides; k++) 00950 { 00951 s2 = b->original_sides + k; 00952 if (s2->planenum == planenum) 00953 { 00954 Log_Print("Entity %i, Brush %i: duplicate plane\n" 00955 , b->entitynum, b->brushnum); 00956 break; 00957 } 00958 if ( s2->planenum == (planenum^1) ) 00959 { 00960 Log_Print("Entity %i, Brush %i: mirrored plane\n" 00961 , b->entitynum, b->brushnum); 00962 break; 00963 } 00964 } 00965 if (k != b->numsides) 00966 continue; // duplicated 00967 00968 // 00969 // keep this side 00970 // 00971 //ME: reset pointer to side, why? hell I dunno (pointer is set above already) 00972 side = b->original_sides + b->numsides; 00973 //ME: store the plane number 00974 side->planenum = planenum; 00975 //ME: texinfo is already stored when bsp is loaded 00976 //NOTE: check for TEXINFO_NODE, otherwise crash in Sin_BrushContents 00977 if (bspbrushside->texinfo < 0) side->texinfo = 0; 00978 else side->texinfo = bspbrushside->texinfo; 00979 00980 // save the td off in case there is an origin brush and we 00981 // have to recalculate the texinfo 00982 // ME: don't need to recalculate because it's already done 00983 // (for non-world entities) in the BSP file 00984 // side_brushtextures[nummapbrushsides] = td; 00985 00986 nummapbrushsides++; 00987 b->numsides++; 00988 } //end for 00989 00990 // get the content for the entire brush 00991 b->contents = bspbrush->contents; 00992 Sin_BrushContents(b); 00993 00994 if (BrushExists(b)) 00995 { 00996 c_squattbrushes++; 00997 b->numsides = 0; 00998 return; 00999 } //end if 01000 01001 //if we're creating AAS 01002 if (create_aas) 01003 { 01004 //create the AAS brushes from this brush, don't add brush bevels 01005 AAS_CreateMapBrushes(b, mapent, false); 01006 return; 01007 } //end if 01008 01009 // allow detail brushes to be removed 01010 if (nodetail && (b->contents & CONTENTS_DETAIL) ) 01011 { 01012 b->numsides = 0; 01013 return; 01014 } //end if 01015 01016 // allow water brushes to be removed 01017 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) 01018 { 01019 b->numsides = 0; 01020 return; 01021 } //end if 01022 01023 // create windings for sides and bounds for brush 01024 MakeBrushWindings(b); 01025 01026 //mark brushes without winding or with a tiny window as bevels 01027 MarkBrushBevels(b); 01028 01029 // brushes that will not be visible at all will never be 01030 // used as bsp splitters 01031 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) 01032 { 01033 c_clipbrushes++; 01034 for (i = 0; i < b->numsides; i++) 01035 b->original_sides[i].texinfo = TEXINFO_NODE; 01036 } //end for 01037 01038 // 01039 // origin brushes are removed, but they set 01040 // the rotation origin for the rest of the brushes 01041 // in the entity. After the entire entity is parsed, 01042 // the planenums and texinfos will be adjusted for 01043 // the origin brush 01044 // 01045 //ME: not needed because the entities in the BSP file already 01046 // have an origin set 01047 // if (b->contents & CONTENTS_ORIGIN) 01048 // { 01049 // char string[32]; 01050 // vec3_t origin; 01051 // 01052 // if (num_entities == 1) 01053 // { 01054 // Error ("Entity %i, Brush %i: origin brushes not allowed in world" 01055 // , b->entitynum, b->brushnum); 01056 // return; 01057 // } 01058 // 01059 // VectorAdd (b->mins, b->maxs, origin); 01060 // VectorScale (origin, 0.5, origin); 01061 // 01062 // sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); 01063 // SetKeyValue (&entities[b->entitynum], "origin", string); 01064 // 01065 // VectorCopy (origin, entities[b->entitynum].origin); 01066 // 01067 // // don't keep this brush 01068 // b->numsides = 0; 01069 // 01070 // return; 01071 // } 01072 01073 //ME: the bsp brushes already have bevels, so we won't try to 01074 // add them again (especially since Johny Boy's bevel adding might 01075 // be crappy) 01076 // AddBrushBevels(b); 01077 01078 nummapbrushes++; 01079 mapent->numbrushes++; 01080 } //end of the function Sin_BSPBrushToMapBrush 01081 //=========================================================================== 01082 //=========================================================================== 01083 void Sin_ParseBSPBrushes(entity_t *mapent) 01084 { 01085 int i, testnum = 0; 01086 01087 //give all the brushes that belong to this entity the number of the 01088 //BSP model used by this entity 01089 Sin_SetBrushModelNumbers(mapent); 01090 //now parse all the brushes with the correct mapent->modelnum 01091 for (i = 0; i < sin_numbrushes; i++) 01092 { 01093 if (brushmodelnumbers[i] == mapent->modelnum) 01094 { 01095 testnum++; 01096 Sin_BSPBrushToMapBrush(&sin_dbrushes[i], mapent); 01097 } //end if 01098 } //end for 01099 } //end of the function Sin_ParseBSPBrushes 01100 //=========================================================================== 01101 //=========================================================================== 01102 qboolean Sin_ParseBSPEntity(int entnum) 01103 { 01104 entity_t *mapent; 01105 char *model; 01106 int startbrush, startsides; 01107 01108 startbrush = nummapbrushes; 01109 startsides = nummapbrushsides; 01110 01111 mapent = &entities[entnum];//num_entities]; 01112 mapent->firstbrush = nummapbrushes; 01113 mapent->numbrushes = 0; 01114 mapent->modelnum = -1; //-1 = no model 01115 01116 model = ValueForKey(mapent, "model"); 01117 if (model && *model == '*') 01118 { 01119 mapent->modelnum = atoi(&model[1]); 01120 //Log_Print("model = %s\n", model); 01121 //Log_Print("mapent->modelnum = %d\n", mapent->modelnum); 01122 } //end if 01123 01124 GetVectorForKey(mapent, "origin", mapent->origin); 01125 01126 //if this is the world entity it has model number zero 01127 //the world entity has no model key 01128 if (!strcmp("worldspawn", ValueForKey(mapent, "classname"))) 01129 { 01130 mapent->modelnum = 0; 01131 } //end if 01132 //if the map entity has a BSP model (a modelnum of -1 is used for 01133 //entities that aren't using a BSP model) 01134 if (mapent->modelnum >= 0) 01135 { 01136 //parse the bsp brushes 01137 Sin_ParseBSPBrushes(mapent); 01138 } //end if 01139 // 01140 //the origin of the entity is already taken into account 01141 // 01142 //func_group entities can't be in the bsp file 01143 // 01144 //check out the func_areaportal entities 01145 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) 01146 { 01147 c_areaportals++; 01148 mapent->areaportalnum = c_areaportals; 01149 return true; 01150 } //end if 01151 return true; 01152 } //end of the function Sin_ParseBSPEntity 01153 //=========================================================================== 01154 // 01155 // Parameter: - 01156 // Returns: - 01157 // Changes Globals: - 01158 //=========================================================================== 01159 void Sin_LoadMapFromBSP(char *filename, int offset, int length) 01160 { 01161 int i; 01162 01163 Log_Print("-- Sin_LoadMapFromBSP --\n"); 01164 //loaded map type 01165 loadedmaptype = MAPTYPE_SIN; 01166 01167 Log_Print("Loading map from %s...\n", filename); 01168 //load the bsp file 01169 Sin_LoadBSPFile(filename, offset, length); 01170 01171 //create an index from bsp planes to map planes 01172 //DPlanes2MapPlanes(); 01173 //clear brush model numbers 01174 for (i = 0; i < MAX_MAPFILE_BRUSHES; i++) 01175 brushmodelnumbers[i] = -1; 01176 01177 nummapbrushsides = 0; 01178 num_entities = 0; 01179 01180 Sin_ParseEntities(); 01181 // 01182 for (i = 0; i < num_entities; i++) 01183 { 01184 Sin_ParseBSPEntity(i); 01185 } //end for 01186 01187 //get the map mins and maxs from the world model 01188 ClearBounds(map_mins, map_maxs); 01189 for (i = 0; i < entities[0].numbrushes; i++) 01190 { 01191 if (mapbrushes[i].mins[0] > 4096) 01192 continue; //no valid points 01193 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs); 01194 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs); 01195 } //end for 01196 // 01197 Sin_CreateMapTexinfo(); 01198 } //end of the function Sin_LoadMapFromBSP 01199 01200 void Sin_ResetMapLoading(void) 01201 { 01202 //reset for map loading from bsp 01203 memset(nodestack, 0, NODESTACKSIZE * sizeof(int)); 01204 nodestackptr = NULL; 01205 nodestacksize = 0; 01206 memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int)); 01207 } //end of the function Sin_ResetMapLoading 01208 01209 //End MAP loading from BSP file 01210 01211 #endif //ME
1.3.9.1