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