Moved modified HL SDK to trunk
This commit is contained in:
267
hlsdk/utils/qbsp2/bsp5.h
Normal file
267
hlsdk/utils/qbsp2/bsp5.h
Normal file
@ -0,0 +1,267 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// bsp5.h
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
#include "threads.h"
|
||||
|
||||
//#define ON_EPSILON 0.05
|
||||
#define BOGUS_RANGE 18000
|
||||
|
||||
// the exact bounding box of the brushes is expanded some for the headnode
|
||||
// volume. is this still needed?
|
||||
#define SIDESPACE 24
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numpoints;
|
||||
vec3_t points[8]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 128
|
||||
|
||||
winding_t *BaseWindingForPlane (dplane_t *p);
|
||||
winding_t *NewWinding (int points);
|
||||
void FreeWinding (winding_t *w);
|
||||
winding_t *CopyWinding (winding_t *w);
|
||||
winding_t *ClipWinding (winding_t *in, dplane_t *split, qboolean keepon);
|
||||
void DivideWinding (winding_t *in, dplane_t *split, winding_t **front, winding_t **back);
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define MAXEDGES 48 // 32
|
||||
#define MAXPOINTS 28 // don't let a base face get past this
|
||||
// because it can be split more later
|
||||
|
||||
typedef struct face_s
|
||||
{
|
||||
struct face_s *next;
|
||||
|
||||
int planenum;
|
||||
int texturenum;
|
||||
int contents; // contents in front of face
|
||||
|
||||
struct face_s *original; // face on node
|
||||
int outputnumber; // only valid for original faces after
|
||||
// write surfaces
|
||||
int numpoints;
|
||||
vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t
|
||||
} face_t;
|
||||
|
||||
|
||||
typedef struct surface_s
|
||||
{
|
||||
struct surface_s *next;
|
||||
int planenum;
|
||||
vec3_t mins, maxs;
|
||||
struct node_s *onnode; // true if surface has already been used
|
||||
// as a splitting node
|
||||
face_t *faces; // links to all the faces on either side of the surf
|
||||
} surface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
surface_t *surfaces;
|
||||
} surfchain_t;
|
||||
|
||||
//
|
||||
// there is a node_t structure for every node and leaf in the bsp tree
|
||||
//
|
||||
#define PLANENUM_LEAF -1
|
||||
|
||||
typedef struct node_s
|
||||
{
|
||||
surface_t *surfaces;
|
||||
|
||||
vec3_t mins,maxs; // bounding volume of portals;
|
||||
|
||||
// information for decision nodes
|
||||
int planenum; // -1 = leaf node
|
||||
struct node_s *children[2]; // only valid for decision nodes
|
||||
face_t *faces; // decision nodes only, list for both sides
|
||||
|
||||
// information for leafs
|
||||
int contents; // leaf nodes (0 for decision nodes)
|
||||
face_t **markfaces; // leaf nodes only, point to node faces
|
||||
struct portal_s *portals;
|
||||
int visleafnum; // -1 = solid
|
||||
int valid; // for flood filling
|
||||
int occupied; // light number in leaf for outside filling
|
||||
} node_t;
|
||||
|
||||
|
||||
#define NUM_HULLS 4
|
||||
|
||||
face_t *NewFaceFromFace (face_t *in);
|
||||
void SplitFace (face_t *in, dplane_t *split, face_t **front, face_t **back);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// solidbsp.c
|
||||
|
||||
void DivideFacet (face_t *in, dplane_t *split, face_t **front, face_t **back);
|
||||
void CalcSurfaceInfo (surface_t *surf);
|
||||
void SubdivideFace (face_t *f, face_t **prevptr);
|
||||
node_t *SolidBSP (surfchain_t *surfhead);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// merge.c
|
||||
|
||||
void MergePlaneFaces (surface_t *plane);
|
||||
face_t *MergeFaceToList (face_t *face, face_t *list);
|
||||
face_t *FreeMergeListScraps (face_t *merged);
|
||||
void MergeAll (surface_t *surfhead);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// surfaces.c
|
||||
|
||||
extern int c_cornerverts;
|
||||
extern int c_tryedges;
|
||||
extern face_t *edgefaces[MAX_MAP_EDGES][2];
|
||||
|
||||
extern int firstmodeledge;
|
||||
extern int firstmodelface;
|
||||
|
||||
void SubdivideFaces (surface_t *surfhead);
|
||||
|
||||
surfchain_t *GatherNodeFaces (node_t *headnode);
|
||||
|
||||
void MakeFaceEdges (node_t *headnode);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// portals.c
|
||||
|
||||
typedef struct portal_s
|
||||
{
|
||||
dplane_t plane;
|
||||
node_t *onnode; // NULL = outside box
|
||||
node_t *nodes[2]; // [0] = front side of plane
|
||||
struct portal_s *next[2];
|
||||
winding_t *winding;
|
||||
} portal_t;
|
||||
|
||||
extern node_t outside_node; // portals outside the world face this
|
||||
|
||||
void AddPortalToNodes (portal_t *p, node_t *front, node_t *back);
|
||||
void RemovePortalFromNode (portal_t *portal, node_t *l);
|
||||
void MakeHeadnodePortals (node_t *node, vec3_t mins, vec3_t maxs);
|
||||
|
||||
void WritePortalfile (node_t *headnode);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// region.c
|
||||
|
||||
void GrowNodeRegions (node_t *headnode);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// tjunc.c
|
||||
|
||||
void tjunc (node_t *headnode);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// writebsp.c
|
||||
|
||||
void WriteNodePlanes (node_t *headnode);
|
||||
void WriteClipNodes (node_t *headnode);
|
||||
void WriteDrawNodes (node_t *headnode);
|
||||
|
||||
void BeginBSPFile (void);
|
||||
void FinishBSPFile (void);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// draw.c
|
||||
|
||||
extern vec3_t draw_mins, draw_maxs;
|
||||
|
||||
void Draw_ClearBounds (void);
|
||||
void Draw_AddToBounds (vec3_t v);
|
||||
void Draw_DrawFace (face_t *f);
|
||||
void Draw_ClearWindow (void);
|
||||
void Draw_SetRed (void);
|
||||
void Draw_SetGrey (void);
|
||||
void Draw_SetBlack (void);
|
||||
void DrawPoint (vec3_t v);
|
||||
|
||||
void Draw_SetColor (int c);
|
||||
void SetColor (int c);
|
||||
void DrawPortal (portal_t *p);
|
||||
void DrawLeaf (node_t *l, int color);
|
||||
|
||||
void DrawWinding (winding_t *w);
|
||||
void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// outside.c
|
||||
|
||||
node_t *FillOutside (node_t *node, qboolean leakfile);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern qboolean drawflag;
|
||||
extern qboolean nofill;
|
||||
extern qboolean notjunc;
|
||||
extern qboolean verbose;
|
||||
extern qboolean nogfx;
|
||||
extern qboolean leakonly;
|
||||
extern qboolean watervis;
|
||||
|
||||
extern int subdivide_size;
|
||||
|
||||
extern int hullnum;
|
||||
|
||||
void qprintf (char *fmt, ...); // only prints if verbose
|
||||
|
||||
extern int valid;
|
||||
|
||||
extern char portfilename[1024];
|
||||
extern char bspfilename[1024];
|
||||
extern char pointfilename[1024];
|
||||
|
||||
extern qboolean worldmodel;
|
||||
|
||||
extern face_t *validfaces[MAX_MAP_PLANES];
|
||||
|
||||
surfchain_t *SurflistFromValidFaces (void);
|
||||
|
||||
|
||||
// misc functions
|
||||
|
||||
face_t *AllocFace (void);
|
||||
void FreeFace (face_t *f);
|
||||
|
||||
struct portal_s *AllocPortal (void);
|
||||
void FreePortal (struct portal_s *p);
|
||||
|
||||
surface_t *AllocSurface (void);
|
||||
void FreeSurface (surface_t *s);
|
||||
|
||||
node_t *AllocNode (void);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// cull.c
|
||||
|
||||
void CullStuff (void);
|
||||
|
28
hlsdk/utils/qbsp2/cull.c
Normal file
28
hlsdk/utils/qbsp2/cull.c
Normal file
@ -0,0 +1,28 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// cull.c
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
/*
|
||||
|
||||
removes unused planes and nodes
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
CullStuff
|
||||
=============
|
||||
*/
|
||||
void CullStuff (void)
|
||||
{
|
||||
}
|
164
hlsdk/utils/qbsp2/gldraw.c
Normal file
164
hlsdk/utils/qbsp2/gldraw.c
Normal file
@ -0,0 +1,164 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glaux.h>
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
vec3_t draw_mins, draw_maxs;
|
||||
|
||||
void Draw_ClearBounds (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_AddToBounds (vec3_t v)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_DrawFace (face_t *f)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor4f (0,0,0,0.5);
|
||||
glBegin (GL_LINE_LOOP);
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
glVertex3f (f->pts[i][0], f->pts[i][1], f->pts[i][2]);
|
||||
glEnd ();
|
||||
|
||||
glColor4f (0,1,0,0.3);
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
glVertex3f (f->pts[i][0], f->pts[i][1], f->pts[i][2]);
|
||||
glEnd ();
|
||||
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
#define WIN_SIZE 512
|
||||
|
||||
void InitWindow (void)
|
||||
{
|
||||
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
|
||||
auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
|
||||
auxInitWindow ("qbsp");
|
||||
}
|
||||
|
||||
void Draw_ClearWindow (void)
|
||||
{
|
||||
static int init;
|
||||
int w, h, g;
|
||||
float mx, my;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
init = true;
|
||||
InitWindow ();
|
||||
}
|
||||
|
||||
glClearColor (1,0.8,0.8,0);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
w = (draw_maxs[0] - draw_mins[0]);
|
||||
h = (draw_maxs[1] - draw_mins[1]);
|
||||
|
||||
mx = draw_mins[0] + w/2;
|
||||
my = draw_mins[1] + h/2;
|
||||
|
||||
g = w > h ? w : h;
|
||||
|
||||
glLoadIdentity ();
|
||||
gluPerspective (90, 1, 2, 16384);
|
||||
gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0);
|
||||
|
||||
glColor4f (0,0,0,1);
|
||||
// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_CULL_FACE);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 0
|
||||
glBegin (GL_POLYGON);
|
||||
|
||||
glVertex3f (mx, my, draw_mins[2]);
|
||||
glVertex3f (mx, my+100, draw_mins[2]);
|
||||
glVertex3f (mx, my+100, draw_mins[2]+100);
|
||||
glVertex3f (mx, my, draw_mins[2]+100);
|
||||
|
||||
glEnd ();
|
||||
#endif
|
||||
glFlush ();
|
||||
|
||||
}
|
||||
|
||||
void Draw_SetRed (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (1,0,0);
|
||||
}
|
||||
|
||||
void Draw_SetGrey (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0.5,0.5,0.5);
|
||||
}
|
||||
|
||||
void Draw_SetBlack (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0,0,0);
|
||||
}
|
||||
|
||||
void DrawPoint (vec3_t v)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawLeaf (node_t *l, int color)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawWinding (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->points[i][0], w->points[i][1], w->points[i][2]);
|
||||
glEnd ();
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawPortal (portal_t *portal)
|
||||
{
|
||||
DrawWinding (portal->winding);
|
||||
}
|
282
hlsdk/utils/qbsp2/merge.c
Normal file
282
hlsdk/utils/qbsp2/merge.c
Normal file
@ -0,0 +1,282 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// merge.c
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
|
||||
// #define CONTINUOUS_EPSILON 0.001
|
||||
#define CONTINUOUS_EPSILON ON_EPSILON
|
||||
|
||||
/*
|
||||
================
|
||||
CheckColinear
|
||||
|
||||
================
|
||||
*/
|
||||
void CheckColinear (face_t *f)
|
||||
{
|
||||
int i, j;
|
||||
vec3_t v1, v2;
|
||||
|
||||
for (i=0 ; i<f->numpoints ;i++)
|
||||
{
|
||||
// skip the point if the vector from the previous point is the same
|
||||
// as the vector to the next point
|
||||
j = (i - 1 < 0) ? f->numpoints - 1 : i - 1;
|
||||
VectorSubtract (f->pts[i], f->pts[j], v1);
|
||||
VectorNormalize (v1);
|
||||
|
||||
j = (i + 1 == f->numpoints) ? 0 : i + 1;
|
||||
VectorSubtract (f->pts[j], f->pts[i], v2);
|
||||
VectorNormalize (v2);
|
||||
|
||||
if (VectorCompare (v1, v2))
|
||||
Error ("Colinear edge");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
TryMerge
|
||||
|
||||
If two polygons share a common edge and the edges that meet at the
|
||||
common points are both inside the other polygons, merge them
|
||||
|
||||
Returns NULL if the faces couldn't be merged, or the new face.
|
||||
The originals will NOT be freed.
|
||||
=============
|
||||
*/
|
||||
face_t *TryMerge (face_t *f1, face_t *f2)
|
||||
{
|
||||
vec_t *p1, *p2, *p3, *p4, *back;
|
||||
face_t *newf;
|
||||
int i, j, k, l;
|
||||
vec3_t normal, delta, planenormal;
|
||||
vec_t dot;
|
||||
dplane_t *plane;
|
||||
qboolean keep1, keep2;
|
||||
|
||||
if (f1->numpoints == -1 || f2->numpoints == -1)
|
||||
return NULL;
|
||||
if (f1->texturenum != f2->texturenum)
|
||||
return NULL;
|
||||
if (f1->contents != f2->contents)
|
||||
return NULL;
|
||||
|
||||
//
|
||||
// find a common edge
|
||||
//
|
||||
p1 = p2 = NULL; // stop compiler warning
|
||||
j = 0; //
|
||||
|
||||
for (i=0 ; i<f1->numpoints ; i++)
|
||||
{
|
||||
p1 = f1->pts[i];
|
||||
p2 = f1->pts[(i+1)%f1->numpoints];
|
||||
for (j=0 ; j<f2->numpoints ; j++)
|
||||
{
|
||||
p3 = f2->pts[j];
|
||||
p4 = f2->pts[(j+1)%f2->numpoints];
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
|
||||
break;
|
||||
if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
|
||||
break;
|
||||
}
|
||||
if (k==3)
|
||||
break;
|
||||
}
|
||||
if (j < f2->numpoints)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == f1->numpoints)
|
||||
return NULL; // no matching edges
|
||||
|
||||
//
|
||||
// check slope of connected lines
|
||||
// if the slopes are colinear, the point can be removed
|
||||
//
|
||||
plane = &dplanes[f1->planenum];
|
||||
VectorCopy (plane->normal, planenormal);
|
||||
|
||||
back = f1->pts[(i+f1->numpoints-1)%f1->numpoints];
|
||||
VectorSubtract (p1, back, delta);
|
||||
CrossProduct (planenormal, delta, normal);
|
||||
VectorNormalize (normal);
|
||||
|
||||
back = f2->pts[(j+2)%f2->numpoints];
|
||||
VectorSubtract (back, p1, delta);
|
||||
dot = DotProduct (delta, normal);
|
||||
if (dot > CONTINUOUS_EPSILON)
|
||||
return NULL; // not a convex polygon
|
||||
keep1 = dot < -CONTINUOUS_EPSILON;
|
||||
|
||||
back = f1->pts[(i+2)%f1->numpoints];
|
||||
VectorSubtract (back, p2, delta);
|
||||
CrossProduct (planenormal, delta, normal);
|
||||
VectorNormalize (normal);
|
||||
|
||||
back = f2->pts[(j+f2->numpoints-1)%f2->numpoints];
|
||||
VectorSubtract (back, p2, delta);
|
||||
dot = DotProduct (delta, normal);
|
||||
if (dot > CONTINUOUS_EPSILON)
|
||||
return NULL; // not a convex polygon
|
||||
keep2 = dot < -CONTINUOUS_EPSILON;
|
||||
|
||||
//
|
||||
// build the new polygon
|
||||
//
|
||||
if (f1->numpoints + f2->numpoints > MAXEDGES)
|
||||
{
|
||||
// Error ("TryMerge: too many edges!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newf = NewFaceFromFace (f1);
|
||||
|
||||
// copy first polygon
|
||||
for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
|
||||
{
|
||||
if (k==(i+1)%f1->numpoints && !keep2)
|
||||
continue;
|
||||
|
||||
VectorCopy (f1->pts[k], newf->pts[newf->numpoints]);
|
||||
newf->numpoints++;
|
||||
}
|
||||
|
||||
// copy second polygon
|
||||
for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
|
||||
{
|
||||
if (l==(j+1)%f2->numpoints && !keep1)
|
||||
continue;
|
||||
VectorCopy (f2->pts[l], newf->pts[newf->numpoints]);
|
||||
newf->numpoints++;
|
||||
}
|
||||
|
||||
return newf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
MergeFaceToList
|
||||
===============
|
||||
*/
|
||||
qboolean mergedebug;
|
||||
face_t *MergeFaceToList (face_t *face, face_t *list)
|
||||
{
|
||||
face_t *newf, *f;
|
||||
|
||||
for (f=list ; f ; f=f->next)
|
||||
{
|
||||
//CheckColinear (f);
|
||||
if (mergedebug)
|
||||
{
|
||||
Draw_ClearWindow ();
|
||||
Draw_DrawFace (face);
|
||||
Draw_DrawFace (f);
|
||||
Draw_SetBlack ();
|
||||
}
|
||||
newf = TryMerge (face, f);
|
||||
if (!newf)
|
||||
continue;
|
||||
FreeFace (face);
|
||||
f->numpoints = -1; // merged out
|
||||
return MergeFaceToList (newf, list);
|
||||
}
|
||||
|
||||
// didn't merge, so add at start
|
||||
face->next = list;
|
||||
return face;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
FreeMergeListScraps
|
||||
===============
|
||||
*/
|
||||
face_t *FreeMergeListScraps (face_t *merged)
|
||||
{
|
||||
face_t *head, *next;
|
||||
|
||||
head = NULL;
|
||||
for ( ; merged ; merged = next)
|
||||
{
|
||||
next = merged->next;
|
||||
if (merged->numpoints == -1)
|
||||
FreeFace (merged);
|
||||
else
|
||||
{
|
||||
merged->next = head;
|
||||
head = merged;
|
||||
}
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
MergePlaneFaces
|
||||
===============
|
||||
*/
|
||||
void MergePlaneFaces (surface_t *plane)
|
||||
{
|
||||
face_t *f1, *next;
|
||||
face_t *merged;
|
||||
|
||||
merged = NULL;
|
||||
|
||||
for (f1 = plane->faces ; f1 ; f1 = next)
|
||||
{
|
||||
next = f1->next;
|
||||
merged = MergeFaceToList (f1, merged);
|
||||
}
|
||||
|
||||
// chain all of the non-empty faces to the plane
|
||||
plane->faces = FreeMergeListScraps (merged);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
MergeAll
|
||||
============
|
||||
*/
|
||||
void MergeAll (surface_t *surfhead)
|
||||
{
|
||||
surface_t *surf;
|
||||
int mergefaces;
|
||||
face_t *f;
|
||||
|
||||
qprintf ("---- MergeAll ----\n");
|
||||
|
||||
mergefaces = 0;
|
||||
for (surf = surfhead ; surf ; surf=surf->next)
|
||||
{
|
||||
MergePlaneFaces (surf);
|
||||
Draw_ClearWindow ();
|
||||
for (f=surf->faces ; f ; f=f->next)
|
||||
{
|
||||
Draw_DrawFace (f);
|
||||
mergefaces++;
|
||||
}
|
||||
}
|
||||
|
||||
qprintf ("%i mergefaces\n", mergefaces);
|
||||
}
|
176
hlsdk/utils/qbsp2/msvc6/qbsp2.dsp
Normal file
176
hlsdk/utils/qbsp2/msvc6/qbsp2.dsp
Normal file
@ -0,0 +1,176 @@
|
||||
# Microsoft Developer Studio Project File - Name="qbsp2" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=qbsp2 - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "qbsp2.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "qbsp2.mak" CFG="qbsp2 - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "qbsp2 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "qbsp2 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/SDKSrc/Tools/utils/qbsp2", VUGBAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "qbsp2 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\qbsp2___"
|
||||
# PROP BASE Intermediate_Dir ".\qbsp2___"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\release"
|
||||
# PROP Intermediate_Dir ".\release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MT /GX /O2 /I "..\..\common" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "DOUBLEVEC_T" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 opengl32.lib glu32.lib glaux.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "qbsp2 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\qbsp2__0"
|
||||
# PROP BASE Intermediate_Dir ".\qbsp2__0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\debug"
|
||||
# PROP Intermediate_Dir ".\debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MT /Gm /GX /ZI /Od /I "..\..\common" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "DOUBLEVEC_T" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 opengl32.lib glu32.lib glaux.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "qbsp2 - Win32 Release"
|
||||
# Name "qbsp2 - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\bsp5.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\bspfile.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\cmdlib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\gldraw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\mathlib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\merge.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\outside.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\portals.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qbsp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\scriplib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\solidbsp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\surfaces.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\threads.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\tjunc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\writebsp.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\bspfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\cmdlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\mathlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\scriplib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\common\threads.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
29
hlsdk/utils/qbsp2/msvc6/qbsp2.dsw
Normal file
29
hlsdk/utils/qbsp2/msvc6/qbsp2.dsw
Normal file
@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "qbsp2"=.\qbsp2.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
434
hlsdk/utils/qbsp2/msvc7/qbsp2.vcproj
Normal file
434
hlsdk/utils/qbsp2/msvc7/qbsp2.vcproj
Normal file
@ -0,0 +1,434 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="qbsp2"
|
||||
ProjectGUID="{4E9A1E80-43D6-4414-B49C-614D629F524B}"
|
||||
SccProjectName=""$/SDKSrc/Tools/utils/qbsp2", VUGBAAAA"
|
||||
SccLocalPath=".">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\release"
|
||||
IntermediateDirectory=".\release"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\common"
|
||||
PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;DOUBLEVEC_T"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\release/qbsp2.pch"
|
||||
AssemblerListingLocation=".\release/"
|
||||
ObjectFile=".\release/"
|
||||
ProgramDataBaseFileName=".\release/"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="opengl32.lib glu32.lib glaux.lib odbc32.lib odbccp32.lib"
|
||||
OutputFile=".\release/qbsp2.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
ProgramDatabaseFile=".\release/qbsp2.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\release/qbsp2.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\debug"
|
||||
IntermediateDirectory=".\debug"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\common"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;DOUBLEVEC_T"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\debug/qbsp2.pch"
|
||||
AssemblerListingLocation=".\debug/"
|
||||
ObjectFile=".\debug/"
|
||||
ProgramDataBaseFileName=".\debug/"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="opengl32.lib glu32.lib glaux.lib odbc32.lib odbccp32.lib"
|
||||
OutputFile=".\debug/qbsp2.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\debug/qbsp2.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\debug/qbsp2.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90">
|
||||
<File
|
||||
RelativePath="..\bsp5.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\bspfile.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\cmdlib.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\gldraw.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mathlib.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\merge.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\outside.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\portals.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\qbsp.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\scriplib.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\solidbsp.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\surfaces.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\threads.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tjunc.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\writebsp.c">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;fi;fd">
|
||||
<File
|
||||
RelativePath="..\..\common\bspfile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\cmdlib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mathlib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\scriplib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\threads.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
575
hlsdk/utils/qbsp2/msvc8/qbsp2.vcproj
Normal file
575
hlsdk/utils/qbsp2/msvc8/qbsp2.vcproj
Normal file
@ -0,0 +1,575 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="qbsp2"
|
||||
ProjectGUID="{4E9A1E80-43D6-4414-B49C-614D629F524B}"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\release"
|
||||
IntermediateDirectory=".\release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\release/qbsp2.tlb"
|
||||
HeaderFileName=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\common"
|
||||
PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;DOUBLEVEC_T"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\release/qbsp2.pch"
|
||||
AssemblerListingLocation=".\release/"
|
||||
ObjectFile=".\release/"
|
||||
ProgramDataBaseFileName=".\release/"
|
||||
SuppressStartupBanner="true"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="opengl32.lib glu32.lib glaux.lib odbc32.lib odbccp32.lib"
|
||||
OutputFile=".\release/qbsp2.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
ProgramDatabaseFile=".\release/qbsp2.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\debug"
|
||||
IntermediateDirectory=".\debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\debug/qbsp2.tlb"
|
||||
HeaderFileName=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\common"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;DOUBLEVEC_T"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\debug/qbsp2.pch"
|
||||
AssemblerListingLocation=".\debug/"
|
||||
ObjectFile=".\debug/"
|
||||
ProgramDataBaseFileName=".\debug/"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="opengl32.lib glu32.lib glaux.lib odbc32.lib odbccp32.lib"
|
||||
OutputFile=".\debug/qbsp2.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile=".\debug/qbsp2.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\bsp5.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\bspfile.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\cmdlib.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\gldraw.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mathlib.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\merge.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\outside.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\portals.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\qbsp.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\scriplib.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\solidbsp.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\surfaces.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\threads.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tjunc.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\writebsp.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;fi;fd"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\common\bspfile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\cmdlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\mathlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\scriplib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\common\threads.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
59
hlsdk/utils/qbsp2/nodraw.c
Normal file
59
hlsdk/utils/qbsp2/nodraw.c
Normal file
@ -0,0 +1,59 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
void Draw_ClearBounds (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_AddToBounds (vec3_t v)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_DrawFace (face_t *f)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_ClearWindow (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_SetRed (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_SetGrey (void)
|
||||
{
|
||||
}
|
||||
|
||||
void Draw_SetBlack (void)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawPoint (vec3_t v)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawLeaf (node_t *l, int color)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawWinding (winding_t *w)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawPortal (portal_t *portal)
|
||||
{
|
||||
}
|
421
hlsdk/utils/qbsp2/outside.c
Normal file
421
hlsdk/utils/qbsp2/outside.c
Normal file
@ -0,0 +1,421 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
int outleafs;
|
||||
int valid;
|
||||
int c_falsenodes;
|
||||
int c_free_faces;
|
||||
int c_keep_faces;
|
||||
|
||||
/*
|
||||
===========
|
||||
PointInLeaf
|
||||
===========
|
||||
*/
|
||||
node_t *PointInLeaf (node_t *node, vec3_t point)
|
||||
{
|
||||
vec_t d;
|
||||
|
||||
if (node->contents)
|
||||
return node;
|
||||
|
||||
d = DotProduct (dplanes[node->planenum].normal, point) - dplanes[node->planenum]. dist;
|
||||
|
||||
if (d > 0)
|
||||
return PointInLeaf (node->children[0], point);
|
||||
|
||||
return PointInLeaf (node->children[1], point);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
PlaceOccupant
|
||||
===========
|
||||
*/
|
||||
qboolean PlaceOccupant (int num, vec3_t point, node_t *headnode)
|
||||
{
|
||||
node_t *n;
|
||||
|
||||
n = PointInLeaf (headnode, point);
|
||||
if (n->contents == CONTENTS_SOLID)
|
||||
return false;
|
||||
n->occupied = num;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
WindingCenter
|
||||
=============
|
||||
*/
|
||||
void WindingCenter (winding_t *w, vec3_t center)
|
||||
{
|
||||
int i;
|
||||
vec3_t d1, d2, cross;
|
||||
float scale;
|
||||
|
||||
VectorCopy (vec3_origin, center);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
VectorAdd (w->points[i], center, center);
|
||||
|
||||
scale = 1.0/w->numpoints;
|
||||
VectorScale (center, scale, center);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
MarkLeakTrail
|
||||
==============
|
||||
*/
|
||||
portal_t *prevleaknode;
|
||||
FILE *pointfile, *linefile;
|
||||
void MarkLeakTrail (portal_t *n2)
|
||||
{
|
||||
int i, j;
|
||||
vec3_t p1, p2, dir;
|
||||
float len;
|
||||
portal_t *n1;
|
||||
|
||||
if (hullnum)
|
||||
return;
|
||||
|
||||
n1 = prevleaknode;
|
||||
prevleaknode = n2;
|
||||
|
||||
if (!n1)
|
||||
return;
|
||||
|
||||
WindingCenter (n2->winding, p1);
|
||||
WindingCenter (n1->winding, p2);
|
||||
|
||||
fprintf (linefile, "%f %f %f\n", p1[0], p1[1], p1[2]);
|
||||
|
||||
VectorSubtract (p2, p1, dir);
|
||||
len = VectorLength (dir);
|
||||
VectorNormalize (dir);
|
||||
|
||||
while (len > 2)
|
||||
{
|
||||
fprintf (pointfile,"%f %f %f\n", p1[0], p1[1], p1[2]);
|
||||
for (i=0 ; i<3 ; i++)
|
||||
p1[i] += dir[i]*2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RecursiveFillOutside
|
||||
|
||||
If fill is false, just check, don't fill
|
||||
Returns true if an occupied leaf is reached
|
||||
==================
|
||||
*/
|
||||
int hit_occupied;
|
||||
int backdraw;
|
||||
qboolean RecursiveFillOutside (node_t *l, qboolean fill)
|
||||
{
|
||||
portal_t *p;
|
||||
int s;
|
||||
|
||||
if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY)
|
||||
return false;
|
||||
|
||||
if (l->valid == valid)
|
||||
return false;
|
||||
|
||||
if (l->occupied)
|
||||
{
|
||||
hit_occupied = l->occupied;
|
||||
backdraw = 1000;
|
||||
return true;
|
||||
}
|
||||
|
||||
l->valid = valid;
|
||||
|
||||
// fill it and it's neighbors
|
||||
if (fill)
|
||||
{
|
||||
l->contents = CONTENTS_SOLID;
|
||||
l->planenum = -1;
|
||||
}
|
||||
outleafs++;
|
||||
|
||||
for (p=l->portals ; p ; )
|
||||
{
|
||||
s = (p->nodes[0] == l);
|
||||
|
||||
if (RecursiveFillOutside (p->nodes[s], fill) )
|
||||
{ // leaked, so stop filling
|
||||
if (backdraw-- > 0)
|
||||
{
|
||||
MarkLeakTrail (p);
|
||||
DrawLeaf (l, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
p = p->next[!s];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
ClearOutFaces_r
|
||||
|
||||
Removes unused nodes
|
||||
==================
|
||||
*/
|
||||
node_t *ClearOutFaces_r (node_t *node)
|
||||
{
|
||||
face_t *f, *fnext;
|
||||
face_t **fp;
|
||||
portal_t *p;
|
||||
|
||||
// mark the node and all it's faces, so they
|
||||
// can be removed if no children use them
|
||||
|
||||
node->valid = 0; // will be set if any children touch it
|
||||
for (f=node->faces ; f ; f=f->next)
|
||||
f->outputnumber = -1;
|
||||
|
||||
// go down the children
|
||||
if (node->planenum != -1)
|
||||
{
|
||||
//
|
||||
// decision node
|
||||
//
|
||||
node->children[0] = ClearOutFaces_r (node->children[0]);
|
||||
node->children[1] = ClearOutFaces_r (node->children[1]);
|
||||
|
||||
// free any faces not in open child leafs
|
||||
f=node->faces;
|
||||
node->faces = NULL;
|
||||
|
||||
for ( ; f ; f=fnext)
|
||||
{
|
||||
fnext = f->next;
|
||||
if (f->outputnumber == -1)
|
||||
{ // never referenced, so free it
|
||||
c_free_faces++;
|
||||
FreeFace (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
c_keep_faces++;
|
||||
f->next = node->faces;
|
||||
node->faces = f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!node->valid)
|
||||
{
|
||||
// this node does not touch any interior leafs
|
||||
|
||||
// if both children are solid, just make this node solid
|
||||
if (node->children[0]->contents == CONTENTS_SOLID
|
||||
&& node->children[1]->contents == CONTENTS_SOLID)
|
||||
{
|
||||
node->contents = CONTENTS_SOLID;
|
||||
node->planenum = -1;
|
||||
return node;
|
||||
}
|
||||
|
||||
// if one child is solid, shortcut down the other side
|
||||
if (node->children[0]->contents == CONTENTS_SOLID)
|
||||
return node->children[1];
|
||||
if (node->children[1]->contents == CONTENTS_SOLID)
|
||||
return node->children[0];
|
||||
|
||||
c_falsenodes++;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// leaf node
|
||||
//
|
||||
if (node->contents != CONTENTS_SOLID)
|
||||
{
|
||||
// this node is still inside
|
||||
|
||||
// mark all the nodes used as portals
|
||||
for (p = node->portals ; p ; )
|
||||
{
|
||||
if (p->onnode)
|
||||
p->onnode->valid = 1;
|
||||
if (p->nodes[0] == node) // only write out from first leaf
|
||||
p = p->next[0];
|
||||
else
|
||||
p = p->next[1];
|
||||
}
|
||||
|
||||
// mark all of the faces to be drawn
|
||||
for (fp = node->markfaces ; *fp ; fp++)
|
||||
(*fp)->outputnumber = 0;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// this was a filled in node, so free the markfaces
|
||||
if (node->planenum != -1)
|
||||
free (node->markfaces);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
===========
|
||||
FillOutside
|
||||
|
||||
===========
|
||||
*/
|
||||
node_t *FillOutside (node_t *node, qboolean leakfile)
|
||||
{
|
||||
int s;
|
||||
vec_t *v;
|
||||
int i;
|
||||
qboolean inside;
|
||||
qboolean ret;
|
||||
vec3_t origin;
|
||||
char *cl;
|
||||
|
||||
qprintf ("----- FillOutside ----\n");
|
||||
|
||||
if (nofill)
|
||||
{
|
||||
printf ("skipped\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// place markers for all entities so
|
||||
// we know if we leak inside
|
||||
//
|
||||
inside = false;
|
||||
for (i=1 ; i<num_entities ; i++)
|
||||
{
|
||||
GetVectorForKey (&entities[i], "origin", origin);
|
||||
if (!VectorCompare(origin, vec3_origin))
|
||||
{
|
||||
cl = ValueForKey (&entities[i], "classname");
|
||||
origin[2] += 1; // so objects on floor are ok
|
||||
|
||||
// nudge playerstart around if needed so clipping hulls allways
|
||||
// have a vlaid point
|
||||
if (!strcmp (cl, "info_player_start"))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (x=-16 ; x<=16 ; x += 16)
|
||||
{
|
||||
for (y=-16 ; y<=16 ; y += 16)
|
||||
{
|
||||
origin[0] += x;
|
||||
origin[1] += y;
|
||||
if (PlaceOccupant (i, origin, node))
|
||||
{
|
||||
inside = true;
|
||||
goto gotit;
|
||||
}
|
||||
origin[0] -= x;
|
||||
origin[1] -= y;
|
||||
}
|
||||
}
|
||||
gotit: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlaceOccupant (i, origin, node))
|
||||
inside = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!inside)
|
||||
{
|
||||
printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum);
|
||||
return node;
|
||||
}
|
||||
|
||||
s = !(outside_node.portals->nodes[1] == &outside_node);
|
||||
|
||||
// first check to see if an occupied leaf is hit
|
||||
outleafs = 0;
|
||||
valid++;
|
||||
|
||||
prevleaknode = NULL;
|
||||
|
||||
if (leakfile)
|
||||
{
|
||||
pointfile = fopen (pointfilename, "w");
|
||||
if (!pointfile)
|
||||
Error ("Couldn't open %s\n", pointfilename);
|
||||
StripExtension (pointfilename);
|
||||
strcat (pointfilename, ".lin");
|
||||
linefile = fopen (pointfilename, "w");
|
||||
if (!linefile)
|
||||
Error ("Couldn't open %s\n", pointfilename);
|
||||
}
|
||||
|
||||
ret = RecursiveFillOutside (outside_node.portals->nodes[s], false);
|
||||
|
||||
if (leakfile)
|
||||
{
|
||||
fclose (pointfile);
|
||||
fclose (linefile);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
printf("LEAK LEAK LEAK\n");
|
||||
GetVectorForKey (&entities[hit_occupied], "origin", origin);
|
||||
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n"
|
||||
, origin[0], origin[1], origin[2]);
|
||||
qprintf ("no filling performed\n");
|
||||
qprintf ("point file and line file generated\n");
|
||||
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
if (leakonly)
|
||||
Error ("Stopped by leak.");
|
||||
return node;
|
||||
}
|
||||
|
||||
// now go back and fill things in
|
||||
valid++;
|
||||
RecursiveFillOutside (outside_node.portals->nodes[s], true);
|
||||
|
||||
// remove faces and nodes from filled in leafs
|
||||
c_falsenodes = 0;
|
||||
c_free_faces = 0;
|
||||
c_keep_faces = 0;
|
||||
node = ClearOutFaces_r (node);
|
||||
|
||||
qprintf ("%5i outleafs\n", outleafs);
|
||||
qprintf ("%5i freed faces\n", c_free_faces);
|
||||
qprintf ("%5i keep faces\n", c_keep_faces);
|
||||
qprintf ("%5i falsenodes\n", c_falsenodes);
|
||||
|
||||
// save portal file for vis tracing
|
||||
if (leakfile)
|
||||
WritePortalfile (node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
433
hlsdk/utils/qbsp2/portals.c
Normal file
433
hlsdk/utils/qbsp2/portals.c
Normal file
@ -0,0 +1,433 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
|
||||
node_t outside_node; // portals outside the world face this
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
AddPortalToNodes
|
||||
=============
|
||||
*/
|
||||
void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
|
||||
{
|
||||
if (p->nodes[0] || p->nodes[1])
|
||||
Error ("AddPortalToNode: allready included");
|
||||
|
||||
p->nodes[0] = front;
|
||||
p->next[0] = front->portals;
|
||||
front->portals = p;
|
||||
|
||||
p->nodes[1] = back;
|
||||
p->next[1] = back->portals;
|
||||
back->portals = p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
RemovePortalFromNode
|
||||
=============
|
||||
*/
|
||||
void RemovePortalFromNode (portal_t *portal, node_t *l)
|
||||
{
|
||||
portal_t **pp, *t;
|
||||
|
||||
// remove reference to the current portal
|
||||
pp = &l->portals;
|
||||
while (1)
|
||||
{
|
||||
t = *pp;
|
||||
if (!t)
|
||||
Error ("RemovePortalFromNode: portal not in leaf");
|
||||
|
||||
if ( t == portal )
|
||||
break;
|
||||
|
||||
if (t->nodes[0] == l)
|
||||
pp = &t->next[0];
|
||||
else if (t->nodes[1] == l)
|
||||
pp = &t->next[1];
|
||||
else
|
||||
Error ("RemovePortalFromNode: portal not bounding leaf");
|
||||
}
|
||||
|
||||
if (portal->nodes[0] == l)
|
||||
{
|
||||
*pp = portal->next[0];
|
||||
portal->nodes[0] = NULL;
|
||||
}
|
||||
else if (portal->nodes[1] == l)
|
||||
{
|
||||
*pp = portal->next[1];
|
||||
portal->nodes[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
void PrintPortal (portal_t *p)
|
||||
{
|
||||
int i;
|
||||
winding_t *w;
|
||||
|
||||
w = p->winding;
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
printf ("(%5.0f,%5.0f,%5.0f)\n",w->points[i][0]
|
||||
, w->points[i][1], w->points[i][2]);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
MakeHeadnodePortals
|
||||
|
||||
The created portals will face the global outside_node
|
||||
================
|
||||
*/
|
||||
void MakeHeadnodePortals (node_t *node, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
vec3_t bounds[2];
|
||||
int i, j, n;
|
||||
portal_t *p, *portals[6];
|
||||
dplane_t bplanes[6], *pl;
|
||||
|
||||
Draw_ClearWindow ();
|
||||
|
||||
// pad with some space so there will never be null volume leafs
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
bounds[0][i] = mins[i] - SIDESPACE;
|
||||
bounds[1][i] = maxs[i] + SIDESPACE;
|
||||
}
|
||||
|
||||
outside_node.contents = CONTENTS_SOLID;
|
||||
outside_node.portals = NULL;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
for (j=0 ; j<2 ; j++)
|
||||
{
|
||||
n = j*3 + i;
|
||||
|
||||
p = AllocPortal ();
|
||||
portals[n] = p;
|
||||
|
||||
pl = &bplanes[n];
|
||||
memset (pl, 0, sizeof(*pl));
|
||||
if (j)
|
||||
{
|
||||
pl->normal[i] = -1;
|
||||
pl->dist = -bounds[j][i];
|
||||
}
|
||||
else
|
||||
{
|
||||
pl->normal[i] = 1;
|
||||
pl->dist = bounds[j][i];
|
||||
}
|
||||
p->plane = *pl;
|
||||
p->winding = BaseWindingForPlane (pl);
|
||||
AddPortalToNodes (p, node, &outside_node);
|
||||
}
|
||||
|
||||
// clip the basewindings by all the other planes
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
for (j=0 ; j<6 ; j++)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
portals[i]->winding = ClipWinding (portals[i]->winding, &bplanes[j], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
void CheckWindingInNode (winding_t *w, node_t *node)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
if (w->points[i][j] < node->mins[j] - 1
|
||||
|| w->points[i][j] > node->maxs[j] + 1)
|
||||
{
|
||||
printf ("WARNING: CheckWindingInNode: outside\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckWindingArea (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
float total, add;
|
||||
vec3_t v1, v2, cross;
|
||||
|
||||
total = 0;
|
||||
for (i=1 ; i<w->numpoints ; i++)
|
||||
{
|
||||
VectorSubtract (w->points[i], w->points[0], v1);
|
||||
VectorSubtract (w->points[i+1], w->points[0], v2);
|
||||
CrossProduct (v1, v2, cross);
|
||||
add = VectorLength (cross);
|
||||
total += add*0.5;
|
||||
}
|
||||
if (total < 16)
|
||||
printf ("WARNING: winding area %f\n", total);
|
||||
}
|
||||
|
||||
|
||||
void PlaneFromWinding (winding_t *w, dplane_t *plane)
|
||||
{
|
||||
vec3_t v1, v2;
|
||||
vec3_t plane_normal;
|
||||
|
||||
// calc plane
|
||||
VectorSubtract (w->points[2], w->points[1], v1);
|
||||
VectorSubtract (w->points[0], w->points[1], v2);
|
||||
|
||||
CrossProduct (v2, v1, plane_normal);
|
||||
VectorNormalize (plane_normal);
|
||||
VectorCopy (plane_normal, plane->normal); // change from vec_t
|
||||
plane->dist = DotProduct (w->points[0], plane->normal);
|
||||
}
|
||||
|
||||
void CheckLeafPortalConsistancy (node_t *node)
|
||||
{
|
||||
int side, side2;
|
||||
portal_t *p, *p2;
|
||||
dplane_t plane, plane2;
|
||||
int i;
|
||||
winding_t *w;
|
||||
float dist;
|
||||
|
||||
side = side2 = 0; // quiet compiler warning
|
||||
|
||||
for (p = node->portals ; p ; p = p->next[side])
|
||||
{
|
||||
if (p->nodes[0] == node)
|
||||
side = 0;
|
||||
else if (p->nodes[1] == node)
|
||||
side = 1;
|
||||
else
|
||||
Error ("CutNodePortals_r: mislinked portal");
|
||||
CheckWindingInNode (p->winding, node);
|
||||
CheckWindingArea (p->winding);
|
||||
|
||||
// check that the side orders are correct
|
||||
plane = p->plane;
|
||||
PlaneFromWinding (p->winding, &plane2);
|
||||
|
||||
for (p2 = node->portals ; p2 ; p2 = p2->next[side2])
|
||||
{
|
||||
if (p2->nodes[0] == node)
|
||||
side2 = 0;
|
||||
else if (p2->nodes[1] == node)
|
||||
side2 = 1;
|
||||
else
|
||||
Error ("CutNodePortals_r: mislinked portal");
|
||||
w = p2->winding;
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
dist = DotProduct (w->points[i], plane.normal) - plane.dist;
|
||||
if ( (side == 0 && dist < -1) || (side == 1 && dist > 1) )
|
||||
{
|
||||
printf ("WARNING: portal siding direction is wrong\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PORTAL FILE GENERATION
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
|
||||
FILE *pf;
|
||||
int num_visleafs; // leafs the player can be in
|
||||
int num_visportals;
|
||||
|
||||
void WriteFloat (FILE *f, vec_t v)
|
||||
{
|
||||
if ( fabs(v - Q_rint(v)) < ON_EPSILON )
|
||||
fprintf (f,"%i ",(int)Q_rint(v));
|
||||
else
|
||||
fprintf (f,"%f ",v);
|
||||
}
|
||||
|
||||
void WritePortalFile_r (node_t *node)
|
||||
{
|
||||
int i;
|
||||
portal_t *p;
|
||||
winding_t *w;
|
||||
dplane_t *pl, plane2;
|
||||
|
||||
if (!node->contents)
|
||||
{
|
||||
WritePortalFile_r (node->children[0]);
|
||||
WritePortalFile_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->contents == CONTENTS_SOLID)
|
||||
return;
|
||||
|
||||
for (p = node->portals ; p ; )
|
||||
{
|
||||
w = p->winding;
|
||||
if (w && p->nodes[0] == node)
|
||||
{
|
||||
if ( (watervis && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
|
||||
|| (p->nodes[0]->contents == p->nodes[1]->contents) )
|
||||
{
|
||||
// write out to the file
|
||||
|
||||
// sometimes planes get turned around when they are very near
|
||||
// the changeover point between different axis. interpret the
|
||||
// plane the same way vis will, and flip the side orders if needed
|
||||
PlaneFromWinding (w, &plane2);
|
||||
if ( DotProduct (p->plane.normal, plane2.normal) < 1.0-ON_EPSILON )
|
||||
{ // backwards...
|
||||
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum);
|
||||
}
|
||||
else
|
||||
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->points[i][0]);
|
||||
WriteFloat (pf, w->points[i][1]);
|
||||
WriteFloat (pf, w->points[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (p->nodes[0] == node)
|
||||
p = p->next[0];
|
||||
else
|
||||
p = p->next[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
NumberLeafs_r
|
||||
================
|
||||
*/
|
||||
void NumberLeafs_r (node_t *node)
|
||||
{
|
||||
portal_t *p;
|
||||
|
||||
if (!node->contents)
|
||||
{ // decision node
|
||||
node->visleafnum = -99;
|
||||
NumberLeafs_r (node->children[0]);
|
||||
NumberLeafs_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
Draw_ClearWindow ();
|
||||
DrawLeaf (node, 1);
|
||||
|
||||
if (node->contents == CONTENTS_SOLID)
|
||||
{ // solid block, viewpoint never inside
|
||||
node->visleafnum = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
node->visleafnum = num_visleafs++;
|
||||
|
||||
for (p = node->portals ; p ; )
|
||||
{
|
||||
if (p->nodes[0] == node) // only write out from first leaf
|
||||
{
|
||||
if ( (watervis && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID)
|
||||
|| (p->nodes[0]->contents == p->nodes[1]->contents) )
|
||||
num_visportals++;
|
||||
p = p->next[0];
|
||||
}
|
||||
else
|
||||
p = p->next[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
WritePortalfile
|
||||
================
|
||||
*/
|
||||
void WritePortalfile (node_t *headnode)
|
||||
{
|
||||
// set the visleafnum field in every leaf and count the total number of portals
|
||||
num_visleafs = 0;
|
||||
num_visportals = 0;
|
||||
NumberLeafs_r (headnode);
|
||||
|
||||
// write the file
|
||||
printf ("writing %s\n", portfilename);
|
||||
pf = fopen (portfilename, "w");
|
||||
if (!pf)
|
||||
Error ("Error opening %s", portfilename);
|
||||
|
||||
fprintf (pf, "%s\n", PORTALFILE);
|
||||
fprintf (pf, "%i\n", num_visleafs);
|
||||
fprintf (pf, "%i\n", num_visportals);
|
||||
|
||||
WritePortalFile_r (headnode);
|
||||
|
||||
fclose (pf);
|
||||
}
|
||||
|
||||
|
||||
//===================================================
|
||||
|
||||
void FreePortals (node_t *node)
|
||||
{
|
||||
portal_t *p, *nextp;
|
||||
|
||||
if (node->planenum != -1)
|
||||
{
|
||||
FreePortals (node->children[0]);
|
||||
FreePortals (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (p=node->portals ; p ; p=nextp)
|
||||
{
|
||||
if (p->nodes[0] == node)
|
||||
nextp = p->next[0];
|
||||
else
|
||||
nextp = p->next[1];
|
||||
RemovePortalFromNode (p, p->nodes[0]);
|
||||
RemovePortalFromNode (p, p->nodes[1]);
|
||||
FreeWinding (p->winding);
|
||||
FreePortal (p);
|
||||
}
|
||||
}
|
1016
hlsdk/utils/qbsp2/qbsp.c
Normal file
1016
hlsdk/utils/qbsp2/qbsp.c
Normal file
File diff suppressed because it is too large
Load Diff
984
hlsdk/utils/qbsp2/solidbsp.c
Normal file
984
hlsdk/utils/qbsp2/solidbsp.c
Normal file
@ -0,0 +1,984 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// solidbsp.c
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
/*
|
||||
|
||||
Each node or leaf will have a set of portals that completely enclose
|
||||
the volume of the node and pass into an adjacent node.
|
||||
|
||||
*/
|
||||
|
||||
int c_leaffaces;
|
||||
int c_nodefaces;
|
||||
int c_splitnodes;
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
FaceSide
|
||||
|
||||
For BSP hueristic
|
||||
==================
|
||||
*/
|
||||
int FaceSide (face_t *in, dplane_t *split)
|
||||
{
|
||||
int frontcount, backcount;
|
||||
vec_t dot;
|
||||
int i;
|
||||
vec_t *p;
|
||||
|
||||
|
||||
frontcount = backcount = 0;
|
||||
|
||||
// axial planes are fast
|
||||
if (split->type < 3)
|
||||
for (i=0, p = in->pts[0]+split->type ; i<in->numpoints ; i++, p+=3)
|
||||
{
|
||||
if (*p > split->dist + ON_EPSILON)
|
||||
{
|
||||
if (backcount)
|
||||
return SIDE_ON;
|
||||
frontcount = 1;
|
||||
}
|
||||
else if (*p < split->dist - ON_EPSILON)
|
||||
{
|
||||
if (frontcount)
|
||||
return SIDE_ON;
|
||||
backcount = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
// sloping planes take longer
|
||||
for (i=0, p = in->pts[0] ; i<in->numpoints ; i++, p+=3)
|
||||
{
|
||||
dot = DotProduct (p, split->normal);
|
||||
dot -= split->dist;
|
||||
if (dot > ON_EPSILON)
|
||||
{
|
||||
if (backcount)
|
||||
return SIDE_ON;
|
||||
frontcount = 1;
|
||||
}
|
||||
else if (dot < -ON_EPSILON)
|
||||
{
|
||||
if (frontcount)
|
||||
return SIDE_ON;
|
||||
backcount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!frontcount)
|
||||
return SIDE_BACK;
|
||||
if (!backcount)
|
||||
return SIDE_FRONT;
|
||||
|
||||
return SIDE_ON;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
ChooseMidPlaneFromList
|
||||
|
||||
When there are a huge number of planes, just choose one closest
|
||||
to the middle.
|
||||
==================
|
||||
*/
|
||||
surface_t *ChooseMidPlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
int j,l;
|
||||
surface_t *p, *bestsurface;
|
||||
vec_t bestvalue, value, dist;
|
||||
dplane_t *plane;
|
||||
|
||||
//
|
||||
// pick the plane that splits the least
|
||||
//
|
||||
bestvalue = 6*8192*8192;
|
||||
bestsurface = NULL;
|
||||
|
||||
for (p=surfaces ; p ; p=p->next)
|
||||
{
|
||||
if (p->onnode)
|
||||
continue;
|
||||
|
||||
plane = &dplanes[p->planenum];
|
||||
|
||||
// check for axis aligned surfaces
|
||||
l = plane->type;
|
||||
if (l > PLANE_Z)
|
||||
continue;
|
||||
|
||||
//
|
||||
// calculate the split metric along axis l, smaller values are better
|
||||
//
|
||||
value = 0;
|
||||
|
||||
dist = plane->dist * plane->normal[l];
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
if (j == l)
|
||||
{
|
||||
value += (maxs[l]-dist)*(maxs[l]-dist);
|
||||
value += (dist-mins[l])*(dist-mins[l]);
|
||||
}
|
||||
else
|
||||
value += 2*(maxs[j]-mins[j])*(maxs[j]-mins[j]);
|
||||
}
|
||||
|
||||
if (value > bestvalue)
|
||||
continue;
|
||||
|
||||
//
|
||||
// currently the best!
|
||||
//
|
||||
bestvalue = value;
|
||||
bestsurface = p;
|
||||
}
|
||||
|
||||
if (!bestsurface)
|
||||
{
|
||||
for (p=surfaces ; p ; p=p->next)
|
||||
if (!p->onnode)
|
||||
return p; // first valid surface
|
||||
Error ("ChooseMidPlaneFromList: no valid planes");
|
||||
}
|
||||
|
||||
return bestsurface;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
ChoosePlaneFromList
|
||||
|
||||
Choose the plane that splits the least faces
|
||||
==================
|
||||
*/
|
||||
surface_t *ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
int j,k,l;
|
||||
surface_t *p, *p2, *bestsurface;
|
||||
vec_t bestvalue, bestdistribution, value, dist;
|
||||
dplane_t *plane;
|
||||
face_t *f;
|
||||
|
||||
//
|
||||
// pick the plane that splits the least
|
||||
//
|
||||
bestvalue = 99999;
|
||||
bestsurface = NULL;
|
||||
bestdistribution = 9e30;
|
||||
|
||||
for (p=surfaces ; p ; p=p->next)
|
||||
{
|
||||
if (p->onnode)
|
||||
continue;
|
||||
|
||||
plane = &dplanes[p->planenum];
|
||||
k = 0;
|
||||
|
||||
for (p2=surfaces ; p2 ; p2=p2->next)
|
||||
{
|
||||
if (p2 == p)
|
||||
continue;
|
||||
if (p2->onnode)
|
||||
continue;
|
||||
|
||||
for (f=p2->faces ; f ; f=f->next)
|
||||
{
|
||||
if (FaceSide (f, plane) == SIDE_ON)
|
||||
{
|
||||
k++;
|
||||
if (k >= bestvalue)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (k > bestvalue)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k > bestvalue)
|
||||
continue;
|
||||
|
||||
// if equal numbers, axial planes win, then decide on spatial subdivision
|
||||
|
||||
if (k < bestvalue || (k == bestvalue && plane->type < PLANE_ANYX) )
|
||||
{
|
||||
// check for axis aligned surfaces
|
||||
l = plane->type;
|
||||
|
||||
if (l <= PLANE_Z)
|
||||
{ // axial aligned
|
||||
//
|
||||
// calculate the split metric along axis l
|
||||
//
|
||||
value = 0;
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
if (j == l)
|
||||
{
|
||||
dist = plane->dist * plane->normal[l];
|
||||
value += (maxs[l]-dist)*(maxs[l]-dist);
|
||||
value += (dist-mins[l])*(dist-mins[l]);
|
||||
}
|
||||
else
|
||||
value += 2*(maxs[j]-mins[j])*(maxs[j]-mins[j]);
|
||||
}
|
||||
|
||||
if (value > bestdistribution && k == bestvalue)
|
||||
continue;
|
||||
bestdistribution = value;
|
||||
}
|
||||
//
|
||||
// currently the best!
|
||||
//
|
||||
bestvalue = k;
|
||||
bestsurface = p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return bestsurface;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SelectPartition
|
||||
|
||||
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)
|
||||
==================
|
||||
*/
|
||||
surface_t *SelectPartition (surface_t *surfaces, node_t *node, qboolean usemidsplit)
|
||||
{
|
||||
int i,j;
|
||||
surface_t *p, *bestsurface;
|
||||
|
||||
//
|
||||
// count surface choices
|
||||
//
|
||||
i = 0;
|
||||
bestsurface = NULL;
|
||||
for (p=surfaces ; p ; p=p->next)
|
||||
if (!p->onnode)
|
||||
{
|
||||
i++;
|
||||
bestsurface = p;
|
||||
}
|
||||
|
||||
if (i==0)
|
||||
return NULL; // this is a leafnode
|
||||
|
||||
if (i==1)
|
||||
return bestsurface; // this is a final split
|
||||
|
||||
|
||||
if (usemidsplit) // do fast way for clipping hull
|
||||
return ChooseMidPlaneFromList (surfaces, node->mins, node->maxs);
|
||||
|
||||
// do slow way to save poly splits for drawing hull
|
||||
return ChoosePlaneFromList (surfaces, node->mins, node->maxs);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
=================
|
||||
CalcSurfaceInfo
|
||||
|
||||
Calculates the bounding box
|
||||
=================
|
||||
*/
|
||||
void CalcSurfaceInfo (surface_t *surf)
|
||||
{
|
||||
int i,j;
|
||||
face_t *f;
|
||||
|
||||
if (!surf->faces)
|
||||
Error ("CalcSurfaceInfo: surface without a face");
|
||||
|
||||
//
|
||||
// calculate a bounding box
|
||||
//
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
surf->mins[i] = 99999;
|
||||
surf->maxs[i] = -99999;
|
||||
}
|
||||
|
||||
for (f=surf->faces ; f ; f=f->next)
|
||||
{
|
||||
if (f->contents >= 0)
|
||||
Error ("Bad contents");
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
if (f->pts[i][j] < surf->mins[j])
|
||||
surf->mins[j] = f->pts[i][j];
|
||||
if (f->pts[i][j] > surf->maxs[j])
|
||||
surf->maxs[j] = f->pts[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
DivideSurface
|
||||
==================
|
||||
*/
|
||||
void DivideSurface (surface_t *in, dplane_t *split, surface_t **front, surface_t **back)
|
||||
{
|
||||
face_t *facet, *next;
|
||||
face_t *frontlist, *backlist;
|
||||
face_t *frontfrag, *backfrag;
|
||||
surface_t *news;
|
||||
dplane_t *inplane;
|
||||
|
||||
inplane = &dplanes[in->planenum];
|
||||
|
||||
// parallel case is easy
|
||||
|
||||
if (inplane->normal[0] == split->normal[0]
|
||||
&& inplane->normal[1] == split->normal[1]
|
||||
&& inplane->normal[2] == split->normal[2])
|
||||
{
|
||||
if (inplane->dist > split->dist)
|
||||
{
|
||||
*front = in;
|
||||
*back = NULL;
|
||||
}
|
||||
else if (inplane->dist < split->dist)
|
||||
{
|
||||
*front = NULL;
|
||||
*back = in;
|
||||
}
|
||||
else
|
||||
{ // split the surface into front and back
|
||||
frontlist = NULL;
|
||||
backlist = NULL;
|
||||
for (facet = in->faces ; facet ; facet = next)
|
||||
{
|
||||
next = facet->next;
|
||||
if (facet->planenum & 1)
|
||||
{
|
||||
facet->next = backlist;
|
||||
backlist = facet;
|
||||
}
|
||||
else
|
||||
{
|
||||
facet->next = frontlist;
|
||||
frontlist = facet;
|
||||
}
|
||||
}
|
||||
goto makesurfs;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// do a real split. may still end up entirely on one side
|
||||
// OPTIMIZE: use bounding box for fast test
|
||||
frontlist = NULL;
|
||||
backlist = NULL;
|
||||
|
||||
for (facet = in->faces ; facet ; facet = next)
|
||||
{
|
||||
next = facet->next;
|
||||
SplitFace (facet, split, &frontfrag, &backfrag);
|
||||
if (frontfrag)
|
||||
{
|
||||
frontfrag->next = frontlist;
|
||||
frontlist = frontfrag;
|
||||
}
|
||||
if (backfrag)
|
||||
{
|
||||
backfrag->next = backlist;
|
||||
backlist = backfrag;
|
||||
}
|
||||
}
|
||||
|
||||
// if nothing actually got split, just move the in plane
|
||||
makesurfs:
|
||||
if (frontlist == NULL)
|
||||
{
|
||||
*front = NULL;
|
||||
*back = in;
|
||||
in->faces = backlist;
|
||||
return;
|
||||
}
|
||||
|
||||
if (backlist == NULL)
|
||||
{
|
||||
*front = in;
|
||||
*back = NULL;
|
||||
in->faces = frontlist;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// stuff got split, so allocate one new surface and reuse in
|
||||
news = AllocSurface ();
|
||||
*news = *in;
|
||||
news->faces = backlist;
|
||||
*back = news;
|
||||
|
||||
in->faces = frontlist;
|
||||
*front = in;
|
||||
|
||||
// recalc bboxes and flags
|
||||
CalcSurfaceInfo (news);
|
||||
CalcSurfaceInfo (in);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SplitNodeSurfaces
|
||||
=============
|
||||
*/
|
||||
void SplitNodeSurfaces (surface_t *surfaces, node_t *node)
|
||||
{
|
||||
surface_t *p, *next;
|
||||
surface_t *frontlist, *backlist;
|
||||
surface_t *frontfrag, *backfrag;
|
||||
dplane_t *splitplane;
|
||||
|
||||
splitplane = &dplanes[node->planenum];
|
||||
|
||||
frontlist = NULL;
|
||||
backlist = NULL;
|
||||
|
||||
for (p=surfaces ; p ; p=next)
|
||||
{
|
||||
next = p->next;
|
||||
DivideSurface (p, splitplane, &frontfrag, &backfrag);
|
||||
|
||||
if (frontfrag)
|
||||
{
|
||||
if (!frontfrag->faces)
|
||||
Error ("surface with no faces");
|
||||
frontfrag->next = frontlist;
|
||||
frontlist = frontfrag;
|
||||
}
|
||||
if (backfrag)
|
||||
{
|
||||
if (!backfrag->faces)
|
||||
Error ("surface with no faces");
|
||||
backfrag->next = backlist;
|
||||
backlist = backfrag;
|
||||
}
|
||||
}
|
||||
|
||||
node->children[0]->surfaces = frontlist;
|
||||
node->children[1]->surfaces = backlist;
|
||||
}
|
||||
|
||||
|
||||
int RankForContents (int contents)
|
||||
{
|
||||
switch (contents)
|
||||
{
|
||||
case CONTENTS_EMPTY: return 0;
|
||||
case CONTENTS_WATER: return 1;
|
||||
case CONTENTS_TRANSLUCENT: return 2;
|
||||
case CONTENTS_CURRENT_0: return 3;
|
||||
case CONTENTS_CURRENT_90: return 4;
|
||||
case CONTENTS_CURRENT_180: return 5;
|
||||
case CONTENTS_CURRENT_270: return 6;
|
||||
case CONTENTS_CURRENT_UP: return 7;
|
||||
case CONTENTS_CURRENT_DOWN: return 8;
|
||||
case CONTENTS_SLIME: return 9;
|
||||
case CONTENTS_LAVA : return 10;
|
||||
case CONTENTS_SKY : return 11;
|
||||
case CONTENTS_SOLID: return 12;
|
||||
default:
|
||||
Error ("RankForContents: bad contents %i", contents);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ContentsForRank (int rank)
|
||||
{
|
||||
switch (rank)
|
||||
{
|
||||
case -1: return CONTENTS_SOLID; // no faces at all
|
||||
case 0: return CONTENTS_EMPTY;
|
||||
case 1: return CONTENTS_WATER;
|
||||
case 2: return CONTENTS_TRANSLUCENT;
|
||||
case 3: return CONTENTS_CURRENT_0;
|
||||
case 4: return CONTENTS_CURRENT_90;
|
||||
case 5: return CONTENTS_CURRENT_180;
|
||||
case 6: return CONTENTS_CURRENT_270;
|
||||
case 7: return CONTENTS_CURRENT_UP;
|
||||
case 8: return CONTENTS_CURRENT_DOWN;
|
||||
case 9: return CONTENTS_SLIME;
|
||||
case 10: return CONTENTS_LAVA;
|
||||
case 11: return CONTENTS_SKY;
|
||||
case 12: return CONTENTS_SOLID;
|
||||
default:
|
||||
Error ("ContentsForRank: bad rank %i", rank);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeLeafSurfs
|
||||
=============
|
||||
*/
|
||||
void FreeLeafSurfs (node_t *leaf)
|
||||
{
|
||||
surface_t *surf, *snext;
|
||||
face_t *f, *fnext;
|
||||
|
||||
for (surf = leaf->surfaces ; surf ; surf=snext)
|
||||
{
|
||||
snext = surf->next;
|
||||
for (f=surf->faces ; f ; f=fnext)
|
||||
{
|
||||
fnext = f->next;
|
||||
FreeFace (f);
|
||||
}
|
||||
FreeSurface (surf);
|
||||
}
|
||||
|
||||
leaf->surfaces = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
LinkLeafFaces
|
||||
|
||||
Determines the contents of the leaf and creates the final list of
|
||||
original faces that have some fragment inside this leaf
|
||||
==================
|
||||
*/
|
||||
#define MAX_LEAF_FACES 1024
|
||||
void LinkLeafFaces (surface_t *planelist, node_t *leafnode)
|
||||
{
|
||||
face_t *f;
|
||||
surface_t *surf;
|
||||
int rank, r;
|
||||
int nummarkfaces;
|
||||
face_t *markfaces[MAX_LEAF_FACES];
|
||||
|
||||
leafnode->faces = NULL;
|
||||
leafnode->planenum = -1;
|
||||
|
||||
rank = -1;
|
||||
for ( surf = planelist ; surf ; surf = surf->next)
|
||||
{
|
||||
for (f = surf->faces ; f ; f=f->next)
|
||||
{
|
||||
r = RankForContents (f->contents);
|
||||
if (r > rank)
|
||||
rank = r;
|
||||
}
|
||||
}
|
||||
|
||||
leafnode->contents = ContentsForRank (rank);
|
||||
|
||||
if (leafnode->contents != CONTENTS_SOLID)
|
||||
{
|
||||
nummarkfaces = 0;
|
||||
for (surf = leafnode->surfaces ; surf ; surf=surf->next)
|
||||
{
|
||||
for (f=surf->faces ; f ; f=f->next)
|
||||
{
|
||||
if (nummarkfaces == MAX_LEAF_FACES)
|
||||
Error ("nummarkfaces == MAX_LEAF_FACES");
|
||||
|
||||
markfaces[nummarkfaces++] = f->original;
|
||||
}
|
||||
}
|
||||
|
||||
c_leaffaces += nummarkfaces;
|
||||
markfaces[nummarkfaces] = NULL; // end marker
|
||||
nummarkfaces++;
|
||||
|
||||
leafnode->markfaces = malloc(nummarkfaces * sizeof(*leafnode->markfaces));
|
||||
memcpy (leafnode->markfaces, markfaces, nummarkfaces * sizeof(*leafnode->markfaces));
|
||||
}
|
||||
|
||||
FreeLeafSurfs (leafnode);
|
||||
leafnode->surfaces = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
MakeNodePortal
|
||||
|
||||
create the new portal by taking the full plane winding for the cutting plane
|
||||
and clipping it by all of the planes from the other portals.
|
||||
|
||||
Each portal tracks the node that created it, so unused nodes
|
||||
can be removed later.
|
||||
==================
|
||||
*/
|
||||
void MakeNodePortal (node_t *node)
|
||||
{
|
||||
portal_t *new_portal, *p;
|
||||
dplane_t *plane;
|
||||
dplane_t clipplane;
|
||||
winding_t *w;
|
||||
int side;
|
||||
|
||||
plane = &dplanes[node->planenum];
|
||||
w = BaseWindingForPlane (plane);
|
||||
|
||||
new_portal = AllocPortal ();
|
||||
new_portal->plane = *plane;
|
||||
new_portal->onnode = node;
|
||||
|
||||
side = 0; // shut up compiler warning
|
||||
for (p = node->portals ; p ; p = p->next[side])
|
||||
{
|
||||
clipplane = p->plane;
|
||||
if (p->nodes[0] == node)
|
||||
side = 0;
|
||||
else if (p->nodes[1] == node)
|
||||
{
|
||||
clipplane.dist = -clipplane.dist;
|
||||
VectorSubtract (vec3_origin, clipplane.normal, clipplane.normal);
|
||||
side = 1;
|
||||
}
|
||||
else
|
||||
Error ("MakeNodePortal: mislinked portal");
|
||||
|
||||
w = ClipWinding (w, &clipplane, true);
|
||||
if (!w)
|
||||
{
|
||||
printf ("WARNING: MakeNodePortal:new portal was clipped away from node@(%.0f,%.0f,%.0f)-(%.0f,%.0f,%.0f)\n",
|
||||
node->mins[0], node->mins[1], node->mins[2],
|
||||
node->maxs[0], node->maxs[1], node->maxs[2]);
|
||||
FreePortal (new_portal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
new_portal->winding = w;
|
||||
AddPortalToNodes (new_portal, node->children[0], node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SplitNodePortals
|
||||
|
||||
Move or split the portals that bound node so that the node's
|
||||
children have portals instead of node.
|
||||
==============
|
||||
*/
|
||||
void SplitNodePortals (node_t *node)
|
||||
{
|
||||
portal_t *p, *next_portal, *new_portal;
|
||||
node_t *f, *b, *other_node;
|
||||
int side;
|
||||
dplane_t *plane;
|
||||
winding_t *frontwinding, *backwinding;
|
||||
|
||||
plane = &dplanes[node->planenum];
|
||||
f = node->children[0];
|
||||
b = node->children[1];
|
||||
|
||||
for (p = node->portals ; p ; p = next_portal)
|
||||
{
|
||||
if (p->nodes[0] == node)
|
||||
side = 0;
|
||||
else if (p->nodes[1] == node)
|
||||
side = 1;
|
||||
else
|
||||
Error ("CutNodePortals_r: mislinked portal");
|
||||
next_portal = p->next[side];
|
||||
|
||||
other_node = p->nodes[!side];
|
||||
RemovePortalFromNode (p, p->nodes[0]);
|
||||
RemovePortalFromNode (p, p->nodes[1]);
|
||||
|
||||
//
|
||||
// cut the portal into two portals, one on each side of the cut plane
|
||||
//
|
||||
DivideWinding (p->winding, plane, &frontwinding, &backwinding);
|
||||
|
||||
if (!frontwinding)
|
||||
{
|
||||
if (side == 0)
|
||||
AddPortalToNodes (p, b, other_node);
|
||||
else
|
||||
AddPortalToNodes (p, other_node, b);
|
||||
continue;
|
||||
}
|
||||
if (!backwinding)
|
||||
{
|
||||
if (side == 0)
|
||||
AddPortalToNodes (p, f, other_node);
|
||||
else
|
||||
AddPortalToNodes (p, other_node, f);
|
||||
continue;
|
||||
}
|
||||
|
||||
// the winding is split
|
||||
new_portal = AllocPortal ();
|
||||
*new_portal = *p;
|
||||
new_portal->winding = backwinding;
|
||||
FreeWinding (p->winding);
|
||||
p->winding = frontwinding;
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
AddPortalToNodes (p, f, other_node);
|
||||
AddPortalToNodes (new_portal, b, other_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPortalToNodes (p, other_node, f);
|
||||
AddPortalToNodes (new_portal, other_node, b);
|
||||
}
|
||||
}
|
||||
|
||||
node->portals = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcNodeBounds
|
||||
|
||||
Determines the boundaries of a node by
|
||||
minmaxing all the portal points, whcih
|
||||
completely enclose the node.
|
||||
|
||||
Returns true if the node should be midsplit.(very large)
|
||||
==================
|
||||
*/
|
||||
qboolean CalcNodeBounds (node_t *node)
|
||||
{
|
||||
int i, j;
|
||||
vec_t v;
|
||||
portal_t *p, *next_portal;
|
||||
int side;
|
||||
|
||||
node->mins[0] = node->mins[1] = node->mins[2] = 9999;
|
||||
node->maxs[0] = node->maxs[1] = node->maxs[2] = -9999;
|
||||
|
||||
for (p = node->portals ; p ; p = next_portal)
|
||||
{
|
||||
if (p->nodes[0] == node)
|
||||
side = 0;
|
||||
else if (p->nodes[1] == node)
|
||||
side = 1;
|
||||
else
|
||||
Error ("CutNodePortals_r: mislinked portal");
|
||||
next_portal = p->next[side];
|
||||
|
||||
for (i=0 ; i<p->winding->numpoints ; i++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
v = p->winding->points[i][j];
|
||||
if (v < node->mins[j])
|
||||
node->mins[j] = v;
|
||||
if (v > node->maxs[j])
|
||||
node->maxs[j] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (node->maxs[i] - node->mins[i] > 1024)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CopyFacesToNode
|
||||
|
||||
Do a final merge attempt, then subdivide the faces
|
||||
to surface cache size if needed.
|
||||
|
||||
These are final faces that will be drawable in the game.
|
||||
Copies of these faces are further chopped up into the leafs,
|
||||
but they will reference these originals.
|
||||
==================
|
||||
*/
|
||||
void CopyFacesToNode (node_t *node, surface_t *surf)
|
||||
{
|
||||
face_t **prevptr, *f, *newf;
|
||||
|
||||
// merge as much as possible
|
||||
MergePlaneFaces (surf);
|
||||
|
||||
// subdivide large faces
|
||||
prevptr = &surf->faces;
|
||||
while (1)
|
||||
{
|
||||
f = *prevptr;
|
||||
if (!f)
|
||||
break;
|
||||
SubdivideFace (f, prevptr);
|
||||
f = *prevptr;
|
||||
prevptr = &f->next;
|
||||
}
|
||||
|
||||
// copy the faces to the node, and consider them the originals
|
||||
node->surfaces = NULL;
|
||||
node->faces = NULL;
|
||||
for (f=surf->faces ; f ; f=f->next)
|
||||
{
|
||||
if (f->contents != CONTENTS_SOLID)
|
||||
{
|
||||
newf = AllocFace ();
|
||||
*newf = *f;
|
||||
f->original = newf;
|
||||
newf->next = node->faces;
|
||||
node->faces = newf;
|
||||
c_nodefaces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
DrawSurfaces
|
||||
==================
|
||||
*/
|
||||
void DrawSurfaces (surface_t *surf)
|
||||
{
|
||||
face_t *f;
|
||||
|
||||
Draw_ClearWindow ();
|
||||
for ( ; surf ; surf=surf->next)
|
||||
{
|
||||
for (f = surf->faces ; f ; f=f->next)
|
||||
{
|
||||
Draw_DrawFace (f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BuildBspTree_r
|
||||
==================
|
||||
*/
|
||||
void BuildBspTree_r (node_t *node)
|
||||
{
|
||||
surface_t *split;
|
||||
qboolean midsplit;
|
||||
surface_t *allsurfs;
|
||||
|
||||
midsplit = CalcNodeBounds (node);
|
||||
|
||||
DrawSurfaces (node->surfaces);
|
||||
|
||||
split = SelectPartition (node->surfaces, node, midsplit);
|
||||
if (!split)
|
||||
{ // this is a leaf node
|
||||
node->planenum = PLANENUM_LEAF;
|
||||
LinkLeafFaces (node->surfaces, node);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// these are final polygons
|
||||
//
|
||||
split->onnode = node; // can't use again
|
||||
allsurfs = node->surfaces;
|
||||
node->planenum = split->planenum;
|
||||
node->faces = NULL;
|
||||
CopyFacesToNode (node, split);
|
||||
c_splitnodes++;
|
||||
|
||||
node->children[0] = AllocNode ();
|
||||
node->children[1] = AllocNode ();
|
||||
|
||||
//
|
||||
// split all the polysurfaces into front and back lists
|
||||
//
|
||||
SplitNodeSurfaces (allsurfs, node);
|
||||
|
||||
//
|
||||
// create the portal that seperates the two children
|
||||
//
|
||||
MakeNodePortal (node);
|
||||
|
||||
//
|
||||
// carve the portals on the boundaries of the node
|
||||
//
|
||||
SplitNodePortals (node);
|
||||
|
||||
//
|
||||
// recursively do the children
|
||||
//
|
||||
BuildBspTree_r (node->children[0]);
|
||||
BuildBspTree_r (node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SolidBSP
|
||||
|
||||
Takes a chain of surfaces plus a split type, and
|
||||
returns a bsp tree with faces off the nodes.
|
||||
|
||||
The original surface chain will be completely freed.
|
||||
==================
|
||||
*/
|
||||
node_t *SolidBSP (surfchain_t *surfhead)
|
||||
{
|
||||
int i;
|
||||
node_t *headnode;
|
||||
|
||||
qprintf ("----- SolidBSP -----\n");
|
||||
|
||||
headnode = AllocNode ();
|
||||
headnode->surfaces = surfhead->surfaces;
|
||||
|
||||
Draw_ClearWindow ();
|
||||
c_splitnodes = 0;
|
||||
c_nodefaces = 0;
|
||||
c_leaffaces = 0;
|
||||
|
||||
if (!surfhead->surfaces)
|
||||
{
|
||||
// nothing at all to build
|
||||
headnode->planenum = -1;
|
||||
headnode->contents = CONTENTS_EMPTY;
|
||||
return headnode;
|
||||
}
|
||||
|
||||
//
|
||||
// generate six portals that enclose the entire world
|
||||
//
|
||||
MakeHeadnodePortals (headnode, surfhead->mins, surfhead->maxs);
|
||||
|
||||
//
|
||||
// recursively partition everything
|
||||
//
|
||||
BuildBspTree_r (headnode);
|
||||
|
||||
qprintf ("%5i split nodes\n", c_splitnodes);
|
||||
qprintf ("%5i node faces\n", c_nodefaces);
|
||||
qprintf ("%5i leaf faces\n", c_leaffaces);
|
||||
|
||||
return headnode;
|
||||
}
|
||||
|
474
hlsdk/utils/qbsp2/surfaces.c
Normal file
474
hlsdk/utils/qbsp2/surfaces.c
Normal file
@ -0,0 +1,474 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// divide.h
|
||||
|
||||
#include "bsp5.h"
|
||||
int TexelDelta( face_t *f, dplane_t *plane );
|
||||
int TexelSize( face_t *f );
|
||||
|
||||
|
||||
surface_t newcopy_t;
|
||||
|
||||
/*
|
||||
a surface has all of the faces that could be drawn on a given plane
|
||||
|
||||
the outside filling stage can remove some of them so a better bsp can be generated
|
||||
|
||||
*/
|
||||
|
||||
int subdivides;
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
SubdivideFace
|
||||
|
||||
If the face is >256 in either texture direction, carve a valid sized
|
||||
piece off and insert the remainder in the next link
|
||||
===============
|
||||
*/
|
||||
void SubdivideFace (face_t *f, face_t **prevptr)
|
||||
{
|
||||
float mins, maxs;
|
||||
vec_t v;
|
||||
int axis, i;
|
||||
dplane_t plane;
|
||||
face_t *front, *back, *next;
|
||||
texinfo_t *tex;
|
||||
vec3_t temp;
|
||||
|
||||
// special (non-surface cached) faces don't need subdivision
|
||||
|
||||
tex = &texinfo[f->texturenum];
|
||||
|
||||
if ( tex->flags & TEX_SPECIAL)
|
||||
return;
|
||||
|
||||
|
||||
for (axis = 0 ; axis < 2 ; axis++)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
mins = 999999;
|
||||
maxs = -999999;
|
||||
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
{
|
||||
v = DotProduct (f->pts[i], tex->vecs[axis]);
|
||||
if (v < mins)
|
||||
mins = v;
|
||||
if (v > maxs)
|
||||
maxs = v;
|
||||
}
|
||||
|
||||
if (maxs - mins <= subdivide_size)
|
||||
break;
|
||||
|
||||
// split it
|
||||
subdivides++;
|
||||
|
||||
VectorCopy (tex->vecs[axis], temp);
|
||||
v = VectorNormalize (temp);
|
||||
|
||||
VectorCopy (temp, plane.normal);
|
||||
plane.dist = (mins + subdivide_size - 16)/v;
|
||||
next = f->next;
|
||||
SplitFace (f, &plane, &front, &back);
|
||||
if (!front || !back)
|
||||
{
|
||||
//PrintMemory();
|
||||
printf("SubdivideFace: didn't split the %d-sided polygon @(%.0f,%.0f,%.0f)",
|
||||
f->numpoints, f->pts[0][0], f->pts[0][1], f->pts[0][2] );
|
||||
break;
|
||||
}
|
||||
*prevptr = back;
|
||||
back->next = front;
|
||||
front->next = next;
|
||||
f = back;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TexelDelta( face_t *f, dplane_t *plane )
|
||||
{
|
||||
int current, delta;
|
||||
|
||||
|
||||
current = delta = 0;
|
||||
// Does the plane split the face?
|
||||
if ( FaceSide (f, plane) == SIDE_ON )
|
||||
{
|
||||
face_t *front, *back;
|
||||
|
||||
// Compute the change in texture cache from splitting the face
|
||||
current = TexelSize( f );
|
||||
|
||||
// Speculatively split the face
|
||||
SplitFaceTmp(f, plane, &front, &back);
|
||||
if (!front || !back) // Didn't actually split the face
|
||||
delta = 0;
|
||||
else
|
||||
{
|
||||
delta = 0;//TexelSize( front ) + TexelSize( back ) - current; // Change in texel size
|
||||
FreeFace( front ); // Free new faces
|
||||
FreeFace( back );
|
||||
}
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
int TexelSize( face_t *f )
|
||||
{
|
||||
float mins, maxs;
|
||||
vec_t v;
|
||||
int i, smax, tmax;
|
||||
dplane_t plane;
|
||||
face_t *front, *back, *next;
|
||||
texinfo_t *tex;
|
||||
vec3_t temp;
|
||||
|
||||
// special (non-surface cached) faces don't need subdivision
|
||||
if ( f->texturenum > numtexinfo )
|
||||
{
|
||||
printf("Error on face\n" );
|
||||
return 0;
|
||||
}
|
||||
tex = &texinfo[f->texturenum];
|
||||
|
||||
if ( tex->flags & TEX_SPECIAL)
|
||||
return 0;
|
||||
|
||||
|
||||
mins = 999999;
|
||||
maxs = -999999;
|
||||
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
{
|
||||
v = DotProduct (f->pts[i], tex->vecs[0]);
|
||||
if (v < mins)
|
||||
mins = v;
|
||||
if (v > maxs)
|
||||
maxs = v;
|
||||
}
|
||||
smax = maxs - mins;
|
||||
|
||||
mins = 999999;
|
||||
maxs = -999999;
|
||||
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
{
|
||||
v = DotProduct (f->pts[i], tex->vecs[1]);
|
||||
if (v < mins)
|
||||
mins = v;
|
||||
if (v > maxs)
|
||||
maxs = v;
|
||||
}
|
||||
tmax = maxs - mins;
|
||||
|
||||
return smax * tmax;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
typedef struct hashvert_s
|
||||
{
|
||||
struct hashvert_s *next;
|
||||
vec3_t point;
|
||||
int num;
|
||||
int numplanes; // for corner determination
|
||||
int planenums[2];
|
||||
int numedges;
|
||||
} hashvert_t;
|
||||
|
||||
// #define POINT_EPSILON 0.01
|
||||
#define POINT_EPSILON ON_EPSILON
|
||||
|
||||
int c_cornerverts;
|
||||
|
||||
hashvert_t hvertex[MAX_MAP_VERTS];
|
||||
hashvert_t *hvert_p;
|
||||
|
||||
face_t *edgefaces[MAX_MAP_EDGES][2];
|
||||
int firstmodeledge = 1;
|
||||
int firstmodelface;
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define NUM_HASH 4096
|
||||
|
||||
hashvert_t *hashverts[NUM_HASH];
|
||||
|
||||
static vec3_t hash_min, hash_scale;
|
||||
|
||||
static void InitHash (void)
|
||||
{
|
||||
vec3_t size;
|
||||
vec_t volume;
|
||||
vec_t scale;
|
||||
int newsize[2];
|
||||
int i;
|
||||
|
||||
memset (hashverts, 0, sizeof(hashverts));
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
hash_min[i] = -8000;
|
||||
size[i] = 16000;
|
||||
}
|
||||
|
||||
volume = size[0]*size[1];
|
||||
|
||||
scale = sqrt(volume / NUM_HASH);
|
||||
|
||||
newsize[0] = size[0] / scale;
|
||||
newsize[1] = size[1] / scale;
|
||||
|
||||
hash_scale[0] = newsize[0] / size[0];
|
||||
hash_scale[1] = newsize[1] / size[1];
|
||||
hash_scale[2] = newsize[1];
|
||||
|
||||
hvert_p = hvertex;
|
||||
}
|
||||
|
||||
static unsigned HashVec (vec3_t vec)
|
||||
{
|
||||
unsigned h;
|
||||
|
||||
h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2]
|
||||
+ hash_scale[1] * (vec[1] - hash_min[1]);
|
||||
if ( h >= NUM_HASH)
|
||||
return NUM_HASH - 1;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
GetVertex
|
||||
=============
|
||||
*/
|
||||
int GetVertex (vec3_t in, int planenum)
|
||||
{
|
||||
int h;
|
||||
int i;
|
||||
hashvert_t *hv;
|
||||
vec3_t vert;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if ( fabs(in[i] - Q_rint(in[i])) < 0.001)
|
||||
vert[i] = Q_rint(in[i]);
|
||||
else
|
||||
vert[i] = in[i];
|
||||
}
|
||||
|
||||
h = HashVec (vert);
|
||||
|
||||
for (hv=hashverts[h] ; hv ; hv=hv->next)
|
||||
{
|
||||
if ( fabs(hv->point[0]-vert[0])<POINT_EPSILON
|
||||
&& fabs(hv->point[1]-vert[1])<POINT_EPSILON
|
||||
&& fabs(hv->point[2]-vert[2])<POINT_EPSILON )
|
||||
{
|
||||
hv->numedges++;
|
||||
if (hv->numplanes == 3)
|
||||
return hv->num; // allready known to be a corner
|
||||
for (i=0 ; i<hv->numplanes ; i++)
|
||||
if (hv->planenums[i] == planenum)
|
||||
return hv->num; // allready know this plane
|
||||
if (hv->numplanes == 2)
|
||||
c_cornerverts++;
|
||||
else
|
||||
hv->planenums[hv->numplanes] = planenum;
|
||||
hv->numplanes++;
|
||||
return hv->num;
|
||||
}
|
||||
}
|
||||
|
||||
hv = hvert_p;
|
||||
hv->numedges = 1;
|
||||
hv->numplanes = 1;
|
||||
hv->planenums[0] = planenum;
|
||||
hv->next = hashverts[h];
|
||||
hashverts[h] = hv;
|
||||
VectorCopy (vert, hv->point);
|
||||
hv->num = numvertexes;
|
||||
if (hv->num==MAX_MAP_VERTS)
|
||||
Error ("GetVertex: MAX_MAP_VERTS");
|
||||
hvert_p++;
|
||||
|
||||
// emit a vertex
|
||||
if (numvertexes == MAX_MAP_VERTS)
|
||||
Error ("numvertexes == MAX_MAP_VERTS");
|
||||
|
||||
dvertexes[numvertexes].point[0] = vert[0];
|
||||
dvertexes[numvertexes].point[1] = vert[1];
|
||||
dvertexes[numvertexes].point[2] = vert[2];
|
||||
numvertexes++;
|
||||
|
||||
return hv->num;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
GetEdge
|
||||
|
||||
Don't allow four way edges
|
||||
==================
|
||||
*/
|
||||
int c_tryedges;
|
||||
|
||||
int GetEdge (vec3_t p1, vec3_t p2, face_t *f)
|
||||
{
|
||||
int v1, v2;
|
||||
dedge_t *edge;
|
||||
int i;
|
||||
|
||||
if (!f->contents)
|
||||
Error ("GetEdge: 0 contents");
|
||||
|
||||
c_tryedges++;
|
||||
v1 = GetVertex (p1, f->planenum);
|
||||
v2 = GetVertex (p2, f->planenum);
|
||||
for (i=firstmodeledge ; i < numedges ; i++)
|
||||
{
|
||||
edge = &dedges[i];
|
||||
if (v1 == edge->v[1] && v2 == edge->v[0]
|
||||
&& !edgefaces[i][1]
|
||||
&& edgefaces[i][0]->contents == f->contents)
|
||||
{
|
||||
edgefaces[i][1] = f;
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
|
||||
// emit an edge
|
||||
if (numedges >= MAX_MAP_EDGES)
|
||||
Error ("numedges == MAX_MAP_EDGES");
|
||||
edge = &dedges[numedges];
|
||||
numedges++;
|
||||
edge->v[0] = v1;
|
||||
edge->v[1] = v2;
|
||||
edgefaces[i][0] = f;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CheckVertexes
|
||||
// debugging
|
||||
=============
|
||||
*/
|
||||
void CheckVertexes (void)
|
||||
{
|
||||
int cb, c0, c1, c2, c3;
|
||||
hashvert_t *hv;
|
||||
|
||||
cb = c0 = c1 = c2 = c3 = 0;
|
||||
for (hv=hvertex ; hv!=hvert_p ; hv++)
|
||||
{
|
||||
if (hv->numedges < 0 || hv->numedges & 1)
|
||||
cb++;
|
||||
else if (!hv->numedges)
|
||||
c0++;
|
||||
else if (hv->numedges == 2)
|
||||
c1++;
|
||||
else if (hv->numedges == 4)
|
||||
c2++;
|
||||
else
|
||||
c3++;
|
||||
}
|
||||
|
||||
qprintf ("%5i bad edge points\n", cb);
|
||||
qprintf ("%5i 0 edge points\n", c0);
|
||||
qprintf ("%5i 2 edge points\n", c1);
|
||||
qprintf ("%5i 4 edge points\n", c2);
|
||||
qprintf ("%5i 6+ edge points\n", c3);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CheckEdges
|
||||
// debugging
|
||||
=============
|
||||
*/
|
||||
void CheckEdges (void)
|
||||
{
|
||||
dedge_t *edge;
|
||||
int i;
|
||||
dvertex_t *d1, *d2;
|
||||
face_t *f1, *f2;
|
||||
int c_nonconvex;
|
||||
int c_multitexture;
|
||||
|
||||
c_nonconvex = c_multitexture = 0;
|
||||
|
||||
// CheckVertexes ();
|
||||
|
||||
for (i=1 ; i < numedges ; i++)
|
||||
{
|
||||
edge = &dedges[i];
|
||||
if (!edgefaces[i][1])
|
||||
{
|
||||
d1 = &dvertexes[edge->v[0]];
|
||||
d2 = &dvertexes[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]);
|
||||
}
|
||||
else
|
||||
{
|
||||
f1 = edgefaces[i][0];
|
||||
f2 = edgefaces[i][1];
|
||||
if (f1->planenum != f2->planenum)
|
||||
continue;
|
||||
|
||||
// on the same plane, might be discardable
|
||||
if (f1->texturenum == f2->texturenum)
|
||||
{
|
||||
hvertex[edge->v[0]].numedges-=2;
|
||||
hvertex[edge->v[1]].numedges-=2;
|
||||
c_nonconvex++;
|
||||
}
|
||||
else
|
||||
c_multitexture++;
|
||||
}
|
||||
}
|
||||
|
||||
// qprintf ("%5i edges\n", i);
|
||||
// qprintf ("%5i c_nonconvex\n", c_nonconvex);
|
||||
// qprintf ("%5i c_multitexture\n", c_multitexture);
|
||||
|
||||
// CheckVertexes ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
MakeFaceEdges
|
||||
================
|
||||
*/
|
||||
void MakeFaceEdges (node_t *headnode)
|
||||
{
|
||||
InitHash ();
|
||||
c_tryedges = 0;
|
||||
c_cornerverts = 0;
|
||||
|
||||
firstmodeledge = numedges;
|
||||
firstmodelface = numfaces;
|
||||
}
|
||||
|
520
hlsdk/utils/qbsp2/tjunc.c
Normal file
520
hlsdk/utils/qbsp2/tjunc.c
Normal file
@ -0,0 +1,520 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
// tjunc.c
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
|
||||
typedef struct wvert_s
|
||||
{
|
||||
vec_t t;
|
||||
struct wvert_s *prev, *next;
|
||||
} wvert_t;
|
||||
|
||||
typedef struct wedge_s
|
||||
{
|
||||
struct wedge_s *next;
|
||||
vec3_t dir;
|
||||
vec3_t origin;
|
||||
wvert_t head;
|
||||
} wedge_t;
|
||||
|
||||
int numwedges, numwverts;
|
||||
int tjuncs;
|
||||
int tjuncfaces;
|
||||
|
||||
#define MAXWVERTS 0x20000
|
||||
#define MAXWEDGES 0x10000
|
||||
|
||||
|
||||
wvert_t wverts[MAXWVERTS];
|
||||
wedge_t wedges[MAXWEDGES];
|
||||
|
||||
|
||||
void PrintFace (face_t *f)
|
||||
{
|
||||
int 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]);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define NUM_HASH 1024
|
||||
|
||||
wedge_t *wedge_hash[NUM_HASH];
|
||||
|
||||
static vec3_t hash_min, hash_scale;
|
||||
|
||||
static void InitHash (vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
vec3_t size;
|
||||
vec_t volume;
|
||||
vec_t scale;
|
||||
int newsize[2];
|
||||
|
||||
VectorCopy (mins, hash_min);
|
||||
VectorSubtract (maxs, mins, size);
|
||||
memset (wedge_hash, 0, sizeof(wedge_hash));
|
||||
|
||||
volume = size[0]*size[1];
|
||||
|
||||
scale = sqrt(volume / NUM_HASH);
|
||||
|
||||
newsize[0] = size[0] / scale;
|
||||
newsize[1] = size[1] / scale;
|
||||
|
||||
hash_scale[0] = newsize[0] / size[0];
|
||||
hash_scale[1] = newsize[1] / size[1];
|
||||
hash_scale[2] = newsize[1];
|
||||
}
|
||||
|
||||
static unsigned HashVec (vec3_t vec)
|
||||
{
|
||||
unsigned h;
|
||||
|
||||
h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2]
|
||||
+ hash_scale[1] * (vec[1] - hash_min[1]);
|
||||
if ( h >= NUM_HASH)
|
||||
return NUM_HASH - 1;
|
||||
return h;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
void CanonicalVector (vec3_t vec)
|
||||
{
|
||||
VectorNormalize (vec);
|
||||
if (vec[0] > 0 /* EQUAL_EPSILON */)
|
||||
return;
|
||||
else if (vec[0] < 0 /* -EQUAL_EPSILON */ )
|
||||
{
|
||||
VectorSubtract (vec3_origin, vec, vec);
|
||||
return;
|
||||
}
|
||||
else
|
||||
vec[0] = 0;
|
||||
|
||||
if (vec[1] > 0 /* EQUAL_EPSILON */)
|
||||
return;
|
||||
else if (vec[1] < 0 /*-EQUAL_EPSILON*/)
|
||||
{
|
||||
VectorSubtract (vec3_origin, vec, vec);
|
||||
return;
|
||||
}
|
||||
else
|
||||
vec[1] = 0;
|
||||
|
||||
if (vec[2] > 0 /* EQUAL_EPSILON */ )
|
||||
return;
|
||||
else if (vec[2] < 0 /*-EQUAL_EPSILON*/ )
|
||||
{
|
||||
VectorSubtract (vec3_origin, vec, vec);
|
||||
return;
|
||||
}
|
||||
else
|
||||
vec[2] = 0;
|
||||
printf ("WARNING: CanonicalVector: degenerate\n");
|
||||
}
|
||||
|
||||
wedge_t *FindEdge (vec3_t p1, vec3_t p2, vec_t *t1, vec_t *t2)
|
||||
{
|
||||
vec3_t origin;
|
||||
vec3_t dir;
|
||||
wedge_t *w;
|
||||
vec_t temp;
|
||||
int h;
|
||||
|
||||
VectorSubtract (p2, p1, dir);
|
||||
CanonicalVector (dir);
|
||||
|
||||
*t1 = DotProduct (p1, dir);
|
||||
*t2 = DotProduct (p2, dir);
|
||||
|
||||
VectorMA (p1, -*t1, dir, origin);
|
||||
|
||||
if (*t1 > *t2)
|
||||
{
|
||||
temp = *t1;
|
||||
*t1 = *t2;
|
||||
*t2 = temp;
|
||||
}
|
||||
|
||||
h = HashVec (origin);
|
||||
|
||||
for (w = wedge_hash[h] ; w ; w=w->next)
|
||||
{
|
||||
temp = w->origin[0] - origin[0];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
temp = w->origin[1] - origin[1];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
temp = w->origin[2] - origin[2];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
|
||||
temp = w->dir[0] - dir[0];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
temp = w->dir[1] - dir[1];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
temp = w->dir[2] - dir[2];
|
||||
if (temp < -EQUAL_EPSILON || temp > EQUAL_EPSILON)
|
||||
continue;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
if (numwedges == MAXWEDGES)
|
||||
Error ("FindEdge: numwedges == MAXWEDGES");
|
||||
w = &wedges[numwedges];
|
||||
numwedges++;
|
||||
|
||||
w->next = wedge_hash[h];
|
||||
wedge_hash[h] = w;
|
||||
|
||||
VectorCopy (origin, w->origin);
|
||||
VectorCopy (dir, w->dir);
|
||||
w->head.next = w->head.prev = &w->head;
|
||||
w->head.t = 99999;
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
AddVert
|
||||
|
||||
===============
|
||||
*/
|
||||
// #define T_EPSILON 0.01
|
||||
#define T_EPSILON ON_EPSILON
|
||||
|
||||
void AddVert (wedge_t *w, vec_t t)
|
||||
{
|
||||
wvert_t *v, *newv;
|
||||
|
||||
v = w->head.next;
|
||||
do
|
||||
{
|
||||
if (fabs(v->t - t) < T_EPSILON)
|
||||
return;
|
||||
if (v->t > t)
|
||||
break;
|
||||
v = v->next;
|
||||
} while (1);
|
||||
|
||||
// insert a new wvert before v
|
||||
if (numwverts == MAXWVERTS)
|
||||
Error ("AddVert: numwverts == MAXWVERTS");
|
||||
|
||||
newv = &wverts[numwverts];
|
||||
numwverts++;
|
||||
|
||||
newv->t = t;
|
||||
newv->next = v;
|
||||
newv->prev = v->prev;
|
||||
v->prev->next = newv;
|
||||
v->prev = newv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
AddEdge
|
||||
|
||||
===============
|
||||
*/
|
||||
void AddEdge (vec3_t p1, vec3_t p2)
|
||||
{
|
||||
wedge_t *w;
|
||||
vec_t t1, t2;
|
||||
|
||||
w = FindEdge(p1, p2, &t1, &t2);
|
||||
AddVert (w, t1);
|
||||
AddVert (w, t2);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
AddFaceEdges
|
||||
|
||||
===============
|
||||
*/
|
||||
void AddFaceEdges (face_t *f)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0 ; i < f->numpoints ; i++)
|
||||
{
|
||||
j = (i+1)%f->numpoints;
|
||||
AddEdge (f->pts[i], f->pts[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
// a specially allocated face that can hold hundreds of edges if needed
|
||||
byte superfacebuf[8192];
|
||||
face_t *superface = (face_t *)superfacebuf;
|
||||
int MAXSUPERFACEEDGES = ( sizeof(superfacebuf)-sizeof(face_t)+sizeof(superface->pts)) / sizeof(vec3_t);
|
||||
|
||||
void FixFaceEdges (face_t *f);
|
||||
|
||||
face_t *newlist;
|
||||
|
||||
void SplitFaceForTjunc (face_t *f, face_t *original)
|
||||
{
|
||||
int i;
|
||||
face_t *new, *chain;
|
||||
vec3_t dir, test;
|
||||
vec_t v;
|
||||
int firstcorner, lastcorner;
|
||||
|
||||
chain = NULL;
|
||||
do
|
||||
{
|
||||
if (f->numpoints <= MAXPOINTS)
|
||||
{ // the face is now small enough without more cutting
|
||||
// so copy it back to the original
|
||||
*original = *f;
|
||||
original->original = chain;
|
||||
original->next = newlist;
|
||||
newlist = original;
|
||||
return;
|
||||
}
|
||||
|
||||
tjuncfaces++;
|
||||
|
||||
restart:
|
||||
// find the last corner
|
||||
VectorSubtract (f->pts[f->numpoints-1], f->pts[0], dir);
|
||||
VectorNormalize (dir);
|
||||
for (lastcorner=f->numpoints-1 ; lastcorner > 0 ; lastcorner--)
|
||||
{
|
||||
VectorSubtract (f->pts[lastcorner-1], f->pts[lastcorner], test);
|
||||
VectorNormalize (test);
|
||||
v = DotProduct (test, dir);
|
||||
if (v < 1.0-ON_EPSILON || v > 1.0+ON_EPSILON)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// find the first corner
|
||||
VectorSubtract (f->pts[1], f->pts[0], dir);
|
||||
VectorNormalize (dir);
|
||||
for (firstcorner=1 ; firstcorner < f->numpoints-1 ; firstcorner++)
|
||||
{
|
||||
VectorSubtract (f->pts[firstcorner+1], f->pts[firstcorner], test);
|
||||
VectorNormalize (test);
|
||||
v = DotProduct (test, dir);
|
||||
if (v < 1.0-ON_EPSILON || v > 1.0+ON_EPSILON)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstcorner+2 >= MAXPOINTS)
|
||||
{
|
||||
// rotate the point winding
|
||||
VectorCopy (f->pts[0], test);
|
||||
for (i=1 ; i<f->numpoints ; i++)
|
||||
{
|
||||
VectorCopy (f->pts[i], f->pts[i-1]);
|
||||
}
|
||||
VectorCopy (test, f->pts[f->numpoints-1]);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
|
||||
// cut off as big a piece as possible, less than MAXPOINTS, and not
|
||||
// past lastcorner
|
||||
|
||||
new = NewFaceFromFace (f);
|
||||
if (f->original)
|
||||
Error ("SplitFaceForTjunc: f->original");
|
||||
|
||||
new->original = chain;
|
||||
chain = new;
|
||||
new->next = newlist;
|
||||
newlist = new;
|
||||
if (f->numpoints - firstcorner <= MAXPOINTS)
|
||||
new->numpoints = firstcorner+2;
|
||||
else if (lastcorner+2 < MAXPOINTS &&
|
||||
f->numpoints - lastcorner <= MAXPOINTS)
|
||||
new->numpoints = lastcorner+2;
|
||||
else
|
||||
new->numpoints = MAXPOINTS;
|
||||
|
||||
for (i=0 ; i<new->numpoints ; i++)
|
||||
{
|
||||
VectorCopy (f->pts[i], new->pts[i]);
|
||||
}
|
||||
|
||||
|
||||
for (i=new->numpoints-1 ; i<f->numpoints ; i++)
|
||||
{
|
||||
VectorCopy (f->pts[i], f->pts[i-(new->numpoints-2)]);
|
||||
}
|
||||
f->numpoints -= (new->numpoints-2);
|
||||
} while (1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
FixFaceEdges
|
||||
|
||||
===============
|
||||
*/
|
||||
void FixFaceEdges (face_t *f)
|
||||
{
|
||||
int i, j, k;
|
||||
wedge_t *w;
|
||||
wvert_t *v;
|
||||
vec_t t1, t2;
|
||||
|
||||
*superface = *f;
|
||||
|
||||
restart:
|
||||
for (i=0 ; i < superface->numpoints ; i++)
|
||||
{
|
||||
j = (i+1)%superface->numpoints;
|
||||
|
||||
w = FindEdge (superface->pts[i], superface->pts[j], &t1, &t2);
|
||||
|
||||
for (v=w->head.next ; v->t < t1 + T_EPSILON; v = v->next)
|
||||
{
|
||||
}
|
||||
|
||||
if (v->t < t2-T_EPSILON)
|
||||
{
|
||||
tjuncs++;
|
||||
// insert a new vertex here
|
||||
for (k = superface->numpoints ; k> j ; k--)
|
||||
{
|
||||
VectorCopy (superface->pts[k-1], superface->pts[k]);
|
||||
}
|
||||
VectorMA (w->origin, v->t, w->dir, superface->pts[j]);
|
||||
superface->numpoints++;
|
||||
if ( superface->numpoints >= MAXSUPERFACEEDGES )
|
||||
Error( "FixFaceEdges: Exceeded MAXSUPERFACEEDGES(%d)!\n", MAXSUPERFACEEDGES );
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (superface->numpoints <= MAXPOINTS)
|
||||
{
|
||||
*f = *superface;
|
||||
f->next = newlist;
|
||||
newlist = f;
|
||||
return;
|
||||
}
|
||||
|
||||
// the face needs to be split into multiple faces because of too many edges
|
||||
|
||||
SplitFaceForTjunc (superface, f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
void tjunc_find_r (node_t *node)
|
||||
{
|
||||
face_t *f;
|
||||
|
||||
if (node->planenum == PLANENUM_LEAF)
|
||||
return;
|
||||
|
||||
for (f=node->faces ; f ; f=f->next)
|
||||
AddFaceEdges (f);
|
||||
|
||||
tjunc_find_r (node->children[0]);
|
||||
tjunc_find_r (node->children[1]);
|
||||
}
|
||||
|
||||
void tjunc_fix_r (node_t *node)
|
||||
{
|
||||
face_t *f, *next;
|
||||
|
||||
if (node->planenum == PLANENUM_LEAF)
|
||||
return;
|
||||
|
||||
newlist = NULL;
|
||||
|
||||
for (f=node->faces ; f ; f=next)
|
||||
{
|
||||
next = f->next;
|
||||
FixFaceEdges (f);
|
||||
}
|
||||
|
||||
node->faces = newlist;
|
||||
|
||||
tjunc_fix_r (node->children[0]);
|
||||
tjunc_fix_r (node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
tjunc
|
||||
|
||||
===========
|
||||
*/
|
||||
void tjunc (node_t *headnode)
|
||||
{
|
||||
vec3_t maxs, mins;
|
||||
int i;
|
||||
|
||||
qprintf ("---- tjunc ----\n");
|
||||
|
||||
if (notjunc)
|
||||
return;
|
||||
|
||||
//
|
||||
// identify all points on common edges
|
||||
//
|
||||
|
||||
// origin points won't allways be inside the map, so extend the hash area
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if ( fabs(headnode->maxs[i]) > fabs(headnode->mins[i]) )
|
||||
maxs[i] = fabs(headnode->maxs[i]);
|
||||
else
|
||||
maxs[i] = fabs(headnode->mins[i]);
|
||||
}
|
||||
VectorSubtract (vec3_origin, maxs, mins);
|
||||
|
||||
InitHash (mins, maxs);
|
||||
|
||||
numwedges = numwverts = 0;
|
||||
|
||||
tjunc_find_r (headnode);
|
||||
|
||||
qprintf ("%i world edges %i edge points\n", numwedges, numwverts);
|
||||
|
||||
//
|
||||
// add extra vertexes on edges where needed
|
||||
//
|
||||
tjuncs = tjuncfaces = 0;
|
||||
|
||||
tjunc_fix_r (headnode);
|
||||
|
||||
qprintf ("%i edges added by tjunctions\n", tjuncs);
|
||||
qprintf ("%i faces added by tjunctions\n", tjuncfaces);
|
||||
}
|
289
hlsdk/utils/qbsp2/writebsp.c
Normal file
289
hlsdk/utils/qbsp2/writebsp.c
Normal file
@ -0,0 +1,289 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
****/
|
||||
|
||||
|
||||
#include "bsp5.h"
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteClipNodes_r
|
||||
|
||||
==================
|
||||
*/
|
||||
int WriteClipNodes_r (node_t *node)
|
||||
{
|
||||
int i, c;
|
||||
dclipnode_t *cn;
|
||||
int num;
|
||||
|
||||
if (node->planenum == -1)
|
||||
{
|
||||
num = node->contents;
|
||||
free (node->markfaces);
|
||||
free (node);
|
||||
return num;
|
||||
}
|
||||
|
||||
// emit a clipnode
|
||||
if (numclipnodes == MAX_MAP_CLIPNODES)
|
||||
Error ("MAX_MAP_CLIPNODES");
|
||||
c = numclipnodes;
|
||||
cn = &dclipnodes[numclipnodes];
|
||||
numclipnodes++;
|
||||
if (node->planenum & 1)
|
||||
Error ("WriteClipNodes_r: odd planenum");
|
||||
cn->planenum = node->planenum;
|
||||
for (i=0 ; i<2 ; i++)
|
||||
cn->children[i] = WriteClipNodes_r(node->children[i]);
|
||||
|
||||
free (node);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteClipNodes
|
||||
|
||||
Called after the clipping hull is completed. Generates a disk format
|
||||
representation and frees the original memory.
|
||||
==================
|
||||
*/
|
||||
void WriteClipNodes (node_t *nodes)
|
||||
{
|
||||
WriteClipNodes_r (nodes);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteDrawLeaf
|
||||
==================
|
||||
*/
|
||||
void WriteDrawLeaf (node_t *node)
|
||||
{
|
||||
face_t **fp, *f;
|
||||
dleaf_t *leaf_p;
|
||||
|
||||
// emit a leaf
|
||||
leaf_p = &dleafs[numleafs];
|
||||
numleafs++;
|
||||
|
||||
leaf_p->contents = node->contents;
|
||||
|
||||
//
|
||||
// write bounding box info
|
||||
//
|
||||
VectorCopy (node->mins, leaf_p->mins);
|
||||
VectorCopy (node->maxs, leaf_p->maxs);
|
||||
|
||||
leaf_p->visofs = -1; // no vis info yet
|
||||
|
||||
//
|
||||
// write the marksurfaces
|
||||
//
|
||||
leaf_p->firstmarksurface = nummarksurfaces;
|
||||
|
||||
for (fp=node->markfaces ; *fp ; fp++)
|
||||
{
|
||||
// emit a marksurface
|
||||
f = *fp;
|
||||
do
|
||||
{
|
||||
dmarksurfaces[nummarksurfaces] = f->outputnumber;
|
||||
if (nummarksurfaces >= MAX_MAP_MARKSURFACES)
|
||||
Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
|
||||
nummarksurfaces++;
|
||||
f=f->original; // grab tjunction split faces
|
||||
} while (f);
|
||||
}
|
||||
free (node->markfaces);
|
||||
|
||||
leaf_p->nummarksurfaces = nummarksurfaces - leaf_p->firstmarksurface;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteFace
|
||||
==================
|
||||
*/
|
||||
void WriteFace (face_t *f)
|
||||
{
|
||||
dface_t *df;
|
||||
int i;
|
||||
int e;
|
||||
|
||||
f->outputnumber = numfaces;
|
||||
|
||||
df = &dfaces[numfaces];
|
||||
if (numfaces >= MAX_MAP_FACES)
|
||||
Error ("numfaces == MAX_MAP_FACES");
|
||||
numfaces++;
|
||||
|
||||
df->planenum = f->planenum & (~1);
|
||||
df->side = f->planenum & 1;
|
||||
df->firstedge = numsurfedges;
|
||||
df->numedges = f->numpoints;
|
||||
df->texinfo = f->texturenum;
|
||||
for (i=0 ; i<f->numpoints ; i++)
|
||||
{
|
||||
e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
|
||||
if (numsurfedges >= MAX_MAP_SURFEDGES)
|
||||
Error ("numsurfedges == MAX_MAP_SURFEDGES");
|
||||
dsurfedges[numsurfedges] = e;
|
||||
numsurfedges++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteDrawNodes_r
|
||||
==================
|
||||
*/
|
||||
void WriteDrawNodes_r (node_t *node)
|
||||
{
|
||||
dnode_t *n;
|
||||
int i;
|
||||
face_t *f, *next;
|
||||
|
||||
// emit a node
|
||||
if (numnodes == MAX_MAP_NODES)
|
||||
Error ("numnodes == MAX_MAP_NODES");
|
||||
n = &dnodes[numnodes];
|
||||
numnodes++;
|
||||
|
||||
VectorCopy (node->mins, n->mins);
|
||||
VectorCopy (node->maxs, n->maxs);
|
||||
|
||||
if (node->planenum & 1)
|
||||
Error ("WriteDrawNodes_r: odd planenum");
|
||||
n->planenum = node->planenum;
|
||||
n->firstface = numfaces;
|
||||
|
||||
for (f=node->faces ; f ; f=f->next)
|
||||
WriteFace (f);
|
||||
|
||||
n->numfaces = numfaces - n->firstface;
|
||||
|
||||
//
|
||||
// recursively output the other nodes
|
||||
//
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (node->children[i]->planenum == -1)
|
||||
{
|
||||
if (node->children[i]->contents == CONTENTS_SOLID)
|
||||
n->children[i] = -1;
|
||||
else
|
||||
{
|
||||
n->children[i] = -(numleafs + 1);
|
||||
WriteDrawLeaf (node->children[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n->children[i] = numnodes;
|
||||
WriteDrawNodes_r (node->children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
FreeDrawNodes_r
|
||||
===========
|
||||
*/
|
||||
void FreeDrawNodes_r (node_t *node)
|
||||
{
|
||||
int i;
|
||||
face_t *f, *next;
|
||||
|
||||
for (i=0 ; i<2 ; i++)
|
||||
if (node->children[i]->planenum != -1)
|
||||
FreeDrawNodes_r (node->children[i]);
|
||||
|
||||
//
|
||||
// free the faces on the node
|
||||
//
|
||||
for (f=node->faces ; f ; f=next)
|
||||
{
|
||||
next = f->next;
|
||||
FreeFace (f);
|
||||
}
|
||||
|
||||
free (node);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WriteDrawNodes
|
||||
|
||||
Called after a drawing hull is completed
|
||||
Frees all nodes and faces.
|
||||
==================
|
||||
*/
|
||||
void WriteDrawNodes (node_t *headnode)
|
||||
{
|
||||
if (headnode->contents < 0)
|
||||
WriteDrawLeaf (headnode);
|
||||
else
|
||||
{
|
||||
WriteDrawNodes_r (headnode);
|
||||
FreeDrawNodes_r (headnode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginBSPFile
|
||||
==================
|
||||
*/
|
||||
void BeginBSPFile (void)
|
||||
{
|
||||
// these values may actually be initialized
|
||||
// if the file existed when loaded, so clear them explicitly
|
||||
nummodels = 0;
|
||||
numfaces = 0;
|
||||
numnodes = 0;
|
||||
numclipnodes = 0;
|
||||
numvertexes = 0;
|
||||
nummarksurfaces = 0;
|
||||
numsurfedges = 0;
|
||||
|
||||
// edge 0 is not used, because 0 can't be negated
|
||||
numedges = 1;
|
||||
|
||||
// leaf 0 is common solid with no faces
|
||||
numleafs = 1;
|
||||
dleafs[0].contents = CONTENTS_SOLID;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
FinishBSPFile
|
||||
==================
|
||||
*/
|
||||
void FinishBSPFile (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
qprintf ("--- FinishBSPFile ---\n");
|
||||
|
||||
if (verbose)
|
||||
PrintBSPFileSizes ();
|
||||
WriteBSPFile (bspfilename);
|
||||
}
|
||||
|
Reference in New Issue
Block a user