📄 map_hl.c
字号:
{
brush->side = CONTENTS_SOLID;
return brush;
} //end case
case HL_CONTENTS_WATER:
{
brush->side = CONTENTS_WATER;
return brush;
} //end case
case HL_CONTENTS_SLIME:
{
brush->side = CONTENTS_SLIME;
return brush;
} //end case
case HL_CONTENTS_LAVA:
{
brush->side = CONTENTS_LAVA;
return brush;
} //end case
#ifdef HLCONTENTS
//these contents should not be found in the BSP
case HL_CONTENTS_ORIGIN:
case HL_CONTENTS_CURRENT_0:
case HL_CONTENTS_CURRENT_90:
case HL_CONTENTS_CURRENT_180:
case HL_CONTENTS_CURRENT_270:
case HL_CONTENTS_CURRENT_UP:
case HL_CONTENTS_CURRENT_DOWN:
{
Error("HL_CreateBrushes_r: found contents %d in Half-Life BSP", leaf->contents);
return NULL;
} //end case
#endif //HLCONTENTS
default:
{
Error("HL_CreateBrushes_r: unknown contents %d in Half-Life BSP", leaf->contents);
return NULL;
} //end default
} //end switch
return NULL;
} //end if
//if the rest of the tree is solid
/*if (HL_SolidTree_r(nodenum))
{
brush->side = CONTENTS_SOLID;
return brush;
} //end if*/
//
planenum = hl_dnodes[nodenum].planenum;
planenum = FindFloatPlane(hl_dplanes[planenum].normal, hl_dplanes[planenum].dist);
//split the brush with the node plane
HL_SplitBrush(brush, planenum, nodenum, &front, &back);
//free the original brush
FreeBrush(brush);
//every node must split the brush in two
if (!front || !back)
{
Log_Print("HL_CreateBrushes_r: WARNING node not splitting brush\n");
//return NULL;
} //end if
//create brushes recursively
if (front) front = HL_CreateBrushes_r(front, hl_dnodes[nodenum].children[0]);
if (back) back = HL_CreateBrushes_r(back, hl_dnodes[nodenum].children[1]);
//link the brushes if possible and return them
if (front)
{
for (brush = front; brush->next; brush = brush->next);
brush->next = back;
return front;
} //end if
else
{
return back;
} //end else
} //end of the function HL_CreateBrushes_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bspbrush_t *HL_CreateBrushesFromBSP(int modelnum)
{
bspbrush_t *brushlist;
bspbrush_t *brush;
hl_dnode_t *headnode;
vec3_t mins, maxs;
int i;
//
headnode = &hl_dnodes[hl_dmodels[modelnum].headnode[0]];
//get the mins and maxs of the world
VectorCopy(headnode->mins, mins);
VectorCopy(headnode->maxs, maxs);
//enlarge these mins and maxs
for (i = 0; i < 3; i++)
{
mins[i] -= 8;
maxs[i] += 8;
} //end for
//NOTE: have to add the BSP tree mins and maxs to the MAP mins and maxs
AddPointToBounds(mins, map_mins, map_maxs);
AddPointToBounds(maxs, map_mins, map_maxs);
//
if (!modelnum)
{
Log_Print("brush size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n",
map_mins[0], map_mins[1], map_mins[2],
map_maxs[0], map_maxs[1], map_maxs[2]);
} //end if
//create one huge brush containing the whole world
brush = BrushFromBounds(mins, maxs);
VectorCopy(mins, brush->mins);
VectorCopy(maxs, brush->maxs);
//
#ifdef HL_PRINT
qprintf("creating Half-Life brushes\n");
qprintf("%5d brushes", hl_numbrushes = 0);
#endif //HL_PRINT
//create the brushes
brushlist = HL_CreateBrushes_r(brush, hl_dmodels[modelnum].headnode[0]);
//
#ifdef HL_PRINT
qprintf("\n");
#endif //HL_PRINT
//now we've got a list with brushes!
return brushlist;
} //end of the function HL_CreateBrushesFromBSP
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bspbrush_t *HL_MergeBrushes(bspbrush_t *brushlist, int modelnum)
{
int nummerges, merged;
bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
bspbrush_t *lastb2;
if (!brushlist) return NULL;
if (!modelnum) qprintf("%5d brushes merged", nummerges = 0);
do
{
for (tail = brushlist; tail; tail = tail->next)
{
if (!tail->next) break;
} //end for
merged = 0;
newbrushlist = NULL;
for (b1 = brushlist; b1; b1 = brushlist)
{
lastb2 = b1;
for (b2 = b1->next; b2; b2 = b2->next)
{
//can't merge brushes with different contents
if (b1->side != b2->side) newbrush = NULL;
else newbrush = TryMergeBrushes(b1, b2);
//if a merged brush is created
if (newbrush)
{
//copy the brush contents
newbrush->side = b1->side;
//add the new brush to the end of the list
tail->next = newbrush;
//remove the second brush from the list
lastb2->next = b2->next;
//remove the first brush from the list
brushlist = brushlist->next;
//free the merged brushes
FreeBrush(b1);
FreeBrush(b2);
//get a new tail brush
for (tail = brushlist; tail; tail = tail->next)
{
if (!tail->next) break;
} //end for
merged++;
if (!modelnum) qprintf("\r%5d", nummerges++);
break;
} //end if
lastb2 = b2;
} //end for
//if b1 can't be merged with any of the other brushes
if (!b2)
{
brushlist = brushlist->next;
//keep b1
b1->next = newbrushlist;
newbrushlist = b1;
} //end else
} //end for
brushlist = newbrushlist;
} while(merged);
if (!modelnum) qprintf("\n");
return newbrushlist;
} //end of the function HL_MergeBrushes
//===========================================================================
// returns the amount the face and the winding have overlap
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float HL_FaceOnWinding(hl_dface_t *face, winding_t *winding)
{
int i, edgenum, side;
float dist, area;
hl_dplane_t plane;
vec_t *v1, *v2;
vec3_t normal, edgevec;
winding_t *w;
//
w = CopyWinding(winding);
memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
//check on which side of the plane the face is
if (face->side)
{
VectorNegate(plane.normal, plane.normal);
plane.dist = -plane.dist;
} //end if
for (i = 0; i < face->numedges && w; i++)
{
//get the first and second vertex of the edge
edgenum = hl_dsurfedges[face->firstedge + i];
side = edgenum > 0;
//if the face plane is flipped
v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
//create a plane through the edge vector, orthogonal to the face plane
//and with the normal vector pointing out of the face
VectorSubtract(v1, v2, edgevec);
CrossProduct(edgevec, plane.normal, normal);
VectorNormalize(normal);
dist = DotProduct(normal, v1);
//
ChopWindingInPlace(&w, normal, dist, 0.9); //CLIP_EPSILON
} //end for
if (w)
{
area = WindingArea(w);
FreeWinding(w);
return area;
} //end if
return 0;
} //end of the function HL_FaceOnWinding
//===========================================================================
// returns a list with brushes created by splitting the given brush with
// planes that go through the face edges and are orthogonal to the face plane
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bspbrush_t *HL_SplitBrushWithFace(bspbrush_t *brush, hl_dface_t *face)
{
int i, edgenum, side, planenum, splits;
float dist;
hl_dplane_t plane;
vec_t *v1, *v2;
vec3_t normal, edgevec;
bspbrush_t *front, *back, *brushlist;
memcpy(&plane, &hl_dplanes[face->planenum], sizeof(hl_dplane_t));
//check on which side of the plane the face is
if (face->side)
{
VectorNegate(plane.normal, plane.normal);
plane.dist = -plane.dist;
} //end if
splits = 0;
brushlist = NULL;
for (i = 0; i < face->numedges; i++)
{
//get the first and second vertex of the edge
edgenum = hl_dsurfedges[face->firstedge + i];
side = edgenum > 0;
//if the face plane is flipped
v1 = hl_dvertexes[hl_dedges[abs(edgenum)].v[side]].point;
v2 = hl_dvertexes[hl_dedges[abs(edgenum)].v[!side]].point;
//create a plane through the edge vector, orthogonal to the face plane
//and with the normal vector pointing out of the face
VectorSubtract(v1, v2, edgevec);
CrossProduct(edgevec, plane.normal, normal);
VectorNormalize(normal);
dist = DotProduct(normal, v1);
//
planenum = FindFloatPlane(normal, dist);
//split the current brush
SplitBrush(brush, planenum, &front, &back);
//if there is a back brush just put it in the list
if (back)
{
//copy the brush contents
back->side = brush->side;
//
back->next = brushlist;
brushlist = back;
splits++;
} //end if
if (!front)
{
Log_Print("HL_SplitBrushWithFace: no new brush\n");
FreeBrushList(brushlist);
return NULL;
} //end if
//copy the brush contents
front->side = brush->side;
//continue splitting the front brush
brush = front;
} //end for
if (!splits)
{
FreeBrush(front);
return NULL;
} //end if
front->next = brushlist;
brushlist = front;
return brushlist;
} //end of the function HL_SplitBrushWithFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bspbrush_t *HL_TextureBrushes(bspbrush_t *brushlist, int modelnum)
{
float area, largestarea;
int i, n, texinfonum, sn, numbrushes, ofs;
int bestfacenum, sidenodenum;
side_t *side;
hl_dmiptexlump_t *miptexlump;
hl_miptex_t *miptex;
bspbrush_t *brush, *nextbrush, *prevbrush, *newbrushes, *brushlistend;
vec_t defaultvec[4] = {1, 0, 0, 0};
if (!modelnum) qprintf("texturing brushes\n");
if (!modelnum) qprintf("%5d brushes", numbrushes = 0);
//get a pointer to the last brush in the list
for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
{
if (!brushlistend->next) break;
} //end for
//there's no previous brush when at the start of the list
prevbrush = NULL;
//go over the brush list
for (brush = brushlist; brush; brush = nextbrush)
{
nextbrush = brush->next;
//find a texinfo for every brush side
for (sn = 0; sn < brush->numsides; sn++)
{
side = &brush->sides[sn];
//
if (side->flags & SFL_TEXTURED) continue;
//number of the node that created this brush side
sidenodenum = side->surf; //see midwinding in HL_SplitBrush
//no face found yet
bestfacenum = -1;
//minimum face size
largestarea = 1;
//if optimizing the texture placement and not going for the
//least number of brushes
if (!lessbrushes)
{
for (i = 0; i < hl_numfaces; i++)
{
//the face must be in the same plane as the node plane that created
//this brush side
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -