00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "qbsp.h"
00024 #include "l_bsp_hl.h"
00025 #include "aas_map.h"
00026
00027 int hl_numbrushes;
00028 int hl_numclipbrushes;
00029
00030
00031 #define HLCONTENTS
00032
00033
00034
00035
00036
00037
00038
00039 int HL_TextureContents(char *name)
00040 {
00041 if (!Q_strncasecmp (name, "sky",3))
00042 return CONTENTS_SOLID;
00043
00044 if (!Q_strncasecmp(name+1,"!lava",5))
00045 return CONTENTS_LAVA;
00046
00047 if (!Q_strncasecmp(name+1,"!slime",6))
00048 return CONTENTS_SLIME;
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 if (name[0] == '!')
00065 return CONTENTS_WATER;
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 return CONTENTS_SOLID;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 void HL_SplitBrush(bspbrush_t *brush, int planenum, int nodenum,
00091 bspbrush_t **front, bspbrush_t **back)
00092 {
00093 bspbrush_t *b[2];
00094 int i, j;
00095 winding_t *w, *cw[2], *midwinding;
00096 plane_t *plane, *plane2;
00097 side_t *s, *cs;
00098 float d, d_front, d_back;
00099
00100 *front = *back = NULL;
00101 plane = &mapplanes[planenum];
00102
00103
00104 d_front = d_back = 0;
00105 for (i=0 ; i<brush->numsides ; i++)
00106 {
00107 w = brush->sides[i].winding;
00108 if (!w)
00109 continue;
00110 for (j=0 ; j<w->numpoints ; j++)
00111 {
00112 d = DotProduct (w->p[j], plane->normal) - plane->dist;
00113 if (d > 0 && d > d_front)
00114 d_front = d;
00115 if (d < 0 && d < d_back)
00116 d_back = d;
00117 }
00118 }
00119
00120 if (d_front < 0.1)
00121 {
00122 *back = CopyBrush (brush);
00123 Log_Print("HL_SplitBrush: only on back\n");
00124 return;
00125 }
00126 if (d_back > -0.1)
00127 {
00128 *front = CopyBrush (brush);
00129 Log_Print("HL_SplitBrush: only on front\n");
00130 return;
00131 }
00132
00133
00134
00135 w = BaseWindingForPlane (plane->normal, plane->dist);
00136 for (i = 0; i < brush->numsides && w; i++)
00137 {
00138 plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
00139 ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0);
00140 }
00141
00142 if (!w || WindingIsTiny(w))
00143 {
00144 int side;
00145
00146 Log_Print("HL_SplitBrush: no split winding\n");
00147 side = BrushMostlyOnSide (brush, plane);
00148 if (side == PSIDE_FRONT)
00149 *front = CopyBrush (brush);
00150 if (side == PSIDE_BACK)
00151 *back = CopyBrush (brush);
00152 return;
00153 }
00154
00155 if (WindingIsHuge(w))
00156 {
00157 Log_Print("HL_SplitBrush: WARNING huge split winding\n");
00158 }
00159
00160 midwinding = w;
00161
00162
00163
00164 for (i = 0; i < 2; i++)
00165 {
00166 b[i] = AllocBrush (brush->numsides+1);
00167 b[i]->original = brush->original;
00168 }
00169
00170
00171
00172 for (i=0 ; i<brush->numsides ; i++)
00173 {
00174 s = &brush->sides[i];
00175 w = s->winding;
00176 if (!w)
00177 continue;
00178 ClipWindingEpsilon (w, plane->normal, plane->dist,
00179 0 , &cw[0], &cw[1]);
00180 for (j=0 ; j<2 ; j++)
00181 {
00182 if (!cw[j])
00183 continue;
00184 #if 0
00185 if (WindingIsTiny (cw[j]))
00186 {
00187 FreeWinding (cw[j]);
00188 continue;
00189 }
00190 #endif
00191 cs = &b[j]->sides[b[j]->numsides];
00192 b[j]->numsides++;
00193 *cs = *s;
00194
00195
00196
00197
00198 cs->winding = cw[j];
00199 cs->flags &= ~SFL_TESTED;
00200 }
00201 }
00202
00203
00204
00205
00206 for (i=0 ; i<2 ; i++)
00207 {
00208 BoundBrush (b[i]);
00209 for (j=0 ; j<3 ; j++)
00210 {
00211 if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
00212 {
00213 Log_Print("HL_SplitBrush: bogus brush after clip\n");
00214 break;
00215 }
00216 }
00217
00218 if (b[i]->numsides < 3 || j < 3)
00219 {
00220 FreeBrush (b[i]);
00221 b[i] = NULL;
00222 Log_Print("HL_SplitBrush: numsides < 3\n");
00223 }
00224 }
00225
00226 if ( !(b[0] && b[1]) )
00227 {
00228 if (!b[0] && !b[1])
00229 Log_Print("HL_SplitBrush: split removed brush\n");
00230 else
00231 Log_Print("HL_SplitBrush: split not on both sides\n");
00232 if (b[0])
00233 {
00234 FreeBrush (b[0]);
00235 *front = CopyBrush (brush);
00236 }
00237 if (b[1])
00238 {
00239 FreeBrush (b[1]);
00240 *back = CopyBrush (brush);
00241 }
00242 return;
00243 }
00244
00245
00246 for (i = 0; i < 2; i++)
00247 {
00248 cs = &b[i]->sides[b[i]->numsides];
00249 b[i]->numsides++;
00250
00251 cs->planenum = planenum^i^1;
00252 cs->texinfo = 0;
00253
00254 cs->surf = nodenum;
00255
00256 cs->flags &= ~SFL_VISIBLE;
00257 cs->flags &= ~SFL_TESTED;
00258 if (i==0)
00259 cs->winding = CopyWinding (midwinding);
00260 else
00261 cs->winding = midwinding;
00262 }
00263
00264
00265 {
00266 vec_t v1;
00267 int i;
00268
00269 for (i=0 ; i<2 ; i++)
00270 {
00271 v1 = BrushVolume (b[i]);
00272 if (v1 < 1)
00273 {
00274 FreeBrush (b[i]);
00275 b[i] = NULL;
00276 Log_Print("HL_SplitBrush: tiny volume after clip\n");
00277 }
00278 }
00279 }
00280
00281 *front = b[0];
00282 *back = b[1];
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 int HL_SolidTree_r(int nodenum)
00292 {
00293 if (nodenum < 0)
00294 {
00295 switch(hl_dleafs[(-nodenum) - 1].contents)
00296 {
00297 case HL_CONTENTS_EMPTY:
00298 {
00299 return false;
00300 }
00301 case HL_CONTENTS_SOLID:
00302 #ifdef HLCONTENTS
00303 case HL_CONTENTS_CLIP:
00304 #endif //HLCONTENTS
00305 case HL_CONTENTS_SKY:
00306 #ifdef HLCONTENTS
00307 case HL_CONTENTS_TRANSLUCENT:
00308 #endif //HLCONTENTS
00309 {
00310 return true;
00311 }
00312 case HL_CONTENTS_WATER:
00313 case HL_CONTENTS_SLIME:
00314 case HL_CONTENTS_LAVA:
00315 #ifdef HLCONTENTS
00316
00317 case HL_CONTENTS_ORIGIN:
00318 case HL_CONTENTS_CURRENT_0:
00319 case HL_CONTENTS_CURRENT_90:
00320 case HL_CONTENTS_CURRENT_180:
00321 case HL_CONTENTS_CURRENT_270:
00322 case HL_CONTENTS_CURRENT_UP:
00323 case HL_CONTENTS_CURRENT_DOWN:
00324 #endif //HLCONTENTS
00325 default:
00326 {
00327 return false;
00328 }
00329 }
00330 return false;
00331 }
00332 if (!HL_SolidTree_r(hl_dnodes[nodenum].children[0])) return false;
00333 if (!HL_SolidTree_r(hl_dnodes[nodenum].children[1])) return false;
00334 return true;
00335 }
00336
00337
00338
00339
00340
00341
00342 bspbrush_t *HL_CreateBrushes_r(bspbrush_t *brush, int nodenum)
00343 {
00344 int planenum;
00345 bspbrush_t *front, *back;
00346 hl_dleaf_t *leaf;
00347
00348
00349 if (nodenum < 0)
00350 {
00351 leaf = &hl_dleafs[(-nodenum) - 1];
00352 if (leaf->contents != HL_CONTENTS_EMPTY)
00353 {
00354 #ifdef HL_PRINT
00355 qprintf("\r%5i", ++hl_numbrushes);
00356 #endif //HL_PRINT
00357 }
00358 switch(leaf->contents)
00359 {
00360 case HL_CONTENTS_EMPTY:
00361 {
00362 FreeBrush(brush);
00363 return NULL;
00364 }
00365 case HL_CONTENTS_SOLID:
00366 #ifdef HLCONTENTS
00367 case HL_CONTENTS_CLIP:
00368 #endif //HLCONTENTS
00369 case HL_CONTENTS_SKY:
00370 #ifdef HLCONTENTS
00371 case HL_CONTENTS_TRANSLUCENT:
00372 #endif //HLCONTENTS
00373 {
00374 brush->side = CONTENTS_SOLID;
00375 return brush;
00376 }
00377 case HL_CONTENTS_WATER:
00378 {
00379 brush->side = CONTENTS_WATER;
00380 return brush;
00381 }
00382 case HL_CONTENTS_SLIME:
00383 {
00384 brush->side = CONTENTS_SLIME;
00385 return brush;
00386 }
00387 case HL_CONTENTS_LAVA:
00388 {
00389 brush->side = CONTENTS_LAVA;
00390 return brush;
00391 }
00392 #ifdef HLCONTENTS
00393
00394 case HL_CONTENTS_ORIGIN:
00395 case HL_CONTENTS_CURRENT_0:
00396 case HL_CONTENTS_CURRENT_90:
00397 case HL_CONTENTS_CURRENT_180:
00398 case HL_CONTENTS_CURRENT_270:
00399 case HL_CONTENTS_CURRENT_UP:
00400 case HL_CONTENTS_CURRENT_DOWN:
00401 {
00402 Error("HL_CreateBrushes_r: found contents %d in Half-Life BSP", leaf->contents);
00403 return NULL;
00404 }
00405 #endif //HLCONTENTS
00406 default:
00407 {
00408 Error("HL_CreateBrushes_r: unknown contents %d in Half-Life BSP", leaf->contents);
00409 return NULL;
00410 }
00411 }
00412 return NULL;
00413 }
00414
00415
00416
00417
00418
00419
00420
00421 planenum = hl_dnodes[nodenum].planenum;
00422 planenum = FindFloatPlane(hl_dplanes[planenum].normal, hl_dplanes[planenum].dist);
00423
00424 HL_SplitBrush(brush, planenum, nodenum, &front, &back);
00425
00426 FreeBrush(brush);
00427
00428 if (!front || !back)
00429 {
00430 Log_Print("HL_CreateBrushes_r: WARNING node not splitting brush\n");
00431
00432 }
00433
00434 if (front) front = HL_CreateBrushes_r(front, hl_dnodes[nodenum].children[0]);
00435 if (back) back = HL_CreateBrushes_r(back, hl_dnodes[nodenum].children[1]);
00436
00437 if (front)
00438 {
00439 for (brush = front; brush->next; brush = brush->next);
00440 brush->next = back;
00441 return front;
00442 }
00443 else
00444 {
00445 return back;
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454 bspbrush_t *HL_CreateBrushesFromBSP(int modelnum)
00455 {
00456 bspbrush_t *brushlist;
00457 bspbrush_t *brush;
00458 hl_dnode_t *headnode;
00459 vec3_t mins, maxs;
00460 int i;
00461
00462
00463 headnode = &hl_dnodes[hl_dmodels[modelnum].headnode[0]];
00464
00465 VectorCopy(headnode->mins, mins);
00466 VectorCopy(headnode->maxs, maxs);
00467
00468 for (i = 0; i < 3; i++)
00469 {
00470 mins[i] -= 8;
00471 maxs[i] += 8;
00472 }
00473
00474 AddPointToBounds(mins, map_mins, map_maxs);
00475 AddPointToBounds(maxs, map_mins, map_maxs);
00476
00477 if (!modelnum)
00478 {
00479 Log_Print("brush size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n",
00480 map_mins[0], map_mins[1], map_mins[2],
00481 map_maxs[0], map_maxs[1], map_maxs[2]);
00482 }
00483
00484 brush = BrushFromBounds(mins, maxs);
00485 VectorCopy(mins, brush->mins);
00486 VectorCopy(maxs, brush->maxs);
00487
00488 #ifdef HL_PRINT
00489 qprintf("creating Half-Life brushes\n");
00490 qprintf("%5d brushes", hl_numbrushes = 0);
00491 #endif //HL_PRINT
00492
00493 brushlist = HL_CreateBrushes_r(brush, hl_dmodels[modelnum].headnode[0]);
00494
00495 #ifdef HL_PRINT
00496 qprintf("\n");
00497 #endif //HL_PRINT
00498
00499 return brushlist;
00500 }
00501
00502
00503
00504
00505
00506
00507 bspbrush_t *HL_MergeBrushes(bspbrush_t *brushlist, int modelnum)
00508 {
00509 int nummerges, merged;
00510 bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
00511 bspbrush_t *lastb2;
00512
00513 if (!brushlist) return NULL;
00514
00515 if (!modelnum) qprintf("%5d brushes merged", nummerges = 0);
00516 do
00517 {
00518 for (tail = brushlist; tail; tail = tail->next)
00519 {
00520 if (!tail->next) break;
00521 }
00522 merged = 0;
00523 newbrushlist = NULL;
00524 for (b1 = brushlist; b1; b1 = brushlist)
00525 {
00526 lastb2 = b1;
00527 for (b2 = b1->next; b2; b2 = b2->next)
00528 {
00529
00530 if (b1->side != b2->side) newbrush = NULL;
00531 else newbrush = TryMergeBrushes(b1, b2);
00532
00533 if (newbrush)
00534 {
00535
00536 newbrush->side = b1->side;
00537
00538 tail->next = newbrush;
00539
00540 lastb2->next = b2->next;
00541
00542 brushlist = brushlist->next;
00543
00544 FreeBrush(b1);
00545 FreeBrush(b2);
00546
00547 for (tail = brushlist; tail; tail = tail->next)
00548 {
00549 if (!tail->next) break;
00550 }
00551 merged++;
00552 if (!modelnum) qprintf("\r%5d", nummerges++);
00553 break;
00554 }
00555 lastb2 = b2;
00556 }
00557
00558 if (!b2)
00559 {
00560 brushlist = brushlist->next;
00561
00562 b1->next = newbrushlist;
00563 newbrushlist = b1;
00564 }
00565 }
00566 brushlist = newbrushlist;
00567 } while(merged);
00568 if (!modelnum) qprintf("\n");
00569 return newbrushlist;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578 float HL_FaceOnWinding(hl_dface_t *face, winding_t *winding)
00579 {
00580 int i, edgenum, side;
00581 float dist, area;
00582 hl_dplane_t plane;
00583 vec_t *v1, *v2;
00584 vec3_t normal, edgevec;
00585 winding_t *w;
00586
00587
00588 w = CopyWinding(winding);
00589 memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
00590
00591 if (face->side)
00592 {
00593 VectorNegate(plane.normal, plane.normal);
00594 plane.dist = -plane.dist;
00595 }
00596 for (i = 0; i < face->numedges && w; i++)
00597 {
00598
00599 edgenum = hl_dsurfedges[face->firstedge + i];
00600 side = edgenum > 0;
00601
00602 v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
00603 v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
00604
00605
00606 VectorSubtract(v1, v2, edgevec);
00607 CrossProduct(edgevec, plane.normal, normal);
00608 VectorNormalize(normal);
00609 dist = DotProduct(normal, v1);
00610
00611 ChopWindingInPlace(&w, normal, dist, 0.9);
00612 }
00613 if (w)
00614 {
00615 area = WindingArea(w);
00616 FreeWinding(w);
00617 return area;
00618 }
00619 return 0;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629 bspbrush_t *HL_SplitBrushWithFace(bspbrush_t *brush, hl_dface_t *face)
00630 {
00631 int i, edgenum, side, planenum, splits;
00632 float dist;
00633 hl_dplane_t plane;
00634 vec_t *v1, *v2;
00635 vec3_t normal, edgevec;
00636 bspbrush_t *front, *back, *brushlist;
00637
00638 memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
00639
00640 if (face->side)
00641 {
00642 VectorNegate(plane.normal, plane.normal);
00643 plane.dist = -plane.dist;
00644 }
00645 splits = 0;
00646 brushlist = NULL;
00647 for (i = 0; i < face->numedges; i++)
00648 {
00649
00650 edgenum = hl_dsurfedges[face->firstedge + i];
00651 side = edgenum > 0;
00652
00653 v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
00654 v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
00655
00656
00657 VectorSubtract(v1, v2, edgevec);
00658 CrossProduct(edgevec, plane.normal, normal);
00659 VectorNormalize(normal);
00660 dist = DotProduct(normal, v1);
00661
00662 planenum = FindFloatPlane(normal, dist);
00663
00664 SplitBrush(brush, planenum, &front, &back);
00665
00666 if (back)
00667 {
00668
00669 back->side = brush->side;
00670
00671 back->next = brushlist;
00672 brushlist = back;
00673 splits++;
00674 }
00675 if (!front)
00676 {
00677 Log_Print("HL_SplitBrushWithFace: no new brush\n");
00678 FreeBrushList(brushlist);
00679 return NULL;
00680 }
00681
00682 front->side = brush->side;
00683
00684 brush = front;
00685 }
00686 if (!splits)
00687 {
00688 FreeBrush(front);
00689 return NULL;
00690 }
00691 front->next = brushlist;
00692 brushlist = front;
00693 return brushlist;
00694 }
00695
00696
00697
00698
00699
00700
00701 bspbrush_t *HL_TextureBrushes(bspbrush_t *brushlist, int modelnum)
00702 {
00703 float area, largestarea;
00704 int i, n, texinfonum, sn, numbrushes, ofs;
00705 int bestfacenum, sidenodenum;
00706 side_t *side;
00707 hl_dmiptexlump_t *miptexlump;
00708 hl_miptex_t *miptex;
00709 bspbrush_t *brush, *nextbrush, *prevbrush, *newbrushes, *brushlistend;
00710 vec_t defaultvec[4] = {1, 0, 0, 0};
00711
00712 if (!modelnum) qprintf("texturing brushes\n");
00713 if (!modelnum) qprintf("%5d brushes", numbrushes = 0);
00714
00715 for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
00716 {
00717 if (!brushlistend->next) break;
00718 }
00719
00720 prevbrush = NULL;
00721
00722 for (brush = brushlist; brush; brush = nextbrush)
00723 {
00724 nextbrush = brush->next;
00725
00726 for (sn = 0; sn < brush->numsides; sn++)
00727 {
00728 side = &brush->sides[sn];
00729
00730 if (side->flags & SFL_TEXTURED) continue;
00731
00732 sidenodenum = side->surf;
00733
00734 bestfacenum = -1;
00735
00736 largestarea = 1;
00737
00738
00739 if (!lessbrushes)
00740 {
00741 for (i = 0; i < hl_numfaces; i++)
00742 {
00743
00744
00745 if (hl_dfaces[i].planenum == hl_dnodes[sidenodenum].planenum)
00746 {
00747
00748 area = HL_FaceOnWinding(&hl_dfaces[i], side->winding);
00749
00750 if (area > largestarea)
00751 {
00752
00753
00754 if (bestfacenum >= 0 &&
00755 (hl_dfaces[bestfacenum].texinfo != hl_dfaces[i].texinfo))
00756 {
00757
00758 newbrushes = HL_SplitBrushWithFace(brush, &hl_dfaces[i]);
00759
00760 if (newbrushes)
00761 {
00762
00763 if (prevbrush) prevbrush->next = brush->next;
00764 else brushlist = brush->next;
00765 if (brushlistend == brush)
00766 {
00767 brushlistend = prevbrush;
00768 nextbrush = newbrushes;
00769 }
00770
00771 if (brushlistend) brushlistend->next = newbrushes;
00772 else brushlist = newbrushes;
00773
00774 FreeBrush(brush);
00775
00776
00777 brush = prevbrush;
00778
00779 for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
00780 {
00781 if (!brushlistend->next) break;
00782 }
00783 break;
00784 }
00785 else
00786 {
00787 Log_Write("brush %d: no real texture split", numbrushes);
00788 }
00789 }
00790 else
00791 {
00792
00793 bestfacenum = i;
00794 }
00795 }
00796 }
00797 }
00798
00799
00800 if (i < hl_numfaces) break;
00801 }
00802 else
00803 {
00804
00805
00806 for (i = 0; i < hl_numfaces; i++)
00807 {
00808
00809
00810 if (hl_dfaces[i].planenum == hl_dnodes[sidenodenum].planenum)
00811 {
00812
00813 area = HL_FaceOnWinding(&hl_dfaces[i], side->winding);
00814
00815 if (area > largestarea)
00816 {
00817 largestarea = area;
00818 bestfacenum = i;
00819 }
00820 }
00821 }
00822 }
00823
00824 if (bestfacenum >= 0)
00825 {
00826
00827 texinfonum = hl_dfaces[bestfacenum].texinfo;
00828 for (n = 0; n < 4; n++)
00829 {
00830 map_texinfo[texinfonum].vecs[0][n] = hl_texinfo[texinfonum].vecs[0][n];
00831 map_texinfo[texinfonum].vecs[1][n] = hl_texinfo[texinfonum].vecs[1][n];
00832 }
00833
00834
00835 if (VectorLength(map_texinfo[texinfonum].vecs[0]) < 0.01)
00836 memcpy(map_texinfo[texinfonum].vecs[0], defaultvec, sizeof(defaultvec));
00837 if (VectorLength(map_texinfo[texinfonum].vecs[1]) < 0.01)
00838 memcpy(map_texinfo[texinfonum].vecs[1], defaultvec, sizeof(defaultvec));
00839
00840 map_texinfo[texinfonum].flags = hl_texinfo[texinfonum].flags;
00841 map_texinfo[texinfonum].value = 0;
00842
00843 miptexlump = (hl_dmiptexlump_t *) hl_dtexdata;
00844 ofs = miptexlump->dataofs[hl_texinfo[texinfonum].miptex];
00845 if ( ofs > hl_texdatasize ) {
00846 ofs = miptexlump->dataofs[0];
00847 }
00848 miptex = (hl_miptex_t *)((byte *)miptexlump + ofs );
00849
00850 strcpy(map_texinfo[texinfonum].texture, miptex->name);
00851
00852 map_texinfo[texinfonum].nexttexinfo = -1;
00853
00854 side->texinfo = texinfonum;
00855
00856 if (texinfonum > map_numtexinfo) map_numtexinfo = texinfonum;
00857
00858 side->flags |= SFL_TEXTURED;
00859 }
00860 else
00861 {
00862
00863 side->texinfo = TEXINFO_NODE;
00864
00865 side->flags |= SFL_TEXTURED;
00866 }
00867 }
00868
00869 if (!modelnum && prevbrush != brush) qprintf("\r%5d", ++numbrushes);
00870
00871 prevbrush = brush;
00872 }
00873 if (!modelnum) qprintf("\n");
00874
00875 return brushlist;
00876 }
00877
00878
00879
00880
00881
00882
00883 void HL_FixContentsTextures(bspbrush_t *brushlist)
00884 {
00885 int i, texinfonum;
00886 bspbrush_t *brush;
00887
00888 for (brush = brushlist; brush; brush = brush->next)
00889 {
00890
00891 if (brush->side != CONTENTS_WATER &&
00892 brush->side != CONTENTS_SLIME &&
00893 brush->side != CONTENTS_LAVA) continue;
00894
00895 for (i = 0; i < brush->numsides; i++)
00896 {
00897 texinfonum = brush->sides[i].texinfo;
00898 if (HL_TextureContents(map_texinfo[texinfonum].texture) == brush->side) break;
00899 }
00900
00901 if (i >= brush->numsides)
00902 {
00903 texinfonum = -1;
00904 for (i = 0; i < map_numtexinfo; i++)
00905 {
00906 if (HL_TextureContents(map_texinfo[i].texture) == brush->side)
00907 {
00908 texinfonum = i;
00909 break;
00910 }
00911 }
00912 }
00913
00914 if (texinfonum >= 0)
00915 {
00916
00917 for (i = 0; i < brush->numsides; i++)
00918 {
00919 brush->sides[i].texinfo = texinfonum;
00920 }
00921 }
00922 else Log_Print("brush contents %d with wrong textures\n", brush->side);
00923
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 }
00939
00940
00941
00942
00943
00944
00945 void HL_BSPBrushToMapBrush(bspbrush_t *bspbrush, entity_t *mapent)
00946 {
00947 mapbrush_t *mapbrush;
00948 side_t *side;
00949 int i, besttexinfo;
00950
00951 if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00952 Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");
00953
00954 mapbrush = &mapbrushes[nummapbrushes];
00955 mapbrush->original_sides = &brushsides[nummapbrushsides];
00956 mapbrush->entitynum = mapent - entities;
00957 mapbrush->brushnum = nummapbrushes - mapent->firstbrush;
00958 mapbrush->leafnum = -1;
00959 mapbrush->numsides = 0;
00960
00961 besttexinfo = TEXINFO_NODE;
00962 for (i = 0; i < bspbrush->numsides; i++)
00963 {
00964 if (!bspbrush->sides[i].winding) continue;
00965
00966 if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00967 Error ("MAX_MAPFILE_BRUSHSIDES");
00968 side = &brushsides[nummapbrushsides];
00969
00970 side->contents = bspbrush->side;
00971 side->surf = 0;
00972 side->planenum = bspbrush->sides[i].planenum;
00973 side->texinfo = bspbrush->sides[i].texinfo;
00974 if (side->texinfo != TEXINFO_NODE)
00975 {
00976
00977 side->flags |= SFL_TEXTURED;
00978 besttexinfo = side->texinfo;
00979 }
00980
00981 nummapbrushsides++;
00982 mapbrush->numsides++;
00983 }
00984
00985 if (besttexinfo == TEXINFO_NODE)
00986 {
00987 mapbrush->numsides = 0;
00988 hl_numclipbrushes++;
00989 return;
00990 }
00991
00992 for (i = 0; i < mapbrush->numsides; i++)
00993 {
00994 if (mapbrush->original_sides[i].texinfo == TEXINFO_NODE)
00995 {
00996 mapbrush->original_sides[i].texinfo = besttexinfo;
00997 }
00998 }
00999
01000 mapbrush->contents = bspbrush->side;
01001
01002 if (create_aas)
01003 {
01004
01005 AAS_CreateMapBrushes(mapbrush, mapent, true);
01006 return;
01007 }
01008
01009 MakeBrushWindings(mapbrush);
01010
01011 AddBrushBevels(mapbrush);
01012
01013 nummapbrushes++;
01014 mapent->numbrushes++;
01015 }
01016
01017
01018
01019
01020
01021
01022 void HL_CreateMapBrushes(entity_t *mapent, int modelnum)
01023 {
01024 bspbrush_t *brushlist, *brush, *nextbrush;
01025 int i;
01026
01027
01028 brushlist = HL_CreateBrushesFromBSP(modelnum);
01029
01030 brushlist = HL_TextureBrushes(brushlist, modelnum);
01031
01032 HL_FixContentsTextures(brushlist);
01033
01034 if (!nobrushmerge)
01035 {
01036 brushlist = HL_MergeBrushes(brushlist, modelnum);
01037
01038 }
01039
01040 if (!modelnum) qprintf("converting brushes to map brushes\n");
01041 if (!modelnum) qprintf("%5d brushes", i = 0);
01042 for (brush = brushlist; brush; brush = nextbrush)
01043 {
01044 nextbrush = brush->next;
01045 HL_BSPBrushToMapBrush(brush, mapent);
01046 brush->next = NULL;
01047 FreeBrush(brush);
01048 if (!modelnum) qprintf("\r%5d", ++i);
01049 }
01050 if (!modelnum) qprintf("\n");
01051 }
01052
01053
01054
01055
01056
01057
01058 void HL_ResetMapLoading(void)
01059 {
01060 }
01061
01062
01063
01064
01065
01066
01067 void HL_LoadMapFromBSP(char *filename, int offset, int length)
01068 {
01069 int i, modelnum;
01070 char *model, *classname;
01071
01072 Log_Print("-- HL_LoadMapFromBSP --\n");
01073
01074 loadedmaptype = MAPTYPE_HALFLIFE;
01075
01076 qprintf("loading map from %s at %d\n", filename, offset);
01077
01078 HL_LoadBSPFile(filename, offset, length);
01079
01080 hl_numclipbrushes = 0;
01081
01082 HL_ParseEntities();
01083
01084 ClearBounds(map_mins, map_maxs);
01085
01086 qprintf("creating Half-Life brushes\n");
01087 if (lessbrushes) qprintf("creating minimum number of brushes\n");
01088 else qprintf("placing textures correctly\n");
01089
01090 for (i = 0; i < num_entities; i++)
01091 {
01092 entities[i].firstbrush = nummapbrushes;
01093 entities[i].numbrushes = 0;
01094
01095 classname = ValueForKey(&entities[i], "classname");
01096 if (classname && !strcmp(classname, "worldspawn"))
01097 {
01098 modelnum = 0;
01099 }
01100 else
01101 {
01102
01103 model = ValueForKey(&entities[i], "model");
01104 if (!model || *model != '*') continue;
01105 model++;
01106 modelnum = atoi(model);
01107 }
01108
01109 HL_CreateMapBrushes(&entities[i], modelnum);
01110 }
01111
01112 qprintf("%5d map brushes\n", nummapbrushes);
01113 qprintf("%5d clip brushes\n", hl_numclipbrushes);
01114 }