Moved modified HL SDK to trunk

This commit is contained in:
Scott Ehlert
2006-08-27 02:22:59 +00:00
parent 28c4ea4fec
commit 30235e05e5
900 changed files with 344676 additions and 0 deletions

267
hlsdk/utils/qbsp2/bsp5.h Normal file
View 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
View 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
View 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
View 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);
}

View 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

View 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>
{{{
}}}
###############################################################################

View 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="&quot;$/SDKSrc/Tools/utils/qbsp2&quot;, 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>

View 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>

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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;
}

View 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
View 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);
}

View 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);
}