00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qbsp.h"
00025
00026
00027 int entitySourceBrushes;
00028
00029 int numMapPatches;
00030
00031
00032 #define USE_HASHING
00033 #define PLANE_HASHES 1024
00034 plane_t *planehash[PLANE_HASHES];
00035
00036 plane_t mapplanes[MAX_MAP_PLANES];
00037 int nummapplanes;
00038
00039
00040
00041
00042 char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH];
00043 int numMapIndexedShaders;
00044
00045 vec3_t map_mins, map_maxs;
00046
00047 entity_t *mapent;
00048
00049
00050
00051 int c_boxbevels;
00052 int c_edgebevels;
00053
00054 int c_areaportals;
00055 int c_detail;
00056 int c_structural;
00057
00058
00059
00060
00061 bspbrush_t *buildBrush;
00062
00063
00064 void TestExpandBrushes (void);
00065 void SetTerrainTextures( void );
00066 void ParseTerrain( void );
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #define NORMAL_EPSILON 0.00001
00084 #define DIST_EPSILON 0.01
00085 qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
00086 {
00087 #if 1
00088 if (
00089 fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
00090 && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
00091 && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
00092 && fabs(p->dist - dist) < DIST_EPSILON )
00093 return qtrue;
00094 #else
00095 if (p->normal[0] == normal[0]
00096 && p->normal[1] == normal[1]
00097 && p->normal[2] == normal[2]
00098 && p->dist == dist)
00099 return qtrue;
00100 #endif
00101 return qfalse;
00102 }
00103
00104
00105
00106
00107
00108
00109 void AddPlaneToHash (plane_t *p)
00110 {
00111 int hash;
00112
00113 hash = (int)fabs(p->dist) / 8;
00114 hash &= (PLANE_HASHES-1);
00115
00116 p->hash_chain = planehash[hash];
00117 planehash[hash] = p;
00118 }
00119
00120
00121
00122
00123
00124
00125 int CreateNewFloatPlane (vec3_t normal, vec_t dist)
00126 {
00127 plane_t *p, temp;
00128
00129 if (VectorLength(normal) < 0.5)
00130 {
00131 _printf( "FloatPlane: bad normal\n");
00132 return -1;
00133 }
00134
00135
00136 if (nummapplanes+2 > MAX_MAP_PLANES)
00137 Error ("MAX_MAP_PLANES");
00138
00139 p = &mapplanes[nummapplanes];
00140 VectorCopy (normal, p->normal);
00141 p->dist = dist;
00142 p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
00143
00144 VectorSubtract (vec3_origin, normal, (p+1)->normal);
00145 (p+1)->dist = -dist;
00146
00147 nummapplanes += 2;
00148
00149
00150 if (p->type < 3)
00151 {
00152 if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
00153 {
00154
00155 temp = *p;
00156 *p = *(p+1);
00157 *(p+1) = temp;
00158
00159 AddPlaneToHash (p);
00160 AddPlaneToHash (p+1);
00161 return nummapplanes - 1;
00162 }
00163 }
00164
00165 AddPlaneToHash (p);
00166 AddPlaneToHash (p+1);
00167 return nummapplanes - 2;
00168 }
00169
00170
00171
00172
00173
00174
00175 void SnapVector (vec3_t normal)
00176 {
00177 int i;
00178
00179 for (i=0 ; i<3 ; i++)
00180 {
00181 if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
00182 {
00183 VectorClear (normal);
00184 normal[i] = 1;
00185 break;
00186 }
00187 if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
00188 {
00189 VectorClear (normal);
00190 normal[i] = -1;
00191 break;
00192 }
00193 }
00194 }
00195
00196
00197
00198
00199
00200
00201 void SnapPlane (vec3_t normal, vec_t *dist)
00202 {
00203 SnapVector (normal);
00204
00205 if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
00206 *dist = Q_rint(*dist);
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 #ifndef USE_HASHING
00216 int FindFloatPlane (vec3_t normal, vec_t dist)
00217 {
00218 int i;
00219 plane_t *p;
00220
00221 SnapPlane (normal, &dist);
00222 for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
00223 {
00224 if (PlaneEqual (p, normal, dist))
00225 return i;
00226 }
00227
00228 return CreateNewFloatPlane (normal, dist);
00229 }
00230 #else
00231 int FindFloatPlane (vec3_t normal, vec_t dist)
00232 {
00233 int i;
00234 plane_t *p;
00235 int hash, h;
00236
00237 SnapPlane (normal, &dist);
00238 hash = (int)fabs(dist) / 8;
00239 hash &= (PLANE_HASHES-1);
00240
00241
00242 for (i=-1 ; i<=1 ; i++)
00243 {
00244 h = (hash+i)&(PLANE_HASHES-1);
00245 for (p = planehash[h] ; p ; p=p->hash_chain)
00246 {
00247 if (PlaneEqual (p, normal, dist))
00248 return p-mapplanes;
00249 }
00250 }
00251
00252 return CreateNewFloatPlane (normal, dist);
00253 }
00254 #endif
00255
00256
00257
00258
00259
00260
00261 int MapPlaneFromPoints (vec3_t p0, vec3_t p1, vec3_t p2) {
00262 vec3_t t1, t2, normal;
00263 vec_t dist;
00264
00265 VectorSubtract (p0, p1, t1);
00266 VectorSubtract (p2, p1, t2);
00267 CrossProduct (t1, t2, normal);
00268 VectorNormalize (normal, normal);
00269
00270 dist = DotProduct (p0, normal);
00271
00272 return FindFloatPlane (normal, dist);
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 void SetBrushContents( bspbrush_t *b ) {
00287 int contents, c2;
00288 side_t *s;
00289 int i;
00290 qboolean mixed;
00291 int allFlags;
00292
00293 s = &b->sides[0];
00294 contents = s->contents;
00295 b->contentShader = s->shaderInfo;
00296 mixed = qfalse;
00297
00298 allFlags = 0;
00299
00300 for ( i=1 ; i<b->numsides ; i++, s++ ) {
00301 s = &b->sides[i];
00302
00303 if ( !s->shaderInfo ) {
00304 continue;
00305 }
00306
00307 c2 = s->contents;
00308 if (c2 != contents) {
00309 mixed = qtrue;
00310 }
00311
00312 allFlags |= s->surfaceFlags;
00313 }
00314
00315 if ( mixed ) {
00316 qprintf ("Entity %i, Brush %i: mixed face contents\n"
00317 , b->entitynum, b->brushnum);
00318 }
00319
00320 if ( ( contents & CONTENTS_DETAIL ) && ( contents & CONTENTS_STRUCTURAL ) ) {
00321 _printf ("Entity %i, Brush %i: mixed CONTENTS_DETAIL and CONTENTS_STRUCTURAL\n"
00322 , num_entities-1, entitySourceBrushes );
00323 contents &= ~CONTENTS_DETAIL;
00324 }
00325
00326
00327
00328 if ( fulldetail ) {
00329 contents &= ~CONTENTS_DETAIL;
00330 }
00331
00332
00333
00334 if ( ( contents & CONTENTS_TRANSLUCENT ) && !( contents & CONTENTS_STRUCTURAL ) ) {
00335 contents |= CONTENTS_DETAIL;
00336 }
00337
00338 if ( contents & CONTENTS_DETAIL ) {
00339 c_detail++;
00340 b->detail = qtrue;
00341 } else {
00342 c_structural++;
00343 b->detail = qfalse;
00344 }
00345
00346 if ( contents & CONTENTS_TRANSLUCENT ) {
00347 b->opaque = qfalse;
00348 } else {
00349 b->opaque = qtrue;
00350 }
00351
00352 if ( contents & CONTENTS_AREAPORTAL ) {
00353 c_areaportals++;
00354 }
00355
00356 b->contents = contents;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 void AddBrushBevels( void ) {
00371 int axis, dir;
00372 int i, order;
00373 side_t sidetemp;
00374 side_t *s;
00375 vec3_t normal;
00376 float dist;
00377
00378
00379
00380
00381 order = 0;
00382 for (axis=0 ; axis <3 ; axis++)
00383 {
00384 for (dir=-1 ; dir <= 1 ; dir+=2, order++)
00385 {
00386
00387 for ( i=0, s=buildBrush->sides ; i < buildBrush->numsides ; i++,s++ ) {
00388 if (mapplanes[s->planenum].normal[axis] == dir)
00389 break;
00390 }
00391
00392 if (i == buildBrush->numsides )
00393 {
00394 if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
00395 Error( "MAX_BUILD_SIDES" );
00396 }
00397 memset( s, 0, sizeof( *s ) );
00398 buildBrush->numsides++;
00399 VectorClear (normal);
00400 normal[axis] = dir;
00401 if (dir == 1)
00402 dist = buildBrush->maxs[axis];
00403 else
00404 dist = -buildBrush->mins[axis];
00405 s->planenum = FindFloatPlane (normal, dist);
00406 s->contents = buildBrush->sides[0].contents;
00407 s->bevel = qtrue;
00408 c_boxbevels++;
00409 }
00410
00411
00412 if (i != order)
00413 {
00414 sidetemp = buildBrush->sides[order];
00415 buildBrush->sides[order] = buildBrush->sides[i];
00416 buildBrush->sides[i] = sidetemp;
00417 }
00418 }
00419 }
00420
00421
00422
00423
00424 if ( buildBrush->numsides == 6 ) {
00425 return;
00426 } else {
00427 int j, k, l;
00428 float d;
00429 winding_t *w, *w2;
00430 side_t *s2;
00431 vec3_t vec, vec2;
00432
00433
00434
00435 for (i=6 ; i<buildBrush->numsides ; i++)
00436 {
00437 s = buildBrush->sides + i;
00438 w = s->winding;
00439 if (!w)
00440 continue;
00441 for (j=0 ; j<w->numpoints ; j++)
00442 {
00443 k = (j+1)%w->numpoints;
00444 VectorSubtract (w->p[j], w->p[k], vec);
00445 if (VectorNormalize (vec, vec) < 0.5)
00446 continue;
00447 SnapVector (vec);
00448 for (k=0 ; k<3 ; k++)
00449 if ( vec[k] == -1 || vec[k] == 1)
00450 break;
00451 if (k != 3)
00452 continue;
00453
00454
00455 for (axis=0 ; axis <3 ; axis++)
00456 {
00457 for (dir=-1 ; dir <= 1 ; dir+=2)
00458 {
00459
00460 VectorClear (vec2);
00461 vec2[axis] = dir;
00462 CrossProduct (vec, vec2, normal);
00463 if (VectorNormalize (normal, normal) < 0.5)
00464 continue;
00465 dist = DotProduct (w->p[j], normal);
00466
00467
00468
00469 for (k=0 ; k < buildBrush->numsides ; k++)
00470 {
00471
00472 if (PlaneEqual (&mapplanes[buildBrush->sides[k].planenum]
00473 , normal, dist) )
00474 break;
00475
00476 w2 = buildBrush->sides[k].winding;
00477 if (!w2)
00478 continue;
00479 for (l=0 ; l<w2->numpoints ; l++)
00480 {
00481 d = DotProduct (w2->p[l], normal) - dist;
00482 if (d > 0.1)
00483 break;
00484 }
00485 if (l != w2->numpoints)
00486 break;
00487 }
00488
00489 if (k != buildBrush->numsides)
00490 continue;
00491
00492 if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
00493 Error( "MAX_BUILD_SIDES" );
00494 }
00495
00496 s2 = &buildBrush->sides[buildBrush->numsides];
00497 buildBrush->numsides++;
00498 memset( s2, 0, sizeof( *s2 ) );
00499
00500 s2->planenum = FindFloatPlane (normal, dist);
00501 s2->contents = buildBrush->sides[0].contents;
00502 s2->bevel = qtrue;
00503 c_edgebevels++;
00504 }
00505 }
00506 }
00507 }
00508 }
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 void AddBackSides( void ) {
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 bspbrush_t *FinishBrush( void ) {
00558 bspbrush_t *b;
00559
00560
00561 AddBackSides();
00562
00563
00564 if ( !CreateBrushWindings( buildBrush ) ) {
00565
00566 return NULL;
00567 }
00568
00569
00570 if ( buildBrush->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
00571 {
00572 buildBrush->detail = qtrue;
00573 c_detail++;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 if ( buildBrush->contents & CONTENTS_ORIGIN )
00584 {
00585 char string[32];
00586 vec3_t origin;
00587
00588 if (num_entities == 1) {
00589 _printf ("Entity %i, Brush %i: origin brushes not allowed in world\n"
00590 , num_entities - 1, entitySourceBrushes);
00591 return NULL;
00592 }
00593
00594 VectorAdd (buildBrush->mins, buildBrush->maxs, origin);
00595 VectorScale (origin, 0.5, origin);
00596
00597 sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
00598 SetKeyValue (&entities[num_entities - 1], "origin", string);
00599
00600 VectorCopy (origin, entities[num_entities - 1].origin);
00601
00602
00603 return NULL;
00604 }
00605
00606 if ( buildBrush->contents & CONTENTS_AREAPORTAL ) {
00607 if (num_entities != 1) {
00608 _printf ("Entity %i, Brush %i: areaportals only allowed in world\n"
00609 , num_entities - 1, entitySourceBrushes);
00610 return NULL;
00611 }
00612 }
00613
00614 AddBrushBevels ();
00615
00616
00617 b = CopyBrush( buildBrush );
00618
00619 b->entitynum = num_entities-1;
00620 b->brushnum = entitySourceBrushes;
00621
00622 b->original = b;
00623
00624 b->next = mapent->brushes;
00625 mapent->brushes = b;
00626
00627 return b;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 vec3_t baseaxis[18] =
00639 {
00640 {0,0,1}, {1,0,0}, {0,-1,0},
00641 {0,0,-1}, {1,0,0}, {0,-1,0},
00642 {1,0,0}, {0,1,0}, {0,0,-1},
00643 {-1,0,0}, {0,1,0}, {0,0,-1},
00644 {0,1,0}, {1,0,0}, {0,0,-1},
00645 {0,-1,0}, {1,0,0}, {0,0,-1}
00646 };
00647
00648 void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
00649 {
00650 int bestaxis;
00651 vec_t dot,best;
00652 int i;
00653
00654 best = 0;
00655 bestaxis = 0;
00656
00657 for (i=0 ; i<6 ; i++)
00658 {
00659 dot = DotProduct (pln->normal, baseaxis[i*3]);
00660 if (dot > best)
00661 {
00662 best = dot;
00663 bestaxis = i;
00664 }
00665 }
00666
00667 VectorCopy (baseaxis[bestaxis*3+1], xv);
00668 VectorCopy (baseaxis[bestaxis*3+2], yv);
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2],
00681 vec_t mappingVecs[2][4] ) {
00682
00683 vec3_t vecs[2];
00684 int sv, tv;
00685 vec_t ang, sinv, cosv;
00686 vec_t ns, nt;
00687 int i, j;
00688
00689 TextureAxisFromPlane(plane, vecs[0], vecs[1]);
00690
00691 if (!scale[0])
00692 scale[0] = 1;
00693 if (!scale[1])
00694 scale[1] = 1;
00695
00696
00697 if (rotate == 0)
00698 { sinv = 0 ; cosv = 1; }
00699 else if (rotate == 90)
00700 { sinv = 1 ; cosv = 0; }
00701 else if (rotate == 180)
00702 { sinv = 0 ; cosv = -1; }
00703 else if (rotate == 270)
00704 { sinv = -1 ; cosv = 0; }
00705 else
00706 {
00707 ang = rotate / 180 * Q_PI;
00708 sinv = sin(ang);
00709 cosv = cos(ang);
00710 }
00711
00712 if (vecs[0][0])
00713 sv = 0;
00714 else if (vecs[0][1])
00715 sv = 1;
00716 else
00717 sv = 2;
00718
00719 if (vecs[1][0])
00720 tv = 0;
00721 else if (vecs[1][1])
00722 tv = 1;
00723 else
00724 tv = 2;
00725
00726 for (i=0 ; i<2 ; i++) {
00727 ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
00728 nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
00729 vecs[i][sv] = ns;
00730 vecs[i][tv] = nt;
00731 }
00732
00733 for (i=0 ; i<2 ; i++)
00734 for (j=0 ; j<3 ; j++)
00735 mappingVecs[i][j] = vecs[i][j] / scale[i];
00736
00737 mappingVecs[0][3] = shift[0];
00738 mappingVecs[1][3] = shift[1];
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 void ParseRawBrush( ) {
00760 side_t *side;
00761 vec3_t planepts[3];
00762 int planenum;
00763 shaderInfo_t *si;
00764
00765 vec_t shift[2];
00766 vec_t rotate;
00767 vec_t scale[2];
00768 char name[MAX_QPATH];
00769 char shader[MAX_QPATH];
00770 int flags;
00771
00772 buildBrush->numsides = 0;
00773 buildBrush->detail = qfalse;
00774
00775 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
00776 MatchToken( "{" );
00777
00778 do
00779 {
00780 if (!GetToken (qtrue))
00781 break;
00782 if (!strcmp (token, "}") )
00783 break;
00784
00785 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
00786 {
00787 do
00788 {
00789 if (strcmp (token, "(") )
00790 GetToken( qfalse );
00791 else
00792 break;
00793 GetToken( qtrue );
00794 } while (1);
00795 }
00796 UnGetToken();
00797
00798 if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
00799 Error( "MAX_BUILD_SIDES" );
00800 }
00801
00802 side = &buildBrush->sides[ buildBrush->numsides ];
00803 memset( side, 0, sizeof( *side ) );
00804 buildBrush->numsides++;
00805
00806
00807 Parse1DMatrix( 3, planepts[0] );
00808 Parse1DMatrix( 3, planepts[1] );
00809 Parse1DMatrix( 3, planepts[2] );
00810
00811 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
00812
00813 Parse2DMatrix( 2, 3, (float *)side->texMat );
00814
00815
00816 GetToken (qfalse);
00817 strcpy (name, token);
00818
00819
00820 if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
00821 Error( "MAX_MAP_BRUSHSIDES" );
00822 }
00823 strcpy( mapIndexedShaders[numMapIndexedShaders], name );
00824 numMapIndexedShaders++;
00825
00826 if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
00827 {
00828 GetToken (qfalse);
00829 shift[0] = atoi(token);
00830 GetToken (qfalse);
00831 shift[1] = atoi(token);
00832 GetToken (qfalse);
00833 rotate = atoi(token);
00834 GetToken (qfalse);
00835 scale[0] = atof(token);
00836 GetToken (qfalse);
00837 scale[1] = atof(token);
00838 }
00839
00840
00841 sprintf( shader, "textures/%s", name );
00842 si = ShaderInfoForShader( shader );
00843 side->shaderInfo = si;
00844 side->surfaceFlags = si->surfaceFlags;
00845 side->value = si->value;
00846 side->contents = si->contents;
00847
00848
00849
00850 if (TokenAvailable())
00851 {
00852 GetToken (qfalse);
00853
00854 flags = atoi(token);
00855 if ( flags & CONTENTS_DETAIL ) {
00856 side->contents |= CONTENTS_DETAIL;
00857 }
00858
00859 GetToken (qfalse);
00860
00861
00862 GetToken (qfalse);
00863
00864 }
00865
00866
00867
00868 planenum = MapPlaneFromPoints (planepts[0], planepts[1], planepts[2]);
00869 side->planenum = planenum;
00870
00871 if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
00872
00873 QuakeTextureVecs( &mapplanes[planenum], shift, rotate, scale, side->vecs );
00874
00875 } while (1);
00876
00877 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
00878 {
00879 UnGetToken();
00880 MatchToken( "}" );
00881 MatchToken( "}" );
00882 }
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 qboolean RemoveDuplicateBrushPlanes( bspbrush_t * b ) {
00895 int i, j, k;
00896 side_t *sides;
00897
00898 sides = b->sides;
00899
00900 for ( i = 1 ; i < b->numsides ; i++ ) {
00901
00902
00903 if ( sides[i].planenum == -1) {
00904 _printf ("Entity %i, Brush %i: degenerate plane\n"
00905 , b->entitynum, b->brushnum);
00906
00907 for ( k = i + 1 ; k < b->numsides ; k++ ) {
00908 sides[k-1] = sides[k];
00909 }
00910 b->numsides--;
00911 i--;
00912 continue;
00913 }
00914
00915
00916 for ( j = 0 ; j < i ; j++ ) {
00917 if ( sides[i].planenum == sides[j].planenum ) {
00918 _printf ("Entity %i, Brush %i: duplicate plane\n"
00919 , b->entitynum, b->brushnum);
00920
00921 for ( k = i + 1 ; k < b->numsides ; k++ ) {
00922 sides[k-1] = sides[k];
00923 }
00924 b->numsides--;
00925 i--;
00926 break;
00927 }
00928
00929 if ( sides[i].planenum == (sides[j].planenum ^ 1) ) {
00930
00931 _printf ("Entity %i, Brush %i: mirrored plane\n"
00932 , b->entitynum, b->brushnum);
00933 return qfalse;
00934 }
00935 }
00936 }
00937 return qtrue;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 void ParseBrush (void) {
00949 bspbrush_t *b;
00950
00951 ParseRawBrush();
00952
00953 buildBrush->portalareas[0] = -1;
00954 buildBrush->portalareas[1] = -1;
00955 buildBrush->entitynum = num_entities-1;
00956 buildBrush->brushnum = entitySourceBrushes;
00957
00958
00959 if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) {
00960 return;
00961 }
00962
00963
00964 SetBrushContents( buildBrush );
00965
00966
00967 if (nodetail && (buildBrush->contents & CONTENTS_DETAIL) ) {
00968 FreeBrush( buildBrush );
00969 return;
00970 }
00971
00972
00973 if (nowater && (buildBrush->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) {
00974 FreeBrush( buildBrush );
00975 return;
00976 }
00977
00978 b = FinishBrush( );
00979 if ( !b ) {
00980 return;
00981 }
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 void MoveBrushesToWorld (entity_t *mapent) {
00996 bspbrush_t *b, *next;
00997 parseMesh_t *pm;
00998
00999
01000 for ( b = mapent->brushes ; b ; b = next ) {
01001 next = b->next;
01002
01003 b->next = entities[0].brushes;
01004 entities[0].brushes = b;
01005 }
01006 mapent->brushes = NULL;
01007
01008
01009 if ( mapent->patches ) {
01010
01011 for ( pm = mapent->patches ; pm->next ; pm = pm->next ) {
01012 }
01013
01014 pm->next = entities[0].patches;
01015 entities[0].patches = mapent->patches;
01016
01017 mapent->patches = NULL;
01018 }
01019 }
01020
01021
01022
01023
01024
01025
01026
01027 void AdjustBrushesForOrigin( entity_t *ent ) {
01028 bspbrush_t *b;
01029 int i;
01030 side_t *s;
01031 vec_t newdist;
01032 parseMesh_t *p;
01033
01034 for ( b = ent->brushes ; b ; b = b->next ) {
01035 for (i=0 ; i<b->numsides ; i++) {
01036 s = &b->sides[i];
01037 newdist = mapplanes[s->planenum].dist -
01038 DotProduct (mapplanes[s->planenum].normal, ent->origin);
01039 s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
01040 }
01041 CreateBrushWindings(b);
01042 }
01043
01044 for ( p = ent->patches ; p ; p = p->next ) {
01045 for ( i = 0 ; i < p->mesh.width*p->mesh.height ; i++ ) {
01046 VectorSubtract( p->mesh.verts[i].xyz, ent->origin, p->mesh.verts[i].xyz );
01047 }
01048 }
01049
01050 }
01051
01052
01053
01054
01055
01056
01057 qboolean ParseMapEntity (void) {
01058 epair_t *e;
01059
01060 if (!GetToken (qtrue))
01061 return qfalse;
01062
01063 if (strcmp (token, "{") )
01064 {
01065 Error ("ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...", token, scriptline, entities[num_entities].origin[0], entities[num_entities].origin[1], entities[num_entities].origin[2]);
01066 }
01067
01068 if (num_entities == MAX_MAP_ENTITIES)
01069 Error ("num_entities == MAX_MAP_ENTITIES");
01070
01071 entitySourceBrushes = 0;
01072
01073 mapent = &entities[num_entities];
01074 num_entities++;
01075 memset (mapent, 0, sizeof(*mapent));
01076
01077 do
01078 {
01079 if (!GetToken (qtrue))
01080 Error ("ParseEntity: EOF without closing brace");
01081 if (!strcmp (token, "}") )
01082 break;
01083
01084 if (!strcmp (token, "{") ) {
01085
01086 if (!GetToken (qtrue))
01087 break;
01088 if ( !strcmp( token, "patchDef2" ) ) {
01089 numMapPatches++;
01090 ParsePatch();
01091 } else if ( !strcmp( token, "terrainDef" ) ) {
01092 ParseTerrain();
01093 } else if ( !strcmp( token, "brushDef" ) ) {
01094 if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
01095 Error("old brush format not allowed in new brush format map");
01096 g_bBrushPrimit=BPRIMIT_NEWBRUSHES;
01097
01098 ParseBrush();
01099 }
01100 else
01101 {
01102 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
01103 Error("new brush format not allowed in old brush format map");
01104 g_bBrushPrimit=BPRIMIT_OLDBRUSHES;
01105
01106 UnGetToken();
01107 ParseBrush();
01108 }
01109 entitySourceBrushes++;
01110 }
01111 else
01112 {
01113
01114 e = ParseEpair ();
01115 e->next = mapent->epairs;
01116 mapent->epairs = e;
01117 }
01118 } while (1);
01119
01120 GetVectorForKey (mapent, "origin", mapent->origin);
01121
01122
01123
01124
01125 if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) {
01126 AdjustBrushesForOrigin( mapent );
01127 }
01128
01129
01130
01131
01132 if (!strcmp("group_info", ValueForKey (mapent, "classname")))
01133 {
01134 num_entities--;
01135 return qtrue;
01136 }
01137
01138
01139
01140 if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
01141 {
01142 if ( !strcmp ("1", ValueForKey (mapent, "terrain"))) {
01143 SetTerrainTextures();
01144 }
01145 MoveBrushesToWorld (mapent);
01146 num_entities--;
01147 return qtrue;
01148 }
01149
01150 return qtrue;
01151 }
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 void LoadMapFile (char *filename) {
01162 bspbrush_t *b;
01163
01164 qprintf ("--- LoadMapFile ---\n");
01165 _printf ("Loading map file %s\n", filename);
01166
01167 LoadScriptFile (filename);
01168
01169 num_entities = 0;
01170 numMapDrawSurfs = 0;
01171 c_detail = 0;
01172
01173 g_bBrushPrimit = BPRIMIT_UNDEFINED;
01174
01175
01176
01177 buildBrush = AllocBrush( MAX_BUILD_SIDES );
01178
01179 while (ParseMapEntity ())
01180 {
01181 }
01182
01183 ClearBounds (map_mins, map_maxs);
01184 for ( b = entities[0].brushes ; b ; b=b->next ) {
01185 AddPointToBounds( b->mins, map_mins, map_maxs );
01186 AddPointToBounds( b->maxs, map_mins, map_maxs );
01187 }
01188
01189 qprintf ("%5i total world brushes\n", CountBrushList( entities[0].brushes ) );
01190 qprintf ("%5i detail brushes\n", c_detail );
01191 qprintf ("%5i patches\n", numMapPatches);
01192 qprintf ("%5i boxbevels\n", c_boxbevels);
01193 qprintf ("%5i edgebevels\n", c_edgebevels);
01194 qprintf ("%5i entities\n", num_entities);
01195 qprintf ("%5i planes\n", nummapplanes);
01196 qprintf ("%5i areaportals\n", c_areaportals);
01197 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],
01198 map_maxs[0],map_maxs[1],map_maxs[2]);
01199
01200 if ( fakemap ) {
01201 WriteBspBrushMap ("fakemap.map", entities[0].brushes );
01202 }
01203
01204 if ( testExpand ) {
01205 TestExpandBrushes ();
01206 }
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221 void TestExpandBrushes( void ) {
01222 side_t *s;
01223 int i, j;
01224 bspbrush_t *brush, *list, *copy;
01225 vec_t dist;
01226 plane_t *plane;
01227
01228 list = NULL;
01229
01230 for ( brush = entities[0].brushes ; brush ; brush = brush->next ) {
01231 copy = CopyBrush( brush );
01232 copy->next = list;
01233 list = copy;
01234
01235
01236 for ( i=0 ; i<brush->numsides ; i++ ) {
01237 s = brush->sides + i;
01238 plane = &mapplanes[s->planenum];
01239 dist = plane->dist;
01240 for (j=0 ; j<3 ; j++) {
01241 dist += fabs( 16 * plane->normal[j] );
01242 }
01243 s->planenum = FindFloatPlane( plane->normal, dist );
01244 }
01245
01246 }
01247
01248 WriteBspBrushMap ( "expanded.map", entities[0].brushes );
01249
01250 Error ("can't proceed after expanding brushes");
01251 }