00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "qbsp.h"
00029 #include "l_mem.h"
00030 #include "../botlib/aasfile.h"
00031 #include "aas_store.h"
00032 #include "aas_cfg.h"
00033 #include "aas_map.h"
00034 #include "l_bsp_q2.h"
00035
00036
00037 #ifdef ME
00038
00039 #define NODESTACKSIZE 1024
00040
00041 int nodestack[NODESTACKSIZE];
00042 int *nodestackptr;
00043 int nodestacksize = 0;
00044 int brushmodelnumbers[MAX_MAPFILE_BRUSHES];
00045 int dbrushleafnums[MAX_MAPFILE_BRUSHES];
00046 int dplanes2mapplanes[MAX_MAPFILE_PLANES];
00047
00048 #endif //ME
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 void Q2_CreateMapTexinfo(void)
00059 {
00060 int i;
00061
00062 for (i = 0; i < numtexinfo; i++)
00063 {
00064 memcpy(map_texinfo[i].vecs, texinfo[i].vecs, sizeof(float) * 2 * 4);
00065 map_texinfo[i].flags = texinfo[i].flags;
00066 map_texinfo[i].value = texinfo[i].value;
00067 strcpy(map_texinfo[i].texture, texinfo[i].texture);
00068 map_texinfo[i].nexttexinfo = 0;
00069 }
00070 }
00071
00072
00073
00074
00075
00076
00077 int Q2_BrushContents (mapbrush_t *b)
00078 {
00079 int contents;
00080 side_t *s;
00081 int i;
00082 int trans;
00083
00084 s = &b->original_sides[0];
00085 contents = s->contents;
00086 trans = texinfo[s->texinfo].flags;
00087 for (i = 1; i < b->numsides; i++, s++)
00088 {
00089 s = &b->original_sides[i];
00090 trans |= texinfo[s->texinfo].flags;
00091 if (s->contents != contents)
00092 {
00093 Log_Print("Entity %i, Brush %i: mixed face contents\n"
00094 , b->entitynum, b->brushnum);
00095 Log_Print("texture name = %s\n", texinfo[s->texinfo].texture);
00096 break;
00097 }
00098 }
00099
00100
00101
00102 if ( trans & (SURF_TRANS33|SURF_TRANS66) )
00103 {
00104 contents |= CONTENTS_Q2TRANSLUCENT;
00105 if (contents & CONTENTS_SOLID)
00106 {
00107 contents &= ~CONTENTS_SOLID;
00108 contents |= CONTENTS_WINDOW;
00109 }
00110 }
00111
00112 return contents;
00113 }
00114
00115 #ifdef ME
00116
00117 #define BBOX_NORMAL_EPSILON 0.0001
00118
00119
00120
00121
00122
00123
00124
00125 void MakeAreaPortalBrush(mapbrush_t *brush)
00126 {
00127 int sn;
00128 side_t *s;
00129
00130 brush->contents = CONTENTS_AREAPORTAL;
00131
00132 for (sn = 0; sn < brush->numsides; sn++)
00133 {
00134 s = brush->original_sides + sn;
00135
00136 s->surf &= ~(SURF_HINT|SURF_SKIP);
00137
00138 s->texinfo = 0;
00139 s->contents = CONTENTS_AREAPORTAL;
00140 }
00141 }
00142
00143
00144
00145
00146
00147
00148 void DPlanes2MapPlanes(void)
00149 {
00150 int i;
00151
00152 for (i = 0; i < numplanes; i++)
00153 {
00154 dplanes2mapplanes[i] = FindFloatPlane(dplanes[i].normal, dplanes[i].dist);
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163 void MarkVisibleBrushSides(mapbrush_t *brush)
00164 {
00165 int n, i, planenum;
00166 side_t *side;
00167 dface_t *face;
00168
00169 for (n = 0; n < brush->numsides; n++)
00170 {
00171 side = brush->original_sides + n;
00172
00173 if ((side->flags & SFL_BEVEL) || brush->leafnum < 0)
00174 {
00175
00176 side->flags |= SFL_VISIBLE;
00177 continue;
00178 }
00179
00180 side->flags &= ~SFL_VISIBLE;
00181
00182 for (i = 0; i < numfaces; i++)
00183 {
00184 face = &dfaces[i];
00185 planenum = dplanes2mapplanes[face->planenum];
00186 if ((planenum & ~1) == (side->planenum & ~1))
00187 {
00188
00189 side->flags |= SFL_VISIBLE;
00190 }
00191 }
00192 }
00193 }
00194
00195 #endif //ME
00196
00197
00198
00199
00200
00201
00202 void Q2_ParseBrush (script_t *script, entity_t *mapent)
00203 {
00204 mapbrush_t *b;
00205 int i, j, k;
00206 int mt;
00207 side_t *side, *s2;
00208 int planenum;
00209 brush_texture_t td;
00210 int planepts[3][3];
00211 token_t token;
00212
00213 if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00214 Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
00215
00216 b = &mapbrushes[nummapbrushes];
00217 b->original_sides = &brushsides[nummapbrushsides];
00218 b->entitynum = num_entities-1;
00219 b->brushnum = nummapbrushes - mapent->firstbrush;
00220 b->leafnum = -1;
00221
00222 do
00223 {
00224 if (!PS_ReadToken(script, &token))
00225 break;
00226 if (!strcmp(token.string, "}") )
00227 break;
00228
00229
00230
00231 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00232 Error ("MAX_MAPFILE_BRUSHSIDES");
00233 side = &brushsides[nummapbrushsides];
00234
00235
00236 for (i = 0; i < 3; i++)
00237 {
00238 if (i != 0) PS_ExpectTokenString(script, "(");
00239 for (j = 0; j < 3; j++)
00240 {
00241 PS_ExpectAnyToken(script, &token);
00242 planepts[i][j] = atof(token.string);
00243 }
00244 PS_ExpectTokenString(script, ")");
00245 }
00246
00247
00248
00249
00250 PS_ExpectAnyToken(script, &token);
00251 strcpy(td.name, token.string);
00252
00253 PS_ExpectAnyToken(script, &token);
00254 td.shift[0] = atol(token.string);
00255 PS_ExpectAnyToken(script, &token);
00256 td.shift[1] = atol(token.string);
00257 PS_ExpectAnyToken(script, &token);
00258 td.rotate = atol(token.string);
00259 PS_ExpectAnyToken(script, &token);
00260 td.scale[0] = atof(token.string);
00261 PS_ExpectAnyToken(script, &token);
00262 td.scale[1] = atof(token.string);
00263
00264
00265 mt = FindMiptex (td.name);
00266 td.flags = textureref[mt].flags;
00267 td.value = textureref[mt].value;
00268 side->contents = textureref[mt].contents;
00269 side->surf = td.flags = textureref[mt].flags;
00270
00271
00272 if (PS_CheckTokenType(script, TT_NUMBER, 0, &token))
00273 {
00274 side->contents = token.intvalue;
00275 PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
00276 side->surf = td.flags = token.intvalue;
00277 PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
00278 td.value = token.intvalue;
00279 }
00280
00281
00282 if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
00283 side->contents |= CONTENTS_DETAIL;
00284 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00285 side->contents |= CONTENTS_DETAIL;
00286 if (fulldetail)
00287 side->contents &= ~CONTENTS_DETAIL;
00288 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
00289 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
00290 side->contents |= CONTENTS_SOLID;
00291
00292
00293 if (side->surf & (SURF_HINT|SURF_SKIP) )
00294 {
00295 side->contents = 0;
00296 side->surf &= ~CONTENTS_DETAIL;
00297 }
00298
00299 #ifdef ME
00300
00301 side->flags |= SFL_TEXTURED;
00302 #endif //ME
00303
00304
00305
00306 planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
00307 if (planenum == -1)
00308 {
00309 Log_Print("Entity %i, Brush %i: plane with no normal\n"
00310 , b->entitynum, b->brushnum);
00311 continue;
00312 }
00313
00314
00315
00316
00317 for (k=0 ; k<b->numsides ; k++)
00318 {
00319 s2 = b->original_sides + k;
00320 if (s2->planenum == planenum)
00321 {
00322 Log_Print("Entity %i, Brush %i: duplicate plane\n"
00323 , b->entitynum, b->brushnum);
00324 break;
00325 }
00326 if ( s2->planenum == (planenum^1) )
00327 {
00328 Log_Print("Entity %i, Brush %i: mirrored plane\n"
00329 , b->entitynum, b->brushnum);
00330 break;
00331 }
00332 }
00333 if (k != b->numsides)
00334 continue;
00335
00336
00337
00338
00339
00340 side = b->original_sides + b->numsides;
00341 side->planenum = planenum;
00342 side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
00343 &td, vec3_origin);
00344
00345
00346
00347 side_brushtextures[nummapbrushsides] = td;
00348
00349 nummapbrushsides++;
00350 b->numsides++;
00351 } while (1);
00352
00353
00354 b->contents = Q2_BrushContents (b);
00355
00356 #ifdef ME
00357 if (BrushExists(b))
00358 {
00359 c_squattbrushes++;
00360 b->numsides = 0;
00361 return;
00362 }
00363
00364 if (create_aas)
00365 {
00366
00367 AAS_CreateMapBrushes(b, mapent, true);
00368
00369 return;
00370 }
00371 #endif //ME
00372
00373
00374 if (nodetail && (b->contents & CONTENTS_DETAIL) )
00375 {
00376 b->numsides = 0;
00377 return;
00378 }
00379
00380
00381 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
00382 {
00383 b->numsides = 0;
00384 return;
00385 }
00386
00387
00388 MakeBrushWindings (b);
00389
00390
00391
00392 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00393 {
00394 c_clipbrushes++;
00395 for (i=0 ; i<b->numsides ; i++)
00396 b->original_sides[i].texinfo = TEXINFO_NODE;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406 if (b->contents & CONTENTS_ORIGIN)
00407 {
00408 char string[32];
00409 vec3_t origin;
00410
00411 if (num_entities == 1)
00412 {
00413 Error ("Entity %i, Brush %i: origin brushes not allowed in world"
00414 , b->entitynum, b->brushnum);
00415 return;
00416 }
00417
00418 VectorAdd (b->mins, b->maxs, origin);
00419 VectorScale (origin, 0.5, origin);
00420
00421 sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
00422 SetKeyValue (&entities[b->entitynum], "origin", string);
00423
00424 VectorCopy (origin, entities[b->entitynum].origin);
00425
00426
00427 b->numsides = 0;
00428
00429 return;
00430 }
00431
00432 AddBrushBevels(b);
00433
00434 nummapbrushes++;
00435 mapent->numbrushes++;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 void Q2_MoveBrushesToWorld (entity_t *mapent)
00449 {
00450 int newbrushes;
00451 int worldbrushes;
00452 mapbrush_t *temp;
00453 int i;
00454
00455
00456
00457
00458 newbrushes = mapent->numbrushes;
00459 worldbrushes = entities[0].numbrushes;
00460
00461 temp = GetMemory(newbrushes*sizeof(mapbrush_t));
00462 memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
00463
00464 #if 0 // let them keep their original brush numbers
00465 for (i=0 ; i<newbrushes ; i++)
00466 temp[i].entitynum = 0;
00467 #endif
00468
00469
00470 memmove (mapbrushes + worldbrushes + newbrushes,
00471 mapbrushes + worldbrushes,
00472 sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
00473
00474
00475 memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
00476
00477
00478 entities[0].numbrushes += newbrushes;
00479 for (i=1 ; i<num_entities ; i++)
00480 entities[i].firstbrush += newbrushes;
00481 FreeMemory(temp);
00482
00483 mapent->numbrushes = 0;
00484 }
00485
00486
00487
00488
00489
00490
00491 qboolean Q2_ParseMapEntity(script_t *script)
00492 {
00493 entity_t *mapent;
00494 epair_t *e;
00495 side_t *s;
00496 int i, j;
00497 int startbrush, startsides;
00498 vec_t newdist;
00499 mapbrush_t *b;
00500 token_t token;
00501
00502 if (!PS_ReadToken(script, &token)) return false;
00503
00504 if (strcmp(token.string, "{") )
00505 Error ("ParseEntity: { not found");
00506
00507 if (num_entities == MAX_MAP_ENTITIES)
00508 Error ("num_entities == MAX_MAP_ENTITIES");
00509
00510 startbrush = nummapbrushes;
00511 startsides = nummapbrushsides;
00512
00513 mapent = &entities[num_entities];
00514 num_entities++;
00515 memset (mapent, 0, sizeof(*mapent));
00516 mapent->firstbrush = nummapbrushes;
00517 mapent->numbrushes = 0;
00518
00519
00520
00521 do
00522 {
00523 if (!PS_ReadToken(script, &token))
00524 {
00525 Error("ParseEntity: EOF without closing brace");
00526 }
00527 if (!strcmp(token.string, "}")) break;
00528 if (!strcmp(token.string, "{"))
00529 {
00530 Q2_ParseBrush(script, mapent);
00531 }
00532 else
00533 {
00534 PS_UnreadLastToken(script);
00535 e = ParseEpair(script);
00536 e->next = mapent->epairs;
00537 mapent->epairs = e;
00538 }
00539 } while(1);
00540
00541 GetVectorForKey(mapent, "origin", mapent->origin);
00542
00543
00544
00545
00546 if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
00547 {
00548 for (i=0 ; i<mapent->numbrushes ; i++)
00549 {
00550 b = &mapbrushes[mapent->firstbrush + i];
00551 for (j=0 ; j<b->numsides ; j++)
00552 {
00553 s = &b->original_sides[j];
00554 newdist = mapplanes[s->planenum].dist -
00555 DotProduct (mapplanes[s->planenum].normal, mapent->origin);
00556 s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
00557 s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
00558 &side_brushtextures[s-brushsides], mapent->origin);
00559 }
00560 MakeBrushWindings (b);
00561 }
00562 }
00563
00564
00565
00566 if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
00567 {
00568 Q2_MoveBrushesToWorld (mapent);
00569 mapent->numbrushes = 0;
00570 return true;
00571 }
00572
00573
00574
00575 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
00576 {
00577 char str[128];
00578
00579 if (mapent->numbrushes != 1)
00580 Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
00581
00582 b = &mapbrushes[nummapbrushes-1];
00583 b->contents = CONTENTS_AREAPORTAL;
00584 c_areaportals++;
00585 mapent->areaportalnum = c_areaportals;
00586
00587 sprintf (str, "%i", c_areaportals);
00588 SetKeyValue (mapent, "style", str);
00589 Q2_MoveBrushesToWorld (mapent);
00590 return true;
00591 }
00592
00593 return true;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603 void Q2_LoadMapFile(char *filename)
00604 {
00605 int i;
00606 script_t *script;
00607
00608 Log_Print("-- Q2_LoadMapFile --\n");
00609 #ifdef ME
00610
00611 loadedmaptype = MAPTYPE_QUAKE2;
00612
00613 ResetMapLoading();
00614 #endif //ME
00615
00616 script = LoadScriptFile(filename);
00617 if (!script)
00618 {
00619 Log_Print("couldn't open %s\n", filename);
00620 return;
00621 }
00622
00623 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
00624 SCFL_NOSTRINGESCAPECHARS |
00625 SCFL_PRIMITIVE);
00626
00627 nummapbrushsides = 0;
00628 num_entities = 0;
00629
00630 while (Q2_ParseMapEntity(script))
00631 {
00632 }
00633
00634 ClearBounds (map_mins, map_maxs);
00635 for (i=0 ; i<entities[0].numbrushes ; i++)
00636 {
00637 if (mapbrushes[i].mins[0] > 4096)
00638 continue;
00639 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
00640 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
00641 }
00642
00643 PrintMapInfo();
00644
00645
00646 FreeScript(script);
00647
00648
00649 Q2_CreateMapTexinfo();
00650 }
00651
00652 #ifdef ME //Begin MAP loading from BSP file
00653
00654
00655
00656
00657
00658
00659 void Q2_SetLeafBrushesModelNumbers(int leafnum, int modelnum)
00660 {
00661 int i, brushnum;
00662 dleaf_t *leaf;
00663
00664 leaf = &dleafs[leafnum];
00665 for (i = 0; i < leaf->numleafbrushes; i++)
00666 {
00667 brushnum = dleafbrushes[leaf->firstleafbrush + i];
00668 brushmodelnumbers[brushnum] = modelnum;
00669 dbrushleafnums[brushnum] = leafnum;
00670 }
00671 }
00672
00673
00674
00675
00676
00677
00678 void Q2_InitNodeStack(void)
00679 {
00680 nodestackptr = nodestack;
00681 nodestacksize = 0;
00682 }
00683
00684
00685
00686
00687
00688
00689 void Q2_PushNodeStack(int num)
00690 {
00691 *nodestackptr = num;
00692 nodestackptr++;
00693 nodestacksize++;
00694
00695 if (nodestackptr >= &nodestack[NODESTACKSIZE])
00696 {
00697 Error("Q2_PushNodeStack: stack overflow\n");
00698 }
00699 }
00700
00701
00702
00703
00704
00705
00706 int Q2_PopNodeStack(void)
00707 {
00708
00709 if (nodestackptr <= nodestack) return -1;
00710
00711 nodestackptr--;
00712 nodestacksize--;
00713
00714 return *nodestackptr;
00715 }
00716
00717
00718
00719
00720
00721
00722 void Q2_SetBrushModelNumbers(entity_t *mapent)
00723 {
00724 int n, pn;
00725 int leafnum;
00726
00727
00728 Q2_InitNodeStack();
00729
00730 n = dmodels[mapent->modelnum].headnode;
00731 pn = 0;
00732
00733 do
00734 {
00735
00736 if (n < 0)
00737 {
00738
00739 leafnum = (-n) - 1;
00740
00741 Q2_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
00742
00743 for (pn = Q2_PopNodeStack(); pn >= 0; n = pn, pn = Q2_PopNodeStack())
00744 {
00745
00746 if (dnodes[pn].children[0] == n) break;
00747 }
00748
00749 if (pn >= 0)
00750 {
00751
00752 Q2_PushNodeStack(pn);
00753
00754 n = dnodes[pn].children[1];
00755 }
00756 }
00757 else
00758 {
00759
00760 Q2_PushNodeStack(n);
00761
00762 n = dnodes[n].children[0];
00763 }
00764 } while(pn >= 0);
00765 }
00766
00767
00768
00769
00770
00771
00772 void Q2_BSPBrushToMapBrush(dbrush_t *bspbrush, entity_t *mapent)
00773 {
00774 mapbrush_t *b;
00775 int i, k, n;
00776 side_t *side, *s2;
00777 int planenum;
00778 dbrushside_t *bspbrushside;
00779 dplane_t *bspplane;
00780
00781 if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00782 Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
00783
00784 b = &mapbrushes[nummapbrushes];
00785 b->original_sides = &brushsides[nummapbrushsides];
00786 b->entitynum = mapent-entities;
00787 b->brushnum = nummapbrushes - mapent->firstbrush;
00788 b->leafnum = dbrushleafnums[bspbrush - dbrushes];
00789
00790 for (n = 0; n < bspbrush->numsides; n++)
00791 {
00792
00793 bspbrushside = &dbrushsides[bspbrush->firstside + n];
00794
00795 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00796 {
00797 Error ("MAX_MAPFILE_BRUSHSIDES");
00798 }
00799
00800 side = &brushsides[nummapbrushsides];
00801
00802 if (brushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED;
00803 else side->flags &= ~SFL_TEXTURED;
00804
00805 side->contents = bspbrush->contents;
00806
00807 if (bspbrushside->texinfo < 0) side->surf = 0;
00808 else side->surf = texinfo[bspbrushside->texinfo].flags;
00809
00810
00811 if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
00812 side->contents |= CONTENTS_DETAIL;
00813 if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00814 side->contents |= CONTENTS_DETAIL;
00815 if (fulldetail)
00816 side->contents &= ~CONTENTS_DETAIL;
00817 if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
00818 | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
00819 side->contents |= CONTENTS_SOLID;
00820
00821
00822 if (side->surf & (SURF_HINT|SURF_SKIP) )
00823 {
00824 side->contents = 0;
00825 side->surf &= ~CONTENTS_DETAIL;
00826 }
00827
00828
00829 bspplane = &dplanes[bspbrushside->planenum];
00830 planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
00831
00832
00833
00834
00835
00836
00837
00838 for (k = 0; k < b->numsides; k++)
00839 {
00840 s2 = b->original_sides + k;
00841
00842
00843
00844 if (s2->planenum == planenum)
00845 {
00846 Log_Print("Entity %i, Brush %i: duplicate plane\n"
00847 , b->entitynum, b->brushnum);
00848 break;
00849 }
00850 if ( s2->planenum == (planenum^1) )
00851 {
00852 Log_Print("Entity %i, Brush %i: mirrored plane\n"
00853 , b->entitynum, b->brushnum);
00854 break;
00855 }
00856 }
00857 if (k != b->numsides)
00858 continue;
00859
00860
00861
00862
00863
00864 side = b->original_sides + b->numsides;
00865
00866 side->planenum = planenum;
00867
00868
00869 if (bspbrushside->texinfo < 0) side->texinfo = 0;
00870 else side->texinfo = bspbrushside->texinfo;
00871
00872
00873
00874
00875
00876
00877
00878 nummapbrushsides++;
00879 b->numsides++;
00880 }
00881
00882
00883 b->contents = bspbrush->contents;
00884 Q2_BrushContents(b);
00885
00886 if (BrushExists(b))
00887 {
00888 c_squattbrushes++;
00889 b->numsides = 0;
00890 return;
00891 }
00892
00893
00894 if (create_aas)
00895 {
00896
00897 AAS_CreateMapBrushes(b, mapent, false);
00898 return;
00899 }
00900
00901
00902 if (nodetail && (b->contents & CONTENTS_DETAIL) )
00903 {
00904 b->numsides = 0;
00905 return;
00906 }
00907
00908
00909 if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
00910 {
00911 b->numsides = 0;
00912 return;
00913 }
00914
00915
00916 MakeBrushWindings(b);
00917
00918
00919 MarkBrushBevels(b);
00920
00921
00922
00923 if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00924 {
00925 c_clipbrushes++;
00926 for (i = 0; i < b->numsides; i++)
00927 b->original_sides[i].texinfo = TEXINFO_NODE;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 nummapbrushes++;
00971 mapent->numbrushes++;
00972 }
00973
00974
00975 void Q2_ParseBSPBrushes(entity_t *mapent)
00976 {
00977 int i;
00978
00979
00980
00981 Q2_SetBrushModelNumbers(mapent);
00982
00983 for (i = 0; i < numbrushes; i++)
00984 {
00985 if (brushmodelnumbers[i] == mapent->modelnum)
00986 {
00987 Q2_BSPBrushToMapBrush(&dbrushes[i], mapent);
00988 }
00989 }
00990 }
00991
00992
00993 qboolean Q2_ParseBSPEntity(int entnum)
00994 {
00995 entity_t *mapent;
00996 char *model;
00997 int startbrush, startsides;
00998
00999 startbrush = nummapbrushes;
01000 startsides = nummapbrushsides;
01001
01002 mapent = &entities[entnum];
01003 mapent->firstbrush = nummapbrushes;
01004 mapent->numbrushes = 0;
01005 mapent->modelnum = -1;
01006
01007 model = ValueForKey(mapent, "model");
01008 if (model && strlen(model))
01009 {
01010 if (*model != '*')
01011 {
01012 Error("Q2_ParseBSPEntity: model number without leading *");
01013 }
01014
01015 mapent->modelnum = atoi(&model[1]);
01016 }
01017
01018 GetVectorForKey(mapent, "origin", mapent->origin);
01019
01020
01021
01022 if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
01023 {
01024 mapent->modelnum = 0;
01025 }
01026
01027
01028 if (mapent->modelnum >= 0)
01029 {
01030
01031 Q2_ParseBSPBrushes(mapent);
01032 }
01033
01034
01035
01036
01037
01038
01039 if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
01040 {
01041 c_areaportals++;
01042 mapent->areaportalnum = c_areaportals;
01043 return true;
01044 }
01045 return true;
01046 }
01047
01048
01049
01050
01051
01052
01053 void Q2_LoadMapFromBSP(char *filename, int offset, int length)
01054 {
01055 int i;
01056
01057 Log_Print("-- Q2_LoadMapFromBSP --\n");
01058
01059 loadedmaptype = MAPTYPE_QUAKE2;
01060
01061 Log_Print("Loading map from %s...\n", filename);
01062
01063 Q2_LoadBSPFile(filename, offset, length);
01064
01065
01066
01067
01068 for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
01069 brushmodelnumbers[i] = -1;
01070
01071 nummapbrushsides = 0;
01072 num_entities = 0;
01073
01074 Q2_ParseEntities();
01075
01076 for (i = 0; i < num_entities; i++)
01077 {
01078 Q2_ParseBSPEntity(i);
01079 }
01080
01081
01082 ClearBounds(map_mins, map_maxs);
01083 for (i = 0; i < entities[0].numbrushes; i++)
01084 {
01085 if (mapbrushes[i].mins[0] > 4096)
01086 continue;
01087 AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
01088 AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
01089 }
01090
01091 PrintMapInfo();
01092
01093 Q2_CreateMapTexinfo();
01094 }
01095
01096 void Q2_ResetMapLoading(void)
01097 {
01098
01099 memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
01100 nodestackptr = NULL;
01101 nodestacksize = 0;
01102 memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
01103 }
01104
01105
01106 #endif //ME
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 void TestExpandBrushes (void)
01118 {
01119 FILE *f;
01120 side_t *s;
01121 int i, j, bn;
01122 winding_t *w;
01123 char *name = "expanded.map";
01124 mapbrush_t *brush;
01125 vec_t dist;
01126
01127 Log_Print("writing %s\n", name);
01128 f = fopen (name, "wb");
01129 if (!f)
01130 Error ("Can't write %s\n", name);
01131
01132 fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
01133
01134 for (bn=0 ; bn<nummapbrushes ; bn++)
01135 {
01136 brush = &mapbrushes[bn];
01137 fprintf (f, "{\n");
01138 for (i=0 ; i<brush->numsides ; i++)
01139 {
01140 s = brush->original_sides + i;
01141 dist = mapplanes[s->planenum].dist;
01142 for (j=0 ; j<3 ; j++)
01143 dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
01144
01145 w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
01146
01147 fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
01148 fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
01149 fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
01150
01151 fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
01152 FreeWinding (w);
01153 }
01154 fprintf (f, "}\n");
01155 }
01156 fprintf (f, "}\n");
01157
01158 fclose (f);
01159
01160 Error ("can't proceed after expanding brushes");
01161 }
01162