enough whitespace to crush a shambler

This commit is contained in:
Bill Currie 2002-09-19 17:14:23 +00:00
parent afa0b21336
commit 4d520d588d
13 changed files with 2351 additions and 2552 deletions

View file

@ -35,11 +35,13 @@
#include "bsp5.h" #include "bsp5.h"
int numbrushplanes; int numbrushplanes;
plane_t planes[MAX_MAP_PLANES]; plane_t planes[MAX_MAP_PLANES];
int numbrushfaces; int numbrushfaces;
mface_t faces[128]; // beveled clipping hull can generate many extra mface_t faces[128]; // beveled clipping hull can generate
// many extra
/* /*
@ -49,38 +51,39 @@ CheckFace
Note: this will not catch 0 area polygons Note: this will not catch 0 area polygons
================= =================
*/ */
void CheckFace (face_t *f) void
CheckFace (face_t * f)
{ {
int i, j; int i, j;
vec_t *p1, *p2; vec_t *p1, *p2;
vec_t d, edgedist; vec_t d, edgedist;
vec3_t dir, edgenormal, facenormal; vec3_t dir, edgenormal, facenormal;
if (f->numpoints < 3) if (f->numpoints < 3)
Sys_Error ("CheckFace: %i points",f->numpoints); Sys_Error ("CheckFace: %i points", f->numpoints);
VectorCopy (planes[f->planenum].normal, facenormal); VectorCopy (planes[f->planenum].normal, facenormal);
if (f->planeside) if (f->planeside) {
{
VectorSubtract (vec3_origin, facenormal, facenormal); VectorSubtract (vec3_origin, facenormal, facenormal);
} }
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++) {
{
p1 = f->pts[i]; p1 = f->pts[i];
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++)
if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
Sys_Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); Sys_Error ("CheckFace: BUGUS_RANGE: %f", p1[j]);
j = i+1 == f->numpoints ? 0 : i+1; j = i + 1 == f->numpoints ? 0 : i + 1;
// check the point is on the face plane // check the point is on the face plane
d = DotProduct (p1, planes[f->planenum].normal) - planes[f->planenum].dist; d =
DotProduct (p1,
planes[f->planenum].normal) - planes[f->planenum].dist;
if (d < -ON_EPSILON || d > ON_EPSILON) if (d < -ON_EPSILON || d > ON_EPSILON)
Sys_Error ("CheckFace: point off plane"); Sys_Error ("CheckFace: point off plane");
// check the edge isn't degenerate // check the edge isn't degenerate
p2 = f->pts[j]; p2 = f->pts[j];
VectorSubtract (p2, p1, dir); VectorSubtract (p2, p1, dir);
@ -92,9 +95,8 @@ void CheckFace (face_t *f)
edgedist = DotProduct (p1, edgenormal); edgedist = DotProduct (p1, edgenormal);
edgedist += ON_EPSILON; edgedist += ON_EPSILON;
// all other points must be on front side // all other points must be on front side
for (j=0 ; j<f->numpoints ; j++) for (j = 0; j < f->numpoints; j++) {
{
if (j == i) if (j == i)
continue; continue;
d = DotProduct (f->pts[j], edgenormal); d = DotProduct (f->pts[j], edgenormal);
@ -112,13 +114,13 @@ void CheckFace (face_t *f)
ClearBounds ClearBounds
================= =================
*/ */
void ClearBounds (brushset_t *bs) void
ClearBounds (brushset_t * bs)
{ {
int i, j; int i, j;
for (j=0 ; j<NUM_HULLS ; j++) for (j = 0; j < NUM_HULLS; j++)
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
bs->mins[i] = 99999; bs->mins[i] = 99999;
bs->maxs[i] = -99999; bs->maxs[i] = -99999;
} }
@ -129,12 +131,12 @@ void ClearBounds (brushset_t *bs)
AddToBounds AddToBounds
================= =================
*/ */
void AddToBounds (brushset_t *bs, vec3_t v) void
AddToBounds (brushset_t * bs, vec3_t v)
{ {
int i; int i;
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
if (v[i] < bs->mins[i]) if (v[i] < bs->mins[i])
bs->mins[i] = v[i]; bs->mins[i] = v[i];
if (v[i] > bs->maxs[i]) if (v[i] > bs->maxs[i])
@ -144,9 +146,10 @@ void AddToBounds (brushset_t *bs, vec3_t v)
//=========================================================================== //===========================================================================
int PlaneTypeForNormal (vec3_t normal) int
PlaneTypeForNormal (vec3_t normal)
{ {
float ax, ay, az; float ax, ay, az;
// NOTE: should these have an epsilon around 1.0? // NOTE: should these have an epsilon around 1.0?
if (normal[0] == 1.0) if (normal[0] == 1.0)
@ -155,14 +158,12 @@ int PlaneTypeForNormal (vec3_t normal)
return PLANE_Y; return PLANE_Y;
if (normal[2] == 1.0) if (normal[2] == 1.0)
return PLANE_Z; return PLANE_Z;
if (normal[0] == -1.0 || if (normal[0] == -1.0 || normal[1] == -1.0 || normal[2] == -1.0)
normal[1] == -1.0 ||
normal[2] == -1.0)
Sys_Error ("PlaneTypeForNormal: not a canonical vector"); Sys_Error ("PlaneTypeForNormal: not a canonical vector");
ax = fabs(normal[0]); ax = fabs (normal[0]);
ay = fabs(normal[1]); ay = fabs (normal[1]);
az = fabs(normal[2]); az = fabs (normal[2]);
if (ax >= ay && ax >= az) if (ax >= ay && ax >= az)
return PLANE_ANYX; return PLANE_ANYX;
@ -174,45 +175,40 @@ int PlaneTypeForNormal (vec3_t normal)
#define DISTEPSILON 0.01 #define DISTEPSILON 0.01
#define ANGLEEPSILON 0.00001 #define ANGLEEPSILON 0.00001
void NormalizePlane (plane_t *dp) void
NormalizePlane (plane_t *dp)
{ {
vec_t ax, ay, az; vec_t ax, ay, az;
if (dp->normal[0] == -1.0) if (dp->normal[0] == -1.0) {
{
dp->normal[0] = 1.0; dp->normal[0] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
} }
if (dp->normal[1] == -1.0) if (dp->normal[1] == -1.0) {
{
dp->normal[1] = 1.0; dp->normal[1] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
} }
if (dp->normal[2] == -1.0) if (dp->normal[2] == -1.0) {
{
dp->normal[2] = 1.0; dp->normal[2] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
} }
if (dp->normal[0] == 1.0) if (dp->normal[0] == 1.0) {
{
dp->type = PLANE_X; dp->type = PLANE_X;
return; return;
} }
if (dp->normal[1] == 1.0) if (dp->normal[1] == 1.0) {
{
dp->type = PLANE_Y; dp->type = PLANE_Y;
return; return;
} }
if (dp->normal[2] == 1.0) if (dp->normal[2] == 1.0) {
{
dp->type = PLANE_Z; dp->type = PLANE_Z;
return; return;
} }
ax = fabs(dp->normal[0]); ax = fabs (dp->normal[0]);
ay = fabs(dp->normal[1]); ay = fabs (dp->normal[1]);
az = fabs(dp->normal[2]); az = fabs (dp->normal[2]);
if (ax >= ay && ax >= az) if (ax >= ay && ax >= az)
dp->type = PLANE_ANYX; dp->type = PLANE_ANYX;
@ -220,8 +216,7 @@ void NormalizePlane (plane_t *dp)
dp->type = PLANE_ANYY; dp->type = PLANE_ANYY;
else else
dp->type = PLANE_ANYZ; dp->type = PLANE_ANYZ;
if (dp->normal[dp->type-PLANE_ANYX] < 0) if (dp->normal[dp->type - PLANE_ANYX] < 0) {
{
VectorSubtract (vec3_origin, dp->normal, dp->normal); VectorSubtract (vec3_origin, dp->normal, dp->normal);
dp->dist = -dp->dist; dp->dist = -dp->dist;
} }
@ -235,30 +230,29 @@ FindPlane
Returns a global plane number and the side that will be the front Returns a global plane number and the side that will be the front
=============== ===============
*/ */
int FindPlane (plane_t *dplane, int *side) int
FindPlane (plane_t *dplane, int *side)
{ {
int i; int i;
plane_t *dp, pl; plane_t *dp, pl;
vec_t dot; vec_t dot;
dot = VectorLength(dplane->normal); dot = VectorLength (dplane->normal);
if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON) if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON)
Sys_Error ("FindPlane: normalization error"); Sys_Error ("FindPlane: normalization error");
pl = *dplane; pl = *dplane;
NormalizePlane (&pl); NormalizePlane (&pl);
if (DotProduct(pl.normal, dplane->normal) > 0) if (DotProduct (pl.normal, dplane->normal) > 0)
*side = 0; *side = 0;
else else
*side = 1; *side = 1;
dp = planes; dp = planes;
for (i=0 ; i<numbrushplanes;i++, dp++) for (i = 0; i < numbrushplanes; i++, dp++) {
{
dot = DotProduct (dp->normal, pl.normal); dot = DotProduct (dp->normal, pl.normal);
if (dot > 1.0 - ANGLEEPSILON if (dot > 1.0 - ANGLEEPSILON && fabs (dp->dist - pl.dist) < DISTEPSILON) { // regular
&& fabs(dp->dist - pl.dist) < DISTEPSILON ) // match
{ // regular match
return i; return i;
} }
} }
@ -270,7 +264,7 @@ int FindPlane (plane_t *dplane, int *side)
numbrushplanes++; numbrushplanes++;
return numbrushplanes-1; return numbrushplanes - 1;
} }
@ -281,30 +275,29 @@ FindPlane_old
Returns a global plane number and the side that will be the front Returns a global plane number and the side that will be the front
=============== ===============
*/ */
int FindPlane_old (plane_t *dplane, int *side) int
FindPlane_old (plane_t *dplane, int *side)
{ {
int i; int i;
plane_t *dp; plane_t *dp;
vec_t dot, ax, ay, az; vec_t dot, ax, ay, az;
dot = VectorLength(dplane->normal); dot = VectorLength (dplane->normal);
if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON) if (dot < 1.0 - ANGLEEPSILON || dot > 1.0 + ANGLEEPSILON)
Sys_Error ("FindPlane: normalization error"); Sys_Error ("FindPlane: normalization error");
dp = planes; dp = planes;
for (i=0 ; i<numbrushplanes;i++, dp++) for (i = 0; i < numbrushplanes; i++, dp++) {
{
dot = DotProduct (dplane->normal, dp->normal); dot = DotProduct (dplane->normal, dp->normal);
if (dot > 1.0 - ANGLEEPSILON if (dot > 1.0 - ANGLEEPSILON && fabs (dplane->dist - dp->dist) < DISTEPSILON) { // regular
&& fabs(dplane->dist - dp->dist) < DISTEPSILON ) // match
{ // regular match
*side = 0; *side = 0;
return i; return i;
} }
if (dot < -1.0+ANGLEEPSILON if (dot < -1.0 + ANGLEEPSILON && fabs (dplane->dist + dp->dist) < DISTEPSILON) { // inverse
&& fabs(dplane->dist + dp->dist) < DISTEPSILON ) // of
{ // inverse of vector // vector
*side = 1; *side = 1;
return i; return i;
} }
@ -327,32 +320,25 @@ int FindPlane_old (plane_t *dplane, int *side)
dp->type = PLANE_Y; dp->type = PLANE_Y;
else if (dplane->normal[2] == 1.0) else if (dplane->normal[2] == 1.0)
dp->type = PLANE_Z; dp->type = PLANE_Z;
else if (dplane->normal[0] == -1.0) else if (dplane->normal[0] == -1.0) {
{
dp->type = PLANE_X; dp->type = PLANE_X;
dp->normal[0] = 1.0; dp->normal[0] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
*side = 1; *side = 1;
} } else if (dplane->normal[1] == -1.0) {
else if (dplane->normal[1] == -1.0)
{
dp->type = PLANE_Y; dp->type = PLANE_Y;
dp->normal[1] = 1.0; dp->normal[1] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
*side = 1; *side = 1;
} } else if (dplane->normal[2] == -1.0) {
else if (dplane->normal[2] == -1.0)
{
dp->type = PLANE_Z; dp->type = PLANE_Z;
dp->normal[2] = 1.0; dp->normal[2] = 1.0;
dp->dist = -dp->dist; dp->dist = -dp->dist;
*side = 1; *side = 1;
} } else {
else ax = fabs (dplane->normal[0]);
{ ay = fabs (dplane->normal[1]);
ax = fabs(dplane->normal[0]); az = fabs (dplane->normal[2]);
ay = fabs(dplane->normal[1]);
az = fabs(dplane->normal[2]);
if (ax >= ay && ax >= az) if (ax >= ay && ax >= az)
dp->type = PLANE_ANYX; dp->type = PLANE_ANYX;
@ -360,8 +346,7 @@ int FindPlane_old (plane_t *dplane, int *side)
dp->type = PLANE_ANYY; dp->type = PLANE_ANYY;
else else
dp->type = PLANE_ANYZ; dp->type = PLANE_ANYZ;
if (dplane->normal[dp->type-PLANE_ANYX] < 0) if (dplane->normal[dp->type - PLANE_ANYX] < 0) {
{
VectorSubtract (vec3_origin, dp->normal, dp->normal); VectorSubtract (vec3_origin, dp->normal, dp->normal);
dp->dist = -dp->dist; dp->dist = -dp->dist;
*side = 1; *side = 1;
@ -381,8 +366,8 @@ int FindPlane_old (plane_t *dplane, int *side)
============================================================================= =============================================================================
*/ */
vec3_t brush_mins, brush_maxs; vec3_t brush_mins, brush_maxs;
face_t *brush_faces; face_t *brush_faces;
/* /*
================= =================
@ -390,52 +375,49 @@ CreateBrushFaces
================= =================
*/ */
#define ZERO_EPSILON 0.001 #define ZERO_EPSILON 0.001
void CreateBrushFaces (void) void
CreateBrushFaces (void)
{ {
int i,j, k; int i, j, k;
vec_t r; vec_t r;
face_t *f; face_t *f;
winding_t *w; winding_t *w;
plane_t plane; plane_t plane;
mface_t *mf; mface_t *mf;
brush_mins[0] = brush_mins[1] = brush_mins[2] = 99999; brush_mins[0] = brush_mins[1] = brush_mins[2] = 99999;
brush_maxs[0] = brush_maxs[1] = brush_maxs[2] = -99999; brush_maxs[0] = brush_maxs[1] = brush_maxs[2] = -99999;
brush_faces = NULL; brush_faces = NULL;
for (i=0 ; i<numbrushfaces ; i++) for (i = 0; i < numbrushfaces; i++) {
{
mf = &faces[i]; mf = &faces[i];
w = BaseWindingForPlane (&mf->plane); w = BaseWindingForPlane (&mf->plane);
for (j=0 ; j<numbrushfaces && w ; j++) for (j = 0; j < numbrushfaces && w; j++) {
{
if (j == i) if (j == i)
continue; continue;
// flip the plane, because we want to keep the back side // flip the plane, because we want to keep the back side
VectorSubtract (vec3_origin,faces[j].plane.normal, plane.normal); VectorSubtract (vec3_origin, faces[j].plane.normal, plane.normal);
plane.dist = -faces[j].plane.dist; plane.dist = -faces[j].plane.dist;
w = ClipWinding (w, &plane, false); w = ClipWinding (w, &plane, false);
} }
if (!w) if (!w)
continue; // overcontrained plane continue; // overcontrained plane
// this face is a keeper // this face is a keeper
f = AllocFace (); f = AllocFace ();
f->numpoints = w->numpoints; f->numpoints = w->numpoints;
if (f->numpoints > MAXEDGES) if (f->numpoints > MAXEDGES)
Sys_Error ("f->numpoints > MAXEDGES"); Sys_Error ("f->numpoints > MAXEDGES");
for (j=0 ; j<w->numpoints ; j++) for (j = 0; j < w->numpoints; j++) {
{ for (k = 0; k < 3; k++) {
for (k=0 ; k<3 ; k++)
{
r = (int) (w->points[j][k] + 0.5); r = (int) (w->points[j][k] + 0.5);
if ( fabs(w->points[j][k] - r) < ZERO_EPSILON) if (fabs (w->points[j][k] - r) < ZERO_EPSILON)
f->pts[j][k] = r; f->pts[j][k] = r;
else else
f->pts[j][k] = w->points[j][k]; f->pts[j][k] = w->points[j][k];
@ -467,32 +449,33 @@ This is done by brute force, and could easily get a lot faster if anyone cares.
============================================================================== ==============================================================================
*/ */
vec3_t hull_size[3][2] = { vec3_t hull_size[3][2] = {
{ {0, 0, 0}, {0, 0, 0} }, {{0, 0, 0}, {0, 0, 0}},
{ {-16,-16,-32}, {16,16,24} }, {{-16, -16, -32}, {16, 16, 24}},
{ {-32,-32,-64}, {32,32,24} } {{-32, -32, -64}, {32, 32, 24}}
}; };
#define MAX_HULL_POINTS 32 #define MAX_HULL_POINTS 32
#define MAX_HULL_EDGES 64 #define MAX_HULL_EDGES 64
int num_hull_points; int num_hull_points;
vec3_t hull_points[MAX_HULL_POINTS]; vec3_t hull_points[MAX_HULL_POINTS];
vec3_t hull_corners[MAX_HULL_POINTS*8]; vec3_t hull_corners[MAX_HULL_POINTS * 8];
int num_hull_edges; int num_hull_edges;
int hull_edges[MAX_HULL_EDGES][2]; int hull_edges[MAX_HULL_EDGES][2];
/* /*
============ ============
AddBrushPlane AddBrushPlane
============= =============
*/ */
void AddBrushPlane (plane_t *plane) void
AddBrushPlane (plane_t *plane)
{ {
int i; int i;
plane_t *pl; plane_t *pl;
float l; float l;
if (numbrushfaces == MAX_FACES) if (numbrushfaces == MAX_FACES)
Sys_Error ("AddBrushPlane: numbrushfaces == MAX_FACES"); Sys_Error ("AddBrushPlane: numbrushfaces == MAX_FACES");
@ -500,11 +483,10 @@ void AddBrushPlane (plane_t *plane)
if (l < 0.999 || l > 1.001) if (l < 0.999 || l > 1.001)
Sys_Error ("AddBrushPlane: bad normal"); Sys_Error ("AddBrushPlane: bad normal");
for (i=0 ; i<numbrushfaces ; i++) for (i = 0; i < numbrushfaces; i++) {
{
pl = &faces[i].plane; pl = &faces[i].plane;
if (VectorCompare (pl->normal, plane->normal) if (VectorCompare (pl->normal, plane->normal)
&& fabs(pl->dist - plane->dist) < ON_EPSILON ) && fabs (pl->dist - plane->dist) < ON_EPSILON)
return; return;
} }
faces[i].plane = *plane; faces[i].plane = *plane;
@ -521,25 +503,26 @@ Adds the given plane to the brush description if all of the original brush
vertexes can be put on the front side vertexes can be put on the front side
============= =============
*/ */
void TestAddPlane (plane_t *plane) void
TestAddPlane (plane_t *plane)
{ {
int i, c; int i, c;
vec_t d; vec_t d;
vec_t *corner; vec_t *corner;
plane_t flip; plane_t flip;
vec3_t inv; vec3_t inv;
int counts[3]; int counts[3];
plane_t *pl; plane_t *pl;
// see if the plane has allready been added // see if the plane has allready been added
for (i=0 ; i<numbrushfaces ; i++) for (i = 0; i < numbrushfaces; i++) {
{
pl = &faces[i].plane; pl = &faces[i].plane;
if (VectorCompare (plane->normal, pl->normal) && fabs(plane->dist - pl->dist) < ON_EPSILON) if (VectorCompare (plane->normal, pl->normal)
&& fabs (plane->dist - pl->dist) < ON_EPSILON)
return; return;
VectorSubtract (vec3_origin, plane->normal, inv); VectorSubtract (vec3_origin, plane->normal, inv);
if (VectorCompare (inv, pl->normal) && fabs(plane->dist + pl->dist) < ON_EPSILON) if (VectorCompare (inv, pl->normal)
return; && fabs (plane->dist + pl->dist) < ON_EPSILON) return;
} }
// check all the corner points // check all the corner points
@ -547,29 +530,23 @@ void TestAddPlane (plane_t *plane)
c = num_hull_points * 8; c = num_hull_points * 8;
corner = hull_corners[0]; corner = hull_corners[0];
for (i=0 ; i<c ; i++, corner += 3) for (i = 0; i < c; i++, corner += 3) {
{
d = DotProduct (corner, plane->normal) - plane->dist; d = DotProduct (corner, plane->normal) - plane->dist;
if (d < -ON_EPSILON) if (d < -ON_EPSILON) {
{
if (counts[0]) if (counts[0])
return; return;
counts[1]++; counts[1]++;
} } else if (d > ON_EPSILON) {
else if (d > ON_EPSILON)
{
if (counts[1]) if (counts[1])
return; return;
counts[0]++; counts[0]++;
} } else
else
counts[2]++; counts[2]++;
} }
// the plane is a seperator // the plane is a seperator
if (counts[0]) if (counts[0]) {
{
VectorSubtract (vec3_origin, plane->normal, flip.normal); VectorSubtract (vec3_origin, plane->normal, flip.normal);
flip.dist = -plane->dist; flip.dist = -plane->dist;
plane = &flip; plane = &flip;
@ -585,24 +562,24 @@ AddHullPoint
Doesn't add if duplicated Doesn't add if duplicated
============= =============
*/ */
int AddHullPoint (vec3_t p, int hullnum) int
AddHullPoint (vec3_t p, int hullnum)
{ {
int i; int i;
vec_t *c; vec_t *c;
int x,y,z; int x, y, z;
for (i=0 ; i<num_hull_points ; i++) for (i = 0; i < num_hull_points; i++)
if (VectorCompare (p, hull_points[i])) if (VectorCompare (p, hull_points[i]))
return i; return i;
VectorCopy (p, hull_points[num_hull_points]); VectorCopy (p, hull_points[num_hull_points]);
c = hull_corners[i*8]; c = hull_corners[i * 8];
for (x=0 ; x<2 ; x++) for (x = 0; x < 2; x++)
for (y=0 ; y<2 ; y++) for (y = 0; y < 2; y++)
for (z=0; z<2 ; z++) for (z = 0; z < 2; z++) {
{
c[0] = p[0] + hull_size[hullnum][x][0]; c[0] = p[0] + hull_size[hullnum][x][0];
c[1] = p[1] + hull_size[hullnum][y][1]; c[1] = p[1] + hull_size[hullnum][y][1];
c[2] = p[2] + hull_size[hullnum][z][2]; c[2] = p[2] + hull_size[hullnum][z][2];
@ -625,22 +602,23 @@ AddHullEdge
Creates all of the hull planes around the given edge, if not done allready Creates all of the hull planes around the given edge, if not done allready
============= =============
*/ */
void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum) void
AddHullEdge (vec3_t p1, vec3_t p2, int hullnum)
{ {
int pt1, pt2; int pt1, pt2;
int i; int i;
int a, b, c, d, e; int a, b, c, d, e;
vec3_t edgevec, planeorg, planevec; vec3_t edgevec, planeorg, planevec;
plane_t plane; plane_t plane;
vec_t l; vec_t l;
pt1 = AddHullPoint (p1, hullnum); pt1 = AddHullPoint (p1, hullnum);
pt2 = AddHullPoint (p2, hullnum); pt2 = AddHullPoint (p2, hullnum);
for (i=0 ; i<num_hull_edges ; i++) for (i = 0; i < num_hull_edges; i++)
if ( (hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2) if ((hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2)
|| (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1) ) || (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1))
return; // allread added return; // allread added
if (num_hull_edges == MAX_HULL_EDGES) if (num_hull_edges == MAX_HULL_EDGES)
Sys_Error ("MAX_HULL_EDGES"); Sys_Error ("MAX_HULL_EDGES");
@ -652,13 +630,11 @@ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum)
VectorSubtract (p1, p2, edgevec); VectorSubtract (p1, p2, edgevec);
VectorNormalize (edgevec); VectorNormalize (edgevec);
for (a=0 ; a<3 ; a++) for (a = 0; a < 3; a++) {
{ b = (a + 1) % 3;
b = (a+1)%3; c = (a + 2) % 3;
c = (a+2)%3; for (d = 0; d <= 1; d++)
for (d=0 ; d<=1 ; d++) for (e = 0; e <= 1; e++) {
for (e=0 ; e<=1 ; e++)
{
VectorCopy (p1, planeorg); VectorCopy (p1, planeorg);
planeorg[b] += hull_size[hullnum][d][b]; planeorg[b] += hull_size[hullnum][d][b];
planeorg[c] += hull_size[hullnum][e][c]; planeorg[c] += hull_size[hullnum][e][c];
@ -668,7 +644,7 @@ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum)
CrossProduct (planevec, edgevec, plane.normal); CrossProduct (planevec, edgevec, plane.normal);
l = VectorLength (plane.normal); l = VectorLength (plane.normal);
if (l < 1-ANGLEEPSILON || l > 1+ANGLEEPSILON) if (l < 1 - ANGLEEPSILON || l > 1 + ANGLEEPSILON)
continue; continue;
plane.dist = DotProduct (planeorg, plane.normal); plane.dist = DotProduct (planeorg, plane.normal);
TestAddPlane (&plane); TestAddPlane (&plane);
@ -683,28 +659,27 @@ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum)
ExpandBrush ExpandBrush
============= =============
*/ */
void ExpandBrush (int hullnum) void
ExpandBrush (int hullnum)
{ {
int i, x, s; int i, x, s;
vec3_t corner; vec3_t corner;
face_t *f; face_t *f;
plane_t plane, *p; plane_t plane, *p;
num_hull_points = 0; num_hull_points = 0;
num_hull_edges = 0; num_hull_edges = 0;
// create all the hull points // create all the hull points
for (f=brush_faces ; f ; f=f->next) for (f = brush_faces; f; f = f->next)
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++)
AddHullPoint (f->pts[i], hullnum); AddHullPoint (f->pts[i], hullnum);
// expand all of the planes // expand all of the planes
for (i=0 ; i<numbrushfaces ; i++) for (i = 0; i < numbrushfaces; i++) {
{
p = &faces[i].plane; p = &faces[i].plane;
VectorCopy (vec3_origin, corner); VectorCopy (vec3_origin, corner);
for (x=0 ; x<3 ; x++) for (x = 0; x < 3; x++) {
{
if (p->normal[x] > 0) if (p->normal[x] > 0)
corner[x] = hull_size[hullnum][1][x]; corner[x] = hull_size[hullnum][1][x];
else if (p->normal[x] < 0) else if (p->normal[x] < 0)
@ -714,10 +689,9 @@ void ExpandBrush (int hullnum)
} }
// add any axis planes not contained in the brush to bevel off corners // add any axis planes not contained in the brush to bevel off corners
for (x=0 ; x<3 ; x++) for (x = 0; x < 3; x++)
for (s=-1 ; s<=1 ; s+=2) for (s = -1; s <= 1; s += 2) {
{ // add the plane
// add the plane
VectorCopy (vec3_origin, plane.normal); VectorCopy (vec3_origin, plane.normal);
plane.normal[x] = s; plane.normal[x] = s;
if (s == -1) if (s == -1)
@ -728,9 +702,9 @@ void ExpandBrush (int hullnum)
} }
// add all of the edge bevels // add all of the edge bevels
for (f=brush_faces ; f ; f=f->next) for (f = brush_faces; f; f = f->next)
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++)
AddHullEdge (f->pts[i], f->pts[(i+1)%f->numpoints], hullnum); AddHullEdge (f->pts[i], f->pts[(i + 1) % f->numpoints], hullnum);
} }
//============================================================================ //============================================================================
@ -743,37 +717,39 @@ LoadBrush
Converts a mapbrush to a bsp brush Converts a mapbrush to a bsp brush
=============== ===============
*/ */
brush_t *LoadBrush (mbrush_t *mb, int hullnum) brush_t *
LoadBrush (mbrush_t * mb, int hullnum)
{ {
brush_t *b; brush_t *b;
int contents; int contents;
char *name; char *name;
mface_t *f; mface_t *f;
// //
// check texture name for attributes // check texture name for attributes
// //
name = miptex[bsp->texinfo[mb->faces->texinfo].miptex]; name = miptex[bsp->texinfo[mb->faces->texinfo].miptex];
if (!strcasecmp(name, "clip") && hullnum == 0) if (!strcasecmp (name, "clip") && hullnum == 0)
return NULL; // "clip" brushes don't show up in the draw hull return NULL; // "clip" brushes don't show up in
// the draw hull
if (name[0] == '*' && worldmodel) // entities never use water merging if (name[0] == '*' && worldmodel) // entities never use water merging
{ {
if (!strncasecmp(name+1,"lava",4)) if (!strncasecmp (name + 1, "lava", 4))
contents = CONTENTS_LAVA; contents = CONTENTS_LAVA;
else if (!strncasecmp(name+1,"slime",5)) else if (!strncasecmp (name + 1, "slime", 5))
contents = CONTENTS_SLIME; contents = CONTENTS_SLIME;
else else
contents = CONTENTS_WATER; contents = CONTENTS_WATER;
} } else if (!strncasecmp (name, "sky", 3) && worldmodel && hullnum == 0)
else if (!strncasecmp (name, "sky",3) && worldmodel && hullnum == 0)
contents = CONTENTS_SKY; contents = CONTENTS_SKY;
else else
contents = CONTENTS_SOLID; contents = CONTENTS_SOLID;
if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY) if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
return NULL; // water brushes don't show up in clipping hulls return NULL; // water brushes don't show up in
// clipping hulls
// no seperate textures on clip hull // no seperate textures on clip hull
@ -783,8 +759,7 @@ brush_t *LoadBrush (mbrush_t *mb, int hullnum)
brush_faces = NULL; brush_faces = NULL;
numbrushfaces = 0; numbrushfaces = 0;
for (f=mb->faces ; f ; f=f->next) for (f = mb->faces; f; f = f->next) {
{
faces[numbrushfaces] = *f; faces[numbrushfaces] = *f;
if (hullnum) if (hullnum)
faces[numbrushfaces].texinfo = 0; faces[numbrushfaces].texinfo = 0;
@ -793,18 +768,15 @@ brush_t *LoadBrush (mbrush_t *mb, int hullnum)
CreateBrushFaces (); CreateBrushFaces ();
if (!brush_faces) if (!brush_faces) {
{
printf ("WARNING: couldn't create brush faces\n"); printf ("WARNING: couldn't create brush faces\n");
return NULL; return NULL;
} }
if (hullnum) if (hullnum) {
{
ExpandBrush (hullnum); ExpandBrush (hullnum);
CreateBrushFaces (); CreateBrushFaces ();
} }
// //
// create the brush // create the brush
// //
@ -827,13 +799,14 @@ Brush_DrawAll
============ ============
*/ */
void Brush_DrawAll (brushset_t *bs) void
Brush_DrawAll (brushset_t * bs)
{ {
brush_t *b; brush_t *b;
face_t *f; face_t *f;
for (b=bs->brushes ; b ; b=b->next) for (b = bs->brushes; b; b = b->next)
for (f=b->faces ; f ; f=f->next) for (f = b->faces; f; f = f->next)
Draw_DrawFace (f); Draw_DrawFace (f);
} }
@ -843,15 +816,16 @@ void Brush_DrawAll (brushset_t *bs)
Brush_LoadEntity Brush_LoadEntity
============ ============
*/ */
brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum) brushset_t *
Brush_LoadEntity (entity_t *ent, int hullnum)
{ {
brush_t *b, *next, *water, *other; brush_t *b, *next, *water, *other;
mbrush_t *mbr; mbrush_t *mbr;
int numbrushes; int numbrushes;
brushset_t *bset; brushset_t *bset;
bset = malloc (sizeof(brushset_t)); bset = malloc (sizeof (brushset_t));
memset (bset, 0, sizeof(brushset_t)); memset (bset, 0, sizeof (brushset_t));
ClearBounds (bset); ClearBounds (bset);
numbrushes = 0; numbrushes = 0;
@ -859,21 +833,17 @@ brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum)
qprintf ("--- Brush_LoadEntity ---\n"); qprintf ("--- Brush_LoadEntity ---\n");
for (mbr = ent->brushes ; mbr ; mbr=mbr->next) for (mbr = ent->brushes; mbr; mbr = mbr->next) {
{
b = LoadBrush (mbr, hullnum); b = LoadBrush (mbr, hullnum);
if (!b) if (!b)
continue; continue;
numbrushes++; numbrushes++;
if (b->contents != CONTENTS_SOLID) if (b->contents != CONTENTS_SOLID) {
{
b->next = water; b->next = water;
water = b; water = b;
} } else {
else
{
b->next = other; b->next = other;
other = b; other = b;
} }
@ -883,8 +853,7 @@ brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum)
} }
// add all of the water textures at the start // add all of the water textures at the start
for (b=water ; b ; b=next) for (b = water; b; b = next) {
{
next = b->next; next = b->next;
b->next = other; b->next = other;
other = b; other = b;
@ -895,9 +864,7 @@ brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum)
brushset = bset; brushset = bset;
Brush_DrawAll (bset); Brush_DrawAll (bset);
qprintf ("%i brushes read\n",numbrushes); qprintf ("%i brushes read\n", numbrushes);
return bset; return bset;
} }

View file

@ -35,17 +35,18 @@ Brushes that touch still need to be split at the cut point to make a tjunction
*/ */
face_t *validfaces[MAX_MAP_PLANES]; face_t *validfaces[MAX_MAP_PLANES];
face_t *inside, *outside; face_t *inside, *outside;
int brushfaces; int brushfaces;
int csgfaces; int csgfaces;
int csgmergefaces; int csgmergefaces;
void DrawList (face_t *list) void
DrawList (face_t * list)
{ {
for ( ; list ; list=list->next) for (; list; list = list->next)
Draw_DrawFace (list); Draw_DrawFace (list);
} }
@ -58,9 +59,10 @@ Duplicates the non point information of a face, used by SplitFace and
MergeFace. MergeFace.
================== ==================
*/ */
face_t *NewFaceFromFace (face_t *in) face_t *
NewFaceFromFace (face_t * in)
{ {
face_t *newf; face_t *newf;
newf = AllocFace (); newf = AllocFace ();
@ -81,24 +83,24 @@ SplitFace
================== ==================
*/ */
void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back) void
SplitFace (face_t * in, plane_t *split, face_t ** front, face_t ** back)
{ {
vec_t dists[MAXEDGES+1]; vec_t dists[MAXEDGES + 1];
int sides[MAXEDGES+1]; int sides[MAXEDGES + 1];
int counts[3]; int counts[3];
vec_t dot; vec_t dot;
int i, j; int i, j;
face_t *newf, *new2; face_t *newf, *new2;
vec_t *p1, *p2; vec_t *p1, *p2;
vec3_t mid; vec3_t mid;
if (in->numpoints < 0) if (in->numpoints < 0)
Sys_Error ("SplitFace: freed face"); Sys_Error ("SplitFace: freed face");
counts[0] = counts[1] = counts[2] = 0; counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point // determine sides for each point
for (i=0 ; i<in->numpoints ; i++) for (i = 0; i < in->numpoints; i++) {
{
dot = DotProduct (in->pts[i], split->normal); dot = DotProduct (in->pts[i], split->normal);
dot -= split->dist; dot -= split->dist;
dists[i] = dot; dists[i] = dot;
@ -113,14 +115,12 @@ void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
sides[i] = sides[0]; sides[i] = sides[0];
dists[i] = dists[0]; dists[i] = dists[0];
if (!counts[0]) if (!counts[0]) {
{
*front = NULL; *front = NULL;
*back = in; *back = in;
return; return;
} }
if (!counts[1]) if (!counts[1]) {
{
*front = in; *front = in;
*back = NULL; *back = NULL;
return; return;
@ -131,15 +131,13 @@ void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
// distribute the points and generate splits // distribute the points and generate splits
for (i=0 ; i<in->numpoints ; i++) for (i = 0; i < in->numpoints; i++) {
{
if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES) if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
Sys_Error ("SplitFace: numpoints > MAXEDGES"); Sys_Error ("SplitFace: numpoints > MAXEDGES");
p1 = in->pts[i]; p1 = in->pts[i];
if (sides[i] == SIDE_ON) if (sides[i] == SIDE_ON) {
{
VectorCopy (p1, newf->pts[newf->numpoints]); VectorCopy (p1, newf->pts[newf->numpoints]);
newf->numpoints++; newf->numpoints++;
VectorCopy (p1, new2->pts[new2->numpoints]); VectorCopy (p1, new2->pts[new2->numpoints]);
@ -147,32 +145,29 @@ void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
continue; continue;
} }
if (sides[i] == SIDE_FRONT) if (sides[i] == SIDE_FRONT) {
{
VectorCopy (p1, new2->pts[new2->numpoints]); VectorCopy (p1, new2->pts[new2->numpoints]);
new2->numpoints++; new2->numpoints++;
} } else {
else
{
VectorCopy (p1, newf->pts[newf->numpoints]); VectorCopy (p1, newf->pts[newf->numpoints]);
newf->numpoints++; newf->numpoints++;
} }
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
continue; continue;
// generate a split point // generate a split point
p2 = in->pts[(i+1)%in->numpoints]; p2 = in->pts[(i + 1) % in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]); dot = dists[i] / (dists[i] - dists[i + 1]);
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) { // avoid round off error when
{ // avoid round off error when possible // possible
if (split->normal[j] == 1) if (split->normal[j] == 1)
mid[j] = split->dist; mid[j] = split->dist;
else if (split->normal[j] == -1) else if (split->normal[j] == -1)
mid[j] = -split->dist; mid[j] = -split->dist;
else else
mid[j] = p1[j] + dot*(p2[j]-p1[j]); mid[j] = p1[j] + dot * (p2[j] - p1[j]);
} }
VectorCopy (mid, newf->pts[newf->numpoints]); VectorCopy (mid, newf->pts[newf->numpoints]);
@ -185,8 +180,8 @@ void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
Sys_Error ("SplitFace: numpoints > MAXEDGES"); Sys_Error ("SplitFace: numpoints > MAXEDGES");
#if 0 #if 0
CheckFace (newf); CheckFace (newf);
CheckFace (new2); CheckFace (new2);
#endif #endif
// free the original face now that is is represented by the fragments // free the original face now that is is represented by the fragments
@ -205,45 +200,39 @@ Faces exactly on the plane will stay inside unless overdrawn by later brush
frontside is the side of the plane that holds the outside list frontside is the side of the plane that holds the outside list
================= =================
*/ */
void ClipInside (int splitplane, int frontside, qboolean precedence) void
ClipInside (int splitplane, int frontside, qboolean precedence)
{ {
face_t *f, *next; face_t *f, *next;
face_t *frags[2]; face_t *frags[2];
face_t *insidelist; face_t *insidelist;
plane_t *split; plane_t *split;
split = &planes[splitplane]; split = &planes[splitplane];
insidelist = NULL; insidelist = NULL;
for (f=inside ; f ; f=next) for (f = inside; f; f = next) {
{
next = f->next; next = f->next;
if (f->planenum == splitplane) if (f->planenum == splitplane) { // exactly on, handle special
{ // exactly on, handle special if (frontside != f->planeside || precedence) { // allways clip
if ( frontside != f->planeside || precedence ) // off opposite
{ // allways clip off opposite faceing // faceing
frags[frontside] = NULL; frags[frontside] = NULL;
frags[!frontside] = f; frags[!frontside] = f;
} } else { // leave it on the outside
else
{ // leave it on the outside
frags[frontside] = f; frags[frontside] = f;
frags[!frontside] = NULL; frags[!frontside] = NULL;
} }
} } else { // proper split
else
{ // proper split
SplitFace (f, split, &frags[0], &frags[1]); SplitFace (f, split, &frags[0], &frags[1]);
} }
if (frags[frontside]) if (frags[frontside]) {
{
frags[frontside]->next = outside; frags[frontside]->next = outside;
outside = frags[frontside]; outside = frags[frontside];
} }
if (frags[!frontside]) if (frags[!frontside]) {
{
frags[!frontside]->next = insidelist; frags[!frontside]->next = insidelist;
insidelist = frags[!frontside]; insidelist = frags[!frontside];
} }
@ -260,21 +249,20 @@ SaveOutside
Saves all of the faces in the outside list to the bsp plane list Saves all of the faces in the outside list to the bsp plane list
================== ==================
*/ */
void SaveOutside (qboolean mirror) void
SaveOutside (qboolean mirror)
{ {
face_t *f , *next, *newf; face_t *f, *next, *newf;
int i; int i;
int planenum; int planenum;
for (f=outside ; f ; f=next) for (f = outside; f; f = next) {
{
next = f->next; next = f->next;
csgfaces++; csgfaces++;
Draw_DrawFace (f); Draw_DrawFace (f);
planenum = f->planenum; planenum = f->planenum;
if (mirror) if (mirror) {
{
newf = NewFaceFromFace (f); newf = NewFaceFromFace (f);
newf->numpoints = f->numpoints; newf->numpoints = f->numpoints;
@ -282,17 +270,16 @@ void SaveOutside (qboolean mirror)
newf->contents[0] = f->contents[1]; newf->contents[0] = f->contents[1];
newf->contents[1] = f->contents[0]; newf->contents[1] = f->contents[0];
for (i=0 ; i<f->numpoints ; i++) // add points backwards for (i = 0; i < f->numpoints; i++) // add points backwards
{ {
VectorCopy (f->pts[f->numpoints-1-i], newf->pts[i]); VectorCopy (f->pts[f->numpoints - 1 - i], newf->pts[i]);
} }
} } else
else
newf = NULL; newf = NULL;
validfaces[planenum] = MergeFaceToList(f, validfaces[planenum]); validfaces[planenum] = MergeFaceToList (f, validfaces[planenum]);
if (newf) if (newf)
validfaces[planenum] = MergeFaceToList(newf, validfaces[planenum]); validfaces[planenum] = MergeFaceToList (newf, validfaces[planenum]);
validfaces[planenum] = FreeMergeListScraps (validfaces[planenum]); validfaces[planenum] = FreeMergeListScraps (validfaces[planenum]);
} }
@ -305,21 +292,19 @@ FreeInside
Free all the faces that got clipped out Free all the faces that got clipped out
================== ==================
*/ */
void FreeInside (int contents) void
FreeInside (int contents)
{ {
face_t *f, *next; face_t *f, *next;
for (f=inside ; f ; f=next) for (f = inside; f; f = next) {
{
next = f->next; next = f->next;
if (contents != CONTENTS_SOLID) if (contents != CONTENTS_SOLID) {
{
f->contents[0] = contents; f->contents[0] = contents;
f->next = outside; f->next = outside;
outside = f; outside = f;
} } else
else
FreeFace (f); FreeFace (f);
} }
} }
@ -335,21 +320,21 @@ Returns a chain of all the external surfaces with one or more visible
faces. faces.
================== ==================
*/ */
surface_t *BuildSurfaces (void) surface_t *
BuildSurfaces (void)
{ {
face_t **f; face_t **f;
face_t *count; face_t *count;
int i; int i;
surface_t *s; surface_t *s;
surface_t *surfhead; surface_t *surfhead;
surfhead = NULL; surfhead = NULL;
f = validfaces; f = validfaces;
for (i=0 ; i<numbrushplanes ; i++, f++) for (i = 0; i < numbrushplanes; i++, f++) {
{
if (!*f) if (!*f)
continue; // nothing left on this plane continue; // nothing left on this plane
// create a new surface to hold the faces on this plane // create a new surface to hold the faces on this plane
s = AllocSurface (); s = AllocSurface ();
@ -357,9 +342,9 @@ surface_t *BuildSurfaces (void)
s->next = surfhead; s->next = surfhead;
surfhead = s; surfhead = s;
s->faces = *f; s->faces = *f;
for (count = s->faces ; count ; count=count->next) for (count = s->faces; count; count = count->next)
csgmergefaces++; csgmergefaces++;
CalcSurfaceInfo (s); // bounding box and flags CalcSurfaceInfo (s); // bounding box and flags
} }
return surfhead; return surfhead;
@ -372,23 +357,24 @@ surface_t *BuildSurfaces (void)
CopyFacesToOutside CopyFacesToOutside
================== ==================
*/ */
void CopyFacesToOutside (brush_t *b) void
CopyFacesToOutside (brush_t * b)
{ {
face_t *f, *newf; face_t *f, *newf;
outside = NULL; outside = NULL;
for (f=b->faces ; f ; f=f->next) for (f = b->faces; f; f = f->next) {
{
brushfaces++; brushfaces++;
#if 0 #if 0
{ {
int i; int i;
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++)
printf ("(%f,%f,%f) ",f->pts[i][0], f->pts[i][1], f->pts[i][2]); printf ("(%f,%f,%f) ", f->pts[i][0], f->pts[i][1],
printf ("\n"); f->pts[i][2]);
} printf ("\n");
}
#endif #endif
newf = AllocFace (); newf = AllocFace ();
*newf = *f; *newf = *f;
@ -407,17 +393,18 @@ CSGFaces
Returns a list of surfaces containing aall of the faces Returns a list of surfaces containing aall of the faces
================== ==================
*/ */
surface_t *CSGFaces (brushset_t *bs) surface_t *
CSGFaces (brushset_t * bs)
{ {
brush_t *b1, *b2; brush_t *b1, *b2;
int i; int i;
qboolean overwrite; qboolean overwrite;
face_t *f; face_t *f;
surface_t *surfhead; surface_t *surfhead;
qprintf ("---- CSGFaces ----\n"); qprintf ("---- CSGFaces ----\n");
memset (validfaces, 0, sizeof(validfaces)); memset (validfaces, 0, sizeof (validfaces));
csgfaces = brushfaces = csgmergefaces = 0; csgfaces = brushfaces = csgmergefaces = 0;
@ -426,48 +413,44 @@ surface_t *CSGFaces (brushset_t *bs)
// //
// do the solid faces // do the solid faces
// //
for (b1=bs->brushes ; b1 ; b1 = b1->next) for (b1 = bs->brushes; b1; b1 = b1->next) {
{ // set outside to a copy of the brush's faces
// set outside to a copy of the brush's faces
CopyFacesToOutside (b1); CopyFacesToOutside (b1);
overwrite = false; overwrite = false;
for (b2=bs->brushes ; b2 ; b2 = b2->next) for (b2 = bs->brushes; b2; b2 = b2->next) {
{ // see if b2 needs to clip a chunk out of b1
// see if b2 needs to clip a chunk out of b1
if (b1==b2) if (b1 == b2) {
{ overwrite = true; // later brushes now overwrite
overwrite = true; // later brushes now overwrite
continue; continue;
} }
// check bounding box first
// check bounding box first for (i = 0; i < 3; i++)
for (i=0 ; i<3 ; i++)
if (b1->mins[i] > b2->maxs[i] || b1->maxs[i] < b2->mins[i]) if (b1->mins[i] > b2->maxs[i] || b1->maxs[i] < b2->mins[i])
break; break;
if (i<3) if (i < 3)
continue; continue;
// divide faces by the planes of the new brush // divide faces by the planes of the new brush
inside = outside; inside = outside;
outside = NULL; outside = NULL;
for (f=b2->faces ; f ; f=f->next) for (f = b2->faces; f; f = f->next)
ClipInside (f->planenum, f->planeside, overwrite); ClipInside (f->planenum, f->planeside, overwrite);
// these faces are continued in another brush, so get rid of them // these faces are continued in another brush, so get rid of them
if (b1->contents == CONTENTS_SOLID && b2->contents <= CONTENTS_WATER) if (b1->contents == CONTENTS_SOLID
FreeInside (b2->contents); && b2->contents <= CONTENTS_WATER) FreeInside (b2->contents);
else else
FreeInside (CONTENTS_SOLID); FreeInside (CONTENTS_SOLID);
} }
// all of the faces left in outside are real surface faces // all of the faces left in outside are real surface faces
if (b1->contents != CONTENTS_SOLID) if (b1->contents != CONTENTS_SOLID)
SaveOutside (true); // mirror faces for inside view SaveOutside (true); // mirror faces for inside view
else else
SaveOutside (false); SaveOutside (false);
} }
@ -485,5 +468,3 @@ surface_t *CSGFaces (brushset_t *bs)
return surfhead; return surfhead;
} }

View file

@ -35,14 +35,14 @@
#include "bsp5.h" #include "bsp5.h"
int nummapbrushes; int nummapbrushes;
mbrush_t mapbrushes[MAX_MAP_BRUSHES]; mbrush_t mapbrushes[MAX_MAP_BRUSHES];
int num_entities; int num_entities;
entity_t entities[MAX_MAP_ENTITIES]; entity_t entities[MAX_MAP_ENTITIES];
int nummiptex; int nummiptex;
char miptex[MAX_MAP_TEXINFO][16]; char miptex[MAX_MAP_TEXINFO][16];
//============================================================================ //============================================================================
@ -52,12 +52,12 @@ FindMiptex
=============== ===============
*/ */
int FindMiptex (char *name) int
FindMiptex (char *name)
{ {
int i; int i;
for (i=0 ; i<nummiptex ; i++) for (i = 0; i < nummiptex; i++) {
{
if (!strcmp (name, miptex[i])) if (!strcmp (name, miptex[i]))
return i; return i;
} }
@ -75,26 +75,25 @@ FindTexinfo
Returns a global texinfo number Returns a global texinfo number
=============== ===============
*/ */
int FindTexinfo (texinfo_t *t) int
FindTexinfo (texinfo_t *t)
{ {
int i, j; int i, j;
texinfo_t *tex; texinfo_t *tex;
// set the special flag // set the special flag
if (miptex[t->miptex][0] == '*' if (miptex[t->miptex][0] == '*'
|| !strncasecmp (miptex[t->miptex], "sky",3) ) || !strncasecmp (miptex[t->miptex], "sky", 3)) t->flags |= TEX_SPECIAL;
t->flags |= TEX_SPECIAL;
tex = bsp->texinfo; tex = bsp->texinfo;
for (i=0 ; i<bsp->numtexinfo;i++, tex++) for (i = 0; i < bsp->numtexinfo; i++, tex++) {
{
if (t->miptex != tex->miptex) if (t->miptex != tex->miptex)
continue; continue;
if (t->flags != tex->flags) if (t->flags != tex->flags)
continue; continue;
for (j=0 ; j<8 ; j++) for (j = 0; j < 8; j++)
if (t->vecs[0][j] != tex->vecs[0][j]) if (t->vecs[0][j] != tex->vecs[0][j])
break; break;
if (j != 8) if (j != 8)
@ -117,41 +116,40 @@ int FindTexinfo (texinfo_t *t)
#define MAXTOKEN 128 #define MAXTOKEN 128
char token[MAXTOKEN]; char token[MAXTOKEN];
qboolean unget; qboolean unget;
char *script_p; char *script_p;
int scriptline; int scriptline;
void StartTokenParsing (char *data) void
StartTokenParsing (char *data)
{ {
scriptline = 1; scriptline = 1;
script_p = data; script_p = data;
unget = false; unget = false;
} }
qboolean GetToken (qboolean crossline) qboolean
GetToken (qboolean crossline)
{ {
char *token_p; char *token_p;
if (unget) // is a token allready waiting? if (unget) // is a token allready waiting?
return true; return true;
// //
// skip space // skip space
// //
skipspace: skipspace:
while (*script_p <= 32) while (*script_p <= 32) {
{ if (!*script_p) {
if (!*script_p)
{
if (!crossline) if (!crossline)
Sys_Error ("Line %i is incomplete",scriptline); Sys_Error ("Line %i is incomplete", scriptline);
return false; return false;
} }
if (*script_p++ == '\n') if (*script_p++ == '\n') {
{
if (!crossline) if (!crossline)
Sys_Error ("Line %i is incomplete",scriptline); Sys_Error ("Line %i is incomplete", scriptline);
scriptline++; scriptline++;
} }
} }
@ -159,48 +157,44 @@ skipspace:
if (script_p[0] == '/' && script_p[1] == '/') // comment field if (script_p[0] == '/' && script_p[1] == '/') // comment field
{ {
if (!crossline) if (!crossline)
Sys_Error ("Line %i is incomplete\n",scriptline); Sys_Error ("Line %i is incomplete\n", scriptline);
while (*script_p++ != '\n') while (*script_p++ != '\n')
if (!*script_p) if (!*script_p) {
{
if (!crossline) if (!crossline)
Sys_Error ("Line %i is incomplete",scriptline); Sys_Error ("Line %i is incomplete", scriptline);
return false; return false;
} }
goto skipspace; goto skipspace;
} }
// //
// copy token // copy token
// //
token_p = token; token_p = token;
if (*script_p == '"') if (*script_p == '"') {
{
script_p++; script_p++;
while ( *script_p != '"' ) while (*script_p != '"') {
{
if (!*script_p) if (!*script_p)
Sys_Error ("EOF inside quoted token"); Sys_Error ("EOF inside quoted token");
*token_p++ = *script_p++; *token_p++ = *script_p++;
if (token_p > &token[MAXTOKEN-1]) if (token_p > &token[MAXTOKEN - 1])
Sys_Error ("Token too large on line %i",scriptline); Sys_Error ("Token too large on line %i", scriptline);
} }
script_p++; script_p++;
} } else
else while ( *script_p > 32 ) while (*script_p > 32) {
{ *token_p++ = *script_p++;
*token_p++ = *script_p++; if (token_p > &token[MAXTOKEN - 1])
if (token_p > &token[MAXTOKEN-1]) Sys_Error ("Token too large on line %i", scriptline);
Sys_Error ("Token too large on line %i",scriptline); }
}
*token_p = 0; *token_p = 0;
return true; return true;
} }
void UngetToken () void
UngetToken ()
{ {
unget = true; unget = true;
} }
@ -208,27 +202,28 @@ void UngetToken ()
//============================================================================ //============================================================================
entity_t *mapent; entity_t *mapent;
/* /*
================= =================
ParseEpair ParseEpair
================= =================
*/ */
void ParseEpair (void) void
ParseEpair (void)
{ {
epair_t *e; epair_t *e;
e = malloc (sizeof(epair_t)); e = malloc (sizeof (epair_t));
memset (e, 0, sizeof(epair_t)); memset (e, 0, sizeof (epair_t));
e->next = mapent->epairs; e->next = mapent->epairs;
mapent->epairs = e; mapent->epairs = e;
if (strlen(token) >= MAX_KEY-1) if (strlen (token) >= MAX_KEY - 1)
Sys_Error ("ParseEpar: token too long"); Sys_Error ("ParseEpar: token too long");
e->key = strdup (token); e->key = strdup (token);
GetToken (false); GetToken (false);
if (strlen(token) >= MAX_VALUE-1) if (strlen (token) >= MAX_VALUE - 1)
Sys_Error ("ParseEpar: token too long"); Sys_Error ("ParseEpar: token too long");
e->value = strdup (token); e->value = strdup (token);
} }
@ -241,37 +236,35 @@ void ParseEpair (void)
textureAxisFromPlane textureAxisFromPlane
================== ==================
*/ */
vec3_t baseaxis[18] = vec3_t baseaxis[18] = {
{ {0, 0, 1}, {1, 0, 0}, {0, -1, 0}, // floor
{0,0,1}, {1,0,0}, {0,-1,0}, // floor {0, 0, -1}, {1, 0, 0}, {0, -1, 0}, // ceiling
{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling {1, 0, 0}, {0, 1, 0}, {0, 0, -1}, // west wall
{1,0,0}, {0,1,0}, {0,0,-1}, // west wall {-1, 0, 0}, {0, 1, 0}, {0, 0, -1}, // east wall
{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, // south wall
{0,1,0}, {1,0,0}, {0,0,-1}, // south wall {0, -1, 0}, {1, 0, 0}, {0, 0, -1} // north wall
{0,-1,0}, {1,0,0}, {0,0,-1} // north wall
}; };
void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv) void
TextureAxisFromPlane (plane_t *pln, vec3_t xv, vec3_t yv)
{ {
int bestaxis; int bestaxis;
float dot,best; float dot, best;
int i; int i;
best = 0; best = 0;
bestaxis = 0; bestaxis = 0;
for (i=0 ; i<6 ; i++) for (i = 0; i < 6; i++) {
{ dot = DotProduct (pln->normal, baseaxis[i * 3]);
dot = DotProduct (pln->normal, baseaxis[i*3]); if (dot > best) {
if (dot > best)
{
best = dot; best = dot;
bestaxis = i; bestaxis = i;
} }
} }
VectorCopy (baseaxis[bestaxis*3+1], xv); VectorCopy (baseaxis[bestaxis * 3 + 1], xv);
VectorCopy (baseaxis[bestaxis*3+2], yv); VectorCopy (baseaxis[bestaxis * 3 + 2], yv);
} }
@ -283,98 +276,91 @@ void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
ParseBrush ParseBrush
================= =================
*/ */
void ParseBrush (void) void
ParseBrush (void)
{ {
mbrush_t *b; mbrush_t *b;
mface_t *f, *f2; mface_t *f, *f2;
vec3_t planepts[3]; vec3_t planepts[3];
vec3_t t1, t2, t3; vec3_t t1, t2, t3;
int i,j; int i, j;
texinfo_t tx; texinfo_t tx;
vec_t d; vec_t d;
float shift[2], rotate, scale[2]; float shift[2], rotate, scale[2];
b = &mapbrushes[nummapbrushes]; b = &mapbrushes[nummapbrushes];
nummapbrushes++; nummapbrushes++;
b->next = mapent->brushes; b->next = mapent->brushes;
mapent->brushes = b; mapent->brushes = b;
do do {
{
if (!GetToken (true)) if (!GetToken (true))
break; break;
if (!strcmp (token, "}") ) if (!strcmp (token, "}"))
break; break;
// read the three point plane definition // read the three point plane definition
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
if (i != 0) if (i != 0)
GetToken (true); GetToken (true);
if (strcmp (token, "(") ) if (strcmp (token, "("))
Sys_Error ("parsing brush"); Sys_Error ("parsing brush");
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) {
{
GetToken (false); GetToken (false);
planepts[i][j] = atoi(token); planepts[i][j] = atoi (token);
} }
GetToken (false); GetToken (false);
if (strcmp (token, ")") ) if (strcmp (token, ")"))
Sys_Error ("parsing brush"); Sys_Error ("parsing brush");
} }
// read the texturedef // read the texturedef
memset (&tx, 0, sizeof(tx)); memset (&tx, 0, sizeof (tx));
GetToken (false); GetToken (false);
tx.miptex = FindMiptex (token); tx.miptex = FindMiptex (token);
GetToken (false); GetToken (false);
shift[0] = atoi(token); shift[0] = atoi (token);
GetToken (false); GetToken (false);
shift[1] = atoi(token); shift[1] = atoi (token);
GetToken (false); GetToken (false);
rotate = atoi(token); rotate = atoi (token);
GetToken (false); GetToken (false);
scale[0] = atof(token); scale[0] = atof (token);
GetToken (false); GetToken (false);
scale[1] = atof(token); scale[1] = atof (token);
// if the three points are all on a previous plane, it is a // if the three points are all on a previous plane, it is a
// duplicate plane // duplicate plane
for (f2 = b->faces ; f2 ; f2=f2->next) for (f2 = b->faces; f2; f2 = f2->next) {
{ for (i = 0; i < 3; i++) {
for (i=0 ; i<3 ; i++) d = DotProduct (planepts[i], f2->plane.normal) - f2->plane.dist;
{
d = DotProduct(planepts[i],f2->plane.normal) - f2->plane.dist;
if (d < -ON_EPSILON || d > ON_EPSILON) if (d < -ON_EPSILON || d > ON_EPSILON)
break; break;
} }
if (i==3) if (i == 3)
break; break;
} }
if (f2) if (f2) {
{
printf ("WARNING: brush with duplicate plane\n"); printf ("WARNING: brush with duplicate plane\n");
continue; continue;
} }
f = malloc(sizeof(mface_t)); f = malloc (sizeof (mface_t));
f->next = b->faces; f->next = b->faces;
b->faces = f; b->faces = f;
// convert to a vector / dist plane // convert to a vector / dist plane
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) {
{
t1[j] = planepts[0][j] - planepts[1][j]; t1[j] = planepts[0][j] - planepts[1][j];
t2[j] = planepts[2][j] - planepts[1][j]; t2[j] = planepts[2][j] - planepts[1][j];
t3[j] = planepts[1][j]; t3[j] = planepts[1][j];
} }
CrossProduct(t1,t2, f->plane.normal); CrossProduct (t1, t2, f->plane.normal);
if (VectorCompare (f->plane.normal, vec3_origin)) if (VectorCompare (f->plane.normal, vec3_origin)) {
{
printf ("WARNING: brush plane with no normal\n"); printf ("WARNING: brush plane with no normal\n");
b->faces = f->next; b->faces = f->next;
free (f); free (f);
@ -383,16 +369,16 @@ void ParseBrush (void)
VectorNormalize (f->plane.normal); VectorNormalize (f->plane.normal);
f->plane.dist = DotProduct (t3, f->plane.normal); f->plane.dist = DotProduct (t3, f->plane.normal);
// //
// fake proper texture vectors from QuakeEd style // fake proper texture vectors from QuakeEd style
// //
{ {
vec3_t vecs[2]; vec3_t vecs[2];
int sv, tv; int sv, tv;
float ang, sinv, cosv; float ang, sinv, cosv;
float ns, nt; float ns, nt;
TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]); TextureAxisFromPlane (&f->plane, vecs[0], vecs[1]);
if (!scale[0]) if (!scale[0])
scale[0] = 1; scale[0] = 1;
@ -400,20 +386,23 @@ void ParseBrush (void)
scale[1] = 1; scale[1] = 1;
// rotate axis // rotate axis
if (rotate == 0) if (rotate == 0) {
{ sinv = 0 ; cosv = 1; } sinv = 0;
else if (rotate == 90) cosv = 1;
{ sinv = 1 ; cosv = 0; } } else if (rotate == 90) {
else if (rotate == 180) sinv = 1;
{ sinv = 0 ; cosv = -1; } cosv = 0;
else if (rotate == 270) } else if (rotate == 180) {
{ sinv = -1 ; cosv = 0; } sinv = 0;
else cosv = -1;
{ } else if (rotate == 270) {
sinv = -1;
cosv = 0;
} else {
ang = rotate / 180 * M_PI; ang = rotate / 180 * M_PI;
sinv = sin(ang); sinv = sin (ang);
cosv = cos(ang); cosv = cos (ang);
} }
if (vecs[0][0]) if (vecs[0][0])
@ -430,23 +419,22 @@ void ParseBrush (void)
else else
tv = 2; tv = 2;
for (i=0 ; i<2 ; i++) for (i = 0; i < 2; i++) {
{
ns = cosv * vecs[i][sv] - sinv * vecs[i][tv]; ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
nt = sinv * vecs[i][sv] + cosv * vecs[i][tv]; nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
vecs[i][sv] = ns; vecs[i][sv] = ns;
vecs[i][tv] = nt; vecs[i][tv] = nt;
} }
for (i=0 ; i<2 ; i++) for (i = 0; i < 2; i++)
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++)
tx.vecs[i][j] = vecs[i][j] / scale[i]; tx.vecs[i][j] = vecs[i][j] / scale[i];
tx.vecs[0][3] = shift[0]; tx.vecs[0][3] = shift[0];
tx.vecs[1][3] = shift[1]; tx.vecs[1][3] = shift[1];
} }
// unique the texinfo // unique the texinfo
f->texinfo = FindTexinfo (&tx); f->texinfo = FindTexinfo (&tx);
} while (1); } while (1);
} }
@ -456,12 +444,13 @@ void ParseBrush (void)
ParseEntity ParseEntity
================ ================
*/ */
qboolean ParseEntity (void) qboolean
ParseEntity (void)
{ {
if (!GetToken (true)) if (!GetToken (true))
return false; return false;
if (strcmp (token, "{") ) if (strcmp (token, "{"))
Sys_Error ("ParseEntity: { not found"); Sys_Error ("ParseEntity: { not found");
if (num_entities == MAX_MAP_ENTITIES) if (num_entities == MAX_MAP_ENTITIES)
@ -470,13 +459,12 @@ qboolean ParseEntity (void)
mapent = &entities[num_entities]; mapent = &entities[num_entities];
num_entities++; num_entities++;
do do {
{
if (!GetToken (true)) if (!GetToken (true))
Sys_Error ("ParseEntity: EOF without closing brace"); Sys_Error ("ParseEntity: EOF without closing brace");
if (!strcmp (token, "}") ) if (!strcmp (token, "}"))
break; break;
if (!strcmp (token, "{") ) if (!strcmp (token, "{"))
ParseBrush (); ParseBrush ();
else else
ParseEpair (); ParseEpair ();
@ -491,9 +479,10 @@ qboolean ParseEntity (void)
LoadMapFile LoadMapFile
================ ================
*/ */
void LoadMapFile (char *filename) void
LoadMapFile (char *filename)
{ {
char *buf; char *buf;
buf = COM_LoadFile (filename, 0); buf = COM_LoadFile (filename, 0);
@ -501,8 +490,7 @@ void LoadMapFile (char *filename)
num_entities = 0; num_entities = 0;
while (ParseEntity ()) while (ParseEntity ()) {
{
} }
free (buf); free (buf);
@ -515,55 +503,59 @@ void LoadMapFile (char *filename)
qprintf ("%5i texinfo\n", bsp->numtexinfo); qprintf ("%5i texinfo\n", bsp->numtexinfo);
} }
void PrintEntity (entity_t *ent) void
PrintEntity (entity_t *ent)
{ {
epair_t *ep; epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next) for (ep = ent->epairs; ep; ep = ep->next)
printf ("%20s : %s\n", ep->key, ep->value); printf ("%20s : %s\n", ep->key, ep->value);
} }
char *ValueForKey (entity_t *ent, char *key) char *
ValueForKey (entity_t *ent, char *key)
{ {
epair_t *ep; epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next) for (ep = ent->epairs; ep; ep = ep->next)
if (!strcmp (ep->key, key) ) if (!strcmp (ep->key, key))
return ep->value; return ep->value;
return ""; return "";
} }
void SetKeyValue (entity_t *ent, char *key, char *value) void
SetKeyValue (entity_t *ent, char *key, char *value)
{ {
epair_t *ep; epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next) for (ep = ent->epairs; ep; ep = ep->next)
if (!strcmp (ep->key, key) ) if (!strcmp (ep->key, key)) {
{
free (ep->value); free (ep->value);
ep->value = strdup (value); ep->value = strdup (value);
return; return;
} }
ep = malloc (sizeof(*ep)); ep = malloc (sizeof (*ep));
ep->next = ent->epairs; ep->next = ent->epairs;
ent->epairs = ep; ent->epairs = ep;
ep->key = strdup (key); ep->key = strdup (key);
ep->value = strdup (value); ep->value = strdup (value);
} }
float FloatForKey (entity_t *ent, char *key) float
FloatForKey (entity_t *ent, char *key)
{ {
char *k; char *k;
k = ValueForKey (ent, key); k = ValueForKey (ent, key);
return atof(k); return atof (k);
} }
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) void
GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
{ {
char *k; char *k;
double v1, v2, v3; double v1, v2, v3;
k = ValueForKey (ent, key); k = ValueForKey (ent, key);
v1 = v2 = v3 = 0; v1 = v2 = v3 = 0;
@ -575,33 +567,32 @@ void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
} }
void WriteEntitiesToString (void) void
WriteEntitiesToString (void)
{ {
char *buf, *end; char *buf, *end;
epair_t *ep; epair_t *ep;
char line[128]; char line[128];
int i; int i;
buf = bsp->entdata; buf = bsp->entdata;
end = buf; end = buf;
*end = 0; *end = 0;
for (i=0 ; i<num_entities ; i++) for (i = 0; i < num_entities; i++) {
{
ep = entities[i].epairs; ep = entities[i].epairs;
if (!ep) if (!ep)
continue; // ent got removed continue; // ent got removed
strcat (end,"{\n"); strcat (end, "{\n");
end += 2; end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next) for (ep = entities[i].epairs; ep; ep = ep->next) {
{
sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
strcat (end, line); strcat (end, line);
end += strlen(line); end += strlen (line);
} }
strcat (end,"}\n"); strcat (end, "}\n");
end += 2; end += 2;
if (end > buf + MAX_MAP_ENTSTRING) if (end > buf + MAX_MAP_ENTSTRING)
@ -609,4 +600,3 @@ void WriteEntitiesToString (void)
} }
bsp->entdatasize = end - buf + 1; bsp->entdatasize = end - buf + 1;
} }

View file

@ -36,13 +36,13 @@ CheckColinear
================ ================
*/ */
void CheckColinear (face_t *f) void
CheckColinear (face_t * f)
{ {
int i, j; int i, j;
vec3_t v1, v2; vec3_t v1, v2;
for (i=0 ; i<f->numpoints ;i++) for (i = 0; i < f->numpoints; i++) {
{
// skip the point if the vector from the previous point is the same // skip the point if the vector from the previous point is the same
// as the vector to the next point // as the vector to the next point
j = (i - 1 < 0) ? f->numpoints - 1 : i - 1; j = (i - 1 < 0) ? f->numpoints - 1 : i - 1;
@ -71,15 +71,16 @@ Returns NULL if the faces couldn't be merged, or the new face.
The originals will NOT be freed. The originals will NOT be freed.
============= =============
*/ */
face_t *TryMerge (face_t *f1, face_t *f2) face_t *
TryMerge (face_t * f1, face_t * f2)
{ {
vec_t *p1, *p2, *p3, *p4, *back; vec_t *p1, *p2, *p3, *p4, *back;
face_t *newf; face_t *newf;
int i, j, k, l; int i, j, k, l;
vec3_t normal, delta, planenormal; vec3_t normal, delta, planenormal;
vec_t dot; vec_t dot;
plane_t *plane; plane_t *plane;
qboolean keep1, keep2; qboolean keep1, keep2;
if (f1->numpoints == -1 || f2->numpoints == -1) if (f1->numpoints == -1 || f2->numpoints == -1)
return NULL; return NULL;
@ -95,25 +96,22 @@ face_t *TryMerge (face_t *f1, face_t *f2)
// //
// find a common edge // find a common edge
// //
p1 = p2 = NULL; // stop compiler warning p1 = p2 = NULL; // stop compiler warning
j = 0; // j = 0; //
for (i=0 ; i<f1->numpoints ; i++) for (i = 0; i < f1->numpoints; i++) {
{
p1 = f1->pts[i]; p1 = f1->pts[i];
p2 = f1->pts[(i+1)%f1->numpoints]; p2 = f1->pts[(i + 1) % f1->numpoints];
for (j=0 ; j<f2->numpoints ; j++) for (j = 0; j < f2->numpoints; j++) {
{
p3 = f2->pts[j]; p3 = f2->pts[j];
p4 = f2->pts[(j+1)%f2->numpoints]; p4 = f2->pts[(j + 1) % f2->numpoints];
for (k=0 ; k<3 ; k++) for (k = 0; k < 3; k++) {
{ if (fabs (p1[k] - p4[k]) > EQUAL_EPSILON)
if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
break; break;
if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON) if (fabs (p2[k] - p3[k]) > EQUAL_EPSILON)
break; break;
} }
if (k==3) if (k == 3)
break; break;
} }
if (j < f2->numpoints) if (j < f2->numpoints)
@ -121,7 +119,7 @@ face_t *TryMerge (face_t *f1, face_t *f2)
} }
if (i == f1->numpoints) if (i == f1->numpoints)
return NULL; // no matching edges return NULL; // no matching edges
// //
// check slope of connected lines // check slope of connected lines
@ -132,45 +130,43 @@ face_t *TryMerge (face_t *f1, face_t *f2)
if (f1->planeside) if (f1->planeside)
VectorSubtract (vec3_origin, planenormal, planenormal); VectorSubtract (vec3_origin, planenormal, planenormal);
back = f1->pts[(i+f1->numpoints-1)%f1->numpoints]; back = f1->pts[(i + f1->numpoints - 1) % f1->numpoints];
VectorSubtract (p1, back, delta); VectorSubtract (p1, back, delta);
CrossProduct (planenormal, delta, normal); CrossProduct (planenormal, delta, normal);
VectorNormalize (normal); VectorNormalize (normal);
back = f2->pts[(j+2)%f2->numpoints]; back = f2->pts[(j + 2) % f2->numpoints];
VectorSubtract (back, p1, delta); VectorSubtract (back, p1, delta);
dot = DotProduct (delta, normal); dot = DotProduct (delta, normal);
if (dot > CONTINUOUS_EPSILON) if (dot > CONTINUOUS_EPSILON)
return NULL; // not a convex polygon return NULL; // not a convex polygon
keep1 = dot < -CONTINUOUS_EPSILON; keep1 = dot < -CONTINUOUS_EPSILON;
back = f1->pts[(i+2)%f1->numpoints]; back = f1->pts[(i + 2) % f1->numpoints];
VectorSubtract (back, p2, delta); VectorSubtract (back, p2, delta);
CrossProduct (planenormal, delta, normal); CrossProduct (planenormal, delta, normal);
VectorNormalize (normal); VectorNormalize (normal);
back = f2->pts[(j+f2->numpoints-1)%f2->numpoints]; back = f2->pts[(j + f2->numpoints - 1) % f2->numpoints];
VectorSubtract (back, p2, delta); VectorSubtract (back, p2, delta);
dot = DotProduct (delta, normal); dot = DotProduct (delta, normal);
if (dot > CONTINUOUS_EPSILON) if (dot > CONTINUOUS_EPSILON)
return NULL; // not a convex polygon return NULL; // not a convex polygon
keep2 = dot < -CONTINUOUS_EPSILON; keep2 = dot < -CONTINUOUS_EPSILON;
// //
// build the new polygon // build the new polygon
// //
if (f1->numpoints + f2->numpoints > MAXEDGES) if (f1->numpoints + f2->numpoints > MAXEDGES) {
{ // Sys_Error ("TryMerge: too many edges!");
// Sys_Error ("TryMerge: too many edges!");
return NULL; return NULL;
} }
newf = NewFaceFromFace (f1); newf = NewFaceFromFace (f1);
// copy first polygon // copy first polygon
for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints) for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) {
{ if (k == (i + 1) % f1->numpoints && !keep2)
if (k==(i+1)%f1->numpoints && !keep2)
continue; continue;
VectorCopy (f1->pts[k], newf->pts[newf->numpoints]); VectorCopy (f1->pts[k], newf->pts[newf->numpoints]);
@ -178,9 +174,8 @@ face_t *TryMerge (face_t *f1, face_t *f2)
} }
// copy second polygon // copy second polygon
for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints) for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) {
{ if (l == (j + 1) % f2->numpoints && !keep1)
if (l==(j+1)%f2->numpoints && !keep1)
continue; continue;
VectorCopy (f2->pts[l], newf->pts[newf->numpoints]); VectorCopy (f2->pts[l], newf->pts[newf->numpoints]);
newf->numpoints++; newf->numpoints++;
@ -195,26 +190,25 @@ face_t *TryMerge (face_t *f1, face_t *f2)
MergeFaceToList MergeFaceToList
=============== ===============
*/ */
qboolean mergedebug; qboolean mergedebug;
face_t *MergeFaceToList (face_t *face, face_t *list) face_t *
MergeFaceToList (face_t * face, face_t * list)
{ {
face_t *newf, *f; face_t *newf, *f;
for (f=list ; f ; f=f->next) for (f = list; f; f = f->next) {
{
//CheckColinear (f); //CheckColinear (f);
if (mergedebug) if (mergedebug) {
{ Draw_ClearWindow ();
Draw_ClearWindow (); Draw_DrawFace (face);
Draw_DrawFace (face); Draw_DrawFace (f);
Draw_DrawFace (f); Draw_SetBlack ();
Draw_SetBlack (); }
}
newf = TryMerge (face, f); newf = TryMerge (face, f);
if (!newf) if (!newf)
continue; continue;
FreeFace (face); FreeFace (face);
f->numpoints = -1; // merged out f->numpoints = -1; // merged out
return MergeFaceToList (newf, list); return MergeFaceToList (newf, list);
} }
@ -229,18 +223,17 @@ Draw_SetBlack ();
FreeMergeListScraps FreeMergeListScraps
=============== ===============
*/ */
face_t *FreeMergeListScraps (face_t *merged) face_t *
FreeMergeListScraps (face_t * merged)
{ {
face_t *head, *next; face_t *head, *next;
head = NULL; head = NULL;
for ( ; merged ; merged = next) for (; merged; merged = next) {
{
next = merged->next; next = merged->next;
if (merged->numpoints == -1) if (merged->numpoints == -1)
FreeFace (merged); FreeFace (merged);
else else {
{
merged->next = head; merged->next = head;
head = merged; head = merged;
} }
@ -255,15 +248,15 @@ face_t *FreeMergeListScraps (face_t *merged)
MergePlaneFaces MergePlaneFaces
=============== ===============
*/ */
void MergePlaneFaces (surface_t *plane) void
MergePlaneFaces (surface_t * plane)
{ {
face_t *f1, *next; face_t *f1, *next;
face_t *merged; face_t *merged;
merged = NULL; merged = NULL;
for (f1 = plane->faces ; f1 ; f1 = next) for (f1 = plane->faces; f1; f1 = next) {
{
next = f1->next; next = f1->next;
merged = MergeFaceToList (f1, merged); merged = MergeFaceToList (f1, merged);
} }
@ -278,22 +271,21 @@ void MergePlaneFaces (surface_t *plane)
MergeAll MergeAll
============ ============
*/ */
void MergeAll (surface_t *surfhead) void
MergeAll (surface_t * surfhead)
{ {
surface_t *surf; surface_t *surf;
int mergefaces; int mergefaces;
face_t *f; face_t *f;
printf ("---- MergeAll ----\n"); printf ("---- MergeAll ----\n");
mergefaces = 0; mergefaces = 0;
for (surf = surfhead ; surf ; surf=surf->next) for (surf = surfhead; surf; surf = surf->next) {
{
MergePlaneFaces (surf); MergePlaneFaces (surf);
Draw_ClearWindow (); Draw_ClearWindow ();
for (f=surf->faces ; f ; f=f->next) for (f = surf->faces; f; f = f->next) {
{ Draw_DrawFace (f);
Draw_DrawFace (f);
mergefaces++; mergefaces++;
} }
} }

View file

@ -20,54 +20,67 @@
#include "bsp5.h" #include "bsp5.h"
void Draw_ClearBounds (void) void
Draw_ClearBounds (void)
{ {
} }
void Draw_AddToBounds (vec3_t v) void
Draw_AddToBounds (vec3_t v)
{ {
} }
void Draw_DrawFace (face_t *f) void
Draw_DrawFace (face_t * f)
{ {
} }
void Draw_ClearWindow (void) void
Draw_ClearWindow (void)
{ {
} }
void Draw_SetRed (void) void
Draw_SetRed (void)
{ {
} }
void Draw_SetGrey (void) void
Draw_SetGrey (void)
{ {
} }
void Draw_SetBlack (void) void
Draw_SetBlack (void)
{ {
} }
void DrawPoint (vec3_t v) void
DrawPoint (vec3_t v)
{ {
} }
void DrawLeaf (node_t *l, int color) void
DrawLeaf (node_t * l, int color)
{ {
} }
void DrawBrush (brush_t *b) void
DrawBrush (brush_t * b)
{ {
} }
void DrawWinding (winding_t *w) void
DrawWinding (winding_t * w)
{ {
} }
void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3) void
DrawTri (vec3_t p1, vec3_t p2, vec3_t p3)
{ {
} }
void DrawPortal (portal_t *portal) void
DrawPortal (portal_t * portal)
{ {
} }

View file

@ -25,21 +25,24 @@
#include "bsp5.h" #include "bsp5.h"
int outleafs; int outleafs;
/* /*
=========== ===========
PointInLeaf PointInLeaf
=========== ===========
*/ */
node_t *PointInLeaf (node_t *node, vec3_t point) node_t *
PointInLeaf (node_t * node, vec3_t point)
{ {
vec_t d; vec_t d;
if (node->contents) if (node->contents)
return node; return node;
d = DotProduct (planes[node->planenum].normal, point) - planes[node->planenum]. dist; d =
DotProduct (planes[node->planenum].normal,
point) - planes[node->planenum].dist;
if (d > 0) if (d > 0)
return PointInLeaf (node->children[0], point); return PointInLeaf (node->children[0], point);
@ -52,9 +55,10 @@ node_t *PointInLeaf (node_t *node, vec3_t point)
PlaceOccupant PlaceOccupant
=========== ===========
*/ */
qboolean PlaceOccupant (int num, vec3_t point, node_t *headnode) qboolean
PlaceOccupant (int num, vec3_t point, node_t * headnode)
{ {
node_t *n; node_t *n;
n = PointInLeaf (headnode, point); n = PointInLeaf (headnode, point);
if (n->contents == CONTENTS_SOLID) if (n->contents == CONTENTS_SOLID)
@ -69,14 +73,15 @@ qboolean PlaceOccupant (int num, vec3_t point, node_t *headnode)
MarkLeakTrail MarkLeakTrail
============== ==============
*/ */
portal_t *prevleaknode; portal_t *prevleaknode;
FILE *leakfile; FILE *leakfile;
void MarkLeakTrail (portal_t *n2) void
MarkLeakTrail (portal_t * n2)
{ {
int i, j; int i, j;
vec3_t p1, p2, dir; vec3_t p1, p2, dir;
float len; float len;
portal_t *n1; portal_t *n1;
if (hullnum) if (hullnum)
return; return;
@ -88,16 +93,14 @@ void MarkLeakTrail (portal_t *n2)
return; return;
VectorCopy (n2->winding->points[0], p1); VectorCopy (n2->winding->points[0], p1);
for (i=1 ; i< n2->winding->numpoints ; i++) for (i = 1; i < n2->winding->numpoints; i++) {
{ for (j = 0; j < 3; j++)
for (j=0 ; j<3 ; j++)
p1[j] = (p1[j] + n2->winding->points[i][j]) / 2; p1[j] = (p1[j] + n2->winding->points[i][j]) / 2;
} }
VectorCopy (n1->winding->points[0], p2); VectorCopy (n1->winding->points[0], p2);
for (i=1 ; i< n1->winding->numpoints ; i++) for (i = 1; i < n1->winding->numpoints; i++) {
{ for (j = 0; j < 3; j++)
for (j=0 ; j<3 ; j++)
p2[j] = (p2[j] + n1->winding->points[i][j]) / 2; p2[j] = (p2[j] + n1->winding->points[i][j]) / 2;
} }
@ -105,11 +108,10 @@ void MarkLeakTrail (portal_t *n2)
len = VectorLength (dir); len = VectorLength (dir);
VectorNormalize (dir); VectorNormalize (dir);
while (len > 2) while (len > 2) {
{ fprintf (leakfile, "%f %f %f\n", p1[0], p1[1], p1[2]);
fprintf (leakfile,"%f %f %f\n", p1[0], p1[1], p1[2]); for (i = 0; i < 3; i++)
for (i=0 ; i<3 ; i++) p1[i] += dir[i] * 2;
p1[i] += dir[i]*2;
len -= 2; len -= 2;
} }
} }
@ -122,12 +124,13 @@ If fill is false, just check, don't fill
Returns true if an occupied leaf is reached Returns true if an occupied leaf is reached
================== ==================
*/ */
int hit_occupied; int hit_occupied;
int backdraw; int backdraw;
qboolean RecursiveFillOutside (node_t *l, qboolean fill) qboolean
RecursiveFillOutside (node_t * l, qboolean fill)
{ {
portal_t *p; portal_t *p;
int s; int s;
if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY) if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY)
return false; return false;
@ -145,14 +148,12 @@ qboolean RecursiveFillOutside (node_t *l, qboolean fill)
l->contents = CONTENTS_SOLID; l->contents = CONTENTS_SOLID;
outleafs++; outleafs++;
for (p=l->portals ; p ; ) for (p = l->portals; p;) {
{
s = (p->nodes[0] == l); s = (p->nodes[0] == l);
if (RecursiveFillOutside (p->nodes[s], fill) ) if (RecursiveFillOutside (p->nodes[s], fill)) { // leaked, so stop
{ // leaked, so stop filling // filling
if (backdraw-- > 0) if (backdraw-- > 0) {
{
MarkLeakTrail (p); MarkLeakTrail (p);
DrawLeaf (l, 2); DrawLeaf (l, 2);
} }
@ -170,12 +171,12 @@ ClearOutFaces
================== ==================
*/ */
void ClearOutFaces (node_t *node) void
ClearOutFaces (node_t * node)
{ {
face_t **fp; face_t **fp;
if (node->planenum != -1) if (node->planenum != -1) {
{
ClearOutFaces (node->children[0]); ClearOutFaces (node->children[0]);
ClearOutFaces (node->children[1]); ClearOutFaces (node->children[1]);
return; return;
@ -183,9 +184,8 @@ void ClearOutFaces (node_t *node)
if (node->contents != CONTENTS_SOLID) if (node->contents != CONTENTS_SOLID)
return; return;
for (fp=node->markfaces ; *fp ; fp++) for (fp = node->markfaces; *fp; fp++) {
{ // mark all the original faces that are removed
// mark all the original faces that are removed
(*fp)->numpoints = 0; (*fp)->numpoints = 0;
} }
node->faces = NULL; node->faces = NULL;
@ -200,34 +200,33 @@ FillOutside
=========== ===========
*/ */
qboolean FillOutside (node_t *node) qboolean
FillOutside (node_t * node)
{ {
int s; int s;
vec_t *v; vec_t *v;
int i; int i;
qboolean inside; qboolean inside;
qprintf ("----- FillOutside ----\n"); qprintf ("----- FillOutside ----\n");
if (nofill) if (nofill) {
{
printf ("skipped\n"); printf ("skipped\n");
return false; return false;
} }
inside = false; inside = false;
for (i=1 ; i<num_entities ; i++) for (i = 1; i < num_entities; i++) {
{ if (!VectorCompare (entities[i].origin, vec3_origin)) {
if (!VectorCompare(entities[i].origin, vec3_origin))
{
if (PlaceOccupant (i, entities[i].origin, node)) if (PlaceOccupant (i, entities[i].origin, node))
inside = true; inside = true;
} }
} }
if (!inside) if (!inside) {
{ printf
printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); ("Hullnum %i: No entities in empty space -- no filling performed\n",
hullnum);
return false; return false;
} }
@ -239,19 +238,17 @@ qboolean FillOutside (node_t *node)
prevleaknode = NULL; prevleaknode = NULL;
if (!hullnum) if (!hullnum) {
{
leakfile = fopen (pointfilename, "w"); leakfile = fopen (pointfilename, "w");
if (!leakfile) if (!leakfile)
Sys_Error ("Couldn't open %s\n", pointfilename); Sys_Error ("Couldn't open %s\n", pointfilename);
} }
if (RecursiveFillOutside (outside_node.portals->nodes[s], false)) if (RecursiveFillOutside (outside_node.portals->nodes[s], false)) {
{
v = entities[hit_occupied].origin; v = entities[hit_occupied].origin;
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n", v[0], v[1],
, v[0], v[1], v[2]); v[2]);
qprintf ("no filling performed\n"); qprintf ("no filling performed\n");
if (!hullnum) if (!hullnum)
fclose (leakfile); fclose (leakfile);
@ -272,5 +269,3 @@ qboolean FillOutside (node_t *node)
qprintf ("%4i outleafs\n", outleafs); qprintf ("%4i outleafs\n", outleafs);
return true; return true;
} }

View file

@ -26,7 +26,9 @@
#include "bsp5.h" #include "bsp5.h"
node_t outside_node; // portals outside the world face this node_t outside_node; // portals outside the world face
// this
//============================================================================= //=============================================================================
@ -35,7 +37,8 @@ node_t outside_node; // portals outside the world face this
AddPortalToNodes AddPortalToNodes
============= =============
*/ */
void AddPortalToNodes (portal_t *p, node_t *front, node_t *back) void
AddPortalToNodes (portal_t * p, node_t * front, node_t * back)
{ {
if (p->nodes[0] || p->nodes[1]) if (p->nodes[0] || p->nodes[1])
Sys_Error ("AddPortalToNode: allready included"); Sys_Error ("AddPortalToNode: allready included");
@ -55,19 +58,19 @@ void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
RemovePortalFromNode RemovePortalFromNode
============= =============
*/ */
void RemovePortalFromNode (portal_t *portal, node_t *l) void
RemovePortalFromNode (portal_t * portal, node_t * l)
{ {
portal_t **pp, *t; portal_t **pp, *t;
// remove reference to the current portal // remove reference to the current portal
pp = &l->portals; pp = &l->portals;
while (1) while (1) {
{
t = *pp; t = *pp;
if (!t) if (!t)
Sys_Error ("RemovePortalFromNode: portal not in leaf"); Sys_Error ("RemovePortalFromNode: portal not in leaf");
if ( t == portal ) if (t == portal)
break; break;
if (t->nodes[0] == l) if (t->nodes[0] == l)
@ -78,13 +81,10 @@ void RemovePortalFromNode (portal_t *portal, node_t *l)
Sys_Error ("RemovePortalFromNode: portal not bounding leaf"); Sys_Error ("RemovePortalFromNode: portal not bounding leaf");
} }
if (portal->nodes[0] == l) if (portal->nodes[0] == l) {
{
*pp = portal->next[0]; *pp = portal->next[0];
portal->nodes[0] = NULL; portal->nodes[0] = NULL;
} } else if (portal->nodes[1] == l) {
else if (portal->nodes[1] == l)
{
*pp = portal->next[1]; *pp = portal->next[1];
portal->nodes[1] = NULL; portal->nodes[1] = NULL;
} }
@ -92,15 +92,16 @@ void RemovePortalFromNode (portal_t *portal, node_t *l)
//============================================================================ //============================================================================
void PrintPortal (portal_t *p) void
PrintPortal (portal_t * p)
{ {
int i; int i;
winding_t *w; winding_t *w;
w = p->winding; w = p->winding;
for (i=0 ; i<w->numpoints ; i++) for (i = 0; i < w->numpoints; i++)
printf ("(%5.0f,%5.0f,%5.0f)\n",w->points[i][0] printf ("(%5.0f,%5.0f,%5.0f)\n", w->points[i][0]
, w->points[i][1], w->points[i][2]); , w->points[i][1], w->points[i][2]);
} }
/* /*
@ -110,19 +111,19 @@ MakeHeadnodePortals
The created portals will face the global outside_node The created portals will face the global outside_node
================ ================
*/ */
void MakeHeadnodePortals (node_t *node) void
MakeHeadnodePortals (node_t * node)
{ {
vec3_t bounds[2]; vec3_t bounds[2];
int i, j, n; int i, j, n;
portal_t *p, *portals[6]; portal_t *p, *portals[6];
plane_t bplanes[6], *pl; plane_t bplanes[6], *pl;
int side; int side;
Draw_ClearWindow (); Draw_ClearWindow ();
// pad with some space so there will never be null volume leafs // pad with some space so there will never be null volume leafs
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
bounds[0][i] = brushset->mins[i] - SIDESPACE; bounds[0][i] = brushset->mins[i] - SIDESPACE;
bounds[1][i] = brushset->maxs[i] + SIDESPACE; bounds[1][i] = brushset->maxs[i] + SIDESPACE;
} }
@ -130,23 +131,19 @@ void MakeHeadnodePortals (node_t *node)
outside_node.contents = CONTENTS_SOLID; outside_node.contents = CONTENTS_SOLID;
outside_node.portals = NULL; outside_node.portals = NULL;
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++)
for (j=0 ; j<2 ; j++) for (j = 0; j < 2; j++) {
{ n = j * 3 + i;
n = j*3 + i;
p = AllocPortal (); p = AllocPortal ();
portals[n] = p; portals[n] = p;
pl = &bplanes[n]; pl = &bplanes[n];
memset (pl, 0, sizeof(*pl)); memset (pl, 0, sizeof (*pl));
if (j) if (j) {
{
pl->normal[i] = -1; pl->normal[i] = -1;
pl->dist = -bounds[j][i]; pl->dist = -bounds[j][i];
} } else {
else
{
pl->normal[i] = 1; pl->normal[i] = 1;
pl->dist = bounds[j][i]; pl->dist = bounds[j][i];
} }
@ -160,58 +157,57 @@ void MakeHeadnodePortals (node_t *node)
} }
// clip the basewindings by all the other planes // clip the basewindings by all the other planes
for (i=0 ; i<6 ; i++) for (i = 0; i < 6; i++) {
{ for (j = 0; j < 6; j++) {
for (j=0 ; j<6 ; j++)
{
if (j == i) if (j == i)
continue; continue;
portals[i]->winding = ClipWinding (portals[i]->winding, &bplanes[j], true); portals[i]->winding =
ClipWinding (portals[i]->winding, &bplanes[j], true);
} }
} }
} }
//============================================================================ //============================================================================
void CheckWindingInNode (winding_t *w, node_t *node) void
CheckWindingInNode (winding_t * w, node_t * node)
{ {
int i, j; int i, j;
for (i=0 ; i<w->numpoints ; i++) for (i = 0; i < w->numpoints; i++) {
{ for (j = 0; j < 3; j++)
for (j=0 ; j<3 ; j++)
if (w->points[i][j] < node->mins[j] - 1 if (w->points[i][j] < node->mins[j] - 1
|| w->points[i][j] > node->maxs[j] + 1) || w->points[i][j] > node->maxs[j] + 1) {
{
printf ("WARNING: CheckWindingInNode: outside\n"); printf ("WARNING: CheckWindingInNode: outside\n");
return; return;
} }
} }
} }
void CheckWindingArea (winding_t *w) void
CheckWindingArea (winding_t * w)
{ {
int i; int i;
float total, add; float total, add;
vec3_t v1, v2, cross; vec3_t v1, v2, cross;
total = 0; total = 0;
for (i=1 ; i<w->numpoints ; i++) for (i = 1; i < w->numpoints; i++) {
{
VectorSubtract (w->points[i], w->points[0], v1); VectorSubtract (w->points[i], w->points[0], v1);
VectorSubtract (w->points[i+1], w->points[0], v2); VectorSubtract (w->points[i + 1], w->points[0], v2);
CrossProduct (v1, v2, cross); CrossProduct (v1, v2, cross);
add = VectorLength (cross); add = VectorLength (cross);
total += add*0.5; total += add * 0.5;
} }
if (total < 16) if (total < 16)
printf ("WARNING: winding area %f\n", total); printf ("WARNING: winding area %f\n", total);
} }
void PlaneFromWinding (winding_t *w, plane_t *plane) void
PlaneFromWinding (winding_t * w, plane_t *plane)
{ {
vec3_t v1, v2; vec3_t v1, v2;
// calc plane // calc plane
VectorSubtract (w->points[2], w->points[1], v1); VectorSubtract (w->points[2], w->points[1], v1);
@ -221,19 +217,19 @@ void PlaneFromWinding (winding_t *w, plane_t *plane)
plane->dist = DotProduct (w->points[0], plane->normal); plane->dist = DotProduct (w->points[0], plane->normal);
} }
void CheckLeafPortalConsistancy (node_t *node) void
CheckLeafPortalConsistancy (node_t * node)
{ {
int side, side2; int side, side2;
portal_t *p, *p2; portal_t *p, *p2;
plane_t plane, plane2; plane_t plane, plane2;
int i; int i;
winding_t *w; winding_t *w;
float dist; float dist;
side = side2 = 0; // quiet compiler warning side = side2 = 0; // quiet compiler warning
for (p = node->portals ; p ; p = p->next[side]) for (p = node->portals; p; p = p->next[side]) {
{
if (p->nodes[0] == node) if (p->nodes[0] == node)
side = 0; side = 0;
else if (p->nodes[1] == node) else if (p->nodes[1] == node)
@ -243,12 +239,11 @@ void CheckLeafPortalConsistancy (node_t *node)
CheckWindingInNode (p->winding, node); CheckWindingInNode (p->winding, node);
CheckWindingArea (p->winding); CheckWindingArea (p->winding);
// check that the side orders are correct // check that the side orders are correct
plane = planes[p->planenum]; plane = planes[p->planenum];
PlaneFromWinding (p->winding, &plane2); PlaneFromWinding (p->winding, &plane2);
for (p2 = node->portals ; p2 ; p2 = p2->next[side2]) for (p2 = node->portals; p2; p2 = p2->next[side2]) {
{
if (p2->nodes[0] == node) if (p2->nodes[0] == node)
side2 = 0; side2 = 0;
else if (p2->nodes[1] == node) else if (p2->nodes[1] == node)
@ -256,11 +251,9 @@ void CheckLeafPortalConsistancy (node_t *node)
else else
Sys_Error ("CutNodePortals_r: mislinked portal"); Sys_Error ("CutNodePortals_r: mislinked portal");
w = p2->winding; w = p2->winding;
for (i=0 ; i<w->numpoints ; i++) for (i = 0; i < w->numpoints; i++) {
{
dist = DotProduct (w->points[i], plane.normal) - plane.dist; dist = DotProduct (w->points[i], plane.normal) - plane.dist;
if ( (side == 0 && dist < -1) || (side == 1 && dist > 1) ) if ((side == 0 && dist < -1) || (side == 1 && dist > 1)) {
{
printf ("WARNING: portal siding direction is wrong\n"); printf ("WARNING: portal siding direction is wrong\n");
return; return;
} }
@ -277,22 +270,22 @@ CutNodePortals_r
================ ================
*/ */
void CutNodePortals_r (node_t *node) void
CutNodePortals_r (node_t * node)
{ {
plane_t *plane, clipplane; plane_t *plane, clipplane;
node_t *f, *b, *other_node; node_t *f, *b, *other_node;
portal_t *p, *new_portal, *next_portal; portal_t *p, *new_portal, *next_portal;
winding_t *w, *frontwinding, *backwinding; winding_t *w, *frontwinding, *backwinding;
int side; int side;
// CheckLeafPortalConsistancy (node); // CheckLeafPortalConsistancy (node);
// //
// seperate the portals on node into it's children // seperate the portals on node into it's children
// //
if (node->contents) if (node->contents) {
{ return; // at a leaf, no more dividing
return; // at a leaf, no more dividing
} }
plane = &planes[node->planenum]; plane = &planes[node->planenum];
@ -308,41 +301,34 @@ void CutNodePortals_r (node_t *node)
new_portal->planenum = node->planenum; new_portal->planenum = node->planenum;
w = BaseWindingForPlane (&planes[node->planenum]); w = BaseWindingForPlane (&planes[node->planenum]);
side = 0; // shut up compiler warning side = 0; // shut up compiler warning
for (p = node->portals ; p ; p = p->next[side]) for (p = node->portals; p; p = p->next[side]) {
{
clipplane = planes[p->planenum]; clipplane = planes[p->planenum];
if (p->nodes[0] == node) if (p->nodes[0] == node)
side = 0; side = 0;
else if (p->nodes[1] == node) else if (p->nodes[1] == node) {
{
clipplane.dist = -clipplane.dist; clipplane.dist = -clipplane.dist;
VectorSubtract (vec3_origin, clipplane.normal, clipplane.normal); VectorSubtract (vec3_origin, clipplane.normal, clipplane.normal);
side = 1; side = 1;
} } else
else
Sys_Error ("CutNodePortals_r: mislinked portal"); Sys_Error ("CutNodePortals_r: mislinked portal");
w = ClipWinding (w, &clipplane, true); w = ClipWinding (w, &clipplane, true);
if (!w) if (!w) {
{
printf ("WARNING: CutNodePortals_r:new portal was clipped away\n"); printf ("WARNING: CutNodePortals_r:new portal was clipped away\n");
break; break;
} }
} }
if (w) if (w) {
{ // if the plane was not clipped on all sides, there was an error
// if the plane was not clipped on all sides, there was an error
new_portal->winding = w; new_portal->winding = w;
AddPortalToNodes (new_portal, f, b); AddPortalToNodes (new_portal, f, b);
} }
// //
// partition the portals // partition the portals
// //
for (p = node->portals ; p ; p = next_portal) for (p = node->portals; p; p = next_portal) {
{
if (p->nodes[0] == node) if (p->nodes[0] == node)
side = 0; side = 0;
else if (p->nodes[1] == node) else if (p->nodes[1] == node)
@ -360,44 +346,38 @@ void CutNodePortals_r (node_t *node)
// //
DivideWinding (p->winding, plane, &frontwinding, &backwinding); DivideWinding (p->winding, plane, &frontwinding, &backwinding);
if (!frontwinding) if (!frontwinding) {
{
if (side == 0) if (side == 0)
AddPortalToNodes (p, b, other_node); AddPortalToNodes (p, b, other_node);
else else
AddPortalToNodes (p, other_node, b); AddPortalToNodes (p, other_node, b);
continue; continue;
} }
if (!backwinding) if (!backwinding) {
{
if (side == 0) if (side == 0)
AddPortalToNodes (p, f, other_node); AddPortalToNodes (p, f, other_node);
else else
AddPortalToNodes (p, other_node, f); AddPortalToNodes (p, other_node, f);
continue; continue;
} }
// the winding is split
// the winding is split
new_portal = AllocPortal (); new_portal = AllocPortal ();
*new_portal = *p; *new_portal = *p;
new_portal->winding = backwinding; new_portal->winding = backwinding;
FreeWinding (p->winding); FreeWinding (p->winding);
p->winding = frontwinding; p->winding = frontwinding;
if (side == 0) if (side == 0) {
{
AddPortalToNodes (p, f, other_node); AddPortalToNodes (p, f, other_node);
AddPortalToNodes (new_portal, b, other_node); AddPortalToNodes (new_portal, b, other_node);
} } else {
else
{
AddPortalToNodes (p, other_node, f); AddPortalToNodes (p, other_node, f);
AddPortalToNodes (new_portal, other_node, b); AddPortalToNodes (new_portal, other_node, b);
} }
} }
DrawLeaf (f,1); DrawLeaf (f, 1);
DrawLeaf (b,2); DrawLeaf (b, 2);
CutNodePortals_r (f); CutNodePortals_r (f);
CutNodePortals_r (b); CutNodePortals_r (b);
@ -412,7 +392,8 @@ PortalizeWorld
Builds the exact polyhedrons for the nodes and leafs Builds the exact polyhedrons for the nodes and leafs
================== ==================
*/ */
void PortalizeWorld (node_t *headnode) void
PortalizeWorld (node_t * headnode)
{ {
qprintf ("----- portalize ----\n"); qprintf ("----- portalize ----\n");
@ -427,18 +408,17 @@ FreeAllPortals
================== ==================
*/ */
void FreeAllPortals (node_t *node) void
FreeAllPortals (node_t * node)
{ {
portal_t *p, *nextp; portal_t *p, *nextp;
if (!node->contents) if (!node->contents) {
{
FreeAllPortals (node->children[0]); FreeAllPortals (node->children[0]);
FreeAllPortals (node->children[1]); FreeAllPortals (node->children[1]);
} }
for (p=node->portals ; p ; p=nextp) for (p = node->portals; p; p = nextp) {
{
if (p->nodes[0] == node) if (p->nodes[0] == node)
nextp = p->next[0]; nextp = p->next[0];
else else
@ -460,27 +440,28 @@ PORTAL FILE GENERATION
#define PORTALFILE "PRT1" #define PORTALFILE "PRT1"
FILE *pf; FILE *pf;
int num_visleafs; // leafs the player can be in int num_visleafs; // leafs the player can be in
int num_visportals; int num_visportals;
void WriteFloat (FILE *f, vec_t v) void
WriteFloat (FILE * f, vec_t v)
{ {
if ( fabs(v - (int) (v + 0.5)) < 0.001 ) if (fabs (v - (int) (v + 0.5)) < 0.001)
fprintf (f,"%i ",(int)(v + 0.5)); fprintf (f, "%i ", (int) (v + 0.5));
else else
fprintf (f,"%f ",v); fprintf (f, "%f ", v);
} }
void WritePortalFile_r (node_t *node) void
WritePortalFile_r (node_t * node)
{ {
int i; int i;
portal_t *p; portal_t *p;
winding_t *w; winding_t *w;
plane_t *pl, plane2; plane_t *pl, plane2;
if (!node->contents) if (!node->contents) {
{
WritePortalFile_r (node->children[0]); WritePortalFile_r (node->children[0]);
WritePortalFile_r (node->children[1]); WritePortalFile_r (node->children[1]);
return; return;
@ -489,34 +470,32 @@ void WritePortalFile_r (node_t *node)
if (node->contents == CONTENTS_SOLID) if (node->contents == CONTENTS_SOLID)
return; return;
for (p = node->portals ; p ; ) for (p = node->portals; p;) {
{
w = p->winding; w = p->winding;
if (w && p->nodes[0] == node if (w && p->nodes[0] == node
&& p->nodes[0]->contents == p->nodes[1]->contents) && p->nodes[0]->contents == p->nodes[1]->contents) {
{ // write out to the file
// write out to the file
// sometimes planes get turned around when they are very near // sometimes planes get turned around when they are very near
// the changeover point between different axis. interpret the // the changeover point between different axis. interpret the
// plane the same way vis will, and flip the side orders if needed // plane the same way vis will, and flip the side orders if
// needed
pl = &planes[p->planenum]; pl = &planes[p->planenum];
PlaneFromWinding (w, &plane2); PlaneFromWinding (w, &plane2);
if ( DotProduct (pl->normal, plane2.normal) < 0.99 ) if (DotProduct (pl->normal, plane2.normal) < 0.99) { // backwards...
{ // backwards... fprintf (pf, "%i %i %i ", w->numpoints, p->nodes[1]->visleafnum,
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum); p->nodes[0]->visleafnum);
} } else
else fprintf (pf, "%i %i %i ", w->numpoints, p->nodes[0]->visleafnum,
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum); p->nodes[1]->visleafnum);
for (i=0 ; i<w->numpoints ; i++) for (i = 0; i < w->numpoints; i++) {
{ fprintf (pf, "(");
fprintf (pf,"(");
WriteFloat (pf, w->points[i][0]); WriteFloat (pf, w->points[i][0]);
WriteFloat (pf, w->points[i][1]); WriteFloat (pf, w->points[i][1]);
WriteFloat (pf, w->points[i][2]); WriteFloat (pf, w->points[i][2]);
fprintf (pf,") "); fprintf (pf, ") ");
} }
fprintf (pf,"\n"); fprintf (pf, "\n");
} }
if (p->nodes[0] == node) if (p->nodes[0] == node)
@ -532,12 +511,12 @@ void WritePortalFile_r (node_t *node)
NumberLeafs_r NumberLeafs_r
================ ================
*/ */
void NumberLeafs_r (node_t *node) void
NumberLeafs_r (node_t * node)
{ {
portal_t *p; portal_t *p;
if (!node->contents) if (!node->contents) { // decision node
{ // decision node
node->visleafnum = -99; node->visleafnum = -99;
NumberLeafs_r (node->children[0]); NumberLeafs_r (node->children[0]);
NumberLeafs_r (node->children[1]); NumberLeafs_r (node->children[1]);
@ -547,23 +526,21 @@ void NumberLeafs_r (node_t *node)
Draw_ClearWindow (); Draw_ClearWindow ();
DrawLeaf (node, 1); DrawLeaf (node, 1);
if (node->contents == CONTENTS_SOLID) if (node->contents == CONTENTS_SOLID) { // solid block, viewpoint never
{ // solid block, viewpoint never inside // inside
node->visleafnum = -1; node->visleafnum = -1;
return; return;
} }
node->visleafnum = num_visleafs++; node->visleafnum = num_visleafs++;
for (p = node->portals ; p ; ) for (p = node->portals; p;) {
{
if (p->nodes[0] == node) // only write out from first leaf if (p->nodes[0] == node) // only write out from first leaf
{ {
if (p->nodes[0]->contents == p->nodes[1]->contents) if (p->nodes[0]->contents == p->nodes[1]->contents)
num_visportals++; num_visportals++;
p = p->next[0]; p = p->next[0];
} } else
else
p = p->next[1]; p = p->next[1];
} }
@ -575,7 +552,8 @@ void NumberLeafs_r (node_t *node)
WritePortalfile WritePortalfile
================ ================
*/ */
void WritePortalfile (node_t *headnode) void
WritePortalfile (node_t * headnode)
{ {
// set the visleafnum field in every leaf and count the total number of portals // set the visleafnum field in every leaf and count the total number of portals
num_visleafs = 0; num_visleafs = 0;
@ -596,5 +574,3 @@ void WritePortalfile (node_t *headnode)
fclose (pf); fclose (pf);
} }

File diff suppressed because it is too large Load diff

View file

@ -47,16 +47,16 @@ face to region mapping numbers
#define MAX_EDGES_IN_REGION 32 #define MAX_EDGES_IN_REGION 32
int firstedge; int firstedge;
vec3_t region_mins, region_maxs; vec3_t region_mins, region_maxs;
void AddPointToRegion (vec3_t p) void
AddPointToRegion (vec3_t p)
{ {
int i; int i;
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
if (p[i] < region_mins[i]) if (p[i] < region_mins[i])
region_mins[i] = p[i]; region_mins[i] = p[i];
if (p[i] > region_maxs[i]) if (p[i] > region_maxs[i])
@ -64,17 +64,19 @@ void AddPointToRegion (vec3_t p)
} }
} }
void ClearRegionSize (void) void
ClearRegionSize (void)
{ {
region_mins[0] = region_mins[1] = region_mins[2] = 9999; region_mins[0] = region_mins[1] = region_mins[2] = 9999;
region_maxs[0] = region_maxs[1] = region_maxs[2] = -9999; region_maxs[0] = region_maxs[1] = region_maxs[2] = -9999;
} }
void AddFaceToRegionSize (face_t *f) void
AddFaceToRegionSize (face_t * f)
{ {
int i; int i;
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++)
AddPointToRegion (f->pts[i]); AddPointToRegion (f->pts[i]);
} }
@ -83,43 +85,37 @@ void AddFaceToRegionSize (face_t *f)
CanJoinFaces CanJoinFaces
============== ==============
*/ */
qboolean CanJoinFaces (face_t *f, face_t *f2) qboolean
CanJoinFaces (face_t * f, face_t * f2)
{ {
vec3_t oldmins, oldmaxs; vec3_t oldmins, oldmaxs;
int i; int i;
if (f2->planenum != f->planenum if (f2->planenum != f->planenum
|| f2->planeside != f->planeside || f2->planeside != f->planeside || f2->texturenum != f->texturenum)
|| f2->texturenum != f->texturenum)
return false; return false;
if (f2->outputnumber != -1) if (f2->outputnumber != -1)
return false; return false;
if (f2->contents[0] != f->contents[0]) if (f2->contents[0] != f->contents[0]) { // does this ever happen?
{ // does this ever happen? theyy shouldn't share. // theyy shouldn't share.
printf ("CanJoinFaces: edge with different contents"); printf ("CanJoinFaces: edge with different contents");
return false; return false;
} }
// check size constraints // check size constraints
if ( ! (bsp->texinfo[f->texturenum].flags & TEX_SPECIAL) ) if (!(bsp->texinfo[f->texturenum].flags & TEX_SPECIAL)) {
{
VectorCopy (region_mins, oldmins); VectorCopy (region_mins, oldmins);
VectorCopy (region_maxs, oldmaxs); VectorCopy (region_maxs, oldmaxs);
AddFaceToRegionSize (f2); AddFaceToRegionSize (f2);
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{ if (region_maxs[i] - region_mins[i] > 240) {
if (region_maxs[i] - region_mins[i] > 240)
{
VectorCopy (oldmins, region_mins); VectorCopy (oldmins, region_mins);
VectorCopy (oldmaxs, region_maxs); VectorCopy (oldmaxs, region_maxs);
return false; return false;
} }
} }
} } else {
else
{
if (bsp->numsurfedges - firstedge + f2->numpoints > MAX_EDGES_IN_REGION) if (bsp->numsurfedges - firstedge + f2->numpoints > MAX_EDGES_IN_REGION)
return false; // a huge water or sky polygon return false; // a huge water or sky polygon
} }
// check edge count constraints // check edge count constraints
@ -132,11 +128,12 @@ qboolean CanJoinFaces (face_t *f, face_t *f2)
RecursiveGrowRegion RecursiveGrowRegion
============== ==============
*/ */
void RecursiveGrowRegion (dface_t *r, face_t *f) void
RecursiveGrowRegion (dface_t *r, face_t * f)
{ {
int e; int e;
face_t *f2; face_t *f2;
int i; int i;
if (f->outputnumber == bsp->numfaces) if (f->outputnumber == bsp->numfaces)
return; return;
@ -146,30 +143,26 @@ void RecursiveGrowRegion (dface_t *r, face_t *f)
f->outputnumber = bsp->numfaces; f->outputnumber = bsp->numfaces;
// add edges // add edges
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++) {
{
e = f->edges[i]; e = f->edges[i];
if (!edgefaces[abs(e)][0]) if (!edgefaces[abs (e)][0])
continue; // edge has allready been removed continue; // edge has allready been removed
if (e > 0) if (e > 0)
f2 = edgefaces[e][1]; f2 = edgefaces[e][1];
else else
f2 = edgefaces[-e][0]; f2 = edgefaces[-e][0];
if (f2 && f2->outputnumber == bsp->numfaces) if (f2 && f2->outputnumber == bsp->numfaces) {
{ edgefaces[abs (e)][0] = NULL;
edgefaces[abs(e)][0] = NULL; edgefaces[abs (e)][1] = NULL;
edgefaces[abs(e)][1] = NULL; continue; // allready merged
continue; // allready merged
} }
if (f2 && CanJoinFaces (f, f2)) if (f2 && CanJoinFaces (f, f2)) { // remove the edge and merge the
{ // remove the edge and merge the faces // faces
edgefaces[abs(e)][0] = NULL; edgefaces[abs (e)][0] = NULL;
edgefaces[abs(e)][1] = NULL; edgefaces[abs (e)][1] = NULL;
RecursiveGrowRegion (r, f2); RecursiveGrowRegion (r, f2);
} } else {
else // emit a surfedge
{
// emit a surfedge
if (bsp->numsurfedges == MAX_MAP_SURFEDGES) if (bsp->numsurfedges == MAX_MAP_SURFEDGES)
Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES"); Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES");
bsp->surfedges[bsp->numsurfedges] = e; bsp->surfedges[bsp->numsurfedges] = e;
@ -179,17 +172,17 @@ void RecursiveGrowRegion (dface_t *r, face_t *f)
} }
void PrintDface (int f) void
{ // for debugging PrintDface (int f)
dface_t *df; { // for debugging
dedge_t *e; dface_t *df;
int i, n; dedge_t *e;
int i, n;
df = &bsp->faces[f]; df = &bsp->faces[f];
for (i=0 ; i<df->numedges ; i++) for (i = 0; i < df->numedges; i++) {
{ n = bsp->surfedges[df->firstedge + i];
n = bsp->surfedges[df->firstedge+i]; e = &bsp->edges[abs (n)];
e = &bsp->edges[abs(n)];
if (n < 0) if (n < 0)
printf ("%5i = %5i : %5i\n", n, e->v[1], e->v[0]); printf ("%5i = %5i : %5i\n", n, e->v[1], e->v[0]);
else else
@ -197,21 +190,19 @@ void PrintDface (int f)
} }
} }
void FindVertexUse (int v) void
{ // for debugging FindVertexUse (int v)
int i, j, n; { // for debugging
dface_t *df; int i, j, n;
dedge_t *e; dface_t *df;
dedge_t *e;
for (i=firstmodelface ; i<bsp->numfaces ; i++) for (i = firstmodelface; i < bsp->numfaces; i++) {
{
df = &bsp->faces[i]; df = &bsp->faces[i];
for (j=0 ; j<df->numedges ; j++) for (j = 0; j < df->numedges; j++) {
{ n = bsp->surfedges[df->firstedge + j];
n = bsp->surfedges[df->firstedge+j]; e = &bsp->edges[abs (n)];
e = &bsp->edges[abs(n)]; if (e->v[0] == v || e->v[1] == v) {
if (e->v[0] == v || e->v[1] == v)
{
printf ("on face %i\n", i); printf ("on face %i\n", i);
break; break;
} }
@ -219,19 +210,17 @@ void FindVertexUse (int v)
} }
} }
void FindEdgeUse (int v) void
{ // for debugging FindEdgeUse (int v)
int i, j, n; { // for debugging
dface_t *df; int i, j, n;
dface_t *df;
for (i=firstmodelface ; i<bsp->numfaces ; i++) for (i = firstmodelface; i < bsp->numfaces; i++) {
{
df = &bsp->faces[i]; df = &bsp->faces[i];
for (j=0 ; j<df->numedges ; j++) for (j = 0; j < df->numedges; j++) {
{ n = bsp->surfedges[df->firstedge + j];
n = bsp->surfedges[df->firstedge+j]; if (n == v || -n == v) {
if (n == v || -n == v)
{
printf ("on face %i\n", i); printf ("on face %i\n", i);
break; break;
} }
@ -247,24 +236,26 @@ Extends e1 so that it goes all the way to e2, and removes all references
to e2 to e2
================ ================
*/ */
int edgemapping[MAX_MAP_EDGES]; int edgemapping[MAX_MAP_EDGES];
void HealEdges (int e1, int e2) void
HealEdges (int e1, int e2)
{ {
int i, j, n, saved; int i, j, n, saved;
dface_t *df; dface_t *df;
dedge_t *ed, *ed2; dedge_t *ed, *ed2;
vec3_t v1, v2; vec3_t v1, v2;
dface_t *found[2]; dface_t *found[2];
int foundj[2]; int foundj[2];
return; return;
e1 = edgemapping[e1]; e1 = edgemapping[e1];
e2 = edgemapping[e2]; e2 = edgemapping[e2];
// extend e1 to e2 // extend e1 to e2
ed = &bsp->edges[e1]; ed = &bsp->edges[e1];
ed2 = &bsp->edges[e2]; ed2 = &bsp->edges[e2];
VectorSubtract (bsp->vertexes[ed->v[1]].point, bsp->vertexes[ed->v[0]].point, v1); VectorSubtract (bsp->vertexes[ed->v[1]].point,
bsp->vertexes[ed->v[0]].point, v1);
VectorNormalize (v1); VectorNormalize (v1);
if (ed->v[0] == ed2->v[0]) if (ed->v[0] == ed2->v[0])
@ -278,7 +269,8 @@ return;
else else
Sys_Error ("HealEdges: edges don't meet"); Sys_Error ("HealEdges: edges don't meet");
VectorSubtract (bsp->vertexes[ed->v[1]].point, bsp->vertexes[ed->v[0]].point, v2); VectorSubtract (bsp->vertexes[ed->v[1]].point,
bsp->vertexes[ed->v[0]].point, v2);
VectorNormalize (v2); VectorNormalize (v2);
if (!VectorCompare (v1, v2)) if (!VectorCompare (v1, v2))
@ -288,14 +280,11 @@ return;
saved = 0; saved = 0;
// remove all uses of e2 // remove all uses of e2
for (i=firstmodelface ; i<bsp->numfaces ; i++) for (i = firstmodelface; i < bsp->numfaces; i++) {
{
df = &bsp->faces[i]; df = &bsp->faces[i];
for (j=0 ; j<df->numedges ; j++) for (j = 0; j < df->numedges; j++) {
{ n = bsp->surfedges[df->firstedge + j];
n = bsp->surfedges[df->firstedge+j]; if (n == e2 || n == -e2) {
if (n == e2 || n == -e2)
{
found[saved] = df; found[saved] = df;
foundj[saved] = j; foundj[saved] = j;
saved++; saved++;
@ -306,16 +295,14 @@ return;
if (saved != 2) if (saved != 2)
printf ("WARNING: didn't find both faces for a saved edge\n"); printf ("WARNING: didn't find both faces for a saved edge\n");
else else {
{ for (i = 0; i < 2; i++) { // remove this edge
for (i=0 ; i<2 ; i++)
{ // remove this edge
df = found[i]; df = found[i];
j = foundj[i]; j = foundj[i];
for (j++ ; j<df->numedges ; j++) for (j++; j < df->numedges; j++)
bsp->surfedges[df->firstedge+j-1] = bsp->surfedges[df->firstedge + j - 1] =
bsp->surfedges[df->firstedge+j]; bsp->surfedges[df->firstedge + j];
bsp->surfedges[df->firstedge+j-1] = 0; bsp->surfedges[df->firstedge + j - 1] = 0;
df->numedges--; df->numedges--;
} }
@ -324,41 +311,39 @@ return;
} }
} }
typedef struct typedef struct {
{ int numedges;
int numedges; int edges[2];
int edges[2];
} checkpoint_t; } checkpoint_t;
checkpoint_t checkpoints[MAX_MAP_VERTS]; checkpoint_t checkpoints[MAX_MAP_VERTS];
/* /*
============== ==============
RemoveColinearEdges RemoveColinearEdges
============== ==============
*/ */
void RemoveColinearEdges (void) void
RemoveColinearEdges (void)
{ {
int i,j, v; int i, j, v;
int c0, c1, c2, c3; int c0, c1, c2, c3;
checkpoint_t *cp; checkpoint_t *cp;
// no edges remapped yet // no edges remapped yet
for (i=0 ; i<bsp->numedges ; i++) for (i = 0; i < bsp->numedges; i++)
edgemapping[i] = i; edgemapping[i] = i;
// find vertexes that only have two edges // find vertexes that only have two edges
memset (checkpoints, 0, sizeof(checkpoints)); memset (checkpoints, 0, sizeof (checkpoints));
for (i=firstmodeledge ; i<bsp->numedges ; i++) for (i = firstmodeledge; i < bsp->numedges; i++) {
{
if (!edgefaces[i][0]) if (!edgefaces[i][0])
continue; // removed continue; // removed
for (j=0 ; j<2 ; j++) for (j = 0; j < 2; j++) {
{
v = bsp->edges[i].v[j]; v = bsp->edges[i].v[j];
cp = &checkpoints[v]; cp = &checkpoints[v];
if (cp->numedges<2) if (cp->numedges < 2)
cp->edges[cp->numedges] = i; cp->edges[cp->numedges] = i;
cp->numedges++; cp->numedges++;
} }
@ -367,31 +352,29 @@ void RemoveColinearEdges (void)
// if a vertex only has two edges and they are colinear, it can be removed // if a vertex only has two edges and they are colinear, it can be removed
c0 = c1 = c2 = c3 = 0; c0 = c1 = c2 = c3 = 0;
for (i=0 ; i<bsp->numvertexes ; i++) for (i = 0; i < bsp->numvertexes; i++) {
{
cp = &checkpoints[i]; cp = &checkpoints[i];
switch (cp->numedges) switch (cp->numedges) {
{ case 0:
case 0: c0++;
c0++; break;
break; case 1:
case 1: c1++;
c1++; break;
break; case 2:
case 2: c2++;
c2++; HealEdges (cp->edges[0], cp->edges[1]);
HealEdges (cp->edges[0], cp->edges[1]); break;
break; default:
default: c3++;
c3++; break;
break;
} }
} }
// qprintf ("%5i c0\n", c0); // qprintf ("%5i c0\n", c0);
// qprintf ("%5i c1\n", c1); // qprintf ("%5i c1\n", c1);
// qprintf ("%5i c2\n", c2); // qprintf ("%5i c2\n", c2);
// qprintf ("%5i c3+\n", c3); // qprintf ("%5i c3+\n", c3);
qprintf ("%5i deges removed by tjunction healing\n", c2); qprintf ("%5i deges removed by tjunction healing\n", c2);
} }
@ -400,22 +383,23 @@ void RemoveColinearEdges (void)
CountRealNumbers CountRealNumbers
============== ==============
*/ */
void CountRealNumbers (void) void
CountRealNumbers (void)
{ {
int i; int i;
int c; int c;
qprintf ("%5i regions\n", bsp->numfaces-firstmodelface); qprintf ("%5i regions\n", bsp->numfaces - firstmodelface);
c = 0; c = 0;
for (i=firstmodelface ; i<bsp->numfaces ; i++) for (i = firstmodelface; i < bsp->numfaces; i++)
c += bsp->faces[i].numedges; c += bsp->faces[i].numedges;
qprintf ("%5i real marksurfaces\n", c); qprintf ("%5i real marksurfaces\n", c);
c = 0; c = 0;
for (i=firstmodeledge ; i<bsp->numedges ; i++) for (i = firstmodeledge; i < bsp->numedges; i++)
if (edgefaces[i][0]) if (edgefaces[i][0])
c++; // not removed c++; // not removed
qprintf ("%5i real edges\n", c); qprintf ("%5i real edges\n", c);
} }
@ -427,23 +411,23 @@ void CountRealNumbers (void)
GrowNodeRegion_r GrowNodeRegion_r
============== ==============
*/ */
void GrowNodeRegion_r (node_t *node) void
GrowNodeRegion_r (node_t * node)
{ {
dface_t *r; dface_t *r;
face_t *f; face_t *f;
int i; int i;
if (node->planenum == PLANENUM_LEAF) if (node->planenum == PLANENUM_LEAF)
return; return;
node->firstface = bsp->numfaces; node->firstface = bsp->numfaces;
for (f=node->faces ; f ; f=f->next) for (f = node->faces; f; f = f->next) {
{ // if (f->outputnumber != -1)
// if (f->outputnumber != -1) // continue; // allready grown into an earlier region
// continue; // allready grown into an earlier region
// emit a region // emit a region
if (bsp->numfaces == MAX_MAP_FACES) if (bsp->numfaces == MAX_MAP_FACES)
Sys_Error ("MAX_MAP_FACES"); Sys_Error ("MAX_MAP_FACES");
@ -453,11 +437,11 @@ void GrowNodeRegion_r (node_t *node)
r->planenum = node->outputplanenum; r->planenum = node->outputplanenum;
r->side = f->planeside; r->side = f->planeside;
r->texinfo = f->texturenum; r->texinfo = f->texturenum;
for (i=0 ; i<MAXLIGHTMAPS ; i++) for (i = 0; i < MAXLIGHTMAPS; i++)
r->styles[i] = 255; r->styles[i] = 255;
r->lightofs = -1; r->lightofs = -1;
// add the face and mergable neighbors to it // add the face and mergable neighbors to it
#if 0 #if 0
ClearRegionSize (); ClearRegionSize ();
@ -465,8 +449,7 @@ void GrowNodeRegion_r (node_t *node)
RecursiveGrowRegion (r, f); RecursiveGrowRegion (r, f);
#endif #endif
r->firstedge = firstedge = bsp->numsurfedges; r->firstedge = firstedge = bsp->numsurfedges;
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++) {
{
if (bsp->numsurfedges == MAX_MAP_SURFEDGES) if (bsp->numsurfedges == MAX_MAP_SURFEDGES)
Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES"); Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES");
bsp->surfedges[bsp->numsurfedges] = f->edges[i]; bsp->surfedges[bsp->numsurfedges] = f->edges[i];
@ -490,7 +473,8 @@ void GrowNodeRegion_r (node_t *node)
GrowNodeRegions GrowNodeRegions
============== ==============
*/ */
void GrowNodeRegions (node_t *headnode) void
GrowNodeRegions (node_t * headnode)
{ {
qprintf ("---- GrowRegions ----\n"); qprintf ("---- GrowRegions ----\n");
@ -521,16 +505,3 @@ for all faces
=============================================================================== ===============================================================================
*/ */

View file

@ -28,13 +28,13 @@
#include "bsp5.h" #include "bsp5.h"
int leaffaces; int leaffaces;
int nodefaces; int nodefaces;
int splitnodes; int splitnodes;
int c_solid, c_empty, c_water; int c_solid, c_empty, c_water;
qboolean usemidsplit; qboolean usemidsplit;
//============================================================================ //============================================================================
@ -45,47 +45,40 @@ FaceSide
For BSP hueristic For BSP hueristic
================== ==================
*/ */
int FaceSide (face_t *in, plane_t *split) int
FaceSide (face_t * in, plane_t *split)
{ {
int frontcount, backcount; int frontcount, backcount;
vec_t dot; vec_t dot;
int i; int i;
vec_t *p; vec_t *p;
frontcount = backcount = 0; frontcount = backcount = 0;
// axial planes are fast // axial planes are fast
if (split->type < 3) if (split->type < 3)
for (i=0, p = in->pts[0]+split->type ; i<in->numpoints ; i++, p+=3) for (i = 0, p = in->pts[0] + split->type; i < in->numpoints;
{ i++, p += 3) {
if (*p > split->dist + ON_EPSILON) if (*p > split->dist + ON_EPSILON) {
{
if (backcount) if (backcount)
return SIDE_ON; return SIDE_ON;
frontcount = 1; frontcount = 1;
} } else if (*p < split->dist - ON_EPSILON) {
else if (*p < split->dist - ON_EPSILON)
{
if (frontcount) if (frontcount)
return SIDE_ON; return SIDE_ON;
backcount = 1; backcount = 1;
} }
} } else
else
// sloping planes take longer // sloping planes take longer
for (i=0, p = in->pts[0] ; i<in->numpoints ; i++, p+=3) for (i = 0, p = in->pts[0]; i < in->numpoints; i++, p += 3) {
{
dot = DotProduct (p, split->normal); dot = DotProduct (p, split->normal);
dot -= split->dist; dot -= split->dist;
if (dot > ON_EPSILON) if (dot > ON_EPSILON) {
{
if (backcount) if (backcount)
return SIDE_ON; return SIDE_ON;
frontcount = 1; frontcount = 1;
} } else if (dot < -ON_EPSILON) {
else if (dot < -ON_EPSILON)
{
if (frontcount) if (frontcount)
return SIDE_ON; return SIDE_ON;
backcount = 1; backcount = 1;
@ -107,63 +100,59 @@ ChooseMidPlaneFromList
The clipping hull BSP doesn't worry about avoiding splits The clipping hull BSP doesn't worry about avoiding splits
================== ==================
*/ */
surface_t *ChooseMidPlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs) surface_t *
ChooseMidPlaneFromList (surface_t * surfaces, vec3_t mins, vec3_t maxs)
{ {
int j,l; int j, l;
surface_t *p, *bestsurface; surface_t *p, *bestsurface;
vec_t bestvalue, value, dist; vec_t bestvalue, value, dist;
plane_t *plane; plane_t *plane;
// //
// pick the plane that splits the least // pick the plane that splits the least
// //
bestvalue = 6*8192*8192; bestvalue = 6 * 8192 * 8192;
bestsurface = NULL; bestsurface = NULL;
for (p=surfaces ; p ; p=p->next) for (p = surfaces; p; p = p->next) {
{
if (p->onnode) if (p->onnode)
continue; continue;
plane = &planes[p->planenum]; plane = &planes[p->planenum];
// check for axis aligned surfaces // check for axis aligned surfaces
l = plane->type; l = plane->type;
if (l > PLANE_Z) if (l > PLANE_Z)
continue; continue;
// //
// calculate the split metric along axis l, smaller values are better // calculate the split metric along axis l, smaller values are better
// //
value = 0; value = 0;
dist = plane->dist * plane->normal[l]; dist = plane->dist * plane->normal[l];
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) {
{ if (j == l) {
if (j == l) value += (maxs[l] - dist) * (maxs[l] - dist);
{ value += (dist - mins[l]) * (dist - mins[l]);
value += (maxs[l]-dist)*(maxs[l]-dist); } else
value += (dist-mins[l])*(dist-mins[l]); value += 2 * (maxs[j] - mins[j]) * (maxs[j] - mins[j]);
}
else
value += 2*(maxs[j]-mins[j])*(maxs[j]-mins[j]);
} }
if (value > bestvalue) if (value > bestvalue)
continue; continue;
// //
// currently the best! // currently the best!
// //
bestvalue = value; bestvalue = value;
bestsurface = p; bestsurface = p;
} }
if (!bestsurface) if (!bestsurface) {
{ for (p = surfaces; p; p = p->next)
for (p=surfaces ; p ; p=p->next)
if (!p->onnode) if (!p->onnode)
return p; // first valid surface return p; // first valid surface
Sys_Error ("ChooseMidPlaneFromList: no valid planes"); Sys_Error ("ChooseMidPlaneFromList: no valid planes");
} }
@ -179,13 +168,15 @@ ChoosePlaneFromList
The real BSP hueristic The real BSP hueristic
================== ==================
*/ */
surface_t *ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs, qboolean usefloors) surface_t *
ChoosePlaneFromList (surface_t * surfaces, vec3_t mins, vec3_t maxs,
qboolean usefloors)
{ {
int j,k,l; int j, k, l;
surface_t *p, *p2, *bestsurface; surface_t *p, *p2, *bestsurface;
vec_t bestvalue, bestdistribution, value, dist; vec_t bestvalue, bestdistribution, value, dist;
plane_t *plane; plane_t *plane;
face_t *f; face_t *f;
// //
// pick the plane that splits the least // pick the plane that splits the least
@ -194,8 +185,7 @@ surface_t *ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs, q
bestsurface = NULL; bestsurface = NULL;
bestdistribution = 9e30; bestdistribution = 9e30;
for (p=surfaces ; p ; p=p->next) for (p = surfaces; p; p = p->next) {
{
if (p->onnode) if (p->onnode)
continue; continue;
@ -205,17 +195,14 @@ surface_t *ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs, q
if (!usefloors && plane->normal[2] == 1) if (!usefloors && plane->normal[2] == 1)
continue; continue;
for (p2=surfaces ; p2 ; p2=p2->next) for (p2 = surfaces; p2; p2 = p2->next) {
{
if (p2 == p) if (p2 == p)
continue; continue;
if (p2->onnode) if (p2->onnode)
continue; continue;
for (f=p2->faces ; f ; f=f->next) for (f = p2->faces; f; f = f->next) {
{ if (FaceSide (f, plane) == SIDE_ON) {
if (FaceSide (f, plane) == SIDE_ON)
{
k++; k++;
if (k >= bestvalue) if (k >= bestvalue)
break; break;
@ -229,39 +216,36 @@ surface_t *ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs, q
if (k > bestvalue) if (k > bestvalue)
continue; continue;
// if equal numbers, axial planes win, then decide on spatial subdivision // if equal numbers, axial planes win, then decide on spatial
// subdivision
if (k < bestvalue || (k == bestvalue && plane->type < PLANE_ANYX) ) if (k < bestvalue || (k == bestvalue && plane->type < PLANE_ANYX)) {
{ // check for axis aligned surfaces
// check for axis aligned surfaces
l = plane->type; l = plane->type;
if (l <= PLANE_Z) if (l <= PLANE_Z) { // axial aligned
{ // axial aligned //
// //
// calculate the split metric along axis l // calculate the split metric along axis l
// //
value = 0; value = 0;
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) {
{ if (j == l) {
if (j == l)
{
dist = plane->dist * plane->normal[l]; dist = plane->dist * plane->normal[l];
value += (maxs[l]-dist)*(maxs[l]-dist); value += (maxs[l] - dist) * (maxs[l] - dist);
value += (dist-mins[l])*(dist-mins[l]); value += (dist - mins[l]) * (dist - mins[l]);
} } else
else value += 2 * (maxs[j] - mins[j]) * (maxs[j] - mins[j]);
value += 2*(maxs[j]-mins[j])*(maxs[j]-mins[j]);
} }
if (value > bestdistribution && k == bestvalue) if (value > bestdistribution && k == bestvalue)
continue; continue;
bestdistribution = value; bestdistribution = value;
} }
// //
// currently the best! // currently the best!
// //
bestvalue = k; bestvalue = k;
bestsurface = p; bestsurface = p;
} }
@ -281,49 +265,47 @@ Selects a surface from a linked list of surfaces to split the group on
returns NULL if the surface list can not be divided any more (a leaf) returns NULL if the surface list can not be divided any more (a leaf)
================== ==================
*/ */
surface_t *SelectPartition (surface_t *surfaces) surface_t *
SelectPartition (surface_t * surfaces)
{ {
int i,j; int i, j;
vec3_t mins, maxs; vec3_t mins, maxs;
surface_t *p, *bestsurface; surface_t *p, *bestsurface;
// //
// count onnode surfaces // count onnode surfaces
// //
i = 0; i = 0;
bestsurface = NULL; bestsurface = NULL;
for (p=surfaces ; p ; p=p->next) for (p = surfaces; p; p = p->next)
if (!p->onnode) if (!p->onnode) {
{
i++; i++;
bestsurface = p; bestsurface = p;
} }
if (i==0) if (i == 0)
return NULL; return NULL;
if (i==1) if (i == 1)
return bestsurface; // this is a final split return bestsurface; // this is a final split
// //
// calculate a bounding box of the entire surfaceset // calculate a bounding box of the entire surfaceset
// //
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
mins[i] = 99999; mins[i] = 99999;
maxs[i] = -99999; maxs[i] = -99999;
} }
for (p=surfaces ; p ; p=p->next) for (p = surfaces; p; p = p->next)
for (j=0 ; j<3 ; j++) for (j = 0; j < 3; j++) {
{
if (p->mins[j] < mins[j]) if (p->mins[j] < mins[j])
mins[j] = p->mins[j]; mins[j] = p->mins[j];
if (p->maxs[j] > maxs[j]) if (p->maxs[j] > maxs[j])
maxs[j] = p->maxs[j]; maxs[j] = p->maxs[j];
} }
if (usemidsplit) // do fast way for clipping hull if (usemidsplit) // do fast way for clipping hull
return ChooseMidPlaneFromList (surfaces, mins, maxs); return ChooseMidPlaneFromList (surfaces, mins, maxs);
// do slow way to save poly splits for drawing hull // do slow way to save poly splits for drawing hull
@ -344,10 +326,11 @@ CalcSurfaceInfo
Calculates the bounding box Calculates the bounding box
================= =================
*/ */
void CalcSurfaceInfo (surface_t *surf) void
CalcSurfaceInfo (surface_t * surf)
{ {
int i,j; int i, j;
face_t *f; face_t *f;
if (!surf->faces) if (!surf->faces)
Sys_Error ("CalcSurfaceInfo: surface without a face"); Sys_Error ("CalcSurfaceInfo: surface without a face");
@ -355,19 +338,16 @@ void CalcSurfaceInfo (surface_t *surf)
// //
// calculate a bounding box // calculate a bounding box
// //
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
surf->mins[i] = 99999; surf->mins[i] = 99999;
surf->maxs[i] = -99999; surf->maxs[i] = -99999;
} }
for (f=surf->faces ; f ; f=f->next) for (f = surf->faces; f; f = f->next) {
{ if (f->contents[0] >= 0 || f->contents[1] >= 0)
if (f->contents[0] >= 0 || f->contents[1] >= 0) Sys_Error ("Bad contents");
Sys_Error ("Bad contents"); for (i = 0; i < f->numpoints; i++)
for (i=0 ; i<f->numpoints ; i++) for (j = 0; j < 3; j++) {
for (j=0 ; j<3 ; j++)
{
if (f->pts[i][j] < surf->mins[j]) if (f->pts[i][j] < surf->mins[j])
surf->mins[j] = f->pts[i][j]; surf->mins[j] = f->pts[i][j];
if (f->pts[i][j] > surf->maxs[j]) if (f->pts[i][j] > surf->maxs[j])
@ -383,40 +363,37 @@ Sys_Error ("Bad contents");
DividePlane DividePlane
================== ==================
*/ */
void DividePlane (surface_t *in, plane_t *split, surface_t **front, surface_t **back) void
DividePlane (surface_t * in, plane_t *split, surface_t ** front,
surface_t ** back)
{ {
face_t *facet, *next; face_t *facet, *next;
face_t *frontlist, *backlist; face_t *frontlist, *backlist;
face_t *frontfrag, *backfrag; face_t *frontfrag, *backfrag;
surface_t *news; surface_t *news;
plane_t *inplane; plane_t *inplane;
inplane = &planes[in->planenum]; inplane = &planes[in->planenum];
// parallel case is easy // parallel case is easy
if (VectorCompare (inplane->normal, split->normal)) if (VectorCompare (inplane->normal, split->normal)) {
{
// check for exactly on node // check for exactly on node
if (inplane->dist == split->dist) if (inplane->dist == split->dist) { // divide the facets to the front
{ // divide the facets to the front and back sides // and back sides
news = AllocSurface (); news = AllocSurface ();
*news = *in; *news = *in;
facet=in->faces; facet = in->faces;
in->faces = NULL; in->faces = NULL;
news->faces = NULL; news->faces = NULL;
in->onnode = news->onnode = true; in->onnode = news->onnode = true;
for ( ; facet ; facet=next) for (; facet; facet = next) {
{
next = facet->next; next = facet->next;
if (facet->planeside == 1) if (facet->planeside == 1) {
{
facet->next = news->faces; facet->next = news->faces;
news->faces = facet; news->faces = facet;
} } else {
else
{
facet->next = in->faces; facet->next = in->faces;
in->faces = facet; in->faces = facet;
} }
@ -433,35 +410,28 @@ void DividePlane (surface_t *in, plane_t *split, surface_t **front, surface_t **
return; return;
} }
if (inplane->dist > split->dist) if (inplane->dist > split->dist) {
{
*front = in; *front = in;
*back = NULL; *back = NULL;
} } else {
else
{
*front = NULL; *front = NULL;
*back = in; *back = in;
} }
return; return;
} }
// do a real split. may still end up entirely on one side // do a real split. may still end up entirely on one side
// OPTIMIZE: use bounding box for fast test // OPTIMIZE: use bounding box for fast test
frontlist = NULL; frontlist = NULL;
backlist = NULL; backlist = NULL;
for (facet = in->faces ; facet ; facet = next) for (facet = in->faces; facet; facet = next) {
{
next = facet->next; next = facet->next;
SplitFace (facet, split, &frontfrag, &backfrag); SplitFace (facet, split, &frontfrag, &backfrag);
if (frontfrag) if (frontfrag) {
{
frontfrag->next = frontlist; frontfrag->next = frontlist;
frontlist = frontfrag; frontlist = frontfrag;
} }
if (backfrag) if (backfrag) {
{
backfrag->next = backlist; backfrag->next = backlist;
backlist = backfrag; backlist = backfrag;
} }
@ -469,23 +439,20 @@ void DividePlane (surface_t *in, plane_t *split, surface_t **front, surface_t **
// if nothing actually got split, just move the in plane // if nothing actually got split, just move the in plane
if (frontlist == NULL) if (frontlist == NULL) {
{
*front = NULL; *front = NULL;
*back = in; *back = in;
in->faces = backlist; in->faces = backlist;
return; return;
} }
if (backlist == NULL) if (backlist == NULL) {
{
*front = in; *front = in;
*back = NULL; *back = NULL;
in->faces = frontlist; in->faces = frontlist;
return; return;
} }
// stuff got split, so allocate one new plane and reuse in // stuff got split, so allocate one new plane and reuse in
news = AllocSurface (); news = AllocSurface ();
*news = *in; *news = *in;
@ -505,7 +472,8 @@ void DividePlane (surface_t *in, plane_t *split, surface_t **front, surface_t **
DivideNodeBounds DivideNodeBounds
================== ==================
*/ */
void DivideNodeBounds (node_t *node, plane_t *split) void
DivideNodeBounds (node_t * node, plane_t *split)
{ {
VectorCopy (node->mins, node->children[0]->mins); VectorCopy (node->mins, node->children[0]->mins);
VectorCopy (node->mins, node->children[1]->mins); VectorCopy (node->mins, node->children[1]->mins);
@ -517,7 +485,7 @@ void DivideNodeBounds (node_t *node, plane_t *split)
return; return;
node->children[0]->mins[split->type] = node->children[0]->mins[split->type] =
node->children[1]->maxs[split->type] = split->dist; node->children[1]->maxs[split->type] = split->dist;
} }
/* /*
@ -528,21 +496,20 @@ Determines the contents of the leaf and creates the final list of
original faces that have some fragment inside this leaf original faces that have some fragment inside this leaf
================== ==================
*/ */
void LinkConvexFaces (surface_t *planelist, node_t *leafnode) void
LinkConvexFaces (surface_t * planelist, node_t * leafnode)
{ {
face_t *f, *next; face_t *f, *next;
surface_t *surf, *pnext; surface_t *surf, *pnext;
int i, count; int i, count;
leafnode->faces = NULL; leafnode->faces = NULL;
leafnode->contents = 0; leafnode->contents = 0;
leafnode->planenum = -1; leafnode->planenum = -1;
count = 0; count = 0;
for ( surf = planelist ; surf ; surf = surf->next) for (surf = planelist; surf; surf = surf->next) {
{ for (f = surf->faces; f; f = f->next) {
for (f = surf->faces ; f ; f=f->next)
{
count++; count++;
if (!leafnode->contents) if (!leafnode->contents)
leafnode->contents = f->contents[0]; leafnode->contents = f->contents[0];
@ -554,35 +521,32 @@ void LinkConvexFaces (surface_t *planelist, node_t *leafnode)
if (!leafnode->contents) if (!leafnode->contents)
leafnode->contents = CONTENTS_SOLID; leafnode->contents = CONTENTS_SOLID;
switch (leafnode->contents) switch (leafnode->contents) {
{ case CONTENTS_EMPTY:
case CONTENTS_EMPTY: c_empty++;
c_empty++; break;
break; case CONTENTS_SOLID:
case CONTENTS_SOLID: c_solid++;
c_solid++; break;
break; case CONTENTS_WATER:
case CONTENTS_WATER: case CONTENTS_SLIME:
case CONTENTS_SLIME: case CONTENTS_LAVA:
case CONTENTS_LAVA: case CONTENTS_SKY:
case CONTENTS_SKY: c_water++;
c_water++; break;
break; default:
default: Sys_Error ("LinkConvexFaces: bad contents number");
Sys_Error ("LinkConvexFaces: bad contents number");
} }
// //
// write the list of faces, and free the originals // write the list of faces, and free the originals
// //
leaffaces += count; leaffaces += count;
leafnode->markfaces = malloc(sizeof(face_t *)*(count+1)); leafnode->markfaces = malloc (sizeof (face_t *) * (count + 1));
i = 0; i = 0;
for ( surf = planelist ; surf ; surf = pnext) for (surf = planelist; surf; surf = pnext) {
{
pnext = surf->next; pnext = surf->next;
for (f = surf->faces ; f ; f=next) for (f = surf->faces; f; f = next) {
{
next = f->next; next = f->next;
leafnode->markfaces[i] = f->original; leafnode->markfaces[i] = f->original;
i++; i++;
@ -590,7 +554,7 @@ void LinkConvexFaces (surface_t *planelist, node_t *leafnode)
} }
FreeSurface (surf); FreeSurface (surf);
} }
leafnode->markfaces[i] = NULL; // sentinal leafnode->markfaces[i] = NULL; // sentinal
} }
@ -601,18 +565,18 @@ LinkNodeFaces
Returns a duplicated list of all faces on surface Returns a duplicated list of all faces on surface
================== ==================
*/ */
face_t *LinkNodeFaces (surface_t *surface) face_t *
LinkNodeFaces (surface_t * surface)
{ {
face_t *f, *new, **prevptr; face_t *f, *new, **prevptr;
face_t *list; face_t *list;
list = NULL; list = NULL;
// subdivide // subdivide
prevptr = &surface->faces; prevptr = &surface->faces;
while (1) while (1) {
{
f = *prevptr; f = *prevptr;
if (!f) if (!f)
break; break;
@ -622,8 +586,7 @@ face_t *LinkNodeFaces (surface_t *surface)
} }
// copy // copy
for (f=surface->faces ; f ; f=f->next) for (f = surface->faces; f; f = f->next) {
{
nodefaces++; nodefaces++;
new = AllocFace (); new = AllocFace ();
*new = *f; *new = *f;
@ -641,16 +604,16 @@ face_t *LinkNodeFaces (surface_t *surface)
PartitionSurfaces PartitionSurfaces
================== ==================
*/ */
void PartitionSurfaces (surface_t *surfaces, node_t *node) void
PartitionSurfaces (surface_t * surfaces, node_t * node)
{ {
surface_t *split, *p, *next; surface_t *split, *p, *next;
surface_t *frontlist, *backlist; surface_t *frontlist, *backlist;
surface_t *frontfrag, *backfrag; surface_t *frontfrag, *backfrag;
plane_t *splitplane; plane_t *splitplane;
split = SelectPartition (surfaces); split = SelectPartition (surfaces);
if (!split) if (!split) { // this is a leaf node
{ // this is a leaf node
node->planenum = PLANENUM_LEAF; node->planenum = PLANENUM_LEAF;
LinkConvexFaces (surfaces, node); LinkConvexFaces (surfaces, node);
return; return;
@ -673,27 +636,23 @@ void PartitionSurfaces (surface_t *surfaces, node_t *node)
frontlist = NULL; frontlist = NULL;
backlist = NULL; backlist = NULL;
for (p=surfaces ; p ; p=next) for (p = surfaces; p; p = next) {
{
next = p->next; next = p->next;
DividePlane (p, splitplane, &frontfrag, &backfrag); DividePlane (p, splitplane, &frontfrag, &backfrag);
if (frontfrag && backfrag) if (frontfrag && backfrag) {
{ // the plane was split, which may expose oportunities to merge
// the plane was split, which may expose oportunities to merge // adjacent faces into a single face
// adjacent faces into a single face // MergePlaneFaces (frontfrag);
// MergePlaneFaces (frontfrag); // MergePlaneFaces (backfrag);
// MergePlaneFaces (backfrag);
} }
if (frontfrag) if (frontfrag) {
{
if (!frontfrag->faces) if (!frontfrag->faces)
Sys_Error ("surface with no faces"); Sys_Error ("surface with no faces");
frontfrag->next = frontlist; frontfrag->next = frontlist;
frontlist = frontfrag; frontlist = frontfrag;
} }
if (backfrag) if (backfrag) {
{
if (!backfrag->faces) if (!backfrag->faces)
Sys_Error ("surface with no faces"); Sys_Error ("surface with no faces");
backfrag->next = backlist; backfrag->next = backlist;
@ -710,11 +669,12 @@ void PartitionSurfaces (surface_t *surfaces, node_t *node)
DrawSurface DrawSurface
================== ==================
*/ */
void DrawSurface (surface_t *surf) void
DrawSurface (surface_t * surf)
{ {
face_t *f; face_t *f;
for (f=surf->faces ; f ; f=f->next) for (f = surf->faces; f; f = f->next)
Draw_DrawFace (f); Draw_DrawFace (f);
} }
@ -723,11 +683,11 @@ void DrawSurface (surface_t *surf)
DrawSurfaceList DrawSurfaceList
================== ==================
*/ */
void DrawSurfaceList (surface_t *surf) void
DrawSurfaceList (surface_t * surf)
{ {
Draw_ClearWindow (); Draw_ClearWindow ();
while (surf) while (surf) {
{
DrawSurface (surf); DrawSurface (surf);
surf = surf->next; surf = surf->next;
} }
@ -738,10 +698,11 @@ void DrawSurfaceList (surface_t *surf)
SolidBSP SolidBSP
================== ==================
*/ */
node_t *SolidBSP (surface_t *surfhead, qboolean midsplit) node_t *
SolidBSP (surface_t * surfhead, qboolean midsplit)
{ {
int i; int i;
node_t *headnode; node_t *headnode;
qprintf ("----- SolidBSP -----\n"); qprintf ("----- SolidBSP -----\n");
@ -751,8 +712,7 @@ node_t *SolidBSP (surface_t *surfhead, qboolean midsplit)
// //
// calculate a bounding box for the entire model // calculate a bounding box for the entire model
// //
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
headnode->mins[i] = brushset->mins[i] - SIDESPACE; headnode->mins[i] = brushset->mins[i] - SIDESPACE;
headnode->maxs[i] = brushset->maxs[i] + SIDESPACE; headnode->maxs[i] = brushset->maxs[i] + SIDESPACE;
} }
@ -772,9 +732,8 @@ node_t *SolidBSP (surface_t *surfhead, qboolean midsplit)
qprintf ("%5i solid leafs\n", c_solid); qprintf ("%5i solid leafs\n", c_solid);
qprintf ("%5i empty leafs\n", c_empty); qprintf ("%5i empty leafs\n", c_empty);
qprintf ("%5i water leafs\n", c_water); qprintf ("%5i water leafs\n", c_water);
qprintf ("%5i leaffaces\n",leaffaces); qprintf ("%5i leaffaces\n", leaffaces);
qprintf ("%5i nodefaces\n", nodefaces); qprintf ("%5i nodefaces\n", nodefaces);
return headnode; return headnode;
} }

View file

@ -29,7 +29,7 @@
#include "bsp5.h" #include "bsp5.h"
surface_t newcopy_t; surface_t newcopy_t;
/* /*
a surface has all of the faces that could be drawn on a given plane a surface has all of the faces that could be drawn on a given plane
@ -38,7 +38,7 @@ the outside filling stage can remove some of them so a better bsp can be generat
*/ */
int subdivides; int subdivides;
/* /*
@ -49,31 +49,29 @@ If the face is >256 in either texture direction, carve a valid sized
piece off and insert the remainder in the next link piece off and insert the remainder in the next link
=============== ===============
*/ */
void SubdivideFace (face_t *f, face_t **prevptr) void
SubdivideFace (face_t * f, face_t ** prevptr)
{ {
float mins, maxs; float mins, maxs;
vec_t v; vec_t v;
int axis, i; int axis, i;
plane_t plane; plane_t plane;
face_t *front, *back, *next; face_t *front, *back, *next;
texinfo_t *tex; texinfo_t *tex;
// special (non-surface cached) faces don't need subdivision // special (non-surface cached) faces don't need subdivision
tex = &bsp->texinfo[f->texturenum]; tex = &bsp->texinfo[f->texturenum];
if ( tex->flags & TEX_SPECIAL) if (tex->flags & TEX_SPECIAL)
return; return;
for (axis = 0 ; axis < 2 ; axis++) for (axis = 0; axis < 2; axis++) {
{ while (1) {
while (1)
{
mins = 9999; mins = 9999;
maxs = -9999; maxs = -9999;
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++) {
{
v = DotProduct (f->pts[i], tex->vecs[axis]); v = DotProduct (f->pts[i], tex->vecs[axis]);
if (v < mins) if (v < mins)
mins = v; mins = v;
@ -84,13 +82,13 @@ void SubdivideFace (face_t *f, face_t **prevptr)
if (maxs - mins <= subdivide_size) if (maxs - mins <= subdivide_size)
break; break;
// split it // split it
subdivides++; subdivides++;
VectorCopy (tex->vecs[axis], plane.normal); VectorCopy (tex->vecs[axis], plane.normal);
v = VectorLength (plane.normal); v = VectorLength (plane.normal);
VectorNormalize (plane.normal); VectorNormalize (plane.normal);
plane.dist = (mins + subdivide_size - 16)/v; plane.dist = (mins + subdivide_size - 16) / v;
next = f->next; next = f->next;
SplitFace (f, &plane, &front, &back); SplitFace (f, &plane, &front, &back);
if (!front || !back) if (!front || !back)
@ -109,20 +107,19 @@ void SubdivideFace (face_t *f, face_t **prevptr)
SubdivideFaces SubdivideFaces
================ ================
*/ */
void SubdivideFaces (surface_t *surfhead) void
SubdivideFaces (surface_t * surfhead)
{ {
surface_t *surf; surface_t *surf;
face_t *f , **prevptr; face_t *f, **prevptr;
qprintf ("--- SubdivideFaces ---\n"); qprintf ("--- SubdivideFaces ---\n");
subdivides = 0; subdivides = 0;
for (surf = surfhead ; surf ; surf=surf->next) for (surf = surfhead; surf; surf = surf->next) {
{
prevptr = &surf->faces; prevptr = &surf->faces;
while (1) while (1) {
{
f = *prevptr; f = *prevptr;
if (!f) if (!f)
break; break;
@ -147,24 +144,20 @@ have inside faces.
============================================================================= =============================================================================
*/ */
void GatherNodeFaces_r (node_t *node) void
GatherNodeFaces_r (node_t * node)
{ {
face_t *f, *next; face_t *f, *next;
if (node->planenum != PLANENUM_LEAF) if (node->planenum != PLANENUM_LEAF) {
{
// //
// decision node // decision node
// //
for (f=node->faces ; f ; f=next) for (f = node->faces; f; f = next) {
{
next = f->next; next = f->next;
if (!f->numpoints) if (!f->numpoints) { // face was removed outside
{ // face was removed outside
FreeFace (f); FreeFace (f);
} } else {
else
{
f->next = validfaces[f->planenum]; f->next = validfaces[f->planenum];
validfaces[f->planenum] = f; validfaces[f->planenum] = f;
} }
@ -174,9 +167,7 @@ void GatherNodeFaces_r (node_t *node)
GatherNodeFaces_r (node->children[1]); GatherNodeFaces_r (node->children[1]);
free (node); free (node);
} } else {
else
{
// //
// leaf node // leaf node
// //
@ -190,63 +181,63 @@ GatherNodeFaces
================ ================
*/ */
surface_t *GatherNodeFaces (node_t *headnode) surface_t *
GatherNodeFaces (node_t * headnode)
{ {
memset (validfaces, 0, sizeof(validfaces)); memset (validfaces, 0, sizeof (validfaces));
GatherNodeFaces_r (headnode); GatherNodeFaces_r (headnode);
return BuildSurfaces (); return BuildSurfaces ();
} }
//=========================================================================== //===========================================================================
typedef struct hashvert_s typedef struct hashvert_s {
{ struct hashvert_s *next;
struct hashvert_s *next; vec3_t point;
vec3_t point; int num;
int num; int numplanes; // for corner determination
int numplanes; // for corner determination int planenums[2];
int planenums[2]; int numedges;
int numedges;
} hashvert_t; } hashvert_t;
#define POINT_EPSILON 0.01 #define POINT_EPSILON 0.01
int c_cornerverts; int c_cornerverts;
hashvert_t hvertex[MAX_MAP_VERTS]; hashvert_t hvertex[MAX_MAP_VERTS];
hashvert_t *hvert_p; hashvert_t *hvert_p;
face_t *edgefaces[MAX_MAP_EDGES][2]; face_t *edgefaces[MAX_MAP_EDGES][2];
int firstmodeledge = 1; int firstmodeledge = 1;
int firstmodelface; int firstmodelface;
//============================================================================ //============================================================================
#define NUM_HASH 4096 #define NUM_HASH 4096
hashvert_t *hashverts[NUM_HASH]; hashvert_t *hashverts[NUM_HASH];
static vec3_t hash_min, hash_scale; static vec3_t hash_min, hash_scale;
static void InitHash (void) static void
InitHash (void)
{ {
vec3_t size; vec3_t size;
vec_t volume; vec_t volume;
vec_t scale; vec_t scale;
int newsize[2]; int newsize[2];
int i; int i;
memset (hashverts, 0, sizeof(hashverts)); memset (hashverts, 0, sizeof (hashverts));
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{
hash_min[i] = -8000; hash_min[i] = -8000;
size[i] = 16000; size[i] = 16000;
} }
volume = size[0]*size[1]; volume = size[0] * size[1];
scale = sqrt(volume / NUM_HASH); scale = sqrt (volume / NUM_HASH);
newsize[0] = size[0] / scale; newsize[0] = size[0] / scale;
newsize[1] = size[1] / scale; newsize[1] = size[1] / scale;
@ -258,13 +249,14 @@ static void InitHash (void)
hvert_p = hvertex; hvert_p = hvertex;
} }
static unsigned HashVec (vec3_t vec) static unsigned
HashVec (vec3_t vec)
{ {
unsigned h; unsigned h;
h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2] h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2]
+ hash_scale[1] * (vec[1] - hash_min[1]); + hash_scale[1] * (vec[1] - hash_min[1]);
if ( h >= NUM_HASH) if (h >= NUM_HASH)
return NUM_HASH - 1; return NUM_HASH - 1;
return h; return h;
} }
@ -275,16 +267,16 @@ static unsigned HashVec (vec3_t vec)
GetVertex GetVertex
============= =============
*/ */
int GetVertex (vec3_t in, int planenum) int
GetVertex (vec3_t in, int planenum)
{ {
int h; int h;
int i; int i;
hashvert_t *hv; hashvert_t *hv;
vec3_t vert; vec3_t vert;
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{ if (fabs (in[i] - (int) (in[i] + 0.5)) < 0.001)
if ( fabs(in[i] - (int) (in[i] + 0.5)) < 0.001)
vert[i] = (int) (in[i] + 0.5); vert[i] = (int) (in[i] + 0.5);
else else
vert[i] = in[i]; vert[i] = in[i];
@ -292,16 +284,14 @@ int GetVertex (vec3_t in, int planenum)
h = HashVec (vert); h = HashVec (vert);
for (hv=hashverts[h] ; hv ; hv=hv->next) for (hv = hashverts[h]; hv; hv = hv->next) {
{ if (fabs (hv->point[0] - vert[0]) < POINT_EPSILON
if ( fabs(hv->point[0]-vert[0])<POINT_EPSILON && fabs (hv->point[1] - vert[1]) < POINT_EPSILON
&& fabs(hv->point[1]-vert[1])<POINT_EPSILON && fabs (hv->point[2] - vert[2]) < POINT_EPSILON) {
&& fabs(hv->point[2]-vert[2])<POINT_EPSILON )
{
hv->numedges++; hv->numedges++;
if (hv->numplanes == 3) if (hv->numplanes == 3)
return hv->num; // allready known to be a corner return hv->num; // allready known to be a corner
for (i=0 ; i<hv->numplanes ; i++) for (i = 0; i < hv->numplanes; i++)
if (hv->planenums[i] == planenum) if (hv->planenums[i] == planenum)
return hv->num; // allready know this plane return hv->num; // allready know this plane
if (hv->numplanes == 2) if (hv->numplanes == 2)
@ -321,7 +311,7 @@ int GetVertex (vec3_t in, int planenum)
hashverts[h] = hv; hashverts[h] = hv;
VectorCopy (vert, hv->point); VectorCopy (vert, hv->point);
hv->num = bsp->numvertexes; hv->num = bsp->numvertexes;
if (hv->num==MAX_MAP_VERTS) if (hv->num == MAX_MAP_VERTS)
Sys_Error ("GetVertex: MAX_MAP_VERTS"); Sys_Error ("GetVertex: MAX_MAP_VERTS");
hvert_p++; hvert_p++;
@ -347,13 +337,14 @@ GetEdge
Don't allow four way edges Don't allow four way edges
================== ==================
*/ */
int c_tryedges; int c_tryedges;
int GetEdge (vec3_t p1, vec3_t p2, face_t *f) int
GetEdge (vec3_t p1, vec3_t p2, face_t * f)
{ {
int v1, v2; int v1, v2;
dedge_t *edge; dedge_t *edge;
int i; int i;
if (!f->contents[0]) if (!f->contents[0])
Sys_Error ("GetEdge: 0 contents"); Sys_Error ("GetEdge: 0 contents");
@ -361,13 +352,11 @@ int GetEdge (vec3_t p1, vec3_t p2, face_t *f)
c_tryedges++; c_tryedges++;
v1 = GetVertex (p1, f->planenum); v1 = GetVertex (p1, f->planenum);
v2 = GetVertex (p2, f->planenum); v2 = GetVertex (p2, f->planenum);
for (i=firstmodeledge ; i < bsp->numedges ; i++) for (i = firstmodeledge; i < bsp->numedges; i++) {
{
edge = &bsp->edges[i]; edge = &bsp->edges[i];
if (v1 == edge->v[1] && v2 == edge->v[0] if (v1 == edge->v[1] && v2 == edge->v[0]
&& !edgefaces[i][1] && !edgefaces[i][1]
&& edgefaces[i][0]->contents[0] == f->contents[0]) && edgefaces[i][0]->contents[0] == f->contents[0]) {
{
edgefaces[i][1] = f; edgefaces[i][1] = f;
return -i; return -i;
} }
@ -391,17 +380,18 @@ int GetEdge (vec3_t p1, vec3_t p2, face_t *f)
FindFaceEdges FindFaceEdges
================== ==================
*/ */
void FindFaceEdges (face_t *face) void
FindFaceEdges (face_t * face)
{ {
int i; int i;
face->outputnumber = -1; face->outputnumber = -1;
if (face->numpoints > MAXEDGES) if (face->numpoints > MAXEDGES)
Sys_Error ("WriteFace: %i points", face->numpoints); Sys_Error ("WriteFace: %i points", face->numpoints);
for (i=0; i<face->numpoints ; i++) for (i = 0; i < face->numpoints; i++)
face->edges[i] = GetEdge face->edges[i] = GetEdge
(face->pts[i], face->pts[(i+1)%face->numpoints], face); (face->pts[i], face->pts[(i + 1) % face->numpoints], face);
} }
/* /*
@ -410,14 +400,14 @@ CheckVertexes
// debugging // debugging
============= =============
*/ */
void CheckVertexes (void) void
CheckVertexes (void)
{ {
int cb, c0, c1, c2, c3; int cb, c0, c1, c2, c3;
hashvert_t *hv; hashvert_t *hv;
cb = c0 = c1 = c2 = c3 = 0; cb = c0 = c1 = c2 = c3 = 0;
for (hv=hvertex ; hv!=hvert_p ; hv++) for (hv = hvertex; hv != hvert_p; hv++) {
{
if (hv->numedges < 0 || hv->numedges & 1) if (hv->numedges < 0 || hv->numedges & 1)
cb++; cb++;
else if (!hv->numedges) else if (!hv->numedges)
@ -443,30 +433,30 @@ CheckEdges
// debugging // debugging
============= =============
*/ */
void CheckEdges (void) void
CheckEdges (void)
{ {
dedge_t *edge; dedge_t *edge;
int i; int i;
dvertex_t *d1, *d2; dvertex_t *d1, *d2;
face_t *f1, *f2; face_t *f1, *f2;
int c_nonconvex; int c_nonconvex;
int c_multitexture; int c_multitexture;
c_nonconvex = c_multitexture = 0; c_nonconvex = c_multitexture = 0;
// CheckVertexes (); // CheckVertexes ();
for (i=1 ; i < bsp->numedges ; i++) for (i = 1; i < bsp->numedges; i++) {
{
edge = &bsp->edges[i]; edge = &bsp->edges[i];
if (!edgefaces[i][1]) if (!edgefaces[i][1]) {
{
d1 = &bsp->vertexes[edge->v[0]]; d1 = &bsp->vertexes[edge->v[0]];
d2 = &bsp->vertexes[edge->v[1]]; d2 = &bsp->vertexes[edge->v[1]];
qprintf ("unshared edge at: (%8.2f, %8.2f, %8.2f) (%8.2f, %8.2f, %8.2f)\n",d1->point[0], d1->point[1], d1->point[2], d2->point[0], d2->point[1], d2->point[2]); qprintf
} ("unshared edge at: (%8.2f, %8.2f, %8.2f) (%8.2f, %8.2f, %8.2f)\n",
else d1->point[0], d1->point[1], d1->point[2], d2->point[0],
{ d2->point[1], d2->point[2]);
} else {
f1 = edgefaces[i][0]; f1 = edgefaces[i][0];
f2 = edgefaces[i][1]; f2 = edgefaces[i][1];
if (f1->planeside != f2->planeside) if (f1->planeside != f2->planeside)
@ -475,22 +465,20 @@ void CheckEdges (void)
continue; continue;
// on the same plane, might be discardable // on the same plane, might be discardable
if (f1->texturenum == f2->texturenum) if (f1->texturenum == f2->texturenum) {
{ hvertex[edge->v[0]].numedges -= 2;
hvertex[edge->v[0]].numedges-=2; hvertex[edge->v[1]].numedges -= 2;
hvertex[edge->v[1]].numedges-=2;
c_nonconvex++; c_nonconvex++;
} } else
else
c_multitexture++; c_multitexture++;
} }
} }
// qprintf ("%5i edges\n", i); // qprintf ("%5i edges\n", i);
// qprintf ("%5i c_nonconvex\n", c_nonconvex); // qprintf ("%5i c_nonconvex\n", c_nonconvex);
// qprintf ("%5i c_multitexture\n", c_multitexture); // qprintf ("%5i c_multitexture\n", c_multitexture);
// CheckVertexes (); // CheckVertexes ();
} }
@ -499,14 +487,15 @@ void CheckEdges (void)
MakeFaceEdges_r MakeFaceEdges_r
================ ================
*/ */
void MakeFaceEdges_r (node_t *node) void
MakeFaceEdges_r (node_t * node)
{ {
face_t *f; face_t *f;
if (node->planenum == PLANENUM_LEAF) if (node->planenum == PLANENUM_LEAF)
return; return;
for (f=node->faces ; f ; f=f->next) for (f = node->faces; f; f = f->next)
FindFaceEdges (f); FindFaceEdges (f);
MakeFaceEdges_r (node->children[0]); MakeFaceEdges_r (node->children[0]);
@ -518,7 +507,8 @@ void MakeFaceEdges_r (node_t *node)
MakeFaceEdges MakeFaceEdges
================ ================
*/ */
void MakeFaceEdges (node_t *headnode) void
MakeFaceEdges (node_t * headnode)
{ {
qprintf ("----- MakeFaceEdges -----\n"); qprintf ("----- MakeFaceEdges -----\n");
@ -528,11 +518,10 @@ void MakeFaceEdges (node_t *headnode)
MakeFaceEdges_r (headnode); MakeFaceEdges_r (headnode);
// CheckEdges (); // CheckEdges ();
GrowNodeRegions (headnode); GrowNodeRegions (headnode);
firstmodeledge = bsp->numedges; firstmodeledge = bsp->numedges;
firstmodelface = bsp->numfaces; firstmodelface = bsp->numfaces;
} }

View file

@ -28,62 +28,63 @@
#include "bsp5.h" #include "bsp5.h"
typedef struct wvert_s typedef struct wvert_s {
{ vec_t t;
vec_t t;
struct wvert_s *prev, *next; struct wvert_s *prev, *next;
} wvert_t; } wvert_t;
typedef struct wedge_s typedef struct wedge_s {
{
struct wedge_s *next; struct wedge_s *next;
vec3_t dir; vec3_t dir;
vec3_t origin; vec3_t origin;
wvert_t head; wvert_t head;
} wedge_t; } wedge_t;
int numwedges, numwverts; int numwedges, numwverts;
int tjuncs; int tjuncs;
int tjuncfaces; int tjuncfaces;
#define MAXWVERTS 0x20000 #define MAXWVERTS 0x20000
#define MAXWEDGES 0x10000 #define MAXWEDGES 0x10000
wvert_t wverts[MAXWVERTS]; wvert_t wverts[MAXWVERTS];
wedge_t wedges[MAXWEDGES]; wedge_t wedges[MAXWEDGES];
void PrintFace (face_t *f) void
PrintFace (face_t * f)
{ {
int i; int i;
for (i=0 ; i<f->numpoints ; i++) for (i = 0; i < f->numpoints; i++)
printf ("(%5.2f, %5.2f, %5.2f)\n", f->pts[i][0], f->pts[i][1], f->pts[i][2]); printf ("(%5.2f, %5.2f, %5.2f)\n", f->pts[i][0], f->pts[i][1],
f->pts[i][2]);
} }
//============================================================================ //============================================================================
#define NUM_HASH 1024 #define NUM_HASH 1024
wedge_t *wedge_hash[NUM_HASH]; wedge_t *wedge_hash[NUM_HASH];
static vec3_t hash_min, hash_scale; static vec3_t hash_min, hash_scale;
static void InitHash (vec3_t mins, vec3_t maxs) static void
InitHash (vec3_t mins, vec3_t maxs)
{ {
vec3_t size; vec3_t size;
vec_t volume; vec_t volume;
vec_t scale; vec_t scale;
int newsize[2]; int newsize[2];
VectorCopy (mins, hash_min); VectorCopy (mins, hash_min);
VectorSubtract (maxs, mins, size); VectorSubtract (maxs, mins, size);
memset (wedge_hash, 0, sizeof(wedge_hash)); memset (wedge_hash, 0, sizeof (wedge_hash));
volume = size[0]*size[1]; volume = size[0] * size[1];
scale = sqrt(volume / NUM_HASH); scale = sqrt (volume / NUM_HASH);
newsize[0] = size[0] / scale; newsize[0] = size[0] / scale;
newsize[1] = size[1] / scale; newsize[1] = size[1] / scale;
@ -93,61 +94,58 @@ static void InitHash (vec3_t mins, vec3_t maxs)
hash_scale[2] = newsize[1]; hash_scale[2] = newsize[1];
} }
static unsigned HashVec (vec3_t vec) static unsigned
HashVec (vec3_t vec)
{ {
unsigned h; unsigned h;
h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2] h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2]
+ hash_scale[1] * (vec[1] - hash_min[1]); + hash_scale[1] * (vec[1] - hash_min[1]);
if ( h >= NUM_HASH) if (h >= NUM_HASH)
return NUM_HASH - 1; return NUM_HASH - 1;
return h; return h;
} }
//============================================================================ //============================================================================
void CanonicalVector (vec3_t vec) void
CanonicalVector (vec3_t vec)
{ {
VectorNormalize (vec); VectorNormalize (vec);
if (vec[0] > EQUAL_EPSILON) if (vec[0] > EQUAL_EPSILON)
return; return;
else if (vec[0] < -EQUAL_EPSILON) else if (vec[0] < -EQUAL_EPSILON) {
{
VectorSubtract (vec3_origin, vec, vec); VectorSubtract (vec3_origin, vec, vec);
return; return;
} } else
else
vec[0] = 0; vec[0] = 0;
if (vec[1] > EQUAL_EPSILON) if (vec[1] > EQUAL_EPSILON)
return; return;
else if (vec[1] < -EQUAL_EPSILON) else if (vec[1] < -EQUAL_EPSILON) {
{
VectorSubtract (vec3_origin, vec, vec); VectorSubtract (vec3_origin, vec, vec);
return; return;
} } else
else
vec[1] = 0; vec[1] = 0;
if (vec[2] > EQUAL_EPSILON) if (vec[2] > EQUAL_EPSILON)
return; return;
else if (vec[2] < -EQUAL_EPSILON) else if (vec[2] < -EQUAL_EPSILON) {
{
VectorSubtract (vec3_origin, vec, vec); VectorSubtract (vec3_origin, vec, vec);
return; return;
} } else
else
vec[2] = 0; vec[2] = 0;
Sys_Error ("CanonicalVector: degenerate"); Sys_Error ("CanonicalVector: degenerate");
} }
wedge_t *FindEdge (vec3_t p1, vec3_t p2, vec_t *t1, vec_t *t2) wedge_t *
FindEdge (vec3_t p1, vec3_t p2, vec_t *t1, vec_t *t2)
{ {
vec3_t origin; vec3_t origin;
vec3_t dir; vec3_t dir;
wedge_t *w; wedge_t *w;
vec_t temp; vec_t temp;
int h; int h;
VectorSubtract (p2, p1, dir); VectorSubtract (p2, p1, dir);
CanonicalVector (dir); CanonicalVector (dir);
@ -157,8 +155,7 @@ wedge_t *FindEdge (vec3_t p1, vec3_t p2, vec_t *t1, vec_t *t2)
VectorMA (p1, -*t1, dir, origin); VectorMA (p1, -*t1, dir, origin);
if (*t1 > *t2) if (*t1 > *t2) {
{
temp = *t1; temp = *t1;
*t1 = *t2; *t1 = *t2;
*t2 = temp; *t2 = temp;
@ -166,8 +163,7 @@ wedge_t *FindEdge (vec3_t p1, vec3_t p2, vec_t *t1, vec_t *t2)
h = HashVec (origin); h = HashVec (origin);
for (w = wedge_hash[h] ; w ; w=w->next) for (w = wedge_hash[h]; w; w = w->next) {
{
temp = w->origin[0] - origin[0]; temp = w->origin[0] - origin[0];
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON) if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
continue; continue;
@ -215,14 +211,14 @@ AddVert
*/ */
#define T_EPSILON 0.01 #define T_EPSILON 0.01
void AddVert (wedge_t *w, vec_t t) void
AddVert (wedge_t * w, vec_t t)
{ {
wvert_t *v, *newv; wvert_t *v, *newv;
v = w->head.next; v = w->head.next;
do do {
{ if (fabs (v->t - t) < T_EPSILON)
if (fabs(v->t - t) < T_EPSILON)
return; return;
if (v->t > t) if (v->t > t)
break; break;
@ -250,12 +246,13 @@ AddEdge
=============== ===============
*/ */
void AddEdge (vec3_t p1, vec3_t p2) void
AddEdge (vec3_t p1, vec3_t p2)
{ {
wedge_t *w; wedge_t *w;
vec_t t1, t2; vec_t t1, t2;
w = FindEdge(p1, p2, &t1, &t2); w = FindEdge (p1, p2, &t1, &t2);
AddVert (w, t1); AddVert (w, t1);
AddVert (w, t2); AddVert (w, t2);
} }
@ -266,14 +263,14 @@ AddFaceEdges
=============== ===============
*/ */
void AddFaceEdges (face_t *f) void
AddFaceEdges (face_t * f)
{ {
int i, j; int i, j;
for (i=0 ; i < f->numpoints ; i++) for (i = 0; i < f->numpoints; i++) {
{ j = (i + 1) % f->numpoints;
j = (i+1)%f->numpoints; AddEdge (f->pts[i], f->pts[j]);
AddEdge (f->pts[i], f->pts[j]);
} }
} }
@ -281,26 +278,26 @@ void AddFaceEdges (face_t *f)
//============================================================================ //============================================================================
// a specially allocated face that can hold hundreds of edges if needed // a specially allocated face that can hold hundreds of edges if needed
byte superfacebuf[8192]; byte superfacebuf[8192];
face_t *superface = (face_t *)superfacebuf; face_t *superface = (face_t *) superfacebuf;
void FixFaceEdges (face_t *f); void FixFaceEdges (face_t * f);
face_t *newlist; face_t *newlist;
void SplitFaceForTjunc (face_t *f, face_t *original) void
SplitFaceForTjunc (face_t * f, face_t * original)
{ {
int i; int i;
face_t *new, *chain; face_t *new, *chain;
vec3_t dir, test; vec3_t dir, test;
vec_t v; vec_t v;
int firstcorner, lastcorner; int firstcorner, lastcorner;
chain = NULL; chain = NULL;
do do {
{ if (f->numpoints <= MAXPOINTS) { // the face is now small enough
if (f->numpoints <= MAXPOINTS) // without more cutting
{ // the face is now small enough without more cutting
// so copy it back to the original // so copy it back to the original
*original = *f; *original = *f;
original->original = chain; original->original = chain;
@ -311,50 +308,43 @@ void SplitFaceForTjunc (face_t *f, face_t *original)
tjuncfaces++; tjuncfaces++;
restart: restart:
// find the last corner // find the last corner
VectorSubtract (f->pts[f->numpoints-1], f->pts[0], dir); VectorSubtract (f->pts[f->numpoints - 1], f->pts[0], dir);
VectorNormalize (dir); VectorNormalize (dir);
for (lastcorner=f->numpoints-1 ; lastcorner > 0 ; lastcorner--) for (lastcorner = f->numpoints - 1; lastcorner > 0; lastcorner--) {
{ VectorSubtract (f->pts[lastcorner - 1], f->pts[lastcorner], test);
VectorSubtract (f->pts[lastcorner-1], f->pts[lastcorner], test);
VectorNormalize (test); VectorNormalize (test);
v = DotProduct (test, dir); v = DotProduct (test, dir);
if (v < 0.9999 || v > 1.00001) if (v < 0.9999 || v > 1.00001) {
{
break; break;
} }
} }
// find the first corner // find the first corner
VectorSubtract (f->pts[1], f->pts[0], dir); VectorSubtract (f->pts[1], f->pts[0], dir);
VectorNormalize (dir); VectorNormalize (dir);
for (firstcorner=1 ; firstcorner < f->numpoints-1 ; firstcorner++) for (firstcorner = 1; firstcorner < f->numpoints - 1; firstcorner++) {
{ VectorSubtract (f->pts[firstcorner + 1], f->pts[firstcorner], test);
VectorSubtract (f->pts[firstcorner+1], f->pts[firstcorner], test);
VectorNormalize (test); VectorNormalize (test);
v = DotProduct (test, dir); v = DotProduct (test, dir);
if (v < 0.9999 || v > 1.00001) if (v < 0.9999 || v > 1.00001) {
{
break; break;
} }
} }
if (firstcorner+2 >= MAXPOINTS) if (firstcorner + 2 >= MAXPOINTS) {
{ // rotate the point winding
// rotate the point winding
VectorCopy (f->pts[0], test); VectorCopy (f->pts[0], test);
for (i=1 ; i<f->numpoints ; i++) for (i = 1; i < f->numpoints; i++) {
{ VectorCopy (f->pts[i], f->pts[i - 1]);
VectorCopy (f->pts[i], f->pts[i-1]);
} }
VectorCopy (test, f->pts[f->numpoints-1]); VectorCopy (test, f->pts[f->numpoints - 1]);
goto restart; goto restart;
} }
// cut off as big a piece as possible, less than MAXPOINTS, and not
// cut off as big a piece as possible, less than MAXPOINTS, and not // past lastcorner
// past lastcorner
new = NewFaceFromFace (f); new = NewFaceFromFace (f);
if (f->original) if (f->original)
@ -365,24 +355,22 @@ restart:
new->next = newlist; new->next = newlist;
newlist = new; newlist = new;
if (f->numpoints - firstcorner <= MAXPOINTS) if (f->numpoints - firstcorner <= MAXPOINTS)
new->numpoints = firstcorner+2; new->numpoints = firstcorner + 2;
else if (lastcorner+2 < MAXPOINTS && else if (lastcorner + 2 < MAXPOINTS &&
f->numpoints - lastcorner <= MAXPOINTS) f->numpoints - lastcorner <= MAXPOINTS)
new->numpoints = lastcorner+2; new->numpoints = lastcorner + 2;
else else
new->numpoints = MAXPOINTS; new->numpoints = MAXPOINTS;
for (i=0 ; i<new->numpoints ; i++) for (i = 0; i < new->numpoints; i++) {
{
VectorCopy (f->pts[i], new->pts[i]); VectorCopy (f->pts[i], new->pts[i]);
} }
for (i=new->numpoints-1 ; i<f->numpoints ; i++) for (i = new->numpoints - 1; i < f->numpoints; i++) {
{ VectorCopy (f->pts[i], f->pts[i - (new->numpoints - 2)]);
VectorCopy (f->pts[i], f->pts[i-(new->numpoints-2)]);
} }
f->numpoints -= (new->numpoints-2); f->numpoints -= (new->numpoints - 2);
} while (1); } while (1);
} }
@ -394,33 +382,30 @@ FixFaceEdges
=============== ===============
*/ */
void FixFaceEdges (face_t *f) void
FixFaceEdges (face_t * f)
{ {
int i, j, k; int i, j, k;
wedge_t *w; wedge_t *w;
wvert_t *v; wvert_t *v;
vec_t t1, t2; vec_t t1, t2;
*superface = *f; *superface = *f;
restart: restart:
for (i=0 ; i < superface->numpoints ; i++) for (i = 0; i < superface->numpoints; i++) {
{ j = (i + 1) % superface->numpoints;
j = (i+1)%superface->numpoints;
w = FindEdge (superface->pts[i], superface->pts[j], &t1, &t2); w = FindEdge (superface->pts[i], superface->pts[j], &t1, &t2);
for (v=w->head.next ; v->t < t1 + T_EPSILON ; v = v->next) for (v = w->head.next; v->t < t1 + T_EPSILON; v = v->next) {
{
} }
if (v->t < t2-T_EPSILON) if (v->t < t2 - T_EPSILON) {
{
tjuncs++; tjuncs++;
// insert a new vertex here // insert a new vertex here
for (k = superface->numpoints ; k> j ; k--) for (k = superface->numpoints; k > j; k--) {
{ VectorCopy (superface->pts[k - 1], superface->pts[k]);
VectorCopy (superface->pts[k-1], superface->pts[k]);
} }
VectorMA (w->origin, v->t, w->dir, superface->pts[j]); VectorMA (w->origin, v->t, w->dir, superface->pts[j]);
superface->numpoints++; superface->numpoints++;
@ -429,14 +414,12 @@ restart:
} }
if (superface->numpoints <= MAXPOINTS) if (superface->numpoints <= MAXPOINTS) {
{
*f = *superface; *f = *superface;
f->next = newlist; f->next = newlist;
newlist = f; newlist = f;
return; return;
} }
// the face needs to be split into multiple faces because of too many edges // the face needs to be split into multiple faces because of too many edges
SplitFaceForTjunc (superface, f); SplitFaceForTjunc (superface, f);
@ -446,31 +429,32 @@ restart:
//============================================================================ //============================================================================
void tjunc_find_r (node_t *node) void
tjunc_find_r (node_t * node)
{ {
face_t *f; face_t *f;
if (node->planenum == PLANENUM_LEAF) if (node->planenum == PLANENUM_LEAF)
return; return;
for (f=node->faces ; f ; f=f->next) for (f = node->faces; f; f = f->next)
AddFaceEdges (f); AddFaceEdges (f);
tjunc_find_r (node->children[0]); tjunc_find_r (node->children[0]);
tjunc_find_r (node->children[1]); tjunc_find_r (node->children[1]);
} }
void tjunc_fix_r (node_t *node) void
tjunc_fix_r (node_t * node)
{ {
face_t *f, *next; face_t *f, *next;
if (node->planenum == PLANENUM_LEAF) if (node->planenum == PLANENUM_LEAF)
return; return;
newlist = NULL; newlist = NULL;
for (f=node->faces ; f ; f=next) for (f = node->faces; f; f = next) {
{
next = f->next; next = f->next;
FixFaceEdges (f); FixFaceEdges (f);
} }
@ -487,10 +471,11 @@ tjunc
=========== ===========
*/ */
void tjunc (node_t *headnode) void
tjunc (node_t * headnode)
{ {
vec3_t maxs, mins; vec3_t maxs, mins;
int i; int i;
qprintf ("---- tjunc ----\n"); qprintf ("---- tjunc ----\n");
@ -502,12 +487,11 @@ void tjunc (node_t *headnode)
// //
// origin points won't allways be inside the map, so extend the hash area // origin points won't allways be inside the map, so extend the hash area
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{ if (fabs (brushset->maxs[i]) > fabs (brushset->mins[i]))
if ( fabs(brushset->maxs[i]) > fabs(brushset->mins[i]) ) maxs[i] = fabs (brushset->maxs[i]);
maxs[i] = fabs(brushset->maxs[i]);
else else
maxs[i] = fabs(brushset->mins[i]); maxs[i] = fabs (brushset->mins[i]);
} }
VectorSubtract (vec3_origin, maxs, mins); VectorSubtract (vec3_origin, maxs, mins);

View file

@ -35,8 +35,8 @@
#include "bsp5.h" #include "bsp5.h"
int headclipnode; int headclipnode;
int firstface; int firstface;
//=========================================================================== //===========================================================================
@ -47,13 +47,13 @@ FindFinalPlane
Used to find plane index numbers for clip nodes read from child processes Used to find plane index numbers for clip nodes read from child processes
================== ==================
*/ */
int FindFinalPlane (dplane_t *p) int
FindFinalPlane (dplane_t *p)
{ {
int i; int i;
dplane_t *dplane; dplane_t *dplane;
for (i=0, dplane = bsp->planes ; i<bsp->numplanes ; i++, dplane++) for (i = 0, dplane = bsp->planes; i < bsp->numplanes; i++, dplane++) {
{
if (p->type != dplane->type) if (p->type != dplane->type)
continue; continue;
if (p->dist != dplane->dist) if (p->dist != dplane->dist)
@ -81,17 +81,17 @@ int FindFinalPlane (dplane_t *p)
int planemapping[MAX_MAP_PLANES]; int planemapping[MAX_MAP_PLANES];
void WriteNodePlanes_r (node_t *node) void
WriteNodePlanes_r (node_t * node)
{ {
plane_t *plane; plane_t *plane;
dplane_t *dplane; dplane_t *dplane;
if (node->planenum == -1) if (node->planenum == -1)
return; return;
if (planemapping[node->planenum] == -1) if (planemapping[node->planenum] == -1) { // a new plane
{ // a new plane
planemapping[node->planenum] = bsp->numplanes; planemapping[node->planenum] = bsp->numplanes;
if (bsp->numplanes == MAX_MAP_PLANES) if (bsp->numplanes == MAX_MAP_PLANES)
@ -119,9 +119,10 @@ WriteNodePlanes
================== ==================
*/ */
void WriteNodePlanes (node_t *nodes) void
WriteNodePlanes (node_t * nodes)
{ {
memset (planemapping,-1, sizeof(planemapping)); memset (planemapping, -1, sizeof (planemapping));
WriteNodePlanes_r (nodes); WriteNodePlanes_r (nodes);
} }
@ -133,27 +134,26 @@ WriteClipNodes_r
================== ==================
*/ */
int WriteClipNodes_r (node_t *node) int
WriteClipNodes_r (node_t * node)
{ {
int i, c; int i, c;
dclipnode_t *cn; dclipnode_t *cn;
int num; int num;
// FIXME: free more stuff? // FIXME: free more stuff?
if (node->planenum == -1) if (node->planenum == -1) {
{
num = node->contents; num = node->contents;
free (node); free (node);
return num; return num;
} }
// emit a clipnode // emit a clipnode
c = bsp->numclipnodes; c = bsp->numclipnodes;
cn = &bsp->clipnodes[bsp->numclipnodes]; cn = &bsp->clipnodes[bsp->numclipnodes];
bsp->numclipnodes++; bsp->numclipnodes++;
cn->planenum = node->outputplanenum; cn->planenum = node->outputplanenum;
for (i=0 ; i<2 ; i++) for (i = 0; i < 2; i++)
cn->children[i] = WriteClipNodes_r(node->children[i]); cn->children[i] = WriteClipNodes_r (node->children[i]);
free (node); free (node);
return c; return c;
@ -167,7 +167,8 @@ Called after the clipping hull is completed. Generates a disk format
representation and frees the original memory. representation and frees the original memory.
================== ==================
*/ */
void WriteClipNodes (node_t *nodes) void
WriteClipNodes (node_t * nodes)
{ {
headclipnode = bsp->numclipnodes; headclipnode = bsp->numclipnodes;
WriteClipNodes_r (nodes); WriteClipNodes_r (nodes);
@ -180,10 +181,11 @@ void WriteClipNodes (node_t *nodes)
WriteLeaf WriteLeaf
================== ==================
*/ */
void WriteLeaf (node_t *node) void
WriteLeaf (node_t * node)
{ {
face_t **fp, *f; face_t **fp, *f;
dleaf_t *leaf_p; dleaf_t *leaf_p;
// emit a leaf // emit a leaf
leaf_p = &bsp->leafs[bsp->numleafs]; leaf_p = &bsp->leafs[bsp->numleafs];
@ -197,24 +199,22 @@ void WriteLeaf (node_t *node)
VectorCopy (node->mins, leaf_p->mins); VectorCopy (node->mins, leaf_p->mins);
VectorCopy (node->maxs, leaf_p->maxs); VectorCopy (node->maxs, leaf_p->maxs);
leaf_p->visofs = -1; // no vis info yet leaf_p->visofs = -1; // no vis info yet
// //
// write the marksurfaces // write the marksurfaces
// //
leaf_p->firstmarksurface = bsp->nummarksurfaces; leaf_p->firstmarksurface = bsp->nummarksurfaces;
for (fp=node->markfaces ; *fp ; fp++) for (fp = node->markfaces; *fp; fp++) {
{ // emit a marksurface
// emit a marksurface
if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES) if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES)
Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES"); Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
f = *fp; f = *fp;
do do {
{ bsp->marksurfaces[bsp->nummarksurfaces] = f->outputnumber;
bsp->marksurfaces[bsp->nummarksurfaces] = f->outputnumber;
bsp->nummarksurfaces++; bsp->nummarksurfaces++;
f=f->original; // grab tjunction split faces f = f->original; // grab tjunction split faces
} while (f); } while (f);
} }
@ -227,10 +227,11 @@ void WriteLeaf (node_t *node)
WriteDrawNodes_r WriteDrawNodes_r
================== ==================
*/ */
void WriteDrawNodes_r (node_t *node) void
WriteDrawNodes_r (node_t * node)
{ {
dnode_t *n; dnode_t *n;
int i; int i;
// emit a node // emit a node
if (bsp->numnodes == MAX_MAP_NODES) if (bsp->numnodes == MAX_MAP_NODES)
@ -249,20 +250,15 @@ void WriteDrawNodes_r (node_t *node)
// recursively output the other nodes // recursively output the other nodes
// //
for (i=0 ; i<2 ; i++) for (i = 0; i < 2; i++) {
{ if (node->children[i]->planenum == -1) {
if (node->children[i]->planenum == -1)
{
if (node->children[i]->contents == CONTENTS_SOLID) if (node->children[i]->contents == CONTENTS_SOLID)
n->children[i] = -1; n->children[i] = -1;
else else {
{
n->children[i] = -(bsp->numleafs + 1); n->children[i] = -(bsp->numleafs + 1);
WriteLeaf (node->children[i]); WriteLeaf (node->children[i]);
} }
} } else {
else
{
n->children[i] = bsp->numnodes; n->children[i] = bsp->numnodes;
WriteDrawNodes_r (node->children[i]); WriteDrawNodes_r (node->children[i]);
} }
@ -274,11 +270,12 @@ void WriteDrawNodes_r (node_t *node)
WriteDrawNodes WriteDrawNodes
================== ==================
*/ */
void WriteDrawNodes (node_t *headnode) void
WriteDrawNodes (node_t * headnode)
{ {
int i; int i;
int start; int start;
dmodel_t *bm; dmodel_t *bm;
#if 0 #if 0
if (headnode->contents < 0) if (headnode->contents < 0)
@ -304,9 +301,9 @@ void WriteDrawNodes (node_t *headnode)
WriteDrawNodes_r (headnode); WriteDrawNodes_r (headnode);
bm->visleafs = bsp->numleafs - start; bm->visleafs = bsp->numleafs - start;
for (i=0 ; i<3 ; i++) for (i = 0; i < 3; i++) {
{ bm->mins[i] = headnode->mins[i] + SIDESPACE + 1; // remove the
bm->mins[i] = headnode->mins[i] + SIDESPACE + 1; // remove the padding // padding
bm->maxs[i] = headnode->maxs[i] - SIDESPACE - 1; bm->maxs[i] = headnode->maxs[i] - SIDESPACE - 1;
} }
// FIXME: are all the children decendant of padded nodes? // FIXME: are all the children decendant of padded nodes?
@ -320,9 +317,10 @@ BumpModel
Used by the clipping hull processes that only need to store headclipnode Used by the clipping hull processes that only need to store headclipnode
================== ==================
*/ */
void BumpModel (int hullnum) void
BumpModel (int hullnum)
{ {
dmodel_t *bm; dmodel_t *bm;
// emit a model // emit a model
if (bsp->nummodels == MAX_MAP_MODELS) if (bsp->nummodels == MAX_MAP_MODELS)
@ -335,42 +333,40 @@ void BumpModel (int hullnum)
//============================================================================= //=============================================================================
typedef struct typedef struct {
{ char identification[4]; // should be WAD2
char identification[4]; // should be WAD2 int numlumps;
int numlumps; int infotableofs;
int infotableofs;
} wadinfo_t; } wadinfo_t;
typedef struct typedef struct {
{ int filepos;
int filepos; int disksize;
int disksize; int size; // uncompressed
int size; // uncompressed char type;
char type; char compression;
char compression; char pad1, pad2;
char pad1, pad2; char name[16]; // must be null terminated
char name[16]; // must be null terminated
} lumpinfo_t; } lumpinfo_t;
QFile *texfile; QFile *texfile;
wadinfo_t wadinfo; wadinfo_t wadinfo;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
void CleanupName (char *in, char *out) void
CleanupName (char *in, char *out)
{ {
int i; int i;
for (i=0 ; i< 16 ; i++ ) for (i = 0; i < 16; i++) {
{
if (!in[i]) if (!in[i])
break; break;
out[i] = toupper(in[i]); out[i] = toupper (in[i]);
} }
for ( ; i< 16 ; i++ ) for (; i < 16; i++)
out[i] = 0; out[i] = 0;
} }
@ -380,25 +376,25 @@ void CleanupName (char *in, char *out)
TEX_InitFromWad TEX_InitFromWad
================= =================
*/ */
void TEX_InitFromWad (char *path) void
TEX_InitFromWad (char *path)
{ {
int i; int i;
texfile = Qopen (path, "rb"); texfile = Qopen (path, "rb");
Qread (texfile, &wadinfo, sizeof(wadinfo)); Qread (texfile, &wadinfo, sizeof (wadinfo));
if (strncmp (wadinfo.identification, "WAD2", 4)) if (strncmp (wadinfo.identification, "WAD2", 4))
Sys_Error ("TEX_InitFromWad: %s isn't a wadfile",path); Sys_Error ("TEX_InitFromWad: %s isn't a wadfile", path);
wadinfo.numlumps = LittleLong(wadinfo.numlumps); wadinfo.numlumps = LittleLong (wadinfo.numlumps);
wadinfo.infotableofs = LittleLong(wadinfo.infotableofs); wadinfo.infotableofs = LittleLong (wadinfo.infotableofs);
Qseek (texfile, wadinfo.infotableofs, SEEK_SET); Qseek (texfile, wadinfo.infotableofs, SEEK_SET);
lumpinfo = malloc(wadinfo.numlumps*sizeof(lumpinfo_t)); lumpinfo = malloc (wadinfo.numlumps * sizeof (lumpinfo_t));
Qread (texfile, lumpinfo, wadinfo.numlumps*sizeof(lumpinfo_t)); Qread (texfile, lumpinfo, wadinfo.numlumps * sizeof (lumpinfo_t));
for (i=0 ; i<wadinfo.numlumps ; i++) for (i = 0; i < wadinfo.numlumps; i++) {
{
CleanupName (lumpinfo[i].name, lumpinfo[i].name); CleanupName (lumpinfo[i].name, lumpinfo[i].name);
lumpinfo[i].filepos = LittleLong(lumpinfo[i].filepos); lumpinfo[i].filepos = LittleLong (lumpinfo[i].filepos);
lumpinfo[i].disksize = LittleLong(lumpinfo[i].disksize); lumpinfo[i].disksize = LittleLong (lumpinfo[i].disksize);
} }
} }
@ -407,17 +403,16 @@ void TEX_InitFromWad (char *path)
LoadLump LoadLump
================== ==================
*/ */
int LoadLump (char *name, byte *dest) int
LoadLump (char *name, byte * dest)
{ {
int i; int i;
char cname[16]; char cname[16];
CleanupName (name, cname); CleanupName (name, cname);
for (i=0 ; i<wadinfo.numlumps ; i++) for (i = 0; i < wadinfo.numlumps; i++) {
{ if (!strcmp (cname, lumpinfo[i].name)) {
if (!strcmp(cname, lumpinfo[i].name))
{
Qseek (texfile, lumpinfo[i].filepos, SEEK_SET); Qseek (texfile, lumpinfo[i].filepos, SEEK_SET);
Qread (texfile, dest, lumpinfo[i].disksize); Qread (texfile, dest, lumpinfo[i].disksize);
return lumpinfo[i].disksize; return lumpinfo[i].disksize;
@ -434,32 +429,30 @@ int LoadLump (char *name, byte *dest)
AddAnimatingTextures AddAnimatingTextures
================== ==================
*/ */
void AddAnimatingTextures (void) void
AddAnimatingTextures (void)
{ {
int base; int base;
int i, j, k; int i, j, k;
char name[32]; char name[32];
base = nummiptex; base = nummiptex;
for (i=0 ; i<base ; i++) for (i = 0; i < base; i++) {
{
if (miptex[i][0] != '+') if (miptex[i][0] != '+')
continue; continue;
strcpy (name, miptex[i]); strcpy (name, miptex[i]);
for (j=0 ; j<20 ; j++) for (j = 0; j < 20; j++) {
{
if (j < 10) if (j < 10)
name[1] = '0'+j; name[1] = '0' + j;
else else
name[1] = 'A'+j-10; // alternate animation name[1] = 'A' + j - 10; // alternate animation
// see if this name exists in the wadfile // see if this name exists in the wadfile
for (k=0 ; k<wadinfo.numlumps ; k++) for (k = 0; k < wadinfo.numlumps; k++)
if (!strcmp(name, lumpinfo[k].name)) if (!strcmp (name, lumpinfo[k].name)) {
{
FindMiptex (name); // add to the miptex list FindMiptex (name); // add to the miptex list
break; break;
} }
@ -474,43 +467,41 @@ void AddAnimatingTextures (void)
WriteMiptex WriteMiptex
================== ==================
*/ */
void WriteMiptex (void) void
WriteMiptex (void)
{ {
int i, len; int i, len;
byte *data; byte *data;
dmiptexlump_t *l; dmiptexlump_t *l;
char *path; char *path;
char fullpath[1024]; char fullpath[1024];
path = ValueForKey (&entities[0], "_wad"); path = ValueForKey (&entities[0], "_wad");
if (!path || !path[0]) if (!path || !path[0]) {
{
path = ValueForKey (&entities[0], "wad"); path = ValueForKey (&entities[0], "wad");
if (!path || !path[0]) if (!path || !path[0]) {
{
printf ("WARNING: no wadfile specified\n"); printf ("WARNING: no wadfile specified\n");
bsp->texdatasize = 0; bsp->texdatasize = 0;
return; return;
} }
} }
sprintf (fullpath, "%s/%s", /*FIXME gamedir*/".", path); sprintf (fullpath, "%s/%s", /* FIXME gamedir */ ".", path);
TEX_InitFromWad (fullpath); TEX_InitFromWad (fullpath);
AddAnimatingTextures (); AddAnimatingTextures ();
l = (dmiptexlump_t *)bsp->texdata; l = (dmiptexlump_t *) bsp->texdata;
data = (byte *)&l->dataofs[nummiptex]; data = (byte *) & l->dataofs[nummiptex];
l->nummiptex = nummiptex; l->nummiptex = nummiptex;
for (i=0 ; i<nummiptex ; i++) for (i = 0; i < nummiptex; i++) {
{ l->dataofs[i] = data - (byte *) l;
l->dataofs[i] = data - (byte *)l;
len = LoadLump (miptex[i], data); len = LoadLump (miptex[i], data);
if (data + len - bsp->texdata >= MAX_MAP_MIPTEX) if (data + len - bsp->texdata >= MAX_MAP_MIPTEX)
Sys_Error ("Textures exceeded MAX_MAP_MIPTEX"); Sys_Error ("Textures exceeded MAX_MAP_MIPTEX");
if (!len) if (!len)
l->dataofs[i] = -1; // didn't find the texture l->dataofs[i] = -1; // didn't find the texture
data += len; data += len;
} }
@ -525,7 +516,8 @@ void WriteMiptex (void)
BeginBSPFile BeginBSPFile
================== ==================
*/ */
void BeginBSPFile (void) void
BeginBSPFile (void)
{ {
// edge 0 is not used, because 0 can't be negated // edge 0 is not used, because 0 can't be negated
bsp->numedges = 1; bsp->numedges = 1;
@ -543,17 +535,18 @@ void BeginBSPFile (void)
FinishBSPFile FinishBSPFile
================== ==================
*/ */
void FinishBSPFile (void) void
FinishBSPFile (void)
{ {
QFile *f; QFile *f;
printf ("--- FinishBSPFile ---\n"); printf ("--- FinishBSPFile ---\n");
printf ("WriteBSPFile: %s\n", bspfilename); printf ("WriteBSPFile: %s\n", bspfilename);
WriteMiptex (); WriteMiptex ();
//XXX PrintBSPFileSizes (); // XXX PrintBSPFileSizes ();
f = Qopen (bspfilename, "wb"); f = Qopen (bspfilename, "wb");
WriteBSPFile (bsp, f); WriteBSPFile (bsp, f);
Qclose (f); Qclose (f);
} }