* General decrufting:

* Removed Q3_STATIC and associated defines
* Removed MAC_STATIC
* Replaced __LCC__ with Q3_VM
* Removed bspc and splines directories
This commit is contained in:
Tim Angus 2005-10-29 23:13:09 +00:00
parent 63fdc74843
commit c41483634c
116 changed files with 16 additions and 48383 deletions

View File

@ -1,114 +0,0 @@
#
# Makefile for the BSPC tool for the Gladiator Bot
# Intended for gcc/Linux
#
# TTimo 5/15/2001
# some cleanup .. only used on i386 for GtkRadiant setups AFAIK .. removing the i386 tag
# TODO: the intermediate object files should go into their own directory
# specially for ../botlib and ../qcommon, the compilation flags on those might not be what you expect
#ARCH=i386
CC=gcc
BASE_CFLAGS=-Dstricmp=strcasecmp
#use these cflags to optimize it
CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
-malign-jumps=2 -malign-functions=2 -DLINUX -DBSPC
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-ldl -lm -lpthread
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
#############################################################################
# SETUP AND BUILD BSPC
#############################################################################
.c.o:
$(DO_CC)
GAME_OBJS = \
_files.o\
aas_areamerging.o\
aas_cfg.o\
aas_create.o\
aas_edgemelting.o\
aas_facemerging.o\
aas_file.o\
aas_gsubdiv.o\
aas_map.o\
aas_prunenodes.o\
aas_store.o\
be_aas_bspc.o\
../botlib/be_aas_bspq3.o\
../botlib/be_aas_cluster.o\
../botlib/be_aas_move.o\
../botlib/be_aas_optimize.o\
../botlib/be_aas_reach.o\
../botlib/be_aas_sample.o\
brushbsp.o\
bspc.o\
../qcommon/cm_load.o\
../qcommon/cm_patch.o\
../qcommon/cm_test.o\
../qcommon/cm_trace.o\
csg.o\
glfile.o\
l_bsp_ent.o\
l_bsp_hl.o\
l_bsp_q1.o\
l_bsp_q2.o\
l_bsp_q3.o\
l_bsp_sin.o\
l_cmd.o\
../botlib/l_libvar.o\
l_log.o\
l_math.o\
l_mem.o\
l_poly.o\
../botlib/l_precomp.o\
l_qfiles.o\
../botlib/l_script.o\
../botlib/l_struct.o\
l_threads.o\
l_utils.o\
leakfile.o\
map.o\
map_hl.o\
map_q1.o\
map_q2.o\
map_q3.o\
map_sin.o\
../qcommon/md4.o\
nodraw.o\
portals.o\
textures.o\
tree.o\
../qcommon/unzip.o
#tetrahedron.o
bspc : $(GAME_OBJS)
$(CC) $(CFLAGS) -o $@ $(GAME_OBJS) $(LDFLAGS)
strip $@
#############################################################################
# MISC
#############################################################################
clean:
-rm -f $(GAME_OBJS)
depend:
gcc -MM $(GAME_OBJS:.o=.c)
#install:
# cp bspci386 ..
#
# From "make depend"
#

View File

@ -1,63 +0,0 @@
//===========================================================================
//
// Name: _files.c
// Function:
// Programmer: Mr Elusive
// Last update: 1999-12-02
// Tab Size: 4
//===========================================================================
/*
aas_areamerging.c //AAS area merging
aas_cfg.c //AAS configuration for different games
aas_create.c //AAS creating
aas_edgemelting.c //AAS edge melting
aas_facemerging.c //AAS face merging
aas_file.c //AAS file writing
aas_gsubdiv.c //AAS gravitational and ladder subdivision
aas_map.c //AAS map brush creation
aas_prunenodes.c //AAS node pruning
aas_store.c //AAS file storing
map.c //map file loading and writing
map_hl.c //Half-Life map loading
map_q1.c //Quake1 map loading
map_q2.c //Quake2 map loading
map_q3.c //Quake3 map loading
map_sin.c //Sin map loading
tree.c //BSP tree management + node pruning (*)
brushbsp.c //brush bsp creation (*)
portals.c //BSP portal creation and leaf filling (*)
csg.c //Constructive Solid Geometry brush chopping (*)
leakfile.c //leak file writing (*)
textures.c //Quake2 BSP textures (*)
l_bsp_ent.c //BSP entity parsing
l_bsp_hl.c //Half-Life BSP loading and writing
l_bsp_q1.c //Quake1 BSP loading and writing
l_bsp_q2.c //Quake2 BSP loading and writing
l_bsp_q3.c //Quake2 BSP loading and writing
l_bsp_sin.c //Sin BSP loading and writing
l_cmd.c //cmd library
l_log.c //log file library
l_math.c //math library
l_mem.c //memory management library
l_poly.c //polygon (winding) library
l_script.c //script file parsing library
l_threads.c //multi-threading library
l_utils.c //utility library
l_qfiles.c //loading of quake files
gldraw.c //GL drawing (*)
glfile.c //GL file writing (*)
nodraw.c //no draw module (*)
bspc.c //BSPC Win32 console version
winbspc.c //WinBSPC Win32 GUI version
win32_terminal.c //Win32 terminal output
win32_qfiles.c //Win32 game file management (also .pak .sin)
win32_font.c //Win32 fonts
win32_folder.c //Win32 folder dialogs
*/

View File

@ -1,390 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
#include "aas_store.h"
#define CONVEX_EPSILON 0.3
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_RefreshMergedTree_r(tmp_node_t *tmpnode)
{
tmp_area_t *tmparea;
//if this is a solid leaf
if (!tmpnode) return NULL;
//if this is an area leaf
if (tmpnode->tmparea)
{
tmparea = tmpnode->tmparea;
while(tmparea->mergedarea) tmparea = tmparea->mergedarea;
tmpnode->tmparea = tmparea;
return tmpnode;
} //end if
//do the children recursively
tmpnode->children[0] = AAS_RefreshMergedTree_r(tmpnode->children[0]);
tmpnode->children[1] = AAS_RefreshMergedTree_r(tmpnode->children[1]);
return tmpnode;
} //end of the function AAS_RefreshMergedTree_r
//===========================================================================
// returns true if the two given faces would create a non-convex area at
// the given sides, otherwise false is returned
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int NonConvex(tmp_face_t *face1, tmp_face_t *face2, int side1, int side2)
{
int i;
winding_t *w1, *w2;
plane_t *plane1, *plane2;
w1 = face1->winding;
w2 = face2->winding;
plane1 = &mapplanes[face1->planenum ^ side1];
plane2 = &mapplanes[face2->planenum ^ side2];
//check if one of the points of face1 is at the back of the plane of face2
for (i = 0; i < w1->numpoints; i++)
{
if (DotProduct(plane2->normal, w1->p[i]) - plane2->dist < -CONVEX_EPSILON) return true;
} //end for
//check if one of the points of face2 is at the back of the plane of face1
for (i = 0; i < w2->numpoints; i++)
{
if (DotProduct(plane1->normal, w2->p[i]) - plane1->dist < -CONVEX_EPSILON) return true;
} //end for
return false;
} //end of the function NonConvex
//===========================================================================
// try to merge the areas at both sides of the given face
//
// Parameter: seperatingface : face that seperates two areas
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TryMergeFaceAreas(tmp_face_t *seperatingface)
{
int side1, side2, area1faceflags, area2faceflags;
tmp_area_t *tmparea1, *tmparea2, *newarea;
tmp_face_t *face1, *face2, *nextface1, *nextface2;
tmparea1 = seperatingface->frontarea;
tmparea2 = seperatingface->backarea;
//areas must have the same presence type
if (tmparea1->presencetype != tmparea2->presencetype) return false;
//areas must have the same area contents
if (tmparea1->contents != tmparea2->contents) return false;
//areas must have the same bsp model inside (or both none)
if (tmparea1->modelnum != tmparea2->modelnum) return false;
area1faceflags = 0;
area2faceflags = 0;
for (face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = (face1->frontarea != tmparea1);
//debug: check if the area belongs to the area
if (face1->frontarea != tmparea1 &&
face1->backarea != tmparea1) Error("face does not belong to area1");
//just continue if the face is seperating the two areas
//NOTE: a result of this is that ground and gap areas can
// be merged if the seperating face is the gap
if ((face1->frontarea == tmparea1 &&
face1->backarea == tmparea2) ||
(face1->frontarea == tmparea2 &&
face1->backarea == tmparea1)) continue;
//get area1 face flags
area1faceflags |= face1->faceflags;
if (AAS_GapFace(face1, side1)) area1faceflags |= FACE_GAP;
//
for (face2 = tmparea2->tmpfaces; face2; face2 = face2->next[side2])
{
side2 = (face2->frontarea != tmparea2);
//debug: check if the area belongs to the area
if (face2->frontarea != tmparea2 &&
face2->backarea != tmparea2) Error("face does not belong to area2");
//just continue if the face is seperating the two areas
//NOTE: a result of this is that ground and gap areas can
// be merged if the seperating face is the gap
if ((face2->frontarea == tmparea1 &&
face2->backarea == tmparea2) ||
(face2->frontarea == tmparea2 &&
face2->backarea == tmparea1)) continue;
//get area2 face flags
area2faceflags |= face2->faceflags;
if (AAS_GapFace(face2, side2)) area2faceflags |= FACE_GAP;
//if the two faces would create a non-convex area
if (NonConvex(face1, face2, side1, side2)) return false;
} //end for
} //end for
//if one area has gap faces (that aren't seperating the two areas)
//and the other has ground faces (that aren't seperating the two areas),
//the areas can't be merged
if (((area1faceflags & FACE_GROUND) && (area2faceflags & FACE_GAP)) ||
((area2faceflags & FACE_GROUND) && (area1faceflags & FACE_GAP)))
{
// Log_Print(" can't merge: ground/gap\n");
return false;
} //end if
// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum, numfaces);
// return false;
//
//AAS_CheckArea(tmparea1);
//AAS_CheckArea(tmparea2);
//create the new area
newarea = AAS_AllocTmpArea();
newarea->presencetype = tmparea1->presencetype;
newarea->contents = tmparea1->contents;
newarea->modelnum = tmparea1->modelnum;
newarea->tmpfaces = NULL;
//add all the faces (except the seperating ones) from the first area
//to the new area
for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
{
side1 = (face1->frontarea != tmparea1);
nextface1 = face1->next[side1];
//don't add seperating faces
if ((face1->frontarea == tmparea1 &&
face1->backarea == tmparea2) ||
(face1->frontarea == tmparea2 &&
face1->backarea == tmparea1))
{
continue;
} //end if
//
AAS_RemoveFaceFromArea(face1, tmparea1);
AAS_AddFaceSideToArea(face1, side1, newarea);
} //end for
//add all the faces (except the seperating ones) from the second area
//to the new area
for (face2 = tmparea2->tmpfaces; face2; face2 = nextface2)
{
side2 = (face2->frontarea != tmparea2);
nextface2 = face2->next[side2];
//don't add seperating faces
if ((face2->frontarea == tmparea1 &&
face2->backarea == tmparea2) ||
(face2->frontarea == tmparea2 &&
face2->backarea == tmparea1))
{
continue;
} //end if
//
AAS_RemoveFaceFromArea(face2, tmparea2);
AAS_AddFaceSideToArea(face2, side2, newarea);
} //end for
//free all shared faces
for (face1 = tmparea1->tmpfaces; face1; face1 = nextface1)
{
side1 = (face1->frontarea != tmparea1);
nextface1 = face1->next[side1];
//
AAS_RemoveFaceFromArea(face1, face1->frontarea);
AAS_RemoveFaceFromArea(face1, face1->backarea);
AAS_FreeTmpFace(face1);
} //end for
//
tmparea1->mergedarea = newarea;
tmparea1->invalid = true;
tmparea2->mergedarea = newarea;
tmparea2->invalid = true;
//
AAS_CheckArea(newarea);
AAS_FlipAreaFaces(newarea);
// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum);
return true;
} //end of the function AAS_TryMergeFaceAreas
//===========================================================================
// try to merge areas
// merged areas are added to the end of the convex area list so merging
// will be tried for those areas as well
//
// Parameter: -
// Returns: -
// Changes Globals: tmpaasworld
//===========================================================================
/*
void AAS_MergeAreas(void)
{
int side, nummerges;
tmp_area_t *tmparea, *othertmparea;
tmp_face_t *face;
nummerges = 0;
Log_Write("AAS_MergeAreas\r\n");
qprintf("%6d areas merged", 1);
//first merge grounded areas only
//NOTE: this is useless because the area settings aren't available yet
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
// Log_Print("checking area %d\n", i);
//if the area is invalid
if (tmparea->invalid)
{
// Log_Print(" area invalid\n");
continue;
} //end if
//
// if (!(tmparea->settings->areaflags & AREA_GROUNDED)) continue;
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
//if the face has both a front and back area
if (face->frontarea && face->backarea)
{
//
if (face->frontarea == tmparea) othertmparea = face->backarea;
else othertmparea = face->frontarea;
// if (!(othertmparea->settings->areaflags & AREA_GROUNDED)) continue;
// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
if (AAS_TryMergeFaceAreas(face))
{
qprintf("\r%6d", ++nummerges);
break;
} //end if
} //end if
} //end for
} //end for
//merge all areas
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
// Log_Print("checking area %d\n", i);
//if the area is invalid
if (tmparea->invalid)
{
// Log_Print(" area invalid\n");
continue;
} //end if
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
//if the face has both a front and back area
if (face->frontarea && face->backarea)
{
// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
if (AAS_TryMergeFaceAreas(face))
{
qprintf("\r%6d", ++nummerges);
break;
} //end if
} //end if
} //end for
} //end for
Log_Print("\r%6d areas merged\n", nummerges);
//refresh the merged tree
AAS_RefreshMergedTree_r(tmpaasworld.nodes);
} //end of the function AAS_MergeAreas*/
int AAS_GroundArea(tmp_area_t *tmparea)
{
tmp_face_t *face;
int side;
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
if (face->faceflags & FACE_GROUND) return true;
} //end for
return false;
} //end of the function AAS_GroundArea
void AAS_MergeAreas(void)
{
int side, nummerges, merges, groundfirst;
tmp_area_t *tmparea, *othertmparea;
tmp_face_t *face;
nummerges = 0;
Log_Write("AAS_MergeAreas\r\n");
qprintf("%6d areas merged", 1);
//
groundfirst = true;
//for (i = 0; i < 4 || merges; i++)
while(1)
{
//if (i < 2) groundfirst = true;
//else groundfirst = false;
//
merges = 0;
//first merge grounded areas only
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
//if the area is invalid
if (tmparea->invalid)
{
continue;
} //end if
//
if (groundfirst)
{
if (!AAS_GroundArea(tmparea)) continue;
} //end if
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
//if the face has both a front and back area
if (face->frontarea && face->backarea)
{
//
if (face->frontarea == tmparea) othertmparea = face->backarea;
else othertmparea = face->frontarea;
//
if (groundfirst)
{
if (!AAS_GroundArea(othertmparea)) continue;
} //end if
if (AAS_TryMergeFaceAreas(face))
{
qprintf("\r%6d", ++nummerges);
merges++;
break;
} //end if
} //end if
} //end for
} //end for
if (!merges)
{
if (groundfirst) groundfirst = false;
else break;
} //end if
} //end for
qprintf("\n");
Log_Write("%6d areas merged\r\n", nummerges);
//refresh the merged tree
AAS_RefreshMergedTree_r(tmpaasworld.nodes);
} //end of the function AAS_MergeAreas

View File

@ -1,24 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MergeAreas(void);

View File

@ -1,252 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "float.h"
#include "../botlib/aasfile.h"
#include "aas_store.h"
#include "aas_cfg.h"
#include "../botlib/l_precomp.h"
#include "../botlib/l_struct.h"
#include "../botlib/l_libvar.h"
//structure field offsets
#define BBOX_OFS(x) (int)&(((aas_bbox_t *)0)->x)
#define CFG_OFS(x) (int)&(((cfg_t *)0)->x)
//bounding box definition
fielddef_t bbox_fields[] =
{
{"presencetype", BBOX_OFS(presencetype), FT_INT},
{"flags", BBOX_OFS(flags), FT_INT},
{"mins", BBOX_OFS(mins), FT_FLOAT|FT_ARRAY, 3},
{"maxs", BBOX_OFS(maxs), FT_FLOAT|FT_ARRAY, 3},
{NULL, 0, 0, 0}
};
fielddef_t cfg_fields[] =
{
{"phys_gravitydirection", CFG_OFS(phys_gravitydirection), FT_FLOAT|FT_ARRAY, 3},
{"phys_friction", CFG_OFS(phys_friction), FT_FLOAT},
{"phys_stopspeed", CFG_OFS(phys_stopspeed), FT_FLOAT},
{"phys_gravity", CFG_OFS(phys_gravity), FT_FLOAT},
{"phys_waterfriction", CFG_OFS(phys_waterfriction), FT_FLOAT},
{"phys_watergravity", CFG_OFS(phys_watergravity), FT_FLOAT},
{"phys_maxvelocity", CFG_OFS(phys_maxvelocity), FT_FLOAT},
{"phys_maxwalkvelocity", CFG_OFS(phys_maxwalkvelocity), FT_FLOAT},
{"phys_maxcrouchvelocity", CFG_OFS(phys_maxcrouchvelocity), FT_FLOAT},
{"phys_maxswimvelocity", CFG_OFS(phys_maxswimvelocity), FT_FLOAT},
{"phys_walkaccelerate", CFG_OFS(phys_walkaccelerate), FT_FLOAT},
{"phys_airaccelerate", CFG_OFS(phys_airaccelerate), FT_FLOAT},
{"phys_swimaccelerate", CFG_OFS(phys_swimaccelerate), FT_FLOAT},
{"phys_maxstep", CFG_OFS(phys_maxstep), FT_FLOAT},
{"phys_maxsteepness", CFG_OFS(phys_maxsteepness), FT_FLOAT},
{"phys_maxwaterjump", CFG_OFS(phys_maxwaterjump), FT_FLOAT},
{"phys_maxbarrier", CFG_OFS(phys_maxbarrier), FT_FLOAT},
{"phys_jumpvel", CFG_OFS(phys_jumpvel), FT_FLOAT},
{"phys_falldelta5", CFG_OFS(phys_falldelta5), FT_FLOAT},
{"phys_falldelta10", CFG_OFS(phys_falldelta10), FT_FLOAT},
{"rs_waterjump", CFG_OFS(rs_waterjump), FT_FLOAT},
{"rs_teleport", CFG_OFS(rs_teleport), FT_FLOAT},
{"rs_barrierjump", CFG_OFS(rs_barrierjump), FT_FLOAT},
{"rs_startcrouch", CFG_OFS(rs_startcrouch), FT_FLOAT},
{"rs_startgrapple", CFG_OFS(rs_startgrapple), FT_FLOAT},
{"rs_startwalkoffledge", CFG_OFS(rs_startwalkoffledge), FT_FLOAT},
{"rs_startjump", CFG_OFS(rs_startjump), FT_FLOAT},
{"rs_rocketjump", CFG_OFS(rs_rocketjump), FT_FLOAT},
{"rs_bfgjump", CFG_OFS(rs_bfgjump), FT_FLOAT},
{"rs_jumppad", CFG_OFS(rs_jumppad), FT_FLOAT},
{"rs_aircontrolledjumppad", CFG_OFS(rs_aircontrolledjumppad), FT_FLOAT},
{"rs_funcbob", CFG_OFS(rs_funcbob), FT_FLOAT},
{"rs_startelevator", CFG_OFS(rs_startelevator), FT_FLOAT},
{"rs_falldamage5", CFG_OFS(rs_falldamage5), FT_FLOAT},
{"rs_falldamage10", CFG_OFS(rs_falldamage10), FT_FLOAT},
{"rs_maxjumpfallheight", CFG_OFS(rs_maxjumpfallheight), FT_FLOAT},
{NULL, 0, 0, 0}
};
structdef_t bbox_struct =
{
sizeof(aas_bbox_t), bbox_fields
};
structdef_t cfg_struct =
{
sizeof(cfg_t), cfg_fields
};
//global cfg
cfg_t cfg;
//===========================================================================
// the default Q3A configuration
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void DefaultCfg(void)
{
int i;
// default all float values to infinite
for (i = 0; cfg_fields[i].name; i++)
{
if ((cfg_fields[i].type & FT_TYPE) == FT_FLOAT)
*(float *)( ((char*)&cfg) + cfg_fields[i].offset ) = FLT_MAX;
} //end for
//
cfg.numbboxes = 2;
//bbox 0
cfg.bboxes[0].presencetype = PRESENCE_NORMAL;
cfg.bboxes[0].flags = 0;
cfg.bboxes[0].mins[0] = -15;
cfg.bboxes[0].mins[1] = -15;
cfg.bboxes[0].mins[2] = -24;
cfg.bboxes[0].maxs[0] = 15;
cfg.bboxes[0].maxs[1] = 15;
cfg.bboxes[0].maxs[2] = 32;
//bbox 1
cfg.bboxes[1].presencetype = PRESENCE_CROUCH;
cfg.bboxes[1].flags = 1;
cfg.bboxes[1].mins[0] = -15;
cfg.bboxes[1].mins[1] = -15;
cfg.bboxes[1].mins[2] = -24;
cfg.bboxes[1].maxs[0] = 15;
cfg.bboxes[1].maxs[1] = 15;
cfg.bboxes[1].maxs[2] = 16;
//
cfg.allpresencetypes = PRESENCE_NORMAL|PRESENCE_CROUCH;
cfg.phys_gravitydirection[0] = 0;
cfg.phys_gravitydirection[1] = 0;
cfg.phys_gravitydirection[2] = -1;
cfg.phys_maxsteepness = 0.7;
} //end of the function DefaultCfg
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char * QDECL va( char *format, ... )
{
va_list argptr;
static char string[2][32000]; // in case va is called by nested functions
static int index = 0;
char *buf;
buf = string[index & 1];
index++;
va_start (argptr, format);
vsprintf (buf, format,argptr);
va_end (argptr);
return buf;
} //end of the function va
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void SetCfgLibVars(void)
{
int i;
float value;
for (i = 0; cfg_fields[i].name; i++)
{
if ((cfg_fields[i].type & FT_TYPE) == FT_FLOAT)
{
value = *(float *)(((char*)&cfg) + cfg_fields[i].offset);
if (value != FLT_MAX)
{
LibVarSet(cfg_fields[i].name, va("%f", value));
} //end if
} //end if
} //end for
} //end of the function SetCfgLibVars
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int LoadCfgFile(char *filename)
{
source_t *source;
token_t token;
int settingsdefined;
source = LoadSourceFile(filename);
if (!source)
{
Log_Print("couldn't open cfg file %s\n", filename);
return false;
} //end if
settingsdefined = false;
memset(&cfg, 0, sizeof(cfg_t));
while(PC_ReadToken(source, &token))
{
if (!stricmp(token.string, "bbox"))
{
if (cfg.numbboxes >= AAS_MAX_BBOXES)
{
SourceError(source, "too many bounding box volumes defined");
} //end if
if (!ReadStructure(source, &bbox_struct, (char *) &cfg.bboxes[cfg.numbboxes]))
{
FreeSource(source);
return false;
} //end if
cfg.allpresencetypes |= cfg.bboxes[cfg.numbboxes].presencetype;
cfg.numbboxes++;
} //end if
else if (!stricmp(token.string, "settings"))
{
if (settingsdefined)
{
SourceWarning(source, "settings already defined\n");
} //end if
settingsdefined = true;
if (!ReadStructure(source, &cfg_struct, (char *) &cfg))
{
FreeSource(source);
return false;
} //end if
} //end else if
} //end while
if (VectorLength(cfg.phys_gravitydirection) < 0.9 || VectorLength(cfg.phys_gravitydirection) > 1.1)
{
SourceError(source, "invalid gravity direction specified");
} //end if
if (cfg.numbboxes <= 0)
{
SourceError(source, "no bounding volumes specified");
} //end if
FreeSource(source);
SetCfgLibVars();
Log_Print("using cfg file %s\n", filename);
return true;
} //end of the function LoadCfgFile

View File

@ -1,73 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#define BBOXFL_GROUNDED 1 //bounding box only valid when on ground
#define BBOXFL_NOTGROUNDED 2 //bounding box only valid when NOT on ground
typedef struct cfg_s
{
int numbboxes; //number of bounding boxes
aas_bbox_t bboxes[AAS_MAX_BBOXES]; //all the bounding boxes
int allpresencetypes; //or of all presence types
// aas settings
vec3_t phys_gravitydirection;
float phys_friction;
float phys_stopspeed;
float phys_gravity;
float phys_waterfriction;
float phys_watergravity;
float phys_maxvelocity;
float phys_maxwalkvelocity;
float phys_maxcrouchvelocity;
float phys_maxswimvelocity;
float phys_walkaccelerate;
float phys_airaccelerate;
float phys_swimaccelerate;
float phys_maxstep;
float phys_maxsteepness;
float phys_maxwaterjump;
float phys_maxbarrier;
float phys_jumpvel;
float phys_falldelta5;
float phys_falldelta10;
float rs_waterjump;
float rs_teleport;
float rs_barrierjump;
float rs_startcrouch;
float rs_startgrapple;
float rs_startwalkoffledge;
float rs_startjump;
float rs_rocketjump;
float rs_bfgjump;
float rs_jumppad;
float rs_aircontrolledjumppad;
float rs_funcbob;
float rs_startelevator;
float rs_falldamage5;
float rs_falldamage10;
float rs_maxjumpfallheight;
} cfg_t;
extern cfg_t cfg;
void DefaultCfg(void);
int LoadCfgFile(char *filename);

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#define AREA_PORTAL 1
//temporary AAS face
typedef struct tmp_face_s
{
int num; //face number
int planenum; //number of the plane the face is in
winding_t *winding; //winding of the face
struct tmp_area_s *frontarea; //area at the front of the face
struct tmp_area_s *backarea; //area at the back of the face
int faceflags; //flags of this face
int aasfacenum; //the number of the aas face used for this face
//double link list pointers for front and back area
struct tmp_face_s *prev[2], *next[2];
//links in the list with faces
struct tmp_face_s *l_prev, *l_next;
} tmp_face_t;
//temporary AAS area settings
typedef struct tmp_areasettings_s
{
//could also add all kind of statistic fields
int contents; //contents of the area
int modelnum; //bsp model inside this area
int areaflags; //area flags
int presencetype; //how a bot can be present in this area
int numreachableareas; //number of reachable areas from this one
int firstreachablearea; //first reachable area in the reachable area index
} tmp_areasettings_t;
//temporary AAS area
typedef struct tmp_area_s
{
int areanum; //number of the area
struct tmp_face_s *tmpfaces; //the faces of the area
int presencetype; //presence type of the area
int contents; //area contents
int modelnum; //bsp model inside this area
int invalid; //true if the area is invalid
tmp_areasettings_t *settings; //area settings
struct tmp_area_s *mergedarea; //points to the new area after merging
//when mergedarea != 0 the area has only the
//seperating face of the merged areas
int aasareanum; //number of the aas area created for this tmp area
//links in the list with areas
struct tmp_area_s *l_prev, *l_next;
} tmp_area_t;
//temporary AAS node
typedef struct tmp_node_s
{
int planenum; //node plane number
struct tmp_area_s *tmparea; //points to an area if this node is an area
struct tmp_node_s *children[2]; //child nodes of this node
} tmp_node_t;
#define NODEBUF_SIZE 128
//node buffer
typedef struct tmp_nodebuf_s
{
int numnodes;
struct tmp_nodebuf_s *next;
tmp_node_t nodes[NODEBUF_SIZE];
} tmp_nodebuf_t;
//the whole temorary AAS
typedef struct tmp_aas_s
{
//faces
int numfaces;
int facenum;
tmp_face_t *faces;
//areas
int numareas;
int areanum;
tmp_area_t *areas;
//area settings
int numareasettings;
tmp_areasettings_t *areasettings;
//nodes
int numnodes;
tmp_node_t *nodes;
//node buffer
tmp_nodebuf_t *nodebuffer;
} tmp_aas_t;
extern tmp_aas_t tmpaasworld;
//creates a .AAS file with the given name from an already loaded map
void AAS_Create(char *aasfile);
//adds a face side to an area
void AAS_AddFaceSideToArea(tmp_face_t *tmpface, int side, tmp_area_t *tmparea);
//remvoes a face from an area
void AAS_RemoveFaceFromArea(tmp_face_t *tmpface, tmp_area_t *tmparea);
//allocate a tmp face
tmp_face_t *AAS_AllocTmpFace(void);
//free the tmp face
void AAS_FreeTmpFace(tmp_face_t *tmpface);
//allocate a tmp area
tmp_area_t *AAS_AllocTmpArea(void);
//free a tmp area
void AAS_FreeTmpArea(tmp_area_t *tmparea);
//allocate a tmp node
tmp_node_t *AAS_AllocTmpNode(void);
//free a tmp node
void AAS_FreeTmpNode(tmp_node_t *node);
//checks if an area is ok
void AAS_CheckArea(tmp_area_t *tmparea);
//flips the area faces where needed
void AAS_FlipAreaFaces(tmp_area_t *tmparea);
//returns true if the face is a gap seen from the given side
int AAS_GapFace(tmp_face_t *tmpface, int side);
//returns true if the face is a ground face
int AAS_GroundFace(tmp_face_t *tmpface);

View File

@ -1,108 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
//===========================================================================
// try to melt the windings of the two faces
// FIXME: this is buggy
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_MeltFaceWinding(tmp_face_t *face1, tmp_face_t *face2)
{
int i, n;
int splits = 0;
winding_t *w2, *neww;
plane_t *plane1;
#ifdef DEBUG
if (!face1->winding) Error("face1 %d without winding", face1->num);
if (!face2->winding) Error("face2 %d without winding", face2->num);
#endif //DEBUG
w2 = face2->winding;
plane1 = &mapplanes[face1->planenum];
for (i = 0; i < w2->numpoints; i++)
{
if (PointOnWinding(face1->winding, plane1->normal, plane1->dist, w2->p[i], &n))
{
neww = AddWindingPoint(face1->winding, w2->p[i], n);
FreeWinding(face1->winding);
face1->winding = neww;
splits++;
} //end if
} //end for
return splits;
} //end of the function AAS_MeltFaceWinding
//===========================================================================
// melt the windings of the area faces
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_MeltFaceWindingsOfArea(tmp_area_t *tmparea)
{
int side1, side2, num_windingsplits = 0;
tmp_face_t *face1, *face2;
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = face1->frontarea != tmparea;
for (face2 = tmparea->tmpfaces; face2; face2 = face2->next[side2])
{
side2 = face2->frontarea != tmparea;
if (face1 == face2) continue;
num_windingsplits += AAS_MeltFaceWinding(face1, face2);
} //end for
} //end for
return num_windingsplits;
} //end of the function AAS_MeltFaceWindingsOfArea
//===========================================================================
// melt the windings of the faces of all areas
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MeltAreaFaceWindings(void)
{
tmp_area_t *tmparea;
int num_windingsplits = 0;
Log_Write("AAS_MeltAreaFaceWindings\r\n");
qprintf("%6d edges melted", num_windingsplits);
//NOTE: first convex area (zero) is a dummy
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
num_windingsplits += AAS_MeltFaceWindingsOfArea(tmparea);
qprintf("\r%6d", num_windingsplits);
} //end for
qprintf("\n");
Log_Write("%6d edges melted\r\n", num_windingsplits);
} //end of the function AAS_MeltAreaFaceWindings

View File

@ -1,24 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MeltAreaFaceWindings(void);

View File

@ -1,282 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
{
winding_t *neww;
#ifdef DEBUG
if (!face1->winding) Error("face1 %d without winding", face1->num);
if (!face2->winding) Error("face2 %d without winding", face2->num);
#endif //DEBUG
//
if (face1->faceflags != face2->faceflags) return false;
//NOTE: if the front or back area is zero this doesn't mean there's
//a real area. It means there's solid at that side of the face
//if both faces have the same front area
if (face1->frontarea == face2->frontarea)
{
//if both faces have the same back area
if (face1->backarea == face2->backarea)
{
//if the faces are in the same plane
if (face1->planenum == face2->planenum)
{
//if they have both a front and a back area (no solid on either side)
if (face1->frontarea && face1->backarea)
{
neww = MergeWindings(face1->winding, face2->winding,
mapplanes[face1->planenum].normal);
} //end if
else
{
//this function is to be found in l_poly.c
neww = TryMergeWinding(face1->winding, face2->winding,
mapplanes[face1->planenum].normal);
} //end else
if (neww)
{
FreeWinding(face1->winding);
face1->winding = neww;
if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
AAS_FreeTmpFace(face2);
return true;
} //end if
} //end if
else if ((face1->planenum & ~1) == (face2->planenum & ~1))
{
Log_Write("face %d and %d, same front and back area but flipped planes\r\n",
face1->num, face2->num);
} //end if
} //end if
} //end if
return false;
} //end of the function AAS_TryMergeFaces
/*
int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
{
winding_t *neww;
#ifdef DEBUG
if (!face1->winding) Error("face1 %d without winding", face1->num);
if (!face2->winding) Error("face2 %d without winding", face2->num);
#endif //DEBUG
//if the faces are in the same plane
if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false;
// if (face1->planenum != face2->planenum) return false;
//NOTE: if the front or back area is zero this doesn't mean there's
//a real area. It means there's solid at that side of the face
//if both faces have the same front area
if (face1->frontarea != face2->frontarea ||
face1->backarea != face2->backarea)
{
if (!face1->frontarea || !face1->backarea ||
!face2->frontarea || !face2->backarea) return false;
else if (face1->frontarea != face2->backarea ||
face1->backarea != face2->frontarea) return false;
// return false;
} //end if
//this function is to be found in l_poly.c
neww = TryMergeWinding(face1->winding, face2->winding,
mapplanes[face1->planenum].normal);
if (!neww) return false;
//
FreeWinding(face1->winding);
face1->winding = neww;
//remove face2
if (face2->frontarea)
AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]);
if (face2->backarea)
AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]);
return true;
} //end of the function AAS_TryMergeFaces*/
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergeAreaFaces(void)
{
int num_facemerges = 0;
int side1, side2, restart;
tmp_area_t *tmparea, *lasttmparea;
tmp_face_t *face1, *face2;
Log_Write("AAS_MergeAreaFaces\r\n");
qprintf("%6d face merges", num_facemerges);
//NOTE: first convex area is a dummy
lasttmparea = tmpaasworld.areas;
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
restart = false;
//
if (tmparea->invalid) continue;
//
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = face1->frontarea != tmparea;
for (face2 = face1->next[side1]; face2; face2 = face2->next[side2])
{
side2 = face2->frontarea != tmparea;
//if succesfully merged
if (AAS_TryMergeFaces(face1, face2))
{
//start over again after merging two faces
restart = true;
num_facemerges++;
qprintf("\r%6d", num_facemerges);
AAS_CheckArea(tmparea);
break;
} //end if
} //end for
if (restart)
{
tmparea = lasttmparea;
break;
} //end if
} //end for
lasttmparea = tmparea;
} //end for
qprintf("\n");
Log_Write("%6d face merges\r\n", num_facemerges);
} //end of the function AAS_MergeAreaFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergePlaneFaces(tmp_area_t *tmparea, int planenum)
{
tmp_face_t *face1, *face2, *nextface2;
winding_t *neww;
int side1, side2;
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = face1->frontarea != tmparea;
if (face1->planenum != planenum) continue;
//
for (face2 = face1->next[side1]; face2; face2 = nextface2)
{
side2 = face2->frontarea != tmparea;
nextface2 = face2->next[side2];
//
if ((face2->planenum & ~1) != (planenum & ~1)) continue;
//
neww = MergeWindings(face1->winding, face2->winding,
mapplanes[face1->planenum].normal);
FreeWinding(face1->winding);
face1->winding = neww;
if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
AAS_FreeTmpFace(face2);
//
nextface2 = face1->next[side1];
} //end for
} //end for
} //end of the function AAS_MergePlaneFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_CanMergePlaneFaces(tmp_area_t *tmparea, int planenum)
{
tmp_area_t *frontarea, *backarea;
tmp_face_t *face1;
int side1, merge, faceflags;
frontarea = backarea = NULL;
merge = false;
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = face1->frontarea != tmparea;
if ((face1->planenum & ~1) != (planenum & ~1)) continue;
if (!frontarea && !backarea)
{
frontarea = face1->frontarea;
backarea = face1->backarea;
faceflags = face1->faceflags;
} //end if
else
{
if (frontarea != face1->frontarea) return false;
if (backarea != face1->backarea) return false;
if (faceflags != face1->faceflags) return false;
merge = true;
} //end else
} //end for
return merge;
} //end of the function AAS_CanMergePlaneFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergeAreaPlaneFaces(void)
{
int num_facemerges = 0;
int side1;
tmp_area_t *tmparea, *nexttmparea;
tmp_face_t *face1;
Log_Write("AAS_MergePlaneFaces\r\n");
qprintf("%6d plane face merges", num_facemerges);
//NOTE: first convex area is a dummy
for (tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea)
{
nexttmparea = tmparea->l_next;
//
if (tmparea->invalid) continue;
//
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
side1 = face1->frontarea != tmparea;
//
if (AAS_CanMergePlaneFaces(tmparea, face1->planenum))
{
AAS_MergePlaneFaces(tmparea, face1->planenum);
nexttmparea = tmparea;
num_facemerges++;
qprintf("\r%6d", num_facemerges);
break;
} //end if
} //end for
} //end for
qprintf("\n");
Log_Write("%6d plane face merges\r\n", num_facemerges);
} //end of the function AAS_MergeAreaPlaneFaces

View File

@ -1,24 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MergeAreaFaces(void);
void AAS_MergeAreaPlaneFaces(void);

View File

@ -1,549 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_file.h"
#include "aas_store.h"
#include "aas_create.h"
#define AAS_Error Error
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SwapAASData(void)
{
int i, j;
//bounding boxes
for (i = 0; i < aasworld.numbboxes; i++)
{
aasworld.bboxes[i].presencetype = LittleLong(aasworld.bboxes[i].presencetype);
aasworld.bboxes[i].flags = LittleLong(aasworld.bboxes[i].flags);
for (j = 0; j < 3; j++)
{
aasworld.bboxes[i].mins[j] = LittleLong(aasworld.bboxes[i].mins[j]);
aasworld.bboxes[i].maxs[j] = LittleLong(aasworld.bboxes[i].maxs[j]);
} //end for
} //end for
//vertexes
for (i = 0; i < aasworld.numvertexes; i++)
{
for (j = 0; j < 3; j++)
aasworld.vertexes[i][j] = LittleFloat(aasworld.vertexes[i][j]);
} //end for
//planes
for (i = 0; i < aasworld.numplanes; i++)
{
for (j = 0; j < 3; j++)
aasworld.planes[i].normal[j] = LittleFloat(aasworld.planes[i].normal[j]);
aasworld.planes[i].dist = LittleFloat(aasworld.planes[i].dist);
aasworld.planes[i].type = LittleLong(aasworld.planes[i].type);
} //end for
//edges
for (i = 0; i < aasworld.numedges; i++)
{
aasworld.edges[i].v[0] = LittleLong(aasworld.edges[i].v[0]);
aasworld.edges[i].v[1] = LittleLong(aasworld.edges[i].v[1]);
} //end for
//edgeindex
for (i = 0; i < aasworld.edgeindexsize; i++)
{
aasworld.edgeindex[i] = LittleLong(aasworld.edgeindex[i]);
} //end for
//faces
for (i = 0; i < aasworld.numfaces; i++)
{
aasworld.faces[i].planenum = LittleLong(aasworld.faces[i].planenum);
aasworld.faces[i].faceflags = LittleLong(aasworld.faces[i].faceflags);
aasworld.faces[i].numedges = LittleLong(aasworld.faces[i].numedges);
aasworld.faces[i].firstedge = LittleLong(aasworld.faces[i].firstedge);
aasworld.faces[i].frontarea = LittleLong(aasworld.faces[i].frontarea);
aasworld.faces[i].backarea = LittleLong(aasworld.faces[i].backarea);
} //end for
//face index
for (i = 0; i < aasworld.faceindexsize; i++)
{
aasworld.faceindex[i] = LittleLong(aasworld.faceindex[i]);
} //end for
//convex areas
for (i = 0; i < aasworld.numareas; i++)
{
aasworld.areas[i].areanum = LittleLong(aasworld.areas[i].areanum);
aasworld.areas[i].numfaces = LittleLong(aasworld.areas[i].numfaces);
aasworld.areas[i].firstface = LittleLong(aasworld.areas[i].firstface);
for (j = 0; j < 3; j++)
{
aasworld.areas[i].mins[j] = LittleFloat(aasworld.areas[i].mins[j]);
aasworld.areas[i].maxs[j] = LittleFloat(aasworld.areas[i].maxs[j]);
aasworld.areas[i].center[j] = LittleFloat(aasworld.areas[i].center[j]);
} //end for
} //end for
//area settings
for (i = 0; i < aasworld.numareasettings; i++)
{
aasworld.areasettings[i].contents = LittleLong(aasworld.areasettings[i].contents);
aasworld.areasettings[i].areaflags = LittleLong(aasworld.areasettings[i].areaflags);
aasworld.areasettings[i].presencetype = LittleLong(aasworld.areasettings[i].presencetype);
aasworld.areasettings[i].cluster = LittleLong(aasworld.areasettings[i].cluster);
aasworld.areasettings[i].clusterareanum = LittleLong(aasworld.areasettings[i].clusterareanum);
aasworld.areasettings[i].numreachableareas = LittleLong(aasworld.areasettings[i].numreachableareas);
aasworld.areasettings[i].firstreachablearea = LittleLong(aasworld.areasettings[i].firstreachablearea);
} //end for
//area reachability
for (i = 0; i < aasworld.reachabilitysize; i++)
{
aasworld.reachability[i].areanum = LittleLong(aasworld.reachability[i].areanum);
aasworld.reachability[i].facenum = LittleLong(aasworld.reachability[i].facenum);
aasworld.reachability[i].edgenum = LittleLong(aasworld.reachability[i].edgenum);
for (j = 0; j < 3; j++)
{
aasworld.reachability[i].start[j] = LittleFloat(aasworld.reachability[i].start[j]);
aasworld.reachability[i].end[j] = LittleFloat(aasworld.reachability[i].end[j]);
} //end for
aasworld.reachability[i].traveltype = LittleLong(aasworld.reachability[i].traveltype);
aasworld.reachability[i].traveltime = LittleShort(aasworld.reachability[i].traveltime);
} //end for
//nodes
for (i = 0; i < aasworld.numnodes; i++)
{
aasworld.nodes[i].planenum = LittleLong(aasworld.nodes[i].planenum);
aasworld.nodes[i].children[0] = LittleLong(aasworld.nodes[i].children[0]);
aasworld.nodes[i].children[1] = LittleLong(aasworld.nodes[i].children[1]);
} //end for
//cluster portals
for (i = 0; i < aasworld.numportals; i++)
{
aasworld.portals[i].areanum = LittleLong(aasworld.portals[i].areanum);
aasworld.portals[i].frontcluster = LittleLong(aasworld.portals[i].frontcluster);
aasworld.portals[i].backcluster = LittleLong(aasworld.portals[i].backcluster);
aasworld.portals[i].clusterareanum[0] = LittleLong(aasworld.portals[i].clusterareanum[0]);
aasworld.portals[i].clusterareanum[1] = LittleLong(aasworld.portals[i].clusterareanum[1]);
} //end for
//cluster portal index
for (i = 0; i < aasworld.portalindexsize; i++)
{
aasworld.portalindex[i] = LittleLong(aasworld.portalindex[i]);
} //end for
//cluster
for (i = 0; i < aasworld.numclusters; i++)
{
aasworld.clusters[i].numareas = LittleLong(aasworld.clusters[i].numareas);
aasworld.clusters[i].numportals = LittleLong(aasworld.clusters[i].numportals);
aasworld.clusters[i].firstportal = LittleLong(aasworld.clusters[i].firstportal);
} //end for
} //end of the function AAS_SwapAASData
//===========================================================================
// dump the current loaded aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DumpAASData(void)
{
/*
if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
aasworld.vertexes = NULL;
if (aasworld.planes) FreeMemory(aasworld.planes);
aasworld.planes = NULL;
if (aasworld.edges) FreeMemory(aasworld.edges);
aasworld.edges = NULL;
if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
aasworld.edgeindex = NULL;
if (aasworld.faces) FreeMemory(aasworld.faces);
aasworld.faces = NULL;
if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
aasworld.faceindex = NULL;
if (aasworld.areas) FreeMemory(aasworld.areas);
aasworld.areas = NULL;
if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
aasworld.areasettings = NULL;
if (aasworld.reachability) FreeMemory(aasworld.reachability);
aasworld.reachability = NULL;
*/
aasworld.loaded = false;
} //end of the function AAS_DumpAASData
//===========================================================================
// allocate memory and read a lump of a AAS file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_LoadAASLump(FILE *fp, int offset, int length, void *buf)
{
if (!length)
{
printf("lump size 0\n");
return buf;
} //end if
//seek to the data
if (fseek(fp, offset, SEEK_SET))
{
AAS_Error("can't seek to lump\n");
AAS_DumpAASData();
fclose(fp);
return 0;
} //end if
//allocate memory
if (!buf) buf = (void *) GetClearedMemory(length);
//read the data
if (fread((char *) buf, 1, length, fp) != length)
{
AAS_Error("can't read lump\n");
FreeMemory(buf);
AAS_DumpAASData();
fclose(fp);
return NULL;
} //end if
return buf;
} //end of the function AAS_LoadAASLump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DData(unsigned char *data, int size)
{
int i;
for (i = 0; i < size; i++)
{
data[i] ^= (unsigned char) i * 119;
} //end for
} //end of the function AAS_DData
//===========================================================================
// load an aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_LoadAASFile(char *filename, int fpoffset, int fplength)
{
FILE *fp;
aas_header_t header;
int offset, length;
//dump current loaded aas file
AAS_DumpAASData();
//open the file
fp = fopen(filename, "rb");
if (!fp)
{
AAS_Error("can't open %s\n", filename);
return false;
} //end if
//seek to the correct position (in the pak file)
if (fseek(fp, fpoffset, SEEK_SET))
{
AAS_Error("can't seek to file %s\n");
fclose(fp);
return false;
} //end if
//read the header
if (fread(&header, sizeof(aas_header_t), 1, fp) != 1)
{
AAS_Error("can't read header of file %s\n", filename);
fclose(fp);
return false;
} //end if
//check header identification
header.ident = LittleLong(header.ident);
if (header.ident != AASID)
{
AAS_Error("%s is not an AAS file\n", filename);
fclose(fp);
return false;
} //end if
//check the version
header.version = LittleLong(header.version);
if (header.version != AASVERSION_OLD && header.version != AASVERSION)
{
AAS_Error("%s is version %i, not %i\n", filename, header.version, AASVERSION);
fclose(fp);
return false;
} //end if
//
if (header.version == AASVERSION)
{
AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
} //end if
aasworld.bspchecksum = LittleLong(header.bspchecksum);
//load the lumps:
//bounding boxes
offset = fpoffset + LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
aasworld.bboxes = (aas_bbox_t *) AAS_LoadAASLump(fp, offset, length, aasworld.bboxes);
if (!aasworld.bboxes) return false;
aasworld.numbboxes = length / sizeof(aas_bbox_t);
//vertexes
offset = fpoffset + LittleLong(header.lumps[AASLUMP_VERTEXES].fileofs);
length = LittleLong(header.lumps[AASLUMP_VERTEXES].filelen);
aasworld.vertexes = (aas_vertex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.vertexes);
if (!aasworld.vertexes) return false;
aasworld.numvertexes = length / sizeof(aas_vertex_t);
//planes
offset = fpoffset + LittleLong(header.lumps[AASLUMP_PLANES].fileofs);
length = LittleLong(header.lumps[AASLUMP_PLANES].filelen);
aasworld.planes = (aas_plane_t *) AAS_LoadAASLump(fp, offset, length, aasworld.planes);
if (!aasworld.planes) return false;
aasworld.numplanes = length / sizeof(aas_plane_t);
//edges
offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGES].fileofs);
length = LittleLong(header.lumps[AASLUMP_EDGES].filelen);
aasworld.edges = (aas_edge_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edges);
if (!aasworld.edges) return false;
aasworld.numedges = length / sizeof(aas_edge_t);
//edgeindex
offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGEINDEX].fileofs);
length = LittleLong(header.lumps[AASLUMP_EDGEINDEX].filelen);
aasworld.edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edgeindex);
if (!aasworld.edgeindex) return false;
aasworld.edgeindexsize = length / sizeof(aas_edgeindex_t);
//faces
offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACES].fileofs);
length = LittleLong(header.lumps[AASLUMP_FACES].filelen);
aasworld.faces = (aas_face_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faces);
if (!aasworld.faces) return false;
aasworld.numfaces = length / sizeof(aas_face_t);
//faceindex
offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACEINDEX].fileofs);
length = LittleLong(header.lumps[AASLUMP_FACEINDEX].filelen);
aasworld.faceindex = (aas_faceindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faceindex);
if (!aasworld.faceindex) return false;
aasworld.faceindexsize = length / sizeof(int);
//convex areas
offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREAS].fileofs);
length = LittleLong(header.lumps[AASLUMP_AREAS].filelen);
aasworld.areas = (aas_area_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areas);
if (!aasworld.areas) return false;
aasworld.numareas = length / sizeof(aas_area_t);
//area settings
offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREASETTINGS].fileofs);
length = LittleLong(header.lumps[AASLUMP_AREASETTINGS].filelen);
aasworld.areasettings = (aas_areasettings_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areasettings);
if (!aasworld.areasettings) return false;
aasworld.numareasettings = length / sizeof(aas_areasettings_t);
//reachability list
offset = fpoffset + LittleLong(header.lumps[AASLUMP_REACHABILITY].fileofs);
length = LittleLong(header.lumps[AASLUMP_REACHABILITY].filelen);
aasworld.reachability = (aas_reachability_t *) AAS_LoadAASLump(fp, offset, length, aasworld.reachability);
if (length && !aasworld.reachability) return false;
aasworld.reachabilitysize = length / sizeof(aas_reachability_t);
//nodes
offset = fpoffset + LittleLong(header.lumps[AASLUMP_NODES].fileofs);
length = LittleLong(header.lumps[AASLUMP_NODES].filelen);
aasworld.nodes = (aas_node_t *) AAS_LoadAASLump(fp, offset, length, aasworld.nodes);
if (!aasworld.nodes) return false;
aasworld.numnodes = length / sizeof(aas_node_t);
//cluster portals
offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALS].fileofs);
length = LittleLong(header.lumps[AASLUMP_PORTALS].filelen);
aasworld.portals = (aas_portal_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portals);
if (length && !aasworld.portals) return false;
aasworld.numportals = length / sizeof(aas_portal_t);
//cluster portal index
offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALINDEX].fileofs);
length = LittleLong(header.lumps[AASLUMP_PORTALINDEX].filelen);
aasworld.portalindex = (aas_portalindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portalindex);
if (length && !aasworld.portalindex) return false;
aasworld.portalindexsize = length / sizeof(aas_portalindex_t);
//clusters
offset = fpoffset + LittleLong(header.lumps[AASLUMP_CLUSTERS].fileofs);
length = LittleLong(header.lumps[AASLUMP_CLUSTERS].filelen);
aasworld.clusters = (aas_cluster_t *) AAS_LoadAASLump(fp, offset, length, aasworld.clusters);
if (length && !aasworld.clusters) return false;
aasworld.numclusters = length / sizeof(aas_cluster_t);
//swap everything
AAS_SwapAASData();
//aas file is loaded
aasworld.loaded = true;
//close the file
fclose(fp);
return true;
} //end of the function AAS_LoadAASFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_WriteAASLump(FILE *fp, aas_header_t *h, int lumpnum, void *data, int length)
{
aas_lump_t *lump;
lump = &h->lumps[lumpnum];
lump->fileofs = LittleLong(ftell(fp));
lump->filelen = LittleLong(length);
if (length > 0)
{
if (fwrite(data, length, 1, fp) < 1)
{
Log_Print("error writing lump %s\n", lumpnum);
fclose(fp);
return false;
} //end if
} //end if
return true;
} //end of the function AAS_WriteAASLump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowNumReachabilities(int tt, char *name)
{
int i, num;
num = 0;
for (i = 0; i < aasworld.reachabilitysize; i++)
{
if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == tt)
num++;
} //end for
Log_Print("%6d %s\n", num, name);
} //end of the function AAS_ShowNumReachabilities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowTotals(void)
{
Log_Print("numvertexes = %d\r\n", aasworld.numvertexes);
Log_Print("numplanes = %d\r\n", aasworld.numplanes);
Log_Print("numedges = %d\r\n", aasworld.numedges);
Log_Print("edgeindexsize = %d\r\n", aasworld.edgeindexsize);
Log_Print("numfaces = %d\r\n", aasworld.numfaces);
Log_Print("faceindexsize = %d\r\n", aasworld.faceindexsize);
Log_Print("numareas = %d\r\n", aasworld.numareas);
Log_Print("numareasettings = %d\r\n", aasworld.numareasettings);
Log_Print("reachabilitysize = %d\r\n", aasworld.reachabilitysize);
Log_Print("numnodes = %d\r\n", aasworld.numnodes);
Log_Print("numportals = %d\r\n", aasworld.numportals);
Log_Print("portalindexsize = %d\r\n", aasworld.portalindexsize);
Log_Print("numclusters = %d\r\n", aasworld.numclusters);
AAS_ShowNumReachabilities(TRAVEL_WALK, "walk");
AAS_ShowNumReachabilities(TRAVEL_CROUCH, "crouch");
AAS_ShowNumReachabilities(TRAVEL_BARRIERJUMP, "barrier jump");
AAS_ShowNumReachabilities(TRAVEL_JUMP, "jump");
AAS_ShowNumReachabilities(TRAVEL_LADDER, "ladder");
AAS_ShowNumReachabilities(TRAVEL_WALKOFFLEDGE, "walk off ledge");
AAS_ShowNumReachabilities(TRAVEL_SWIM, "swim");
AAS_ShowNumReachabilities(TRAVEL_WATERJUMP, "water jump");
AAS_ShowNumReachabilities(TRAVEL_TELEPORT, "teleport");
AAS_ShowNumReachabilities(TRAVEL_ELEVATOR, "elevator");
AAS_ShowNumReachabilities(TRAVEL_ROCKETJUMP, "rocket jump");
AAS_ShowNumReachabilities(TRAVEL_BFGJUMP, "bfg jump");
AAS_ShowNumReachabilities(TRAVEL_GRAPPLEHOOK, "grapple hook");
AAS_ShowNumReachabilities(TRAVEL_DOUBLEJUMP, "double jump");
AAS_ShowNumReachabilities(TRAVEL_RAMPJUMP, "ramp jump");
AAS_ShowNumReachabilities(TRAVEL_STRAFEJUMP, "strafe jump");
AAS_ShowNumReachabilities(TRAVEL_JUMPPAD, "jump pad");
AAS_ShowNumReachabilities(TRAVEL_FUNCBOB, "func bob");
} //end of the function AAS_ShowTotals
//===========================================================================
// aas data is useless after writing to file because it is byte swapped
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_WriteAASFile(char *filename)
{
aas_header_t header;
FILE *fp;
Log_Print("writing %s\n", filename);
AAS_ShowTotals();
//swap the aas data
AAS_SwapAASData();
//initialize the file header
memset(&header, 0, sizeof(aas_header_t));
header.ident = LittleLong(AASID);
header.version = LittleLong(AASVERSION);
header.bspchecksum = LittleLong(aasworld.bspchecksum);
//open a new file
fp = fopen(filename, "wb");
if (!fp)
{
Log_Print("error opening %s\n", filename);
return false;
} //end if
//write the header
if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
{
fclose(fp);
return false;
} //end if
//add the data lumps to the file
if (!AAS_WriteAASLump(fp, &header, AASLUMP_BBOXES, aasworld.bboxes,
aasworld.numbboxes * sizeof(aas_bbox_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_VERTEXES, aasworld.vertexes,
aasworld.numvertexes * sizeof(aas_vertex_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PLANES, aasworld.planes,
aasworld.numplanes * sizeof(aas_plane_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGES, aasworld.edges,
aasworld.numedges * sizeof(aas_edge_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGEINDEX, aasworld.edgeindex,
aasworld.edgeindexsize * sizeof(aas_edgeindex_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACES, aasworld.faces,
aasworld.numfaces * sizeof(aas_face_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACEINDEX, aasworld.faceindex,
aasworld.faceindexsize * sizeof(aas_faceindex_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREAS, aasworld.areas,
aasworld.numareas * sizeof(aas_area_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREASETTINGS, aasworld.areasettings,
aasworld.numareasettings * sizeof(aas_areasettings_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_REACHABILITY, aasworld.reachability,
aasworld.reachabilitysize * sizeof(aas_reachability_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_NODES, aasworld.nodes,
aasworld.numnodes * sizeof(aas_node_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALS, aasworld.portals,
aasworld.numportals * sizeof(aas_portal_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALINDEX, aasworld.portalindex,
aasworld.portalindexsize * sizeof(aas_portalindex_t))) return false;
if (!AAS_WriteAASLump(fp, &header, AASLUMP_CLUSTERS, aasworld.clusters,
aasworld.numclusters * sizeof(aas_cluster_t))) return false;
//rewrite the header with the added lumps
fseek(fp, 0, SEEK_SET);
AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
{
fclose(fp);
return false;
} //end if
//close the file
fclose(fp);
return true;
} //end of the function AAS_WriteAASFile

View File

@ -1,25 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
qboolean AAS_WriteAASFile(char *filename);
qboolean AAS_LoadAASFile(char *filename, int fpoffset, int fplength);

View File

@ -1,656 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
#include "aas_store.h"
#include "aas_cfg.h"
#define FACECLIP_EPSILON 0.2
#define FACE_EPSILON 1.0
int numgravitationalsubdivisions = 0;
int numladdersubdivisions = 0;
//NOTE: only do gravitational subdivision BEFORE area merging!!!!!!!
// because the bsp tree isn't refreshes like with ladder subdivision
//===========================================================================
// NOTE: the original face is invalid after splitting
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SplitFace(tmp_face_t *face, vec3_t normal, float dist,
tmp_face_t **frontface, tmp_face_t **backface)
{
winding_t *frontw, *backw;
//
*frontface = *backface = NULL;
ClipWindingEpsilon(face->winding, normal, dist, FACECLIP_EPSILON, &frontw, &backw);
#ifdef DEBUG
//
if (frontw)
{
if (WindingIsTiny(frontw))
{
Log_Write("AAS_SplitFace: tiny back face\r\n");
FreeWinding(frontw);
frontw = NULL;
} //end if
} //end if
if (backw)
{
if (WindingIsTiny(backw))
{
Log_Write("AAS_SplitFace: tiny back face\r\n");
FreeWinding(backw);
backw = NULL;
} //end if
} //end if
#endif //DEBUG
//if the winding was split
if (frontw)
{
//check bounds
(*frontface) = AAS_AllocTmpFace();
(*frontface)->planenum = face->planenum;
(*frontface)->winding = frontw;
(*frontface)->faceflags = face->faceflags;
} //end if
if (backw)
{
//check bounds
(*backface) = AAS_AllocTmpFace();
(*backface)->planenum = face->planenum;
(*backface)->winding = backw;
(*backface)->faceflags = face->faceflags;
} //end if
} //end of the function AAS_SplitFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
winding_t *AAS_SplitWinding(tmp_area_t *tmparea, int planenum)
{
tmp_face_t *face;
plane_t *plane;
int side;
winding_t *splitwinding;
//
plane = &mapplanes[planenum];
//create a split winding, first base winding for plane
splitwinding = BaseWindingForPlane(plane->normal, plane->dist);
//chop with all the faces of the area
for (face = tmparea->tmpfaces; face && splitwinding; face = face->next[side])
{
//side of the face the original area was on
side = face->frontarea != tmparea;
plane = &mapplanes[face->planenum ^ side];
ChopWindingInPlace(&splitwinding, plane->normal, plane->dist, 0); // PLANESIDE_EPSILON);
} //end for
return splitwinding;
} //end of the function AAS_SplitWinding
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TestSplitPlane(tmp_area_t *tmparea, vec3_t normal, float dist,
int *facesplits, int *groundsplits, int *epsilonfaces)
{
int j, side, front, back, planenum;
float d, d_front, d_back;
tmp_face_t *face;
winding_t *w;
*facesplits = *groundsplits = *epsilonfaces = 0;
planenum = FindFloatPlane(normal, dist);
w = AAS_SplitWinding(tmparea, planenum);
if (!w) return false;
FreeWinding(w);
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
//side of the face the area is on
side = face->frontarea != tmparea;
if ((face->planenum & ~1) == (planenum & ~1))
{
Log_Print("AAS_TestSplitPlane: tried face plane as splitter\n");
return false;
} //end if
w = face->winding;
//reset distance at front and back side of plane
d_front = d_back = 0;
//reset front and back flags
front = back = 0;
for (j = 0; j < w->numpoints; j++)
{
d = DotProduct(w->p[j], normal) - dist;
if (d > d_front) d_front = d;
if (d < d_back) d_back = d;
if (d > 0.4) // PLANESIDE_EPSILON)
front = 1;
if (d < -0.4) // PLANESIDE_EPSILON)
back = 1;
} //end for
//check for an epsilon face
if ( (d_front > FACECLIP_EPSILON && d_front < FACE_EPSILON)
|| (d_back < -FACECLIP_EPSILON && d_back > -FACE_EPSILON) )
{
(*epsilonfaces)++;
} //end if
//if the face has points at both sides of the plane
if (front && back)
{
(*facesplits)++;
if (face->faceflags & FACE_GROUND)
{
(*groundsplits)++;
} //end if
} //end if
} //end for
return true;
} //end of the function AAS_TestSplitPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SplitArea(tmp_area_t *tmparea, int planenum, tmp_area_t **frontarea, tmp_area_t **backarea)
{
int side;
tmp_area_t *facefrontarea, *facebackarea, *faceotherarea;
tmp_face_t *face, *frontface, *backface, *splitface, *nextface;
winding_t *splitwinding;
plane_t *splitplane;
/*
#ifdef AW_DEBUG
int facesplits, groundsplits, epsilonface;
Log_Print("\n----------------------\n");
Log_Print("splitting area %d\n", areanum);
Log_Print("with normal = \'%f %f %f\', dist = %f\n", normal[0], normal[1], normal[2], dist);
AAS_TestSplitPlane(areanum, normal, dist,
&facesplits, &groundsplits, &epsilonface);
Log_Print("face splits = %d\nground splits = %d\n", facesplits, groundsplits);
if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //AW_DEBUG*/
//the original area
AAS_FlipAreaFaces(tmparea);
AAS_CheckArea(tmparea);
//
splitplane = &mapplanes[planenum];
/* //create a split winding, first base winding for plane
splitwinding = BaseWindingForPlane(splitplane->normal, splitplane->dist);
//chop with all the faces of the area
for (face = tmparea->tmpfaces; face && splitwinding; face = face->next[side])
{
//side of the face the original area was on
side = face->frontarea != tmparea->areanum;
plane = &mapplanes[face->planenum ^ side];
ChopWindingInPlace(&splitwinding, plane->normal, plane->dist, 0); // PLANESIDE_EPSILON);
} //end for*/
splitwinding = AAS_SplitWinding(tmparea, planenum);
if (!splitwinding)
{
/*
#ifdef DEBUG
AAS_TestSplitPlane(areanum, normal, dist,
&facesplits, &groundsplits, &epsilonface);
Log_Print("\nface splits = %d\nground splits = %d\n", facesplits, groundsplits);
if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //DEBUG*/
Error("AAS_SplitArea: no split winding when splitting area %d\n", tmparea->areanum);
} //end if
//create a split face
splitface = AAS_AllocTmpFace();
//get the map plane
splitface->planenum = planenum;
//store the split winding
splitface->winding = splitwinding;
//the new front area
(*frontarea) = AAS_AllocTmpArea();
(*frontarea)->presencetype = tmparea->presencetype;
(*frontarea)->contents = tmparea->contents;
(*frontarea)->modelnum = tmparea->modelnum;
(*frontarea)->tmpfaces = NULL;
//the new back area
(*backarea) = AAS_AllocTmpArea();
(*backarea)->presencetype = tmparea->presencetype;
(*backarea)->contents = tmparea->contents;
(*backarea)->modelnum = tmparea->modelnum;
(*backarea)->tmpfaces = NULL;
//add the split face to the new areas
AAS_AddFaceSideToArea(splitface, 0, (*frontarea));
AAS_AddFaceSideToArea(splitface, 1, (*backarea));
//split all the faces of the original area
for (face = tmparea->tmpfaces; face; face = nextface)
{
//side of the face the original area was on
side = face->frontarea != tmparea;
//next face of the original area
nextface = face->next[side];
//front area of the face
facefrontarea = face->frontarea;
//back area of the face
facebackarea = face->backarea;
//remove the face from both the front and back areas
if (facefrontarea) AAS_RemoveFaceFromArea(face, facefrontarea);
if (facebackarea) AAS_RemoveFaceFromArea(face, facebackarea);
//split the face
AAS_SplitFace(face, splitplane->normal, splitplane->dist, &frontface, &backface);
//free the original face
AAS_FreeTmpFace(face);
//get the number of the area at the other side of the face
if (side) faceotherarea = facefrontarea;
else faceotherarea = facebackarea;
//if there is an area at the other side of the original face
if (faceotherarea)
{
if (frontface) AAS_AddFaceSideToArea(frontface, !side, faceotherarea);
if (backface) AAS_AddFaceSideToArea(backface, !side, faceotherarea);
} //end if
//add the front and back part left after splitting the original face to the new areas
if (frontface) AAS_AddFaceSideToArea(frontface, side, (*frontarea));
if (backface) AAS_AddFaceSideToArea(backface, side, (*backarea));
} //end for
if (!(*frontarea)->tmpfaces) Log_Print("AAS_SplitArea: front area without faces\n");
if (!(*backarea)->tmpfaces) Log_Print("AAS_SplitArea: back area without faces\n");
tmparea->invalid = true;
/*
#ifdef AW_DEBUG
for (i = 0, face = frontarea->tmpfaces; face; face = face->next[side])
{
side = face->frontarea != frontarea->areanum;
i++;
} //end for
Log_Print("created front area %d with %d faces\n", frontarea->areanum, i);
for (i = 0, face = backarea->tmpfaces; face; face = face->next[side])
{
side = face->frontarea != backarea->areanum;
i++;
} //end for
Log_Print("created back area %d with %d faces\n", backarea->areanum, i);
#endif //AW_DEBUG*/
AAS_FlipAreaFaces((*frontarea));
AAS_FlipAreaFaces((*backarea));
//
AAS_CheckArea((*frontarea));
AAS_CheckArea((*backarea));
} //end of the function AAS_SplitArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_FindBestAreaSplitPlane(tmp_area_t *tmparea, vec3_t normal, float *dist)
{
int side1, side2;
int foundsplitter, facesplits, groundsplits, epsilonfaces, bestepsilonfaces;
float bestvalue, value;
tmp_face_t *face1, *face2;
vec3_t tmpnormal, invgravity;
float tmpdist;
//get inverse of gravity direction
VectorCopy(cfg.phys_gravitydirection, invgravity);
VectorInverse(invgravity);
foundsplitter = false;
bestvalue = -999999;
bestepsilonfaces = 0;
//
#ifdef AW_DEBUG
Log_Print("finding split plane for area %d\n", tmparea->areanum);
#endif //AW_DEBUG
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//
if (WindingIsTiny(face1->winding))
{
Log_Write("gsubdiv: area %d has a tiny winding\r\n", tmparea->areanum);
continue;
} //end if
//if the face isn't a gap or ground there's no split edge
if (!(face1->faceflags & FACE_GROUND) && !AAS_GapFace(face1, side1)) continue;
//
for (face2 = face1->next[side1]; face2; face2 = face2->next[side2])
{
//side of the face the area is on
side2 = face2->frontarea != tmparea;
//
if (WindingIsTiny(face1->winding))
{
Log_Write("gsubdiv: area %d has a tiny winding\r\n", tmparea->areanum);
continue;
} //end if
//if the face isn't a gap or ground there's no split edge
if (!(face2->faceflags & FACE_GROUND) && !AAS_GapFace(face2, side2)) continue;
//only split between gaps and ground
if (!(((face1->faceflags & FACE_GROUND) && AAS_GapFace(face2, side2)) ||
((face2->faceflags & FACE_GROUND) && AAS_GapFace(face1, side1)))) continue;
//find a plane seperating the windings of the faces
if (!FindPlaneSeperatingWindings(face1->winding, face2->winding, invgravity,
tmpnormal, &tmpdist)) continue;
#ifdef AW_DEBUG
Log_Print("normal = \'%f %f %f\', dist = %f\n",
tmpnormal[0], tmpnormal[1], tmpnormal[2], tmpdist);
#endif //AW_DEBUG
//get metrics for this vertical plane
if (!AAS_TestSplitPlane(tmparea, tmpnormal, tmpdist,
&facesplits, &groundsplits, &epsilonfaces))
{
continue;
} //end if
#ifdef AW_DEBUG
Log_Print("face splits = %d\nground splits = %d\n",
facesplits, groundsplits);
#endif //AW_DEBUG
value = 100 - facesplits - 2 * groundsplits;
//avoid epsilon faces
value += epsilonfaces * -1000;
if (value > bestvalue)
{
VectorCopy(tmpnormal, normal);
*dist = tmpdist;
bestvalue = value;
bestepsilonfaces = epsilonfaces;
foundsplitter = true;
} //end if
} //end for
} //end for
if (bestepsilonfaces)
{
Log_Write("found %d epsilon faces trying to split area %d\r\n",
epsilonfaces, tmparea->areanum);
} //end else
return foundsplitter;
} //end of the function AAS_FindBestAreaSplitPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_SubdivideArea_r(tmp_node_t *tmpnode)
{
int planenum;
tmp_area_t *frontarea, *backarea;
tmp_node_t *tmpnode1, *tmpnode2;
vec3_t normal;
float dist;
if (AAS_FindBestAreaSplitPlane(tmpnode->tmparea, normal, &dist))
{
qprintf("\r%6d", ++numgravitationalsubdivisions);
//
planenum = FindFloatPlane(normal, dist);
//split the area
AAS_SplitArea(tmpnode->tmparea, planenum, &frontarea, &backarea);
//
tmpnode->tmparea = NULL;
tmpnode->planenum = FindFloatPlane(normal, dist);
//
tmpnode1 = AAS_AllocTmpNode();
tmpnode1->planenum = 0;
tmpnode1->tmparea = frontarea;
//
tmpnode2 = AAS_AllocTmpNode();
tmpnode2->planenum = 0;
tmpnode2->tmparea = backarea;
//subdivide the areas created by splitting recursively
tmpnode->children[0] = AAS_SubdivideArea_r(tmpnode1);
tmpnode->children[1] = AAS_SubdivideArea_r(tmpnode2);
} //end if
return tmpnode;
} //end of the function AAS_SubdivideArea_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_GravitationalSubdivision_r(tmp_node_t *tmpnode)
{
//if this is a solid leaf
if (!tmpnode) return NULL;
//negative so it's an area
if (tmpnode->tmparea) return AAS_SubdivideArea_r(tmpnode);
//do the children recursively
tmpnode->children[0] = AAS_GravitationalSubdivision_r(tmpnode->children[0]);
tmpnode->children[1] = AAS_GravitationalSubdivision_r(tmpnode->children[1]);
return tmpnode;
} //end of the function AAS_GravitationalSubdivision_r
//===========================================================================
// NOTE: merge faces and melt edges first
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_GravitationalSubdivision(void)
{
Log_Write("AAS_GravitationalSubdivision\r\n");
numgravitationalsubdivisions = 0;
qprintf("%6i gravitational subdivisions", numgravitationalsubdivisions);
//start with the head node
AAS_GravitationalSubdivision_r(tmpaasworld.nodes);
qprintf("\n");
Log_Write("%6i gravitational subdivisions\r\n", numgravitationalsubdivisions);
} //end of the function AAS_GravitationalSubdivision
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_RefreshLadderSubdividedTree_r(tmp_node_t *tmpnode, tmp_area_t *tmparea,
tmp_node_t *tmpnode1, tmp_node_t *tmpnode2, int planenum)
{
//if this is a solid leaf
if (!tmpnode) return NULL;
//negative so it's an area
if (tmpnode->tmparea)
{
if (tmpnode->tmparea == tmparea)
{
tmpnode->tmparea = NULL;
tmpnode->planenum = planenum;
tmpnode->children[0] = tmpnode1;
tmpnode->children[1] = tmpnode2;
} //end if
return tmpnode;
} //end if
//do the children recursively
tmpnode->children[0] = AAS_RefreshLadderSubdividedTree_r(tmpnode->children[0],
tmparea, tmpnode1, tmpnode2, planenum);
tmpnode->children[1] = AAS_RefreshLadderSubdividedTree_r(tmpnode->children[1],
tmparea, tmpnode1, tmpnode2, planenum);
return tmpnode;
} //end of the function AAS_RefreshLadderSubdividedTree_r
//===========================================================================
// find an area with ladder faces and ground faces that are not connected
// split the area with a horizontal plane at the lowest vertex of all
// ladder faces in the area
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_LadderSubdivideArea_r(tmp_node_t *tmpnode)
{
int side1, i, planenum;
int foundladderface, foundgroundface;
float dist;
tmp_area_t *tmparea, *frontarea, *backarea;
tmp_face_t *face1;
tmp_node_t *tmpnode1, *tmpnode2;
vec3_t lowestpoint, normal = {0, 0, 1};
plane_t *plane;
winding_t *w;
tmparea = tmpnode->tmparea;
//skip areas with a liquid
if (tmparea->contents & (AREACONTENTS_WATER
| AREACONTENTS_LAVA
| AREACONTENTS_SLIME)) return tmpnode;
//must be possible to stand in the area
if (!(tmparea->presencetype & PRESENCE_NORMAL)) return tmpnode;
//
foundladderface = false;
foundgroundface = false;
lowestpoint[2] = 99999;
//
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//if the face is a ladder face
if (face1->faceflags & FACE_LADDER)
{
plane = &mapplanes[face1->planenum];
//the ladder face plane should be pretty much vertical
if (DotProduct(plane->normal, normal) > -0.1)
{
foundladderface = true;
//find lowest point
for (i = 0; i < face1->winding->numpoints; i++)
{
if (face1->winding->p[i][2] < lowestpoint[2])
{
VectorCopy(face1->winding->p[i], lowestpoint);
} //end if
} //end for
} //end if
} //end if
else if (face1->faceflags & FACE_GROUND)
{
foundgroundface = true;
} //end else if
} //end for
//
if ((!foundladderface) || (!foundgroundface)) return tmpnode;
//
for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//if the face isn't a ground face
if (!(face1->faceflags & FACE_GROUND)) continue;
//the ground plane
plane = &mapplanes[face1->planenum];
//get the difference between the ground plane and the lowest point
dist = DotProduct(plane->normal, lowestpoint) - plane->dist;
//if the lowest point is very near one of the ground planes
if (dist > -1 && dist < 1)
{
return tmpnode;
} //end if
} //end for
//
dist = DotProduct(normal, lowestpoint);
planenum = FindFloatPlane(normal, dist);
//
w = AAS_SplitWinding(tmparea, planenum);
if (!w) return tmpnode;
FreeWinding(w);
//split the area with a horizontal plane through the lowest point
qprintf("\r%6d", ++numladdersubdivisions);
//
AAS_SplitArea(tmparea, planenum, &frontarea, &backarea);
//
tmpnode->tmparea = NULL;
tmpnode->planenum = planenum;
//
tmpnode1 = AAS_AllocTmpNode();
tmpnode1->planenum = 0;
tmpnode1->tmparea = frontarea;
//
tmpnode2 = AAS_AllocTmpNode();
tmpnode2->planenum = 0;
tmpnode2->tmparea = backarea;
//subdivide the areas created by splitting recursively
tmpnode->children[0] = AAS_LadderSubdivideArea_r(tmpnode1);
tmpnode->children[1] = AAS_LadderSubdivideArea_r(tmpnode2);
//refresh the tree
AAS_RefreshLadderSubdividedTree_r(tmpaasworld.nodes, tmparea, tmpnode1, tmpnode2, planenum);
//
return tmpnode;
} //end of the function AAS_LadderSubdivideArea_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_LadderSubdivision_r(tmp_node_t *tmpnode)
{
//if this is a solid leaf
if (!tmpnode) return 0;
//negative so it's an area
if (tmpnode->tmparea) return AAS_LadderSubdivideArea_r(tmpnode);
//do the children recursively
tmpnode->children[0] = AAS_LadderSubdivision_r(tmpnode->children[0]);
tmpnode->children[1] = AAS_LadderSubdivision_r(tmpnode->children[1]);
return tmpnode;
} //end of the function AAS_LadderSubdivision_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_LadderSubdivision(void)
{
Log_Write("AAS_LadderSubdivision\r\n");
numladdersubdivisions = 0;
qprintf("%6i ladder subdivisions", numladdersubdivisions);
//start with the head node
AAS_LadderSubdivision_r(tmpaasworld.nodes);
//
qprintf("\n");
Log_Write("%6i ladder subdivisions\r\n", numladdersubdivisions);
} //end of the function AAS_LadderSubdivision

View File

@ -1,25 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//works with the global tmpaasworld
void AAS_GravitationalSubdivision(void);
void AAS_LadderSubdivision(void);

View File

@ -1,849 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h" //aas_bbox_t
#include "aas_store.h" //AAS_MAX_BBOXES
#include "aas_cfg.h"
#include "../qcommon/surfaceflags.h"
#define SPAWNFLAG_NOT_EASY 0x00000100
#define SPAWNFLAG_NOT_MEDIUM 0x00000200
#define SPAWNFLAG_NOT_HARD 0x00000400
#define SPAWNFLAG_NOT_DEATHMATCH 0x00000800
#define SPAWNFLAG_NOT_COOP 0x00001000
#define STATE_TOP 0
#define STATE_BOTTOM 1
#define STATE_UP 2
#define STATE_DOWN 3
#define DOOR_START_OPEN 1
#define DOOR_REVERSE 2
#define DOOR_CRUSHER 4
#define DOOR_NOMONSTER 8
#define DOOR_TOGGLE 32
#define DOOR_X_AXIS 64
#define DOOR_Y_AXIS 128
#define BBOX_NORMAL_EPSILON 0.0001
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec_t BoxOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs, int side)
{
vec3_t v1, v2;
int i;
if (side)
{
for (i = 0; i < 3; i++)
{
if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = mins[i];
else v1[i] = 0;
} //end for
} //end if
else
{
for (i = 0; i < 3; i++)
{
if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = mins[i];
else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
else v1[i] = 0;
} //end for
} //end else
VectorCopy(normal, v2);
VectorInverse(v2);
return DotProduct(v1, v2);
} //end of the function BoxOriginDistanceFromPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec_t CapsuleOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs)
{
float offset_up, offset_down, width, radius;
width = maxs[0] - mins[0];
// if the box is less high then it is wide
if (maxs[2] - mins[2] < width) {
width = maxs[2] - mins[2];
}
radius = width * 0.5;
// offset to upper and lower sphere
offset_up = maxs[2] - radius;
offset_down = -mins[2] - radius;
// if normal points upward
if ( normal[2] > 0 ) {
// touches lower sphere first
return normal[2] * offset_down + radius;
}
else {
// touched upper sphere first
return -normal[2] * offset_up + radius;
}
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ExpandMapBrush(mapbrush_t *brush, vec3_t mins, vec3_t maxs)
{
int sn;
float dist;
side_t *s;
plane_t *plane;
for (sn = 0; sn < brush->numsides; sn++)
{
s = brush->original_sides + sn;
plane = &mapplanes[s->planenum];
dist = plane->dist;
if (capsule_collision) {
dist += CapsuleOriginDistanceFromPlane(plane->normal, mins, maxs);
}
else {
dist += BoxOriginDistanceFromPlane(plane->normal, mins, maxs, 0);
}
s->planenum = FindFloatPlane(plane->normal, dist);
//the side isn't a bevel after expanding
s->flags &= ~SFL_BEVEL;
//don't skip the surface
s->surf &= ~SURF_SKIP;
//make sure the texinfo is not TEXINFO_NODE
//when player clip contents brushes are read from the bsp tree
//they have the texinfo field set to TEXINFO_NODE
//s->texinfo = 0;
} //end for
} //end of the function AAS_ExpandMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SetTexinfo(mapbrush_t *brush)
{
int n;
side_t *side;
if (brush->contents & (CONTENTS_LADDER
| CONTENTS_AREAPORTAL
| CONTENTS_CLUSTERPORTAL
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_DONOTENTER
| CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_WINDOW
| CONTENTS_PLAYERCLIP))
{
//we just set texinfo to 0 because these brush sides MUST be used as
//bsp splitters textured or not textured
for (n = 0; n < brush->numsides; n++)
{
side = brush->original_sides + n;
//side->flags |= SFL_TEXTURED|SFL_VISIBLE;
side->texinfo = 0;
} //end for
} //end if
else
{
//only use brush sides as splitters if they are textured
//texinfo of non-textured sides will be set to TEXINFO_NODE
for (n = 0; n < brush->numsides; n++)
{
side = brush->original_sides + n;
//don't use side as splitter (set texinfo to TEXINFO_NODE) if not textured
if (side->flags & (SFL_TEXTURED|SFL_BEVEL)) side->texinfo = 0;
else side->texinfo = TEXINFO_NODE;
} //end for
} //end else
} //end of the function AAS_SetTexinfo
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeBrushWindings(mapbrush_t *brush)
{
int n;
side_t *side;
//
for (n = 0; n < brush->numsides; n++)
{
side = brush->original_sides + n;
//
if (side->winding) FreeWinding(side->winding);
} //end for
} //end of the function FreeBrushWindings
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_AddMapBrushSide(mapbrush_t *brush, int planenum)
{
side_t *side;
//
if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
Error ("MAX_MAPFILE_BRUSHSIDES");
//
side = brush->original_sides + brush->numsides;
side->original = NULL;
side->winding = NULL;
side->contents = brush->contents;
side->flags &= ~(SFL_BEVEL|SFL_VISIBLE);
side->surf = 0;
side->planenum = planenum;
side->texinfo = 0;
//
nummapbrushsides++;
brush->numsides++;
} //end of the function AAS_AddMapBrushSide
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_FixMapBrush(mapbrush_t *brush)
{
int i, j, planenum;
float dist;
winding_t *w;
plane_t *plane, *plane1, *plane2;
side_t *side;
vec3_t normal;
//calculate the brush bounds
ClearBounds(brush->mins, brush->maxs);
for (i = 0; i < brush->numsides; i++)
{
plane = &mapplanes[brush->original_sides[i].planenum];
w = BaseWindingForPlane(plane->normal, plane->dist);
for (j = 0; j < brush->numsides && w; j++)
{
if (i == j) continue;
//there are no brush bevels marked but who cares :)
if (brush->original_sides[j].flags & SFL_BEVEL) continue;
plane = &mapplanes[brush->original_sides[j].planenum^1];
ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
} //end for
side = &brush->original_sides[i];
side->winding = w;
if (w)
{
for (j = 0; j < w->numpoints; j++)
{
AddPointToBounds(w->p[j], brush->mins, brush->maxs);
} //end for
} //end if
} //end for
//
for (i = 0; i < brush->numsides; i++)
{
for (j = 0; j < brush->numsides; j++)
{
if (i == j) continue;
plane1 = &mapplanes[brush->original_sides[i].planenum];
plane2 = &mapplanes[brush->original_sides[j].planenum];
if (WindingsNonConvex(brush->original_sides[i].winding,
brush->original_sides[j].winding,
plane1->normal, plane2->normal,
plane1->dist, plane2->dist))
{
Log_Print("non convex brush");
} //end if
} //end for
} //end for
//NOW close the fucking brush!!
for (i = 0; i < 3; i++)
{
if (brush->mins[i] < -MAX_MAP_BOUNDS)
{
VectorClear(normal);
normal[i] = -1;
dist = MAX_MAP_BOUNDS - 10;
planenum = FindFloatPlane(normal, dist);
//
Log_Print("mins out of range: added extra brush side\n");
AAS_AddMapBrushSide(brush, planenum);
} //end if
if (brush->maxs[i] > MAX_MAP_BOUNDS)
{
VectorClear(normal);
normal[i] = 1;
dist = MAX_MAP_BOUNDS - 10;
planenum = FindFloatPlane(normal, dist);
//
Log_Print("maxs out of range: added extra brush side\n");
AAS_AddMapBrushSide(brush, planenum);
} //end if
if (brush->mins[i] > MAX_MAP_BOUNDS || brush->maxs[i] < -MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
} //end if
} //end for
//free all the windings
FreeBrushWindings(brush);
} //end of the function AAS_FixMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_MakeBrushWindings(mapbrush_t *ob)
{
int i, j;
winding_t *w;
side_t *side;
plane_t *plane, *plane1, *plane2;
ClearBounds (ob->mins, ob->maxs);
for (i = 0; i < ob->numsides; i++)
{
plane = &mapplanes[ob->original_sides[i].planenum];
w = BaseWindingForPlane(plane->normal, plane->dist);
for (j = 0; j <ob->numsides && w; j++)
{
if (i == j) continue;
if (ob->original_sides[j].flags & SFL_BEVEL) continue;
plane = &mapplanes[ob->original_sides[j].planenum^1];
ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
}
side = &ob->original_sides[i];
side->winding = w;
if (w)
{
side->flags |= SFL_VISIBLE;
for (j = 0; j < w->numpoints; j++)
AddPointToBounds (w->p[j], ob->mins, ob->maxs);
}
}
//check if the brush is convex
for (i = 0; i < ob->numsides; i++)
{
for (j = 0; j < ob->numsides; j++)
{
if (i == j) continue;
plane1 = &mapplanes[ob->original_sides[i].planenum];
plane2 = &mapplanes[ob->original_sides[j].planenum];
if (WindingsNonConvex(ob->original_sides[i].winding,
ob->original_sides[j].winding,
plane1->normal, plane2->normal,
plane1->dist, plane2->dist))
{
Log_Print("non convex brush");
} //end if
} //end for
} //end for
//check for out of bound brushes
for (i = 0; i < 3; i++)
{
//IDBUG: all the indexes into the mins and maxs were zero (not using i)
if (ob->mins[i] < -MAX_MAP_BOUNDS || ob->maxs[i] > MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
ob->numsides = 0; //remove the brush
break;
} //end if
if (ob->mins[i] > MAX_MAP_BOUNDS || ob->maxs[i] < -MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
ob->numsides = 0; //remove the brush
break;
} //end if
} //end for
return true;
} //end of the function AAS_MakeBrushWindings
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
mapbrush_t *AAS_CopyMapBrush(mapbrush_t *brush, entity_t *mapent)
{
int n;
mapbrush_t *newbrush;
side_t *side, *newside;
if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
Error ("MAX_MAPFILE_BRUSHES");
newbrush = &mapbrushes[nummapbrushes];
newbrush->original_sides = &brushsides[nummapbrushsides];
newbrush->entitynum = brush->entitynum;
newbrush->brushnum = nummapbrushes - mapent->firstbrush;
newbrush->numsides = brush->numsides;
newbrush->contents = brush->contents;
//copy the sides
for (n = 0; n < brush->numsides; n++)
{
if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
Error ("MAX_MAPFILE_BRUSHSIDES");
side = brush->original_sides + n;
newside = newbrush->original_sides + n;
newside->original = NULL;
newside->winding = NULL;
newside->contents = side->contents;
newside->flags = side->flags;
newside->surf = side->surf;
newside->planenum = side->planenum;
newside->texinfo = side->texinfo;
nummapbrushsides++;
} //end for
//
nummapbrushes++;
mapent->numbrushes++;
return newbrush;
} //end of the function AAS_CopyMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int mark_entities[MAX_MAP_ENTITIES];
int AAS_AlwaysTriggered_r(char *targetname)
{
int i;
if (!strlen(targetname)) {
return false;
}
//
for (i = 0; i < num_entities; i++) {
// if the entity will activate the given targetname
if ( !strcmp(targetname, ValueForKey(&entities[i], "target")) ) {
// if this activator is present in deathmatch
if (!(atoi(ValueForKey(&entities[i], "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH)) {
// if it is a trigger_always entity
if (!strcmp("trigger_always", ValueForKey(&entities[i], "classname"))) {
return true;
}
// check for possible trigger_always entities activating this entity
if ( mark_entities[i] ) {
Warning( "entity %d, classname %s has recursive targetname %s\n", i,
ValueForKey(&entities[i], "classname"), targetname );
return false;
}
mark_entities[i] = true;
if ( AAS_AlwaysTriggered_r(ValueForKey(&entities[i], "targetname")) ) {
return true;
}
}
}
}
return false;
}
int AAS_AlwaysTriggered(char *targetname) {
memset( mark_entities, 0, sizeof(mark_entities) );
return AAS_AlwaysTriggered_r( targetname );
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_ValidEntity(entity_t *mapent)
{
int i;
char target[1024];
//all world brushes are used for AAS
if (mapent == &entities[0])
{
return true;
} //end if
//some of the func_wall brushes are also used for AAS
else if (!strcmp("func_wall", ValueForKey(mapent, "classname")))
{
//Log_Print("found func_wall entity %d\n", mapent - entities);
//if the func wall is used in deathmatch
if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
{
//Log_Print("func_wall USED in deathmatch mode %d\n", atoi(ValueForKey(mapent, "spawnflags")));
return true;
} //end if
} //end else if
else if (!strcmp("func_door_rotating", ValueForKey(mapent, "classname")))
{
//if the func_door_rotating is present in deathmatch
if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
{
//if the func_door_rotating is always activated in deathmatch
if (AAS_AlwaysTriggered(ValueForKey(mapent, "targetname")))
{
//Log_Print("found func_door_rotating in deathmatch\ntargetname %s\n", ValueForKey(mapent, "targetname"));
return true;
} //end if
} //end if
} //end else if
else if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
{
//"dmg" is the damage, for instance: "dmg" "666"
return true;
} //end else if
else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
{
return true;
} //end else if
else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
{
//find out if the trigger_multiple is pointing to a target_teleporter
strcpy(target, ValueForKey(mapent, "target"));
for (i = 0; i < num_entities; i++)
{
//if the entity will activate the given targetname
if (!strcmp(target, ValueForKey(&entities[i], "targetname")))
{
if (!strcmp("target_teleporter", ValueForKey(&entities[i], "classname")))
{
return true;
} //end if
} //end if
} //end for
} //end else if
else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
{
return true;
} //end else if
else if (!strcmp("func_static", ValueForKey(mapent, "classname")))
{
//FIXME: easy/medium/hard/deathmatch specific?
return true;
} //end else if
else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
{
return true;
} //end else if
return false;
} //end of the function AAS_ValidEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TransformPlane(int planenum, vec3_t origin, vec3_t angles)
{
float newdist, matrix[3][3];
vec3_t normal;
//rotate the node plane
VectorCopy(mapplanes[planenum].normal, normal);
CreateRotationMatrix(angles, matrix);
RotatePoint(normal, matrix);
newdist = mapplanes[planenum].dist + DotProduct(normal, origin);
return FindFloatPlane(normal, newdist);
} //end of the function AAS_TransformPlane
//===========================================================================
// this function sets the func_rotating_door in it's final position
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush)
{
int spawnflags, i;
float distance;
vec3_t movedir, angles, pos1, pos2;
side_t *s;
spawnflags = FloatForKey(mapent, "spawnflags");
VectorClear(movedir);
if (spawnflags & DOOR_X_AXIS)
movedir[2] = 1.0; //roll
else if (spawnflags & DOOR_Y_AXIS)
movedir[0] = 1.0; //pitch
else // Z_AXIS
movedir[1] = 1.0; //yaw
// check for reverse rotation
if (spawnflags & DOOR_REVERSE)
VectorInverse(movedir);
distance = FloatForKey(mapent, "distance");
if (!distance) distance = 90;
GetVectorForKey(mapent, "angles", angles);
VectorCopy(angles, pos1);
VectorMA(angles, -distance, movedir, pos2);
// if it starts open, switch the positions
if (spawnflags & DOOR_START_OPEN)
{
VectorCopy(pos2, angles);
VectorCopy(pos1, pos2);
VectorCopy(angles, pos1);
VectorInverse(movedir);
} //end if
//
for (i = 0; i < brush->numsides; i++)
{
s = &brush->original_sides[i];
s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2);
} //end for
//
FreeBrushWindings(brush);
AAS_MakeBrushWindings(brush);
AddBrushBevels(brush);
FreeBrushWindings(brush);
} //end of the function AAS_PositionFuncRotatingBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PositionBrush(entity_t *mapent, mapbrush_t *brush)
{
side_t *s;
float newdist;
int i, notteam;
char *model;
if (!strcmp(ValueForKey(mapent, "classname"), "func_door_rotating"))
{
AAS_PositionFuncRotatingBrush(mapent, brush);
} //end if
else
{
if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
{
for (i = 0; i < brush->numsides; i++)
{
s = &brush->original_sides[i];
newdist = mapplanes[s->planenum].dist +
DotProduct(mapplanes[s->planenum].normal, mapent->origin);
s->planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist);
} //end for
} //end if
//if it's a trigger hurt
if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
{
notteam = FloatForKey(mapent, "bot_notteam");
if ( notteam == 1 ) {
brush->contents |= CONTENTS_NOTTEAM1;
}
else if ( notteam == 2 ) {
brush->contents |= CONTENTS_NOTTEAM2;
}
else {
// always avoid so set lava contents
brush->contents |= CONTENTS_LAVA;
}
} //end if
//
else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
{
//set the jumppad contents
brush->contents = CONTENTS_JUMPPAD;
//Log_Print("found trigger_push brush\n");
} //end if
//
else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
{
//set teleporter contents
brush->contents = CONTENTS_TELEPORTER;
//Log_Print("found trigger_multiple teleporter brush\n");
} //end if
//
else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
{
//set teleporter contents
brush->contents = CONTENTS_TELEPORTER;
//Log_Print("found trigger_teleport teleporter brush\n");
} //end if
else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
{
//set mover contents
brush->contents = CONTENTS_MOVER;
//get the model number
model = ValueForKey(mapent, "model");
brush->modelnum = atoi(model+1);
} //end if
} //end else
} //end of the function AAS_PositionBrush
//===========================================================================
// uses the global cfg_t cfg
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels)
{
int i;
//side_t *s;
mapbrush_t *bboxbrushes[16];
//if the brushes are not from an entity used for AAS
if (!AAS_ValidEntity(mapent))
{
nummapbrushsides -= brush->numsides;
brush->numsides = 0;
return;
} //end if
//
AAS_PositionBrush(mapent, brush);
//from all normal solid brushes only the textured brush sides will
//be used as bsp splitters, so set the right texinfo reference here
AAS_SetTexinfo(brush);
//remove contents detail flag, otherwise player clip contents won't be
//bsped correctly for AAS!
brush->contents &= ~CONTENTS_DETAIL;
//if the brush has contents area portal it should be the only contents
if (brush->contents & (CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL))
{
brush->contents = CONTENTS_CLUSTERPORTAL;
brush->leafnum = -1;
} //end if
//window and playerclip are used for player clipping, make them solid
if (brush->contents & (CONTENTS_WINDOW | CONTENTS_PLAYERCLIP))
{
//
brush->contents &= ~(CONTENTS_WINDOW | CONTENTS_PLAYERCLIP);
brush->contents |= CONTENTS_SOLID;
brush->leafnum = -1;
} //end if
//
if (brush->contents & CONTENTS_BOTCLIP)
{
brush->contents = CONTENTS_SOLID;
brush->leafnum = -1;
} //end if
//
//Log_Write("brush %d contents = ", brush->brushnum);
//PrintContents(brush->contents);
//Log_Write("\r\n");
//if not one of the following brushes then the brush is NOT used for AAS
if (!(brush->contents & (CONTENTS_SOLID
| CONTENTS_LADDER
| CONTENTS_CLUSTERPORTAL
| CONTENTS_DONOTENTER
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_MOVER
)))
{
nummapbrushsides -= brush->numsides;
brush->numsides = 0;
return;
} //end if
//fix the map brush
//AAS_FixMapBrush(brush);
//if brush bevels should be added (for real map brushes, not bsp map brushes)
if (addbevels)
{
//NOTE: we first have to get the mins and maxs of the brush before
// creating the brush bevels... the mins and maxs are used to
// create them. so we call MakeBrushWindings to get the mins
// and maxs and then after creating the bevels we free the
// windings because they are created for all sides (including
// bevels) a little later
AAS_MakeBrushWindings(brush);
AddBrushBevels(brush);
FreeBrushWindings(brush);
} //end if
//NOTE: add the brush to the WORLD entity!!!
mapent = &entities[0];
//there's at least one new brush for now
nummapbrushes++;
mapent->numbrushes++;
//liquid brushes are expanded for the maximum possible bounding box
if (brush->contents & (CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_DONOTENTER
| CONTENTS_MOVER
))
{
brush->expansionbbox = 0;
//NOTE: the first bounding box is the max
//FIXME: use max bounding box created from all bboxes
AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
AAS_MakeBrushWindings(brush);
} //end if
//area portal brushes are NOT expanded
else if (brush->contents & CONTENTS_CLUSTERPORTAL)
{
brush->expansionbbox = 0;
//NOTE: the first bounding box is the max
//FIXME: use max bounding box created from all bboxes
AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
AAS_MakeBrushWindings(brush);
} //end if
//all solid brushes are expanded for all bounding boxes
else if (brush->contents & (CONTENTS_SOLID
| CONTENTS_LADDER
))
{
//brush for the first bounding box
bboxbrushes[0] = brush;
//make a copy for the other bounding boxes
for (i = 1; i < cfg.numbboxes; i++)
{
bboxbrushes[i] = AAS_CopyMapBrush(brush, mapent);
} //end for
//expand every brush for it's bounding box and create windings
for (i = 0; i < cfg.numbboxes; i++)
{
AAS_ExpandMapBrush(bboxbrushes[i], cfg.bboxes[i].mins, cfg.bboxes[i].maxs);
bboxbrushes[i]->expansionbbox = cfg.bboxes[i].presencetype;
AAS_MakeBrushWindings(bboxbrushes[i]);
} //end for
} //end else
} //end of the function AAS_CreateMapBrushes

View File

@ -1,23 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels);

View File

@ -1,89 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
int c_numprunes;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_PruneNodes_r(tmp_node_t *tmpnode)
{
tmp_area_t *tmparea1, *tmparea2;
//if it is a solid leaf
if (!tmpnode) return NULL;
//
if (tmpnode->tmparea) return tmpnode;
//process the children first
tmpnode->children[0] = AAS_PruneNodes_r(tmpnode->children[0]);
tmpnode->children[1] = AAS_PruneNodes_r(tmpnode->children[1]);
//if both children are areas
if (tmpnode->children[0] && tmpnode->children[1] &&
tmpnode->children[0]->tmparea && tmpnode->children[1]->tmparea)
{
tmparea1 = tmpnode->children[0]->tmparea;
while(tmparea1->mergedarea) tmparea1 = tmparea1->mergedarea;
tmparea2 = tmpnode->children[1]->tmparea;
while(tmparea2->mergedarea) tmparea2 = tmparea2->mergedarea;
if (tmparea1 == tmparea2)
{
c_numprunes++;
tmpnode->tmparea = tmparea1;
tmpnode->planenum = 0;
AAS_FreeTmpNode(tmpnode->children[0]);
AAS_FreeTmpNode(tmpnode->children[1]);
tmpnode->children[0] = NULL;
tmpnode->children[1] = NULL;
return tmpnode;
} //end if
} //end if
//if both solid leafs
if (!tmpnode->children[0] && !tmpnode->children[1])
{
c_numprunes++;
AAS_FreeTmpNode(tmpnode);
return NULL;
} //end if
//
return tmpnode;
} //end of the function AAS_PruneNodes_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PruneNodes(void)
{
Log_Write("AAS_PruneNodes\r\n");
AAS_PruneNodes_r(tmpaasworld.nodes);
Log_Print("%6d nodes pruned\r\n", c_numprunes);
} //end of the function AAS_PruneNodes

View File

@ -1,24 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_PruneNodes(void);

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#define AAS_MAX_BBOXES 5
#define AAS_MAX_VERTEXES 512000
#define AAS_MAX_PLANES 65536
#define AAS_MAX_EDGES 512000
#define AAS_MAX_EDGEINDEXSIZE 512000
#define AAS_MAX_FACES 512000
#define AAS_MAX_FACEINDEXSIZE 512000
#define AAS_MAX_AREAS 65536
#define AAS_MAX_AREASETTINGS 65536
#define AAS_MAX_REACHABILITYSIZE 65536
#define AAS_MAX_NODES 256000
#define AAS_MAX_PORTALS 65536
#define AAS_MAX_PORTALINDEXSIZE 65536
#define AAS_MAX_CLUSTERS 65536
#define BSPCINCLUDE
#include "../botlib/be_aas.h"
#include "../botlib/be_aas_def.h"
/*
typedef struct bspc_aas_s
{
int loaded;
int initialized; //true when AAS has been initialized
int savefile; //set true when file should be saved
//bounding boxes
int numbboxes;
aas_bbox_t *bboxes;
//vertexes
int numvertexes;
aas_vertex_t *vertexes;
//planes
int numplanes;
aas_plane_t *planes;
//edges
int numedges;
aas_edge_t *edges;
//edge index
int edgeindexsize;
aas_edgeindex_t *edgeindex;
//faces
int numfaces;
aas_face_t *faces;
//face index
int faceindexsize;
aas_faceindex_t *faceindex;
//convex areas
int numareas;
aas_area_t *areas;
//convex area settings
int numareasettings;
aas_areasettings_t *areasettings;
//reachablity list
int reachabilitysize;
aas_reachability_t *reachability;
//nodes of the bsp tree
int numnodes;
aas_node_t *nodes;
//cluster portals
int numportals;
aas_portal_t *portals;
//cluster portal index
int portalindexsize;
aas_portalindex_t *portalindex;
//clusters
int numclusters;
aas_cluster_t *clusters;
//
int numreachabilityareas;
float reachabilitytime;
} bspc_aas_t;
extern bspc_aas_t aasworld;
//*/
extern aas_t aasworld;
//stores the AAS file from the temporary AAS
void AAS_StoreFile(char *filename);
//returns a number of the given plane
qboolean AAS_FindPlane(vec3_t normal, float dist, int *planenum);
//allocates the maximum AAS memory for storage
void AAS_AllocMaxAAS(void);
//frees the maximum AAS memory for storage
void AAS_FreeMaxAAS(void);

View File

@ -1,252 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//NOTE: int = default signed
// default long
#define AASID (('S'<<24)+('A'<<16)+('A'<<8)+'E')
#define AASVERSION_OLD 4
#define AASVERSION 5
//presence types
#define PRESENCE_NONE 1
#define PRESENCE_NORMAL 2
#define PRESENCE_CROUCH 4
//travel types
#define MAX_TRAVELTYPES 32
#define TRAVEL_INVALID 1 //temporary not possible
#define TRAVEL_WALK 2 //walking
#define TRAVEL_CROUCH 3 //crouching
#define TRAVEL_BARRIERJUMP 4 //jumping onto a barrier
#define TRAVEL_JUMP 5 //jumping
#define TRAVEL_LADDER 6 //climbing a ladder
#define TRAVEL_WALKOFFLEDGE 7 //walking of a ledge
#define TRAVEL_SWIM 8 //swimming
#define TRAVEL_WATERJUMP 9 //jump out of the water
#define TRAVEL_TELEPORT 10 //teleportation
#define TRAVEL_ELEVATOR 11 //travel by elevator
#define TRAVEL_ROCKETJUMP 12 //rocket jumping required for travel
#define TRAVEL_BFGJUMP 13 //bfg jumping required for travel
#define TRAVEL_GRAPPLEHOOK 14 //grappling hook required for travel
#define TRAVEL_DOUBLEJUMP 15 //double jump
#define TRAVEL_RAMPJUMP 16 //ramp jump
#define TRAVEL_STRAFEJUMP 17 //strafe jump
#define TRAVEL_JUMPPAD 18 //jump pad
#define TRAVEL_FUNCBOB 19 //func bob
//face flags
#define FACE_SOLID 1 //just solid at the other side
#define FACE_LADDER 2 //ladder
#define FACE_GROUND 4 //standing on ground when in this face
#define FACE_GAP 8 //gap in the ground
#define FACE_LIQUID 16
#define FACE_LIQUIDSURFACE 32
//area contents
#define AREACONTENTS_WATER 1
#define AREACONTENTS_LAVA 2
#define AREACONTENTS_SLIME 4
#define AREACONTENTS_CLUSTERPORTAL 8
#define AREACONTENTS_TELEPORTAL 16
#define AREACONTENTS_ROUTEPORTAL 32
#define AREACONTENTS_TELEPORTER 64
#define AREACONTENTS_JUMPPAD 128
#define AREACONTENTS_DONOTENTER 256
#define AREACONTENTS_VIEWPORTAL 512
//area flags
#define AREA_GROUNDED 1 //bot can stand on the ground
#define AREA_LADDER 2 //area contains one or more ladder faces
#define AREA_LIQUID 4 //area contains a liquid
//aas file header lumps
#define AAS_LUMPS 14
#define AASLUMP_BBOXES 0
#define AASLUMP_VERTEXES 1
#define AASLUMP_PLANES 2
#define AASLUMP_EDGES 3
#define AASLUMP_EDGEINDEX 4
#define AASLUMP_FACES 5
#define AASLUMP_FACEINDEX 6
#define AASLUMP_AREAS 7
#define AASLUMP_AREASETTINGS 8
#define AASLUMP_REACHABILITY 9
#define AASLUMP_NODES 10
#define AASLUMP_PORTALS 11
#define AASLUMP_PORTALINDEX 12
#define AASLUMP_CLUSTERS 13
//========== bounding box =========
//bounding box
typedef struct aas_bbox_s
{
int presencetype;
int flags;
vec3_t mins, maxs;
} aas_bbox_t;
//============ settings ===========
//reachability to another area
typedef struct aas_reachability_s
{
int areanum; //number of the reachable area
int facenum; //number of the face towards the other area
int edgenum; //number of the edge towards the other area
vec3_t start; //start point of inter area movement
vec3_t end; //end point of inter area movement
int traveltype; //type of travel required to get to the area
unsigned short int traveltime;//travel time of the inter area movement
} aas_reachability_t;
//area settings
typedef struct aas_areasettings_s
{
//could also add all kind of statistic fields
int contents; //contents of the convex area
int areaflags; //several area flags
int presencetype; //how a bot can be present in this convex area
int cluster; //cluster the area belongs to, if negative it's a portal
int clusterareanum; //number of the area in the cluster
int numreachableareas; //number of reachable areas from this one
int firstreachablearea; //first reachable area in the reachable area index
} aas_areasettings_t;
//cluster portal
typedef struct aas_portal_s
{
int areanum; //area that is the actual portal
int frontcluster; //cluster at front of portal
int backcluster; //cluster at back of portal
int clusterareanum[2]; //number of the area in the front and back cluster
} aas_portal_t;
//cluster portal index
typedef int aas_portalindex_t;
//cluster
typedef struct aas_cluster_s
{
int numareas; //number of areas in the cluster
int numreachabilityareas; //number of areas with reachabilities
int numportals; //number of cluster portals
int firstportal; //first cluster portal in the index
} aas_cluster_t;
//============ 3d definition ============
typedef vec3_t aas_vertex_t;
//just a plane in the third dimension
typedef struct aas_plane_s
{
vec3_t normal; //normal vector of the plane
float dist; //distance of the plane (normal vector * distance = point in plane)
int type;
} aas_plane_t;
//edge
typedef struct aas_edge_s
{
int v[2]; //numbers of the vertexes of this edge
} aas_edge_t;
//edge index, negative if vertexes are reversed
typedef int aas_edgeindex_t;
//a face bounds a convex area, often it will also seperate two convex areas
typedef struct aas_face_s
{
int planenum; //number of the plane this face is in
int faceflags; //face flags (no use to create face settings for just this field)
int numedges; //number of edges in the boundary of the face
int firstedge; //first edge in the edge index
int frontarea; //convex area at the front of this face
int backarea; //convex area at the back of this face
} aas_face_t;
//face index, stores a negative index if backside of face
typedef int aas_faceindex_t;
//convex area with a boundary of faces
typedef struct aas_area_s
{
int areanum; //number of this area
//3d definition
int numfaces; //number of faces used for the boundary of the convex area
int firstface; //first face in the face index used for the boundary of the convex area
vec3_t mins; //mins of the convex area
vec3_t maxs; //maxs of the convex area
vec3_t center; //'center' of the convex area
} aas_area_t;
//nodes of the bsp tree
typedef struct aas_node_s
{
int planenum;
int children[2]; //child nodes of this node, or convex areas as leaves when negative
//when a child is zero it's a solid leaf
} aas_node_t;
//=========== aas file ===============
//header lump
typedef struct
{
int fileofs;
int filelen;
} aas_lump_t;
//aas file header
typedef struct aas_header_s
{
int ident;
int version;
int bspchecksum;
//data entries
aas_lump_t lumps[AAS_LUMPS];
} aas_header_t;
//====== additional information ======
/*
- when a node child is a solid leaf the node child number is zero
- two adjacent areas (sharing a plane at opposite sides) share a face
this face is a portal between the areas
- when an area uses a face from the faceindex with a positive index
then the face plane normal points into the area
- the face edges are stored counter clockwise using the edgeindex
- two adjacent convex areas (sharing a face) only share One face
this is a simple result of the areas being convex
- the convex areas can't have a mixture of ground and gap faces
other mixtures of faces in one area are allowed
- areas with the AREACONTENTS_CLUSTERPORTAL in the settings have
cluster number zero
- edge zero is a dummy
- face zero is a dummy
- area zero is a dummy
- node zero is a dummy
*/

View File

@ -1,292 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../bspc/l_log.h"
#include "../bspc/l_qfiles.h"
#include "../botlib/l_memory.h"
#include "../botlib/l_script.h"
#include "../botlib/l_precomp.h"
#include "../botlib/l_struct.h"
#include "../botlib/aasfile.h"
#include "../botlib/botlib.h"
#include "../botlib/be_aas.h"
#include "../botlib/be_aas_def.h"
#include "../qcommon/cm_public.h"
//#define BSPC
extern botlib_import_t botimport;
extern qboolean capsule_collision;
botlib_import_t botimport;
clipHandle_t worldmodel;
void Error (char *error, ...);
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_Error(char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, fmt);
vsprintf(text, fmt, argptr);
va_end(argptr);
Error(text);
} //end of the function AAS_Error
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Sys_MilliSeconds(void)
{
return clock() * 1000 / CLOCKS_PER_SEC;
} //end of the function Sys_MilliSeconds
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DebugLine(vec3_t start, vec3_t end, int color)
{
} //end of the function AAS_DebugLine
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ClearShownDebugLines(void)
{
} //end of the function AAS_ClearShownDebugLines
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *BotImport_BSPEntityData(void)
{
return CM_EntityString();
} //end of the function AAS_GetEntityData
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_Trace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
{
trace_t result;
CM_BoxTrace(&result, start, end, mins, maxs, worldmodel, contentmask, capsule_collision);
bsptrace->allsolid = result.allsolid;
bsptrace->contents = result.contents;
VectorCopy(result.endpos, bsptrace->endpos);
bsptrace->ent = result.entityNum;
bsptrace->fraction = result.fraction;
bsptrace->exp_dist = 0;
bsptrace->plane.dist = result.plane.dist;
VectorCopy(result.plane.normal, bsptrace->plane.normal);
bsptrace->plane.signbits = result.plane.signbits;
bsptrace->plane.type = result.plane.type;
bsptrace->sidenum = 0;
bsptrace->startsolid = result.startsolid;
bsptrace->surface.flags = result.surfaceFlags;
} //end of the function BotImport_Trace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotImport_PointContents(vec3_t p)
{
return CM_PointContents(p, worldmodel);
} //end of the function BotImport_PointContents
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *BotImport_GetMemory(int size)
{
return GetMemory(size);
} //end of the function BotImport_GetMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_Print(int type, char *fmt, ...)
{
va_list argptr;
char buf[1024];
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
printf(buf);
if (buf[0] != '\r') Log_Write(buf);
va_end(argptr);
} //end of the function BotImport_Print
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t outmins, vec3_t outmaxs, vec3_t origin)
{
clipHandle_t h;
vec3_t mins, maxs;
float max;
int i;
h = CM_InlineModel(modelnum);
CM_ModelBounds(h, mins, maxs);
//if the model is rotated
if ((angles[0] || angles[1] || angles[2]))
{ // expand for rotation
max = RadiusFromBounds(mins, maxs);
for (i = 0; i < 3; i++)
{
mins[i] = (mins[i] + maxs[i]) * 0.5 - max;
maxs[i] = (mins[i] + maxs[i]) * 0.5 + max;
} //end for
} //end if
if (outmins) VectorCopy(mins, outmins);
if (outmaxs) VectorCopy(maxs, outmaxs);
if (origin) VectorClear(origin);
} //end of the function BotImport_BSPModelMinsMaxsOrigin
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_DPrintf(char *fmt, ...)
{
va_list argptr;
char buf[1024];
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
printf(buf);
if (buf[0] != '\r') Log_Write(buf);
va_end(argptr);
} //end of the function Com_DPrintf
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int COM_Compress( char *data_p ) {
return strlen(data_p);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_Memset (void* dest, const int val, const size_t count) {
memset(dest, val, count);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_Memcpy (void* dest, const void* src, const size_t count) {
memcpy(dest, src, count);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InitBotImport(void)
{
botimport.BSPEntityData = BotImport_BSPEntityData;
botimport.GetMemory = BotImport_GetMemory;
botimport.FreeMemory = FreeMemory;
botimport.Trace = BotImport_Trace;
botimport.PointContents = BotImport_PointContents;
botimport.Print = BotImport_Print;
botimport.BSPModelMinsMaxsOrigin = BotImport_BSPModelMinsMaxsOrigin;
} //end of the function AAS_InitBotImport
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_CalcReachAndClusters(struct quakefile_s *qf)
{
float time;
Log_Print("loading collision map...\n");
//
if (!qf->pakfile[0]) strcpy(qf->pakfile, qf->filename);
//load the map
CM_LoadMap((char *) qf, qfalse, &aasworld.bspchecksum);
//get a handle to the world model
worldmodel = CM_InlineModel(0); // 0 = world, 1 + are bmodels
//initialize bot import structure
AAS_InitBotImport();
//load the BSP entity string
AAS_LoadBSPFile();
//init physics settings
AAS_InitSettings();
//initialize AAS link heap
AAS_InitAASLinkHeap();
//initialize the AAS linked entities for the new map
AAS_InitAASLinkedEntities();
//reset all reachabilities and clusters
aasworld.reachabilitysize = 0;
aasworld.numclusters = 0;
//set all view portals as cluster portals in case we re-calculate the reachabilities and clusters (with -reach)
AAS_SetViewPortalsAsClusterPortals();
//calculate reachabilities
AAS_InitReachability();
time = 0;
while(AAS_ContinueInitReachability(time)) time++;
//calculate clusters
AAS_InitClustering();
} //end of the function AAS_CalcReachAndClusters

View File

@ -1,23 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_CalcReachAndClusters(struct quakefile_s *qf);

File diff suppressed because it is too large Load Diff

View File

@ -1,991 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if defined(WIN32) || defined(_WIN32)
#include <direct.h>
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <unistd.h>
#include <glob.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h"
#include "../botlib/be_aas_cluster.h"
#include "../botlib/be_aas_optimize.h"
#include "aas_create.h"
#include "aas_store.h"
#include "aas_file.h"
#include "aas_cfg.h"
#include "be_aas_bspc.h"
extern int use_nodequeue; //brushbsp.c
extern int calcgrapplereach; //be_aas_reach.c
float subdivide_size = 240;
char source[1024];
char name[1024];
vec_t microvolume = 1.0;
char outbase[32];
int entity_num;
aas_settings_t aassettings;
qboolean noprune; //don't prune nodes (bspc.c)
qboolean glview; //create a gl view
qboolean nodetail; //don't use detail brushes (map.c)
qboolean fulldetail; //use but don't mark detail brushes (map.c)
qboolean onlyents; //only process the entities (bspc.c)
qboolean nomerge; //don't merge bsp node faces (faces.c)
qboolean nowater; //don't use the water brushes (map.c)
qboolean nocsg; //don't carve intersecting brushes (bspc.c)
qboolean noweld; //use unique face vertexes (faces.c)
qboolean noshare; //don't share bsp edges (faces.c)
qboolean nosubdiv; //don't subdivide bsp node faces (faces.c)
qboolean notjunc; //don't create tjunctions (edge melting) (faces.c)
qboolean optimize; //enable optimisation
qboolean leaktest; //perform a leak test
qboolean verboseentities;
qboolean freetree; //free the bsp tree when not needed anymore
qboolean create_aas; //create an .AAS file
qboolean nobrushmerge; //don't merge brushes
qboolean lessbrushes; //create less brushes instead of correct texture placement
qboolean cancelconversion; //true if the conversion is being cancelled
qboolean noliquids; //no liquids when writing map file
qboolean forcesidesvisible; //force all brush sides to be visible when loaded from bsp
qboolean capsule_collision = 0;
/*
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessWorldModel (void)
{
entity_t *e;
tree_t *tree;
qboolean leaked;
int brush_start, brush_end;
e = &entities[entity_num];
brush_start = e->firstbrush;
brush_end = brush_start + e->numbrushes;
leaked = false;
//process the whole world in one time
tree = ProcessWorldBrushes(brush_start, brush_end);
//create the bsp tree portals
MakeTreePortals(tree);
//mark all leafs that can be reached by entities
if (FloodEntities(tree))
{
FillOutside(tree->headnode);
} //end if
else
{
Log_Print("**** leaked ****\n");
leaked = true;
LeakFile(tree);
if (leaktest)
{
Log_Print("--- MAP LEAKED ---\n");
exit(0);
} //end if
} //end else
MarkVisibleSides (tree, brush_start, brush_end);
FloodAreas (tree);
#ifndef ME
if (glview) WriteGLView(tree, source);
#endif
MakeFaces(tree->headnode);
FixTjuncs(tree->headnode);
//NOTE: Never prune the nodes because the portals
// are screwed when prunning is done and as
// a result portal writing will crash
//if (!noprune) PruneNodes(tree->headnode);
WriteBSP(tree->headnode);
if (!leaked) WritePortalFile(tree);
Tree_Free(tree);
} //end of the function ProcessWorldModel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessSubModel (void)
{
entity_t *e;
int start, end;
tree_t *tree;
bspbrush_t *list;
vec3_t mins, maxs;
e = &entities[entity_num];
start = e->firstbrush;
end = start + e->numbrushes;
mins[0] = mins[1] = mins[2] = -4096;
maxs[0] = maxs[1] = maxs[2] = 4096;
list = MakeBspBrushList(start, end, mins, maxs);
if (!nocsg) list = ChopBrushes (list);
tree = BrushBSP (list, mins, maxs);
MakeTreePortals (tree);
MarkVisibleSides (tree, start, end);
MakeFaces (tree->headnode);
FixTjuncs (tree->headnode);
WriteBSP (tree->headnode);
Tree_Free(tree);
} //end of the function ProcessSubModel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessModels (void)
{
BeginBSPFile();
for (entity_num = 0; entity_num < num_entities; entity_num++)
{
if (!entities[entity_num].numbrushes)
continue;
Log_Print("############### model %i ###############\n", nummodels);
BeginModel();
if (entity_num == 0) ProcessWorldModel();
else ProcessSubModel();
EndModel();
if (!verboseentities)
verbose = false; // don't bother printing submodels
} //end for
EndBSPFile();
} //end of the function ProcessModels
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Win_Map2Bsp(char *bspfilename)
{
double start, end;
char path[1024];
start = I_FloatTime();
ThreadSetDefault();
//yeah sure Carmack
//numthreads = 1; // multiple threads aren't helping...
strcpy(source, ExpandArg(bspfilename));
StripExtension(source);
//delete portal and line files
sprintf(path, "%s.prt", source);
remove(path);
sprintf(path, "%s.lin", source);
remove(path);
strcpy(name, ExpandArg(bspfilename));
DefaultExtension(name, ".map"); // might be .reg
Q2_AllocMaxBSP();
//
SetModelNumbers();
SetLightStyles();
ProcessModels();
//write the BSP
Q2_WriteBSPFile(bspfilename);
Q2_FreeMaxBSP();
end = I_FloatTime();
Log_Print("%5.0f seconds elapsed\n", end-start);
} //end of the function Win_Map2Bsp
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Map2Bsp(char *mapfilename, char *outputfilename)
{
double start, end;
char path[1024];
start = I_FloatTime ();
ThreadSetDefault ();
//yeah sure Carmack
//numthreads = 1; //multiple threads aren't helping...
//SetQdirFromPath(bspfilename);
strcpy(source, ExpandArg(mapfilename));
StripExtension(source);
// delete portal and line files
sprintf(path, "%s.prt", source);
remove(path);
sprintf(path, "%s.lin", source);
remove(path);
strcpy(name, ExpandArg(mapfilename));
DefaultExtension(name, ".map"); // might be .reg
//
// if onlyents, just grab the entites and resave
//
if (onlyents)
{
char out[1024];
Q2_AllocMaxBSP();
sprintf (out, "%s.bsp", source);
Q2_LoadBSPFile(out, 0, 0);
num_entities = 0;
Q2_LoadMapFile(name);
SetModelNumbers();
SetLightStyles();
Q2_UnparseEntities();
Q2_WriteBSPFile(out);
//
Q2_FreeMaxBSP();
} //end if
else
{
//
// start from scratch
//
Q2_AllocMaxBSP();
//load the map
Q2_LoadMapFile(name);
//create the .bsp file
SetModelNumbers();
SetLightStyles();
ProcessModels();
//write the BSP
Q2_WriteBSPFile(outputfilename);
//
Q2_FreeMaxBSP();
} //end else
end = I_FloatTime();
Log_Print("%5.0f seconds elapsed\n", end-start);
} //end of the function Map2Bsp
*/
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AASOuputFile(quakefile_t *qf, char *outputpath, char *filename)
{
char ext[MAX_PATH];
//
if (strlen(outputpath))
{
strcpy(filename, outputpath);
//append the bsp file base
AppendPathSeperator(filename, MAX_PATH);
ExtractFileBase(qf->origname, &filename[strlen(filename)]);
//append .aas
strcat(filename, ".aas");
return;
} //end if
//
ExtractFileExtension(qf->filename, ext);
if (!stricmp(ext, "pk3") || !stricmp(ext, "pak") || !stricmp(ext, "sin"))
{
strcpy(filename, qf->filename);
while(strlen(filename) &&
filename[strlen(filename)-1] != '\\' &&
filename[strlen(filename)-1] != '/')
{
filename[strlen(filename)-1] = '\0';
} //end while
strcat(filename, "maps");
if (access(filename, 0x04)) CreatePath(filename);
//append the bsp file base
AppendPathSeperator(filename, MAX_PATH);
ExtractFileBase(qf->origname, &filename[strlen(filename)]);
//append .aas
strcat(filename, ".aas");
} //end if
else
{
strcpy(filename, qf->filename);
while(strlen(filename) &&
filename[strlen(filename)-1] != '.')
{
filename[strlen(filename)-1] = '\0';
} //end while
strcat(filename, "aas");
} //end else
} //end of the function AASOutputFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void CreateAASFilesForAllBSPFiles(char *quakepath)
{
#if defined(WIN32)|defined(_WIN32)
WIN32_FIND_DATA filedata;
HWND handle;
struct _stat statbuf;
#else
glob_t globbuf;
struct stat statbuf;
int j;
#endif
int done;
char filter[_MAX_PATH], bspfilter[_MAX_PATH], aasfilter[_MAX_PATH];
char aasfile[_MAX_PATH], buf[_MAX_PATH], foldername[_MAX_PATH];
quakefile_t *qf, *qf2, *files, *bspfiles, *aasfiles;
strcpy(filter, quakepath);
AppendPathSeperator(filter, sizeof(filter));
strcat(filter, "*");
#if defined(WIN32)|defined(_WIN32)
handle = FindFirstFile(filter, &filedata);
done = (handle == INVALID_HANDLE_VALUE);
while(!done)
{
_splitpath(filter, foldername, NULL, NULL, NULL);
_splitpath(filter, NULL, &foldername[strlen(foldername)], NULL, NULL);
AppendPathSeperator(foldername, _MAX_PATH);
strcat(foldername, filedata.cFileName);
_stat(foldername, &statbuf);
#else
glob(filter, 0, NULL, &globbuf);
for (j = 0; j < globbuf.gl_pathc; j++)
{
strcpy(foldername, globbuf.gl_pathv[j]);
stat(foldername, &statbuf);
#endif
//if it is a folder
if (statbuf.st_mode & S_IFDIR)
{
//
AppendPathSeperator(foldername, sizeof(foldername));
//get all the bsp files
strcpy(bspfilter, foldername);
strcat(bspfilter, "maps/*.bsp");
files = FindQuakeFiles(bspfilter);
strcpy(bspfilter, foldername);
strcat(bspfilter, "*.pk3/maps/*.bsp");
bspfiles = FindQuakeFiles(bspfilter);
for (qf = bspfiles; qf; qf = qf->next) if (!qf->next) break;
if (qf) qf->next = files;
else bspfiles = files;
//get all the aas files
strcpy(aasfilter, foldername);
strcat(aasfilter, "maps/*.aas");
files = FindQuakeFiles(aasfilter);
strcpy(aasfilter, foldername);
strcat(aasfilter, "*.pk3/maps/*.aas");
aasfiles = FindQuakeFiles(aasfilter);
for (qf = aasfiles; qf; qf = qf->next) if (!qf->next) break;
if (qf) qf->next = files;
else aasfiles = files;
//
for (qf = bspfiles; qf; qf = qf->next)
{
sprintf(aasfile, "%s/%s", qf->pakfile, qf->origname);
Log_Print("found %s\n", aasfile);
strcpy(&aasfile[strlen(aasfile)-strlen(".bsp")], ".aas");
for (qf2 = aasfiles; qf2; qf2 = qf2->next)
{
sprintf(buf, "%s/%s", qf2->pakfile, qf2->origname);
if (!stricmp(aasfile, buf))
{
Log_Print("found %s\n", buf);
break;
} //end if
} //end for
} //end for
} //end if
#if defined(WIN32)|defined(_WIN32)
//find the next file
done = !FindNextFile(handle, &filedata);
} //end while
#else
} //end for
globfree(&globbuf);
#endif
} //end of the function CreateAASFilesForAllBSPFiles
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *GetArgumentFiles(int argc, char *argv[], int *i, char *ext)
{
quakefile_t *qfiles, *lastqf, *qf;
int j;
char buf[1024];
qfiles = NULL;
lastqf = NULL;
for (; (*i)+1 < argc && argv[(*i)+1][0] != '-'; (*i)++)
{
strcpy(buf, argv[(*i)+1]);
for (j = strlen(buf)-1; j >= strlen(buf)-4; j--)
if (buf[j] == '.') break;
if (j >= strlen(buf)-4)
strcpy(&buf[j+1], ext);
qf = FindQuakeFiles(buf);
if (!qf) continue;
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
while(lastqf->next) lastqf = lastqf->next;
} //end for
return qfiles;
} //end of the function GetArgumentFiles
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#define COMP_BSP2MAP 1
#define COMP_BSP2AAS 2
#define COMP_REACH 3
#define COMP_CLUSTER 4
#define COMP_AASOPTIMIZE 5
#define COMP_AASINFO 6
int main (int argc, char **argv)
{
int i, comp = 0;
char outputpath[MAX_PATH] = "";
char filename[MAX_PATH] = "unknown";
quakefile_t *qfiles, *qf;
double start_time;
myargc = argc;
myargv = argv;
start_time = I_FloatTime();
Log_Open("bspc.log"); //open a log file
Log_Print("BSPC version "BSPC_VERSION", %s %s\n", __DATE__, __TIME__);
DefaultCfg();
for (i = 1; i < argc; i++)
{
if (!stricmp(argv[i],"-threads"))
{
if (i + 1 >= argc) {i = 0; break;}
numthreads = atoi(argv[++i]);
Log_Print("threads = %d\n", numthreads);
} //end if
else if (!stricmp(argv[i], "-noverbose"))
{
Log_Print("verbose = false\n");
verbose = false;
} //end else if
else if (!stricmp(argv[i], "-nocsg"))
{
Log_Print("nocsg = true\n");
nocsg = true;
} //end else if
else if (!stricmp(argv[i], "-optimize"))
{
Log_Print("optimize = true\n");
optimize = true;
} //end else if
/*
else if (!stricmp(argv[i],"-glview"))
{
glview = true;
} //end else if
else if (!stricmp(argv[i], "-draw"))
{
Log_Print("drawflag = true\n");
drawflag = true;
} //end else if
else if (!stricmp(argv[i], "-noweld"))
{
Log_Print("noweld = true\n");
noweld = true;
} //end else if
else if (!stricmp(argv[i], "-noshare"))
{
Log_Print("noshare = true\n");
noshare = true;
} //end else if
else if (!stricmp(argv[i], "-notjunc"))
{
Log_Print("notjunc = true\n");
notjunc = true;
} //end else if
else if (!stricmp(argv[i], "-nowater"))
{
Log_Print("nowater = true\n");
nowater = true;
} //end else if
else if (!stricmp(argv[i], "-noprune"))
{
Log_Print("noprune = true\n");
noprune = true;
} //end else if
else if (!stricmp(argv[i], "-nomerge"))
{
Log_Print("nomerge = true\n");
nomerge = true;
} //end else if
else if (!stricmp(argv[i], "-nosubdiv"))
{
Log_Print("nosubdiv = true\n");
nosubdiv = true;
} //end else if
else if (!stricmp(argv[i], "-nodetail"))
{
Log_Print("nodetail = true\n");
nodetail = true;
} //end else if
else if (!stricmp(argv[i], "-fulldetail"))
{
Log_Print("fulldetail = true\n");
fulldetail = true;
} //end else if
else if (!stricmp(argv[i], "-onlyents"))
{
Log_Print("onlyents = true\n");
onlyents = true;
} //end else if
else if (!stricmp(argv[i], "-micro"))
{
if (i + 1 >= argc) {i = 0; break;}
microvolume = atof(argv[++i]);
Log_Print("microvolume = %f\n", microvolume);
} //end else if
else if (!stricmp(argv[i], "-leaktest"))
{
Log_Print("leaktest = true\n");
leaktest = true;
} //end else if
else if (!stricmp(argv[i], "-verboseentities"))
{
Log_Print("verboseentities = true\n");
verboseentities = true;
} //end else if
else if (!stricmp(argv[i], "-chop"))
{
if (i + 1 >= argc) {i = 0; break;}
subdivide_size = atof(argv[++i]);
Log_Print("subdivide_size = %f\n", subdivide_size);
} //end else if
else if (!stricmp (argv[i], "-tmpout"))
{
strcpy (outbase, "/tmp");
Log_Print("temp output\n");
} //end else if
*/
#ifdef ME
else if (!stricmp(argv[i], "-freetree"))
{
freetree = true;
Log_Print("freetree = true\n");
} //end else if
else if (!stricmp(argv[i], "-grapplereach"))
{
calcgrapplereach = true;
Log_Print("grapplereach = true\n");
} //end else if
else if (!stricmp(argv[i], "-nobrushmerge"))
{
nobrushmerge = true;
Log_Print("nobrushmerge = true\n");
} //end else if
else if (!stricmp(argv[i], "-noliquids"))
{
noliquids = true;
Log_Print("noliquids = true\n");
} //end else if
else if (!stricmp(argv[i], "-forcesidesvisible"))
{
forcesidesvisible = true;
Log_Print("forcesidesvisible = true\n");
} //end else if
else if (!stricmp(argv[i], "-output"))
{
if (i + 1 >= argc) {i = 0; break;}
if (access(argv[i+1], 0x04)) Warning("the folder %s does not exist", argv[i+1]);
strcpy(outputpath, argv[++i]);
} //end else if
else if (!stricmp(argv[i], "-breadthfirst"))
{
use_nodequeue = true;
Log_Print("breadthfirst = true\n");
} //end else if
else if (!stricmp(argv[i], "-capsule"))
{
capsule_collision = true;
Log_Print("capsule_collision = true\n");
} //end else if
else if (!stricmp(argv[i], "-cfg"))
{
if (i + 1 >= argc) {i = 0; break;}
if (!LoadCfgFile(argv[++i]))
exit(0);
} //end else if
else if (!stricmp(argv[i], "-bsp2map"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_BSP2MAP;
qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
} //end else if
else if (!stricmp(argv[i], "-bsp2aas"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_BSP2AAS;
qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
} //end else if
else if (!stricmp(argv[i], "-aasall"))
{
if (i + 1 >= argc) {i = 0; break;}
CreateAASFilesForAllBSPFiles(argv[++i]);
} //end else if
else if (!stricmp(argv[i], "-reach"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_REACH;
qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
} //end else if
else if (!stricmp(argv[i], "-cluster"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_CLUSTER;
qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
} //end else if
else if (!stricmp(argv[i], "-aasinfo"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_AASINFO;
qfiles = GetArgumentFiles(argc, argv, &i, "aas");
} //end else if
else if (!stricmp(argv[i], "-aasopt"))
{
if (i + 1 >= argc) {i = 0; break;}
comp = COMP_AASOPTIMIZE;
qfiles = GetArgumentFiles(argc, argv, &i, "aas");
} //end else if
#endif //ME
else
{
Log_Print("unknown parameter %s\n", argv[i]);
break;
} //end else
} //end for
//if there are parameters and there's no mismatch in one of the parameters
if (argc > 1 && i == argc)
{
switch(comp)
{
case COMP_BSP2MAP:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
//copy the output path
strcpy(filename, outputpath);
//append the bsp file base
AppendPathSeperator(filename, MAX_PATH);
ExtractFileBase(qf->origname, &filename[strlen(filename)]);
//append .map
strcat(filename, ".map");
//
Log_Print("bsp2map: %s to %s\n", qf->origname, filename);
if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
//
LoadMapFromBSP(qf);
//write the map file
WriteMapFile(filename);
} //end for
break;
} //end case
case COMP_BSP2AAS:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
AASOuputFile(qf, outputpath, filename);
//
Log_Print("bsp2aas: %s to %s\n", qf->origname, filename);
if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
//set before map loading
create_aas = 1;
LoadMapFromBSP(qf);
//create the AAS file
AAS_Create(filename);
//if it's a Quake3 map calculate the reachabilities and clusters
if (loadedmaptype == MAPTYPE_QUAKE3) AAS_CalcReachAndClusters(qf);
//
if (optimize) AAS_Optimize();
//
//write out the stored AAS file
if (!AAS_WriteAASFile(filename))
{
Error("error writing %s\n", filename);
} //end if
//deallocate memory
AAS_FreeMaxAAS();
} //end for
break;
} //end case
case COMP_REACH:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
AASOuputFile(qf, outputpath, filename);
//
Log_Print("reach: %s to %s\n", qf->origname, filename);
if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
//if the AAS file exists in the output directory
if (!access(filename, 0x04))
{
if (!AAS_LoadAASFile(filename, 0, 0))
{
Error("error loading aas file %s\n", filename);
} //end if
//assume it's a Quake3 BSP file
loadedmaptype = MAPTYPE_QUAKE3;
} //end if
else
{
Warning("AAS file %s not found in output folder\n", filename);
Log_Print("creating %s...\n", filename);
//set before map loading
create_aas = 1;
LoadMapFromBSP(qf);
//create the AAS file
AAS_Create(filename);
} //end else
//if it's a Quake3 map calculate the reachabilities and clusters
if (loadedmaptype == MAPTYPE_QUAKE3)
{
AAS_CalcReachAndClusters(qf);
} //end if
//
if (optimize) AAS_Optimize();
//write out the stored AAS file
if (!AAS_WriteAASFile(filename))
{
Error("error writing %s\n", filename);
} //end if
//deallocate memory
AAS_FreeMaxAAS();
} //end for
break;
} //end case
case COMP_CLUSTER:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
AASOuputFile(qf, outputpath, filename);
//
Log_Print("cluster: %s to %s\n", qf->origname, filename);
if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
//if the AAS file exists in the output directory
if (!access(filename, 0x04))
{
if (!AAS_LoadAASFile(filename, 0, 0))
{
Error("error loading aas file %s\n", filename);
} //end if
//assume it's a Quake3 BSP file
loadedmaptype = MAPTYPE_QUAKE3;
//if it's a Quake3 map calculate the clusters
if (loadedmaptype == MAPTYPE_QUAKE3)
{
aasworld.numclusters = 0;
AAS_InitBotImport();
AAS_InitClustering();
} //end if
} //end if
else
{
Warning("AAS file %s not found in output folder\n", filename);
Log_Print("creating %s...\n", filename);
//set before map loading
create_aas = 1;
LoadMapFromBSP(qf);
//create the AAS file
AAS_Create(filename);
//if it's a Quake3 map calculate the reachabilities and clusters
if (loadedmaptype == MAPTYPE_QUAKE3) AAS_CalcReachAndClusters(qf);
} //end else
//
if (optimize) AAS_Optimize();
//write out the stored AAS file
if (!AAS_WriteAASFile(filename))
{
Error("error writing %s\n", filename);
} //end if
//deallocate memory
AAS_FreeMaxAAS();
} //end for
break;
} //end case
case COMP_AASOPTIMIZE:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
AASOuputFile(qf, outputpath, filename);
//
Log_Print("optimizing: %s to %s\n", qf->origname, filename);
if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname);
//
AAS_InitBotImport();
//
if (!AAS_LoadAASFile(qf->filename, qf->offset, qf->length))
{
Error("error loading aas file %s\n", qf->filename);
} //end if
AAS_Optimize();
//write out the stored AAS file
if (!AAS_WriteAASFile(filename))
{
Error("error writing %s\n", filename);
} //end if
//deallocate memory
AAS_FreeMaxAAS();
} //end for
break;
} //end case
case COMP_AASINFO:
{
if (!qfiles) Log_Print("no files found\n");
for (qf = qfiles; qf; qf = qf->next)
{
AASOuputFile(qf, outputpath, filename);
//
Log_Print("aas info for: %s\n", filename);
if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname);
//
AAS_InitBotImport();
//
if (!AAS_LoadAASFile(qf->filename, qf->offset, qf->length))
{
Error("error loading aas file %s\n", qf->filename);
} //end if
AAS_ShowTotals();
} //end for
} //end case
default:
{
Log_Print("don't know what to do\n");
break;
} //end default
} //end switch
} //end if
else
{
Log_Print("Usage: bspc [-<switch> [-<switch> ...]]\n"
#if defined(WIN32) || defined(_WIN32)
"Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n"
"Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n"
#else
"Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n"
"Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n"
#endif
"\n"
"Switches:\n"
//" bsp2map <[pakfilter/]filter.bsp> = convert BSP to MAP\n"
//" aasall <quake3folder> = create AAS files for all BSPs\n"
" bsp2aas <[pakfilter/]filter.bsp> = convert BSP to AAS\n"
" reach <filter.bsp> = compute reachability & clusters\n"
" cluster <filter.aas> = compute clusters\n"
" aasopt <filter.aas> = optimize aas file\n"
" aasinfo <filter.aas> = show AAS file info\n"
" output <output path> = set output path\n"
" threads <X> = set number of threads to X\n"
" cfg <filename> = use this cfg file\n"
" optimize = enable optimization\n"
" noverbose = disable verbose output\n"
" breadthfirst = breadth first bsp building\n"
" nobrushmerge = don't merge brushes\n"
" noliquids = don't write liquids to map\n"
" freetree = free the bsp tree\n"
" nocsg = disables brush chopping\n"
" forcesidesvisible = force all sides to be visible\n"
" grapplereach = calculate grapple reachabilities\n"
/* " glview = output a GL view\n"
" draw = enables drawing\n"
" noweld = disables weld\n"
" noshare = disables sharing\n"
" notjunc = disables juncs\n"
" nowater = disables water brushes\n"
" noprune = disables node prunes\n"
" nomerge = disables face merging\n"
" nosubdiv = disables subdeviding\n"
" nodetail = disables detail brushes\n"
" fulldetail = enables full detail\n"
" onlyents = only compile entities with bsp\n"
" micro <volume>\n"
" = sets the micro volume to the given float\n"
" leaktest = perform a leak test\n"
" verboseentities\n"
" = enable entity verbose mode\n"
" chop <subdivide_size>\n"
" = sets the subdivide size to the given float\n"*/
"\n");
} //end else
Log_Print("BSPC run time is %5.0f seconds\n", I_FloatTime() - start_time);
Log_Close(); //close the log file
return 0;
} //end of the function main

View File

@ -1,28 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bspc", "bspc.vcproj", "{4E4EBC16-F345-4667-84E1-86633BAFDAE6}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SourceCodeControl) = preSolution
SccNumberOfProjects = 1
SccProjectUniqueName0 = bspc.vcproj
SccProjectName0 = \u0022$/source/code/bspc\u0022,\u0020IGAAAAAA
SccLocalPath0 = .
SccProvider0 = MSSCCI:Perforce\u0020SCM
EndGlobalSection
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{4E4EBC16-F345-4667-84E1-86633BAFDAE6}.Debug.ActiveCfg = Debug|Win32
{4E4EBC16-F345-4667-84E1-86633BAFDAE6}.Debug.Build.0 = Debug|Win32
{4E4EBC16-F345-4667-84E1-86633BAFDAE6}.Release.ActiveCfg = Release|Win32
{4E4EBC16-F345-4667-84E1-86633BAFDAE6}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//===========================================================================
// BSPC configuration file
// Quake3
//===========================================================================
#define PRESENCE_NONE 1
#define PRESENCE_NORMAL 2
#define PRESENCE_CROUCH 4
bbox //30x30x56
{
presencetype PRESENCE_NORMAL
flags 0x0000
mins {-15, -15, -24}
maxs {15, 15, 32}
} //end bbox
bbox //30x30x40
{
presencetype PRESENCE_CROUCH
flags 0x0001
mins {-15, -15, -24}
maxs {15, 15, 16}
} //end bbox
settings
{
phys_gravitydirection {0, 0, -1}
phys_friction 6
phys_stopspeed 100
phys_gravity 800
phys_waterfriction 1
phys_watergravity 400
phys_maxvelocity 320
phys_maxwalkvelocity 320
phys_maxcrouchvelocity 100
phys_maxswimvelocity 150
phys_maxacceleration 2200
phys_airaccelerate 0
phys_maxstep 18
phys_maxsteepness 0.7
phys_maxwaterjump 19
phys_maxbarrier 33
phys_jumpvel 270
phys_falldelta5 40
phys_falldelta10 60
rs_waterjump 400
rs_teleport 50
rs_barrierjump 100
rs_startcrouch 300
rs_startgrapple 500
rs_startwalkoffledge 70
rs_startjump 300
rs_rocketjump 500
rs_bfgjump 500
rs_jumppad 250
rs_aircontrolledjumppad 300
rs_funcbob 300
rs_startelevator 50
rs_falldamage5 300
rs_falldamage10 500
rs_maxjumpfallheight 450
} //end settings

File diff suppressed because it is too large Load Diff

View File

@ -1,978 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// faces.c
#include "qbsp.h"
#include "l_mem.h"
/*
some faces will be removed before saving, but still form nodes:
the insides of sky volumes
meeting planes of different water current volumes
*/
// undefine for dumb linear searches
#define USE_HASHING
#define INTEGRAL_EPSILON 0.01
#define POINT_EPSILON 0.5
#define OFF_EPSILON 0.5
int c_merge;
int c_subdivide;
int c_totalverts;
int c_uniqueverts;
int c_degenerate;
int c_tjunctions;
int c_faceoverflows;
int c_facecollapse;
int c_badstartverts;
#define MAX_SUPERVERTS 512
int superverts[MAX_SUPERVERTS];
int numsuperverts;
face_t *edgefaces[MAX_MAP_EDGES][2];
int firstmodeledge = 1;
int firstmodelface;
int c_tryedges;
vec3_t edge_dir;
vec3_t edge_start;
vec_t edge_len;
int num_edge_verts;
int edge_verts[MAX_MAP_VERTS];
face_t *NewFaceFromFace (face_t *f);
//===========================================================================
typedef struct hashvert_s
{
struct hashvert_s *next;
int num;
} hashvert_t;
#define HASH_SIZE 64
int vertexchain[MAX_MAP_VERTS]; // the next vertex in a hash chain
int hashverts[HASH_SIZE*HASH_SIZE]; // a vertex number, or 0 for no verts
face_t *edgefaces[MAX_MAP_EDGES][2];
//============================================================================
unsigned HashVec (vec3_t vec)
{
int x, y;
x = (4096 + (int)(vec[0]+0.5)) >> 7;
y = (4096 + (int)(vec[1]+0.5)) >> 7;
if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
Error ("HashVec: point outside valid range");
return y*HASH_SIZE + x;
}
#ifdef USE_HASHING
/*
=============
GetVertex
Uses hashing
=============
*/
int GetVertexnum (vec3_t in)
{
int h;
int i;
float *p;
vec3_t vert;
int vnum;
c_totalverts++;
for (i=0 ; i<3 ; i++)
{
if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
vert[i] = Q_rint(in[i]);
else
vert[i] = in[i];
}
h = HashVec (vert);
for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
{
p = dvertexes[vnum].point;
if ( fabs(p[0]-vert[0])<POINT_EPSILON
&& fabs(p[1]-vert[1])<POINT_EPSILON
&& fabs(p[2]-vert[2])<POINT_EPSILON )
return vnum;
}
// 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];
vertexchain[numvertexes] = hashverts[h];
hashverts[h] = numvertexes;
c_uniqueverts++;
numvertexes++;
return numvertexes-1;
}
#else
/*
==================
GetVertexnum
Dumb linear search
==================
*/
int GetVertexnum (vec3_t v)
{
int i, j;
dvertex_t *dv;
vec_t d;
c_totalverts++;
// make really close values exactly integral
for (i=0 ; i<3 ; i++)
{
if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
v[i] = (int)(v[i]+0.5);
if (v[i] < -4096 || v[i] > 4096)
Error ("GetVertexnum: outside +/- 4096");
}
// search for an existing vertex match
for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
{
for (j=0 ; j<3 ; j++)
{
d = v[j] - dv->point[j];
if ( d > POINT_EPSILON || d < -POINT_EPSILON)
break;
}
if (j == 3)
return i; // a match
}
// new point
if (numvertexes == MAX_MAP_VERTS)
Error ("MAX_MAP_VERTS");
VectorCopy (v, dv->point);
numvertexes++;
c_uniqueverts++;
return numvertexes-1;
}
#endif
/*
==================
FaceFromSuperverts
The faces vertexes have been added to the superverts[] array,
and there may be more there than can be held in a face (MAXEDGES).
If less, the faces vertexnums[] will be filled in, otherwise
face will reference a tree of split[] faces until all of the
vertexnums can be added.
superverts[base] will become face->vertexnums[0], and the others
will be circularly filled in.
==================
*/
void FaceFromSuperverts (node_t *node, face_t *f, int base)
{
face_t *newf;
int remaining;
int i;
remaining = numsuperverts;
while (remaining > MAXEDGES)
{ // must split into two faces, because of vertex overload
c_faceoverflows++;
newf = f->split[0] = NewFaceFromFace (f);
newf = f->split[0];
newf->next = node->faces;
node->faces = newf;
newf->numpoints = MAXEDGES;
for (i=0 ; i<MAXEDGES ; i++)
newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
f->split[1] = NewFaceFromFace (f);
f = f->split[1];
f->next = node->faces;
node->faces = f;
remaining -= (MAXEDGES-2);
base = (base+MAXEDGES-1)%numsuperverts;
}
// copy the vertexes back to the face
f->numpoints = remaining;
for (i=0 ; i<remaining ; i++)
f->vertexnums[i] = superverts[(i+base)%numsuperverts];
}
/*
==================
EmitFaceVertexes
==================
*/
void EmitFaceVertexes (node_t *node, face_t *f)
{
winding_t *w;
int i;
if (f->merged || f->split[0] || f->split[1])
return;
w = f->w;
for (i=0 ; i<w->numpoints ; i++)
{
if (noweld)
{ // make every point unique
if (numvertexes == MAX_MAP_VERTS)
Error ("MAX_MAP_VERTS");
superverts[i] = numvertexes;
VectorCopy (w->p[i], dvertexes[numvertexes].point);
numvertexes++;
c_uniqueverts++;
c_totalverts++;
}
else
superverts[i] = GetVertexnum (w->p[i]);
}
numsuperverts = w->numpoints;
// this may fragment the face if > MAXEDGES
FaceFromSuperverts (node, f, 0);
}
/*
==================
EmitVertexes_r
==================
*/
void EmitVertexes_r (node_t *node)
{
int i;
face_t *f;
if (node->planenum == PLANENUM_LEAF)
return;
for (f=node->faces ; f ; f=f->next)
{
EmitFaceVertexes (node, f);
}
for (i=0 ; i<2 ; i++)
EmitVertexes_r (node->children[i]);
}
#ifdef USE_HASHING
/*
==========
FindEdgeVerts
Uses the hash tables to cut down to a small number
==========
*/
void FindEdgeVerts (vec3_t v1, vec3_t v2)
{
int x1, x2, y1, y2, t;
int x, y;
int vnum;
#if 0
{
int i;
num_edge_verts = numvertexes-1;
for (i=0 ; i<numvertexes-1 ; i++)
edge_verts[i] = i+1;
}
#endif
x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
if (x1 > x2)
{
t = x1;
x1 = x2;
x2 = t;
}
if (y1 > y2)
{
t = y1;
y1 = y2;
y2 = t;
}
#if 0
x1--;
x2++;
y1--;
y2++;
if (x1 < 0)
x1 = 0;
if (x2 >= HASH_SIZE)
x2 = HASH_SIZE;
if (y1 < 0)
y1 = 0;
if (y2 >= HASH_SIZE)
y2 = HASH_SIZE;
#endif
num_edge_verts = 0;
for (x=x1 ; x <= x2 ; x++)
{
for (y=y1 ; y <= y2 ; y++)
{
for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
{
edge_verts[num_edge_verts++] = vnum;
}
}
}
}
#else
/*
==========
FindEdgeVerts
Forced a dumb check of everything
==========
*/
void FindEdgeVerts (vec3_t v1, vec3_t v2)
{
int i;
num_edge_verts = numvertexes-1;
for (i=0 ; i<num_edge_verts ; i++)
edge_verts[i] = i+1;
}
#endif
/*
==========
TestEdge
Can be recursively reentered
==========
*/
void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
{
int j, k;
vec_t dist;
vec3_t delta;
vec3_t exact;
vec3_t off;
vec_t error;
vec3_t p;
if (p1 == p2)
{
c_degenerate++;
return; // degenerate edge
}
for (k=startvert ; k<num_edge_verts ; k++)
{
j = edge_verts[k];
if (j==p1 || j == p2)
continue;
VectorCopy (dvertexes[j].point, p);
VectorSubtract (p, edge_start, delta);
dist = DotProduct (delta, edge_dir);
if (dist <=start || dist >= end)
continue; // off an end
VectorMA (edge_start, dist, edge_dir, exact);
VectorSubtract (p, exact, off);
error = VectorLength (off);
if (fabs(error) > OFF_EPSILON)
continue; // not on the edge
// break the edge
c_tjunctions++;
TestEdge (start, dist, p1, j, k+1);
TestEdge (dist, end, j, p2, k+1);
return;
}
// the edge p1 to p2 is now free of tjunctions
if (numsuperverts >= MAX_SUPERVERTS)
Error ("MAX_SUPERVERTS");
superverts[numsuperverts] = p1;
numsuperverts++;
}
/*
==================
FixFaceEdges
==================
*/
void FixFaceEdges (node_t *node, face_t *f)
{
int p1, p2;
int i;
vec3_t e2;
vec_t len;
int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
int base;
if (f->merged || f->split[0] || f->split[1])
return;
numsuperverts = 0;
for (i=0 ; i<f->numpoints ; i++)
{
p1 = f->vertexnums[i];
p2 = f->vertexnums[(i+1)%f->numpoints];
VectorCopy (dvertexes[p1].point, edge_start);
VectorCopy (dvertexes[p2].point, e2);
FindEdgeVerts (edge_start, e2);
VectorSubtract (e2, edge_start, edge_dir);
len = VectorNormalize(edge_dir);
start[i] = numsuperverts;
TestEdge (0, len, p1, p2, 0);
count[i] = numsuperverts - start[i];
}
if (numsuperverts < 3)
{ // entire face collapsed
f->numpoints = 0;
c_facecollapse++;
return;
}
// we want to pick a vertex that doesn't have tjunctions
// on either side, which can cause artifacts on trifans,
// especially underwater
for (i=0 ; i<f->numpoints ; i++)
{
if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
break;
}
if (i == f->numpoints)
{
f->badstartvert = true;
c_badstartverts++;
base = 0;
}
else
{ // rotate the vertex order
base = start[i];
}
// this may fragment the face if > MAXEDGES
FaceFromSuperverts (node, f, base);
}
/*
==================
FixEdges_r
==================
*/
void FixEdges_r (node_t *node)
{
int i;
face_t *f;
if (node->planenum == PLANENUM_LEAF)
return;
for (f=node->faces ; f ; f=f->next)
FixFaceEdges (node, f);
for (i=0 ; i<2 ; i++)
FixEdges_r (node->children[i]);
}
/*
===========
FixTjuncs
===========
*/
void FixTjuncs (node_t *headnode)
{
// snap and merge all vertexes
qprintf ("---- snap verts ----\n");
memset (hashverts, 0, sizeof(hashverts));
c_totalverts = 0;
c_uniqueverts = 0;
c_faceoverflows = 0;
EmitVertexes_r (headnode);
qprintf ("%i unique from %i\n", c_uniqueverts, c_totalverts);
// break edges on tjunctions
qprintf ("---- tjunc ----\n");
c_tryedges = 0;
c_degenerate = 0;
c_facecollapse = 0;
c_tjunctions = 0;
if (!notjunc)
FixEdges_r (headnode);
qprintf ("%5i edges degenerated\n", c_degenerate);
qprintf ("%5i faces degenerated\n", c_facecollapse);
qprintf ("%5i edges added by tjunctions\n", c_tjunctions);
qprintf ("%5i faces added by tjunctions\n", c_faceoverflows);
qprintf ("%5i bad start verts\n", c_badstartverts);
}
//========================================================
int c_faces;
face_t *AllocFace (void)
{
face_t *f;
f = GetMemory(sizeof(*f));
memset (f, 0, sizeof(*f));
c_faces++;
return f;
}
face_t *NewFaceFromFace (face_t *f)
{
face_t *newf;
newf = AllocFace ();
*newf = *f;
newf->merged = NULL;
newf->split[0] = newf->split[1] = NULL;
newf->w = NULL;
return newf;
}
void FreeFace (face_t *f)
{
if (f->w)
FreeWinding (f->w);
FreeMemory(f);
c_faces--;
}
//========================================================
/*
==================
GetEdge
Called by writebsp.
Don't allow four way edges
==================
*/
int GetEdge2 (int v1, int v2, face_t *f)
{
dedge_t *edge;
int i;
c_tryedges++;
if (!noshare)
{
for (i=firstmodeledge ; i < numedges ; i++)
{
edge = &dedges[i];
if (v1 == edge->v[1] && v2 == edge->v[0]
&& edgefaces[i][0]->contents == f->contents)
{
if (edgefaces[i][1])
// printf ("WARNING: multiple backward edge\n");
continue;
edgefaces[i][1] = f;
return -i;
}
#if 0
if (v1 == edge->v[0] && v2 == edge->v[1])
{
printf ("WARNING: multiple forward edge\n");
return i;
}
#endif
}
}
// 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[numedges-1][0] = f;
return numedges-1;
}
/*
===========================================================================
FACE MERGING
===========================================================================
*/
/*
=============
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, vec3_t planenormal)
{
face_t *newf;
winding_t *nw;
if (!f1->w || !f2->w)
return NULL;
if (f1->texinfo != f2->texinfo)
return NULL;
if (f1->planenum != f2->planenum) // on front and back sides
return NULL;
if (f1->contents != f2->contents)
return NULL;
nw = TryMergeWinding (f1->w, f2->w, planenormal);
if (!nw)
return NULL;
c_merge++;
newf = NewFaceFromFace (f1);
newf->w = nw;
f1->merged = newf;
f2->merged = newf;
return newf;
}
/*
===============
MergeNodeFaces
===============
*/
void MergeNodeFaces (node_t *node)
{
face_t *f1, *f2, *end;
face_t *merged;
plane_t *plane;
plane = &mapplanes[node->planenum];
merged = NULL;
for (f1 = node->faces ; f1 ; f1 = f1->next)
{
if (f1->merged || f1->split[0] || f1->split[1])
continue;
for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
{
if (f2->merged || f2->split[0] || f2->split[1])
continue;
//IDBUG: always passes the face's node's normal to TryMerge()
//regardless of which side the face is on. Approximately 50% of
//the time the face will be on the other side of node, and thus
//the result of the convex/concave test in TryMergeWinding(),
//which depends on the normal, is flipped. This causes faces
//that shouldn't be merged to be merged and faces that
//should be merged to not be merged.
//the following added line fixes this bug
//thanks to: Alexander Malmberg <alexander@malmberg.org>
plane = &mapplanes[f1->planenum];
//
merged = TryMerge (f1, f2, plane->normal);
if (!merged)
continue;
// add merged to the end of the node face list
// so it will be checked against all the faces again
for (end = node->faces ; end->next ; end = end->next)
;
merged->next = NULL;
end->next = merged;
break;
}
}
}
//=====================================================================
/*
===============
SubdivideFace
Chop up faces that are larger than we want in the surface cache
===============
*/
void SubdivideFace (node_t *node, face_t *f)
{
float mins, maxs;
vec_t v;
int axis, i;
texinfo_t *tex;
vec3_t temp;
vec_t dist;
winding_t *w, *frontw, *backw;
if (f->merged)
return;
// special (non-surface cached) faces don't need subdivision
tex = &texinfo[f->texinfo];
if ( tex->flags & (SURF_WARP|SURF_SKY) )
{
return;
}
for (axis = 0 ; axis < 2 ; axis++)
{
while (1)
{
mins = 999999;
maxs = -999999;
VectorCopy (tex->vecs[axis], temp);
w = f->w;
for (i=0 ; i<w->numpoints ; i++)
{
v = DotProduct (w->p[i], temp);
if (v < mins)
mins = v;
if (v > maxs)
maxs = v;
}
#if 0
if (maxs - mins <= 0)
Error ("zero extents");
#endif
if (axis == 2)
{ // allow double high walls
if (maxs - mins <= subdivide_size/* *2 */)
break;
}
else if (maxs - mins <= subdivide_size)
break;
// split it
c_subdivide++;
v = VectorNormalize (temp);
dist = (mins + subdivide_size - 16)/v;
ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
if (!frontw || !backw)
Error ("SubdivideFace: didn't split the polygon");
f->split[0] = NewFaceFromFace (f);
f->split[0]->w = frontw;
f->split[0]->next = node->faces;
node->faces = f->split[0];
f->split[1] = NewFaceFromFace (f);
f->split[1]->w = backw;
f->split[1]->next = node->faces;
node->faces = f->split[1];
SubdivideFace (node, f->split[0]);
SubdivideFace (node, f->split[1]);
return;
}
}
}
void SubdivideNodeFaces (node_t *node)
{
face_t *f;
for (f = node->faces ; f ; f=f->next)
{
SubdivideFace (node, f);
}
}
//===========================================================================
int c_nodefaces;
/*
============
FaceFromPortal
============
*/
face_t *FaceFromPortal (portal_t *p, int pside)
{
face_t *f;
side_t *side;
side = p->side;
if (!side)
return NULL; // portal does not bridge different visible contents
f = AllocFace ();
f->texinfo = side->texinfo;
f->planenum = (side->planenum & ~1) | pside;
f->portal = p;
if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
&& VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
return NULL; // don't show insides of windows
if (pside)
{
f->w = ReverseWinding(p->winding);
f->contents = p->nodes[1]->contents;
}
else
{
f->w = CopyWinding(p->winding);
f->contents = p->nodes[0]->contents;
}
return f;
}
/*
===============
MakeFaces_r
If a portal will make a visible face,
mark the side that originally created it
solid / empty : solid
solid / water : solid
water / empty : water
water / water : none
===============
*/
void MakeFaces_r (node_t *node)
{
portal_t *p;
int s;
// recurse down to leafs
if (node->planenum != PLANENUM_LEAF)
{
MakeFaces_r (node->children[0]);
MakeFaces_r (node->children[1]);
// merge together all visible faces on the node
if (!nomerge)
MergeNodeFaces (node);
if (!nosubdiv)
SubdivideNodeFaces (node);
return;
}
// solid leafs never have visible faces
if (node->contents & CONTENTS_SOLID)
return;
// see which portals are valid
for (p=node->portals ; p ; p = p->next[s])
{
s = (p->nodes[1] == node);
p->face[s] = FaceFromPortal (p, s);
if (p->face[s])
{
c_nodefaces++;
p->face[s]->next = p->onnode->faces;
p->onnode->faces = p->face[s];
}
}
}
/*
============
MakeFaces
============
*/
void MakeFaces (node_t *node)
{
qprintf ("--- MakeFaces ---\n");
c_merge = 0;
c_subdivide = 0;
c_nodefaces = 0;
MakeFaces_r (node);
qprintf ("%5i makefaces\n", c_nodefaces);
qprintf ("%5i merged\n", c_merge);
qprintf ("%5i subdivided\n", c_subdivide);
}

View File

@ -1,232 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include "qbsp.h"
// can't use the glvertex3fv functions, because the vec3_t fields
// could be either floats or doubles, depending on DOUBLEVEC_T
qboolean drawflag;
vec3_t draw_mins, draw_maxs;
#define WIN_SIZE 512
void InitWindow (void)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
auxInitWindow ("qcsg");
}
void Draw_ClearWindow (void)
{
static int init;
int w, h, g;
vec_t 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);
glColor3f (0,0,0);
// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glDisable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#if 0
glColor4f (1,0,0,0.5);
glBegin (GL_POLYGON);
glVertex3f (0, 500, 0);
glVertex3f (0, 900, 0);
glVertex3f (0, 900, 100);
glVertex3f (0, 500, 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 DrawWinding (winding_t *w)
{
int i;
if (!drawflag)
return;
glColor4f (0,0,0,0.5);
glBegin (GL_LINE_LOOP);
for (i=0 ; i<w->numpoints ; i++)
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
glEnd ();
glColor4f (0,1,0,0.3);
glBegin (GL_POLYGON);
for (i=0 ; i<w->numpoints ; i++)
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
glEnd ();
glFlush ();
}
void DrawAuxWinding (winding_t *w)
{
int i;
if (!drawflag)
return;
glColor4f (0,0,0,0.5);
glBegin (GL_LINE_LOOP);
for (i=0 ; i<w->numpoints ; i++)
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
glEnd ();
glColor4f (1,0,0,0.3);
glBegin (GL_POLYGON);
for (i=0 ; i<w->numpoints ; i++)
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
glEnd ();
glFlush ();
}
//============================================================
#define GLSERV_PORT 25001
qboolean wins_init;
int draw_socket;
void GLS_BeginScene (void)
{
WSADATA winsockdata;
WORD wVersionRequested;
struct sockaddr_in address;
int r;
if (!wins_init)
{
wins_init = true;
wVersionRequested = MAKEWORD(1, 1);
r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
if (r)
Error ("Winsock initialization failed.");
}
// connect a socket to the server
draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (draw_socket == -1)
Error ("draw_socket failed");
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
address.sin_port = GLSERV_PORT;
r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address));
if (r == -1)
{
closesocket (draw_socket);
draw_socket = 0;
}
}
void GLS_Winding (winding_t *w, int code)
{
byte buf[1024];
int i, j;
if (!draw_socket)
return;
((int *)buf)[0] = w->numpoints;
((int *)buf)[1] = code;
for (i=0 ; i<w->numpoints ; i++)
for (j=0 ; j<3 ; j++)
((float *)buf)[2+i*3+j] = w->p[i][j];
send (draw_socket, buf, w->numpoints*12+8, 0);
}
void GLS_EndScene (void)
{
closesocket (draw_socket);
draw_socket = 0;
}

View File

@ -1,149 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
int c_glfaces;
int PortalVisibleSides (portal_t *p)
{
int fcon, bcon;
if (!p->onnode)
return 0; // outside
fcon = p->nodes[0]->contents;
bcon = p->nodes[1]->contents;
// same contents never create a face
if (fcon == bcon)
return 0;
// FIXME: is this correct now?
if (!fcon)
return 1;
if (!bcon)
return 2;
return 0;
}
void OutputWinding (winding_t *w, FILE *glview)
{
static int level = 128;
vec_t light;
int i;
fprintf (glview, "%i\n", w->numpoints);
level+=28;
light = (level&255)/255.0;
for (i=0 ; i<w->numpoints ; i++)
{
fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
w->p[i][0],
w->p[i][1],
w->p[i][2],
light,
light,
light);
}
fprintf (glview, "\n");
}
/*
=============
OutputPortal
=============
*/
void OutputPortal (portal_t *p, FILE *glview)
{
winding_t *w;
int sides;
sides = PortalVisibleSides (p);
if (!sides)
return;
c_glfaces++;
w = p->winding;
if (sides == 2) // back side
w = ReverseWinding (w);
OutputWinding (w, glview);
if (sides == 2)
FreeWinding(w);
}
/*
=============
WriteGLView_r
=============
*/
void WriteGLView_r (node_t *node, FILE *glview)
{
portal_t *p, *nextp;
if (node->planenum != PLANENUM_LEAF)
{
WriteGLView_r (node->children[0], glview);
WriteGLView_r (node->children[1], glview);
return;
}
// write all the portals
for (p=node->portals ; p ; p=nextp)
{
if (p->nodes[0] == node)
{
OutputPortal (p, glview);
nextp = p->next[0];
}
else
nextp = p->next[1];
}
}
/*
=============
WriteGLView
=============
*/
void WriteGLView (tree_t *tree, char *source)
{
char name[1024];
FILE *glview;
c_glfaces = 0;
sprintf (name, "%s%s.gl",outbase, source);
printf ("Writing %s\n", name);
glview = fopen (name, "w");
if (!glview)
Error ("Couldn't open %s", name);
WriteGLView_r (tree->headnode, glview);
fclose (glview);
printf ("%5i c_glfaces\n", c_glfaces);
}

View File

@ -1,180 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "l_cmd.h"
#include "l_math.h"
#include "l_mem.h"
#include "l_log.h"
#include "../botlib/l_script.h"
#include "l_bsp_ent.h"
#define MAX_KEY 32
#define MAX_VALUE 1024
int num_entities;
entity_t entities[MAX_MAP_ENTITIES];
void StripTrailing(char *e)
{
char *s;
s = e + strlen(e)-1;
while (s >= e && *s <= 32)
{
*s = 0;
s--;
}
}
/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair(script_t *script)
{
epair_t *e;
token_t token;
e = GetMemory(sizeof(epair_t));
memset (e, 0, sizeof(epair_t));
PS_ExpectAnyToken(script, &token);
StripDoubleQuotes(token.string);
if (strlen(token.string) >= MAX_KEY-1)
Error ("ParseEpair: token %s too long", token.string);
e->key = copystring(token.string);
PS_ExpectAnyToken(script, &token);
StripDoubleQuotes(token.string);
if (strlen(token.string) >= MAX_VALUE-1)
Error ("ParseEpair: token %s too long", token.string);
e->value = copystring(token.string);
// strip trailing spaces
StripTrailing(e->key);
StripTrailing(e->value);
return e;
} //end of the function ParseEpair
/*
================
ParseEntity
================
*/
qboolean ParseEntity(script_t *script)
{
epair_t *e;
entity_t *mapent;
token_t token;
if (!PS_ReadToken(script, &token))
return false;
if (strcmp(token.string, "{"))
Error ("ParseEntity: { not found");
if (num_entities == MAX_MAP_ENTITIES)
Error ("num_entities == MAX_MAP_ENTITIES");
mapent = &entities[num_entities];
num_entities++;
do
{
if (!PS_ReadToken(script, &token))
Error ("ParseEntity: EOF without closing brace");
if (!strcmp(token.string, "}") )
break;
PS_UnreadLastToken(script);
e = ParseEpair(script);
e->next = mapent->epairs;
mapent->epairs = e;
} while (1);
return true;
} //end of the function ParseEntity
void PrintEntity (entity_t *ent)
{
epair_t *ep;
printf ("------- entity %p -------\n", ent);
for (ep=ent->epairs ; ep ; ep=ep->next)
{
printf ("%s = %s\n", ep->key, ep->value);
}
}
void SetKeyValue (entity_t *ent, char *key, char *value)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
{
FreeMemory(ep->value);
ep->value = copystring(value);
return;
}
ep = GetMemory(sizeof(*ep));
ep->next = ent->epairs;
ent->epairs = ep;
ep->key = copystring(key);
ep->value = copystring(value);
}
char *ValueForKey (entity_t *ent, char *key)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
return ep->value;
return "";
}
vec_t FloatForKey (entity_t *ent, char *key)
{
char *k;
k = ValueForKey (ent, key);
return atof(k);
}
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
{
char *k;
double v1, v2, v3;
k = ValueForKey (ent, key);
// scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
vec[0] = v1;
vec[1] = v2;
vec[2] = v3;
}

View File

@ -1,58 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef MAX_MAP_ENTITIES
#define MAX_MAP_ENTITIES 2048
#endif
typedef struct epair_s
{
struct epair_s *next;
char *key;
char *value;
} epair_t;
typedef struct
{
vec3_t origin;
int firstbrush;
int numbrushes;
epair_t *epairs;
// only valid for func_areaportals
int areaportalnum;
int portalareas[2];
int modelnum; //for bsp 2 map conversion
qboolean wasdetail; //for SIN
} entity_t;
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void StripTrailing(char *e);
void SetKeyValue(entity_t *ent, char *key, char *value);
char *ValueForKey(entity_t *ent, char *key); // will return "" if not present
vec_t FloatForKey(entity_t *ent, char *key);
void GetVectorForKey(entity_t *ent, char *key, vec3_t vec);
qboolean ParseEntity(script_t *script);
epair_t *ParseEpair(script_t *script);
void PrintEntity(entity_t *ent);

View File

@ -1,888 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "l_cmd.h"
#include "l_math.h"
#include "l_mem.h"
#include "l_log.h"
#include "../botlib/l_script.h"
#include "l_bsp_hl.h"
#include "l_bsp_ent.h"
//=============================================================================
int hl_nummodels;
hl_dmodel_t *hl_dmodels;//[HL_MAX_MAP_MODELS];
int hl_dmodels_checksum;
int hl_visdatasize;
byte *hl_dvisdata;//[HL_MAX_MAP_VISIBILITY];
int hl_dvisdata_checksum;
int hl_lightdatasize;
byte *hl_dlightdata;//[HL_MAX_MAP_LIGHTING];
int hl_dlightdata_checksum;
int hl_texdatasize;
byte *hl_dtexdata;//[HL_MAX_MAP_MIPTEX]; // (dmiptexlump_t)
int hl_dtexdata_checksum;
int hl_entdatasize;
char *hl_dentdata;//[HL_MAX_MAP_ENTSTRING];
int hl_dentdata_checksum;
int hl_numleafs;
hl_dleaf_t *hl_dleafs;//[HL_MAX_MAP_LEAFS];
int hl_dleafs_checksum;
int hl_numplanes;
hl_dplane_t *hl_dplanes;//[HL_MAX_MAP_PLANES];
int hl_dplanes_checksum;
int hl_numvertexes;
hl_dvertex_t *hl_dvertexes;//[HL_MAX_MAP_VERTS];
int hl_dvertexes_checksum;
int hl_numnodes;
hl_dnode_t *hl_dnodes;//[HL_MAX_MAP_NODES];
int hl_dnodes_checksum;
int hl_numtexinfo;
hl_texinfo_t *hl_texinfo;//[HL_MAX_MAP_TEXINFO];
int hl_texinfo_checksum;
int hl_numfaces;
hl_dface_t *hl_dfaces;//[HL_MAX_MAP_FACES];
int hl_dfaces_checksum;
int hl_numclipnodes;
hl_dclipnode_t *hl_dclipnodes;//[HL_MAX_MAP_CLIPNODES];
int hl_dclipnodes_checksum;
int hl_numedges;
hl_dedge_t *hl_dedges;//[HL_MAX_MAP_EDGES];
int hl_dedges_checksum;
int hl_nummarksurfaces;
unsigned short *hl_dmarksurfaces;//[HL_MAX_MAP_MARKSURFACES];
int hl_dmarksurfaces_checksum;
int hl_numsurfedges;
int *hl_dsurfedges;//[HL_MAX_MAP_SURFEDGES];
int hl_dsurfedges_checksum;
//int num_entities;
//entity_t entities[HL_MAX_MAP_ENTITIES];
//#ifdef //ME
int hl_bspallocated = false;
int hl_allocatedbspmem = 0;
void HL_AllocMaxBSP(void)
{
//models
hl_nummodels = 0;
hl_dmodels = (hl_dmodel_t *) GetMemory(HL_MAX_MAP_MODELS * sizeof(hl_dmodel_t));
hl_allocatedbspmem = HL_MAX_MAP_MODELS * sizeof(hl_dmodel_t);
//visibility
hl_visdatasize = 0;
hl_dvisdata = (byte *) GetMemory(HL_MAX_MAP_VISIBILITY * sizeof(byte));
hl_allocatedbspmem += HL_MAX_MAP_VISIBILITY * sizeof(byte);
//light data
hl_lightdatasize = 0;
hl_dlightdata = (byte *) GetMemory(HL_MAX_MAP_LIGHTING * sizeof(byte));
hl_allocatedbspmem += HL_MAX_MAP_LIGHTING * sizeof(byte);
//texture data
hl_texdatasize = 0;
hl_dtexdata = (byte *) GetMemory(HL_MAX_MAP_MIPTEX * sizeof(byte)); // (dmiptexlump_t)
hl_allocatedbspmem += HL_MAX_MAP_MIPTEX * sizeof(byte);
//entities
hl_entdatasize = 0;
hl_dentdata = (char *) GetMemory(HL_MAX_MAP_ENTSTRING * sizeof(char));
hl_allocatedbspmem += HL_MAX_MAP_ENTSTRING * sizeof(char);
//leaves
hl_numleafs = 0;
hl_dleafs = (hl_dleaf_t *) GetMemory(HL_MAX_MAP_LEAFS * sizeof(hl_dleaf_t));
hl_allocatedbspmem += HL_MAX_MAP_LEAFS * sizeof(hl_dleaf_t);
//planes
hl_numplanes = 0;
hl_dplanes = (hl_dplane_t *) GetMemory(HL_MAX_MAP_PLANES * sizeof(hl_dplane_t));
hl_allocatedbspmem += HL_MAX_MAP_PLANES * sizeof(hl_dplane_t);
//vertexes
hl_numvertexes = 0;
hl_dvertexes = (hl_dvertex_t *) GetMemory(HL_MAX_MAP_VERTS * sizeof(hl_dvertex_t));
hl_allocatedbspmem += HL_MAX_MAP_VERTS * sizeof(hl_dvertex_t);
//nodes
hl_numnodes = 0;
hl_dnodes = (hl_dnode_t *) GetMemory(HL_MAX_MAP_NODES * sizeof(hl_dnode_t));
hl_allocatedbspmem += HL_MAX_MAP_NODES * sizeof(hl_dnode_t);
//texture info
hl_numtexinfo = 0;
hl_texinfo = (hl_texinfo_t *) GetMemory(HL_MAX_MAP_TEXINFO * sizeof(hl_texinfo_t));
hl_allocatedbspmem += HL_MAX_MAP_TEXINFO * sizeof(hl_texinfo_t);
//faces
hl_numfaces = 0;
hl_dfaces = (hl_dface_t *) GetMemory(HL_MAX_MAP_FACES * sizeof(hl_dface_t));
hl_allocatedbspmem += HL_MAX_MAP_FACES * sizeof(hl_dface_t);
//clip nodes
hl_numclipnodes = 0;
hl_dclipnodes = (hl_dclipnode_t *) GetMemory(HL_MAX_MAP_CLIPNODES * sizeof(hl_dclipnode_t));
hl_allocatedbspmem += HL_MAX_MAP_CLIPNODES * sizeof(hl_dclipnode_t);
//edges
hl_numedges = 0;
hl_dedges = (hl_dedge_t *) GetMemory(HL_MAX_MAP_EDGES * sizeof(hl_dedge_t));
hl_allocatedbspmem += HL_MAX_MAP_EDGES, sizeof(hl_dedge_t);
//mark surfaces
hl_nummarksurfaces = 0;
hl_dmarksurfaces = (unsigned short *) GetMemory(HL_MAX_MAP_MARKSURFACES * sizeof(unsigned short));
hl_allocatedbspmem += HL_MAX_MAP_MARKSURFACES * sizeof(unsigned short);
//surface edges
hl_numsurfedges = 0;
hl_dsurfedges = (int *) GetMemory(HL_MAX_MAP_SURFEDGES * sizeof(int));
hl_allocatedbspmem += HL_MAX_MAP_SURFEDGES * sizeof(int);
//print allocated memory
Log_Print("allocated ");
PrintMemorySize(hl_allocatedbspmem);
Log_Print(" of BSP memory\n");
} //end of the function HL_AllocMaxBSP
void HL_FreeMaxBSP(void)
{
//models
hl_nummodels = 0;
FreeMemory(hl_dmodels);
hl_dmodels = NULL;
//visibility
hl_visdatasize = 0;
FreeMemory(hl_dvisdata);
hl_dvisdata = NULL;
//light data
hl_lightdatasize = 0;
FreeMemory(hl_dlightdata);
hl_dlightdata = NULL;
//texture data
hl_texdatasize = 0;
FreeMemory(hl_dtexdata);
hl_dtexdata = NULL;
//entities
hl_entdatasize = 0;
FreeMemory(hl_dentdata);
hl_dentdata = NULL;
//leaves
hl_numleafs = 0;
FreeMemory(hl_dleafs);
hl_dleafs = NULL;
//planes
hl_numplanes = 0;
FreeMemory(hl_dplanes);
hl_dplanes = NULL;
//vertexes
hl_numvertexes = 0;
FreeMemory(hl_dvertexes);
hl_dvertexes = NULL;
//nodes
hl_numnodes = 0;
FreeMemory(hl_dnodes);
hl_dnodes = NULL;
//texture info
hl_numtexinfo = 0;
FreeMemory(hl_texinfo);
hl_texinfo = NULL;
//faces
hl_numfaces = 0;
FreeMemory(hl_dfaces);
hl_dfaces = NULL;
//clip nodes
hl_numclipnodes = 0;
FreeMemory(hl_dclipnodes);
hl_dclipnodes = NULL;
//edges
hl_numedges = 0;
FreeMemory(hl_dedges);
hl_dedges = NULL;
//mark surfaces
hl_nummarksurfaces = 0;
FreeMemory(hl_dmarksurfaces);
hl_dmarksurfaces = NULL;
//surface edges
hl_numsurfedges = 0;
FreeMemory(hl_dsurfedges);
hl_dsurfedges = NULL;
//
Log_Print("freed ");
PrintMemorySize(hl_allocatedbspmem);
Log_Print(" of BSP memory\n");
hl_allocatedbspmem = 0;
} //end of the function HL_FreeMaxBSP
//#endif //ME
/*
===============
FastChecksum
===============
*/
int FastChecksum(void *buffer, int bytes)
{
int checksum = 0;
while( bytes-- )
checksum = (checksum << 4) ^ *((char *)buffer)++;
return checksum;
}
/*
===============
HL_CompressVis
===============
*/
int HL_CompressVis(byte *vis, byte *dest)
{
int j;
int rep;
int visrow;
byte *dest_p;
dest_p = dest;
visrow = (hl_numleafs + 7)>>3;
for (j=0 ; j<visrow ; j++)
{
*dest_p++ = vis[j];
if (vis[j])
continue;
rep = 1;
for ( j++; j<visrow ; j++)
if (vis[j] || rep == 255)
break;
else
rep++;
*dest_p++ = rep;
j--;
}
return dest_p - dest;
}
/*
===================
HL_DecompressVis
===================
*/
void HL_DecompressVis (byte *in, byte *decompressed)
{
int c;
byte *out;
int row;
row = (hl_numleafs+7)>>3;
out = decompressed;
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
}
//=============================================================================
/*
=============
HL_SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void HL_SwapBSPFile (qboolean todisk)
{
int i, j, c;
hl_dmodel_t *d;
hl_dmiptexlump_t *mtl;
// models
for (i = 0; i < hl_nummodels; i++)
{
d = &hl_dmodels[i];
for (j = 0; j < HL_MAX_MAP_HULLS; j++)
d->headnode[j] = LittleLong(d->headnode[j]);
d->visleafs = LittleLong(d->visleafs);
d->firstface = LittleLong(d->firstface);
d->numfaces = LittleLong(d->numfaces);
for (j = 0; j < 3; j++)
{
d->mins[j] = LittleFloat(d->mins[j]);
d->maxs[j] = LittleFloat(d->maxs[j]);
d->origin[j] = LittleFloat(d->origin[j]);
}
}
//
// vertexes
//
for (i = 0; i < hl_numvertexes; i++)
{
for (j = 0; j < 3; j++)
hl_dvertexes[i].point[j] = LittleFloat (hl_dvertexes[i].point[j]);
}
//
// planes
//
for (i=0 ; i<hl_numplanes ; i++)
{
for (j=0 ; j<3 ; j++)
hl_dplanes[i].normal[j] = LittleFloat (hl_dplanes[i].normal[j]);
hl_dplanes[i].dist = LittleFloat (hl_dplanes[i].dist);
hl_dplanes[i].type = LittleLong (hl_dplanes[i].type);
}
//
// texinfos
//
for (i=0 ; i<hl_numtexinfo ; i++)
{
for (j=0 ; j<8 ; j++)
hl_texinfo[i].vecs[0][j] = LittleFloat (hl_texinfo[i].vecs[0][j]);
hl_texinfo[i].miptex = LittleLong (hl_texinfo[i].miptex);
hl_texinfo[i].flags = LittleLong (hl_texinfo[i].flags);
}
//
// faces
//
for (i=0 ; i<hl_numfaces ; i++)
{
hl_dfaces[i].texinfo = LittleShort (hl_dfaces[i].texinfo);
hl_dfaces[i].planenum = LittleShort (hl_dfaces[i].planenum);
hl_dfaces[i].side = LittleShort (hl_dfaces[i].side);
hl_dfaces[i].lightofs = LittleLong (hl_dfaces[i].lightofs);
hl_dfaces[i].firstedge = LittleLong (hl_dfaces[i].firstedge);
hl_dfaces[i].numedges = LittleShort (hl_dfaces[i].numedges);
}
//
// nodes
//
for (i=0 ; i<hl_numnodes ; i++)
{
hl_dnodes[i].planenum = LittleLong (hl_dnodes[i].planenum);
for (j=0 ; j<3 ; j++)
{
hl_dnodes[i].mins[j] = LittleShort (hl_dnodes[i].mins[j]);
hl_dnodes[i].maxs[j] = LittleShort (hl_dnodes[i].maxs[j]);
}
hl_dnodes[i].children[0] = LittleShort (hl_dnodes[i].children[0]);
hl_dnodes[i].children[1] = LittleShort (hl_dnodes[i].children[1]);
hl_dnodes[i].firstface = LittleShort (hl_dnodes[i].firstface);
hl_dnodes[i].numfaces = LittleShort (hl_dnodes[i].numfaces);
}
//
// leafs
//
for (i=0 ; i<hl_numleafs ; i++)
{
hl_dleafs[i].contents = LittleLong (hl_dleafs[i].contents);
for (j=0 ; j<3 ; j++)
{
hl_dleafs[i].mins[j] = LittleShort (hl_dleafs[i].mins[j]);
hl_dleafs[i].maxs[j] = LittleShort (hl_dleafs[i].maxs[j]);
}
hl_dleafs[i].firstmarksurface = LittleShort (hl_dleafs[i].firstmarksurface);
hl_dleafs[i].nummarksurfaces = LittleShort (hl_dleafs[i].nummarksurfaces);
hl_dleafs[i].visofs = LittleLong (hl_dleafs[i].visofs);
}
//
// clipnodes
//
for (i=0 ; i<hl_numclipnodes ; i++)
{
hl_dclipnodes[i].planenum = LittleLong (hl_dclipnodes[i].planenum);
hl_dclipnodes[i].children[0] = LittleShort (hl_dclipnodes[i].children[0]);
hl_dclipnodes[i].children[1] = LittleShort (hl_dclipnodes[i].children[1]);
}
//
// miptex
//
if (hl_texdatasize)
{
mtl = (hl_dmiptexlump_t *)hl_dtexdata;
if (todisk)
c = mtl->nummiptex;
else
c = LittleLong(mtl->nummiptex);
mtl->nummiptex = LittleLong (mtl->nummiptex);
for (i=0 ; i<c ; i++)
mtl->dataofs[i] = LittleLong(mtl->dataofs[i]);
}
//
// marksurfaces
//
for (i=0 ; i<hl_nummarksurfaces ; i++)
hl_dmarksurfaces[i] = LittleShort (hl_dmarksurfaces[i]);
//
// surfedges
//
for (i=0 ; i<hl_numsurfedges ; i++)
hl_dsurfedges[i] = LittleLong (hl_dsurfedges[i]);
//
// edges
//
for (i=0 ; i<hl_numedges ; i++)
{
hl_dedges[i].v[0] = LittleShort (hl_dedges[i].v[0]);
hl_dedges[i].v[1] = LittleShort (hl_dedges[i].v[1]);
}
} //end of the function HL_SwapBSPFile
hl_dheader_t *hl_header;
int hl_fileLength;
int HL_CopyLump (int lump, void *dest, int size, int maxsize)
{
int length, ofs;
length = hl_header->lumps[lump].filelen;
ofs = hl_header->lumps[lump].fileofs;
if (length % size) {
Error ("LoadBSPFile: odd lump size");
}
// somehow things got out of range
if ((length/size) > maxsize) {
printf("WARNING: exceeded max size for lump %d size %d > maxsize %d\n", lump, (length/size), maxsize);
length = maxsize * size;
}
if ( ofs + length > hl_fileLength ) {
printf("WARNING: exceeded file length for lump %d\n", lump);
length = hl_fileLength - ofs;
if ( length <= 0 ) {
return 0;
}
}
memcpy (dest, (byte *)hl_header + ofs, length);
return length / size;
}
/*
=============
HL_LoadBSPFile
=============
*/
void HL_LoadBSPFile (char *filename, int offset, int length)
{
int i;
//
// load the file header
//
hl_fileLength = LoadFile (filename, (void **)&hl_header, offset, length);
// swap the header
for (i=0 ; i< sizeof(hl_dheader_t)/4 ; i++)
((int *)hl_header)[i] = LittleLong ( ((int *)hl_header)[i]);
if (hl_header->version != HL_BSPVERSION)
Error ("%s is version %i, not %i", filename, hl_header->version, HL_BSPVERSION);
hl_nummodels = HL_CopyLump (HL_LUMP_MODELS, hl_dmodels, sizeof(hl_dmodel_t), HL_MAX_MAP_MODELS );
hl_numvertexes = HL_CopyLump (HL_LUMP_VERTEXES, hl_dvertexes, sizeof(hl_dvertex_t), HL_MAX_MAP_VERTS );
hl_numplanes = HL_CopyLump (HL_LUMP_PLANES, hl_dplanes, sizeof(hl_dplane_t), HL_MAX_MAP_PLANES );
hl_numleafs = HL_CopyLump (HL_LUMP_LEAFS, hl_dleafs, sizeof(hl_dleaf_t), HL_MAX_MAP_LEAFS );
hl_numnodes = HL_CopyLump (HL_LUMP_NODES, hl_dnodes, sizeof(hl_dnode_t), HL_MAX_MAP_NODES );
hl_numtexinfo = HL_CopyLump (HL_LUMP_TEXINFO, hl_texinfo, sizeof(hl_texinfo_t), HL_MAX_MAP_TEXINFO );
hl_numclipnodes = HL_CopyLump (HL_LUMP_CLIPNODES, hl_dclipnodes, sizeof(hl_dclipnode_t), HL_MAX_MAP_CLIPNODES );
hl_numfaces = HL_CopyLump (HL_LUMP_FACES, hl_dfaces, sizeof(hl_dface_t), HL_MAX_MAP_FACES );
hl_nummarksurfaces = HL_CopyLump (HL_LUMP_MARKSURFACES, hl_dmarksurfaces, sizeof(hl_dmarksurfaces[0]), HL_MAX_MAP_MARKSURFACES );
hl_numsurfedges = HL_CopyLump (HL_LUMP_SURFEDGES, hl_dsurfedges, sizeof(hl_dsurfedges[0]), HL_MAX_MAP_SURFEDGES );
hl_numedges = HL_CopyLump (HL_LUMP_EDGES, hl_dedges, sizeof(hl_dedge_t), HL_MAX_MAP_EDGES );
hl_texdatasize = HL_CopyLump (HL_LUMP_TEXTURES, hl_dtexdata, 1, HL_MAX_MAP_MIPTEX );
hl_visdatasize = HL_CopyLump (HL_LUMP_VISIBILITY, hl_dvisdata, 1, HL_MAX_MAP_VISIBILITY );
hl_lightdatasize = HL_CopyLump (HL_LUMP_LIGHTING, hl_dlightdata, 1, HL_MAX_MAP_LIGHTING );
hl_entdatasize = HL_CopyLump (HL_LUMP_ENTITIES, hl_dentdata, 1, HL_MAX_MAP_ENTSTRING );
FreeMemory(hl_header); // everything has been copied out
//
// swap everything
//
HL_SwapBSPFile (false);
hl_dmodels_checksum = FastChecksum( hl_dmodels, hl_nummodels*sizeof(hl_dmodels[0]) );
hl_dvertexes_checksum = FastChecksum( hl_dvertexes, hl_numvertexes*sizeof(hl_dvertexes[0]) );
hl_dplanes_checksum = FastChecksum( hl_dplanes, hl_numplanes*sizeof(hl_dplanes[0]) );
hl_dleafs_checksum = FastChecksum( hl_dleafs, hl_numleafs*sizeof(hl_dleafs[0]) );
hl_dnodes_checksum = FastChecksum( hl_dnodes, hl_numnodes*sizeof(hl_dnodes[0]) );
hl_texinfo_checksum = FastChecksum( hl_texinfo, hl_numtexinfo*sizeof(hl_texinfo[0]) );
hl_dclipnodes_checksum = FastChecksum( hl_dclipnodes, hl_numclipnodes*sizeof(hl_dclipnodes[0]) );
hl_dfaces_checksum = FastChecksum( hl_dfaces, hl_numfaces*sizeof(hl_dfaces[0]) );
hl_dmarksurfaces_checksum = FastChecksum( hl_dmarksurfaces, hl_nummarksurfaces*sizeof(hl_dmarksurfaces[0]) );
hl_dsurfedges_checksum = FastChecksum( hl_dsurfedges, hl_numsurfedges*sizeof(hl_dsurfedges[0]) );
hl_dedges_checksum = FastChecksum( hl_dedges, hl_numedges*sizeof(hl_dedges[0]) );
hl_dtexdata_checksum = FastChecksum( hl_dtexdata, hl_numedges*sizeof(hl_dtexdata[0]) );
hl_dvisdata_checksum = FastChecksum( hl_dvisdata, hl_visdatasize*sizeof(hl_dvisdata[0]) );
hl_dlightdata_checksum = FastChecksum( hl_dlightdata, hl_lightdatasize*sizeof(hl_dlightdata[0]) );
hl_dentdata_checksum = FastChecksum( hl_dentdata, hl_entdatasize*sizeof(hl_dentdata[0]) );
}
//============================================================================
FILE *wadfile;
hl_dheader_t outheader;
void HL_AddLump (int lumpnum, void *data, int len)
{
hl_lump_t *lump;
lump = &hl_header->lumps[lumpnum];
lump->fileofs = LittleLong( ftell(wadfile) );
lump->filelen = LittleLong(len);
SafeWrite (wadfile, data, (len+3)&~3);
}
/*
=============
HL_WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void HL_WriteBSPFile (char *filename)
{
hl_header = &outheader;
memset (hl_header, 0, sizeof(hl_dheader_t));
HL_SwapBSPFile (true);
hl_header->version = LittleLong (HL_BSPVERSION);
wadfile = SafeOpenWrite (filename);
SafeWrite (wadfile, hl_header, sizeof(hl_dheader_t)); // overwritten later
HL_AddLump (HL_LUMP_PLANES, hl_dplanes, hl_numplanes*sizeof(hl_dplane_t));
HL_AddLump (HL_LUMP_LEAFS, hl_dleafs, hl_numleafs*sizeof(hl_dleaf_t));
HL_AddLump (HL_LUMP_VERTEXES, hl_dvertexes, hl_numvertexes*sizeof(hl_dvertex_t));
HL_AddLump (HL_LUMP_NODES, hl_dnodes, hl_numnodes*sizeof(hl_dnode_t));
HL_AddLump (HL_LUMP_TEXINFO, hl_texinfo, hl_numtexinfo*sizeof(hl_texinfo_t));
HL_AddLump (HL_LUMP_FACES, hl_dfaces, hl_numfaces*sizeof(hl_dface_t));
HL_AddLump (HL_LUMP_CLIPNODES, hl_dclipnodes, hl_numclipnodes*sizeof(hl_dclipnode_t));
HL_AddLump (HL_LUMP_MARKSURFACES, hl_dmarksurfaces, hl_nummarksurfaces*sizeof(hl_dmarksurfaces[0]));
HL_AddLump (HL_LUMP_SURFEDGES, hl_dsurfedges, hl_numsurfedges*sizeof(hl_dsurfedges[0]));
HL_AddLump (HL_LUMP_EDGES, hl_dedges, hl_numedges*sizeof(hl_dedge_t));
HL_AddLump (HL_LUMP_MODELS, hl_dmodels, hl_nummodels*sizeof(hl_dmodel_t));
HL_AddLump (HL_LUMP_LIGHTING, hl_dlightdata, hl_lightdatasize);
HL_AddLump (HL_LUMP_VISIBILITY, hl_dvisdata, hl_visdatasize);
HL_AddLump (HL_LUMP_ENTITIES, hl_dentdata, hl_entdatasize);
HL_AddLump (HL_LUMP_TEXTURES, hl_dtexdata, hl_texdatasize);
fseek (wadfile, 0, SEEK_SET);
SafeWrite (wadfile, hl_header, sizeof(hl_dheader_t));
fclose (wadfile);
}
//============================================================================
#define ENTRIES(a) (sizeof(a)/sizeof(*(a)))
#define ENTRYSIZE(a) (sizeof(*(a)))
ArrayUsage( char *szItem, int items, int maxitems, int itemsize )
{
float percentage = maxitems ? items * 100.0 / maxitems : 0.0;
qprintf("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)",
szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage );
if ( percentage > 80.0 )
qprintf( "VERY FULL!\n" );
else if ( percentage > 95.0 )
qprintf( "SIZE DANGER!\n" );
else if ( percentage > 99.9 )
qprintf( "SIZE OVERFLOW!!!\n" );
else
qprintf( "\n" );
return items * itemsize;
}
GlobUsage( char *szItem, int itemstorage, int maxstorage )
{
float percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0;
qprintf("%-12s [variable] %7i/%-7i (%4.1f%%)",
szItem, itemstorage, maxstorage, percentage );
if ( percentage > 80.0 )
qprintf( "VERY FULL!\n" );
else if ( percentage > 95.0 )
qprintf( "SIZE DANGER!\n" );
else if ( percentage > 99.9 )
qprintf( "SIZE OVERFLOW!!!\n" );
else
qprintf( "\n" );
return itemstorage;
}
/*
=============
HL_PrintBSPFileSizes
Dumps info about current file
=============
*/
void HL_PrintBSPFileSizes(void)
{
int numtextures = hl_texdatasize ? ((hl_dmiptexlump_t*)hl_dtexdata)->nummiptex : 0;
int totalmemory = 0;
qprintf("\n");
qprintf("Object names Objects/Maxobjs Memory / Maxmem Fullness\n" );
qprintf("------------ --------------- --------------- --------\n" );
totalmemory += ArrayUsage( "models", hl_nummodels, ENTRIES(hl_dmodels), ENTRYSIZE(hl_dmodels) );
totalmemory += ArrayUsage( "planes", hl_numplanes, ENTRIES(hl_dplanes), ENTRYSIZE(hl_dplanes) );
totalmemory += ArrayUsage( "vertexes", hl_numvertexes, ENTRIES(hl_dvertexes), ENTRYSIZE(hl_dvertexes) );
totalmemory += ArrayUsage( "nodes", hl_numnodes, ENTRIES(hl_dnodes), ENTRYSIZE(hl_dnodes) );
totalmemory += ArrayUsage( "texinfos", hl_numtexinfo, ENTRIES(hl_texinfo), ENTRYSIZE(hl_texinfo) );
totalmemory += ArrayUsage( "faces", hl_numfaces, ENTRIES(hl_dfaces), ENTRYSIZE(hl_dfaces) );
totalmemory += ArrayUsage( "clipnodes", hl_numclipnodes, ENTRIES(hl_dclipnodes), ENTRYSIZE(hl_dclipnodes) );
totalmemory += ArrayUsage( "leaves", hl_numleafs, ENTRIES(hl_dleafs), ENTRYSIZE(hl_dleafs) );
totalmemory += ArrayUsage( "marksurfaces",hl_nummarksurfaces,ENTRIES(hl_dmarksurfaces),ENTRYSIZE(hl_dmarksurfaces) );
totalmemory += ArrayUsage( "surfedges", hl_numsurfedges, ENTRIES(hl_dsurfedges), ENTRYSIZE(hl_dsurfedges) );
totalmemory += ArrayUsage( "edges", hl_numedges, ENTRIES(hl_dedges), ENTRYSIZE(hl_dedges) );
totalmemory += GlobUsage( "texdata", hl_texdatasize, sizeof(hl_dtexdata) );
totalmemory += GlobUsage( "lightdata", hl_lightdatasize, sizeof(hl_dlightdata) );
totalmemory += GlobUsage( "visdata", hl_visdatasize, sizeof(hl_dvisdata) );
totalmemory += GlobUsage( "entdata", hl_entdatasize, sizeof(hl_dentdata) );
qprintf( "=== Total BSP file data space used: %d bytes ===\n\n", totalmemory );
}
/*
=================
ParseEpair
=================
* /
epair_t *ParseEpair (void)
{
epair_t *e;
e = malloc (sizeof(epair_t));
memset (e, 0, sizeof(epair_t));
if (strlen(token) >= MAX_KEY-1)
Error ("ParseEpar: token too long");
e->key = copystring(token);
GetToken (false);
if (strlen(token) >= MAX_VALUE-1)
Error ("ParseEpar: token too long");
e->value = copystring(token);
return e;
} //*/
/*
================
ParseEntity
================
* /
qboolean ParseEntity (void)
{
epair_t *e;
entity_t *mapent;
if (!GetToken (true))
return false;
if (strcmp (token, "{") )
Error ("ParseEntity: { not found");
if (num_entities == HL_MAX_MAP_ENTITIES)
Error ("num_entities == HL_MAX_MAP_ENTITIES");
mapent = &entities[num_entities];
num_entities++;
do
{
if (!GetToken (true))
Error ("ParseEntity: EOF without closing brace");
if (!strcmp (token, "}") )
break;
e = ParseEpair ();
e->next = mapent->epairs;
mapent->epairs = e;
} while (1);
return true;
} //*/
/*
================
ParseEntities
Parses the dentdata string into entities
================
*/
void HL_ParseEntities (void)
{
script_t *script;
num_entities = 0;
script = LoadScriptMemory(hl_dentdata, hl_entdatasize, "*Half-Life bsp file");
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
SCFL_NOSTRINGESCAPECHARS);
while(ParseEntity(script))
{
} //end while
FreeScript(script);
} //end of the function HL_ParseEntities
/*
================
UnparseEntities
Generates the dentdata string from all the entities
================
*/
void HL_UnparseEntities (void)
{
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
buf = hl_dentdata;
end = buf;
*end = 0;
for (i=0 ; i<num_entities ; i++)
{
ep = entities[i].epairs;
if (!ep)
continue; // ent got removed
strcat (end,"{\n");
end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next)
{
sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
strcat (end, line);
end += strlen(line);
}
strcat (end,"}\n");
end += 2;
if (end > buf + HL_MAX_MAP_ENTSTRING)
Error ("Entity text too long");
}
hl_entdatasize = end - buf + 1;
} //end of the function HL_UnparseEntities
/*
void SetKeyValue (entity_t *ent, char *key, char *value)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
{
free (ep->value);
ep->value = copystring(value);
return;
}
ep = malloc (sizeof(*ep));
ep->next = ent->epairs;
ent->epairs = ep;
ep->key = copystring(key);
ep->value = copystring(value);
}
char *ValueForKey (entity_t *ent, char *key)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
return ep->value;
return "";
}
vec_t FloatForKey (entity_t *ent, char *key)
{
char *k;
k = ValueForKey (ent, key);
return atof(k);
}
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
{
char *k;
double v1, v2, v3;
k = ValueForKey (ent, key);
// scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
vec[0] = v1;
vec[1] = v2;
vec[2] = v3;
} //*/

View File

@ -1,314 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// upper design bounds
#define HL_MAX_MAP_HULLS 4
#define HL_MAX_MAP_MODELS 400
#define HL_MAX_MAP_BRUSHES 4096
#define HL_MAX_MAP_ENTITIES 1024
#define HL_MAX_MAP_ENTSTRING (128*1024)
#define HL_MAX_MAP_PLANES 32767
#define HL_MAX_MAP_NODES 32767 // because negative shorts are contents
#define HL_MAX_MAP_CLIPNODES 32767 //
#define HL_MAX_MAP_LEAFS 8192
#define HL_MAX_MAP_VERTS 65535
#define HL_MAX_MAP_FACES 65535
#define HL_MAX_MAP_MARKSURFACES 65535
#define HL_MAX_MAP_TEXINFO 8192
#define HL_MAX_MAP_EDGES 256000
#define HL_MAX_MAP_SURFEDGES 512000
#define HL_MAX_MAP_TEXTURES 512
#define HL_MAX_MAP_MIPTEX 0x200000
#define HL_MAX_MAP_LIGHTING 0x200000
#define HL_MAX_MAP_VISIBILITY 0x200000
#define HL_MAX_MAP_PORTALS 65536
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
#define HL_BSPVERSION 30
#define HL_TOOLVERSION 2
typedef struct
{
int fileofs, filelen;
} hl_lump_t;
#define HL_LUMP_ENTITIES 0
#define HL_LUMP_PLANES 1
#define HL_LUMP_TEXTURES 2
#define HL_LUMP_VERTEXES 3
#define HL_LUMP_VISIBILITY 4
#define HL_LUMP_NODES 5
#define HL_LUMP_TEXINFO 6
#define HL_LUMP_FACES 7
#define HL_LUMP_LIGHTING 8
#define HL_LUMP_CLIPNODES 9
#define HL_LUMP_LEAFS 10
#define HL_LUMP_MARKSURFACES 11
#define HL_LUMP_EDGES 12
#define HL_LUMP_SURFEDGES 13
#define HL_LUMP_MODELS 14
#define HL_HEADER_LUMPS 15
typedef struct
{
float mins[3], maxs[3];
float origin[3];
int headnode[HL_MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} hl_dmodel_t;
typedef struct
{
int version;
hl_lump_t lumps[HL_HEADER_LUMPS];
} hl_dheader_t;
typedef struct
{
int nummiptex;
int dataofs[4]; // [nummiptex]
} hl_dmiptexlump_t;
#define MIPLEVELS 4
typedef struct hl_miptex_s
{
char name[16];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
} hl_miptex_t;
typedef struct
{
float point[3];
} hl_dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} hl_dplane_t;
#define HL_CONTENTS_EMPTY -1
#define HL_CONTENTS_SOLID -2
#define HL_CONTENTS_WATER -3
#define HL_CONTENTS_SLIME -4
#define HL_CONTENTS_LAVA -5
#define HL_CONTENTS_SKY -6
#define HL_CONTENTS_ORIGIN -7 // removed at csg time
#define HL_CONTENTS_CLIP -8 // changed to contents_solid
#define HL_CONTENTS_CURRENT_0 -9
#define HL_CONTENTS_CURRENT_90 -10
#define HL_CONTENTS_CURRENT_180 -11
#define HL_CONTENTS_CURRENT_270 -12
#define HL_CONTENTS_CURRENT_UP -13
#define HL_CONTENTS_CURRENT_DOWN -14
#define HL_CONTENTS_TRANSLUCENT -15
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
int planenum;
short children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} hl_dnode_t;
typedef struct
{
int planenum;
short children[2]; // negative numbers are contents
} hl_dclipnode_t;
typedef struct hl_texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int miptex;
int flags;
} hl_texinfo_t;
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} hl_dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} hl_dface_t;
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
#define NUM_AMBIENTS 4 // automatic ambient sounds
// leaf 0 is the generic HL_CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct
{
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
byte ambient_level[NUM_AMBIENTS];
} hl_dleaf_t;
//============================================================================
#ifndef QUAKE_GAME
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the utilities get to be lazy and just use large static arrays
extern int hl_nummodels;
extern hl_dmodel_t *hl_dmodels;//[MAX_MAP_MODELS];
extern int hl_dmodels_checksum;
extern int hl_visdatasize;
extern byte *hl_dvisdata;//[MAX_MAP_VISIBILITY];
extern int hl_dvisdata_checksum;
extern int hl_lightdatasize;
extern byte *hl_dlightdata;//[MAX_MAP_LIGHTING];
extern int hl_dlightdata_checksum;
extern int hl_texdatasize;
extern byte *hl_dtexdata;//[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
extern int hl_dtexdata_checksum;
extern int hl_entdatasize;
extern char *hl_dentdata;//[MAX_MAP_ENTSTRING];
extern int hl_dentdata_checksum;
extern int hl_numleafs;
extern hl_dleaf_t *hl_dleafs;//[MAX_MAP_LEAFS];
extern int hl_dleafs_checksum;
extern int hl_numplanes;
extern hl_dplane_t *hl_dplanes;//[MAX_MAP_PLANES];
extern int hl_dplanes_checksum;
extern int hl_numvertexes;
extern hl_dvertex_t *hl_dvertexes;//[MAX_MAP_VERTS];
extern int hl_dvertexes_checksum;
extern int hl_numnodes;
extern hl_dnode_t *hl_dnodes;//[MAX_MAP_NODES];
extern int hl_dnodes_checksum;
extern int hl_numtexinfo;
extern hl_texinfo_t *hl_texinfo;//[MAX_MAP_TEXINFO];
extern int hl_texinfo_checksum;
extern int hl_numfaces;
extern hl_dface_t *hl_dfaces;//[MAX_MAP_FACES];
extern int hl_dfaces_checksum;
extern int hl_numclipnodes;
extern hl_dclipnode_t *hl_dclipnodes;//[MAX_MAP_CLIPNODES];
extern int hl_dclipnodes_checksum;
extern int hl_numedges;
extern hl_dedge_t *hl_dedges;//[MAX_MAP_EDGES];
extern int hl_dedges_checksum;
extern int hl_nummarksurfaces;
extern unsigned short *hl_dmarksurfaces;//[MAX_MAP_MARKSURFACES];
extern int hl_dmarksurfaces_checksum;
extern int hl_numsurfedges;
extern int *hl_dsurfedges;//[MAX_MAP_SURFEDGES];
extern int hl_dsurfedges_checksum;
int FastChecksum(void *buffer, int bytes);
void HL_AllocMaxBSP(void);
void HL_FreeMaxBSP(void);
void HL_DecompressVis(byte *in, byte *decompressed);
int HL_CompressVis(byte *vis, byte *dest);
void HL_LoadBSPFile(char *filename, int offset, int length);
void HL_WriteBSPFile(char *filename);
void HL_PrintBSPFileSizes(void);
void HL_PrintBSPFileSizes(void);
void HL_ParseEntities(void);
void HL_UnparseEntities(void);
#endif

View File

@ -1,620 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "l_cmd.h"
#include "l_math.h"
#include "l_mem.h"
#include "l_log.h"
#include "../botlib/l_script.h"
#include "l_bsp_q1.h"
#include "l_bsp_ent.h"
//=============================================================================
int q1_nummodels;
q1_dmodel_t *q1_dmodels;//[MAX_MAP_MODELS];
int q1_visdatasize;
byte *q1_dvisdata;//[MAX_MAP_VISIBILITY];
int q1_lightdatasize;
byte *q1_dlightdata;//[MAX_MAP_LIGHTING];
int q1_texdatasize;
byte *q1_dtexdata;//[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
int q1_entdatasize;
char *q1_dentdata;//[MAX_MAP_ENTSTRING];
int q1_numleafs;
q1_dleaf_t *q1_dleafs;//[MAX_MAP_LEAFS];
int q1_numplanes;
q1_dplane_t *q1_dplanes;//[MAX_MAP_PLANES];
int q1_numvertexes;
q1_dvertex_t *q1_dvertexes;//[MAX_MAP_VERTS];
int q1_numnodes;
q1_dnode_t *q1_dnodes;//[MAX_MAP_NODES];
int q1_numtexinfo;
q1_texinfo_t *q1_texinfo;//[MAX_MAP_TEXINFO];
int q1_numfaces;
q1_dface_t *q1_dfaces;//[MAX_MAP_FACES];
int q1_numclipnodes;
q1_dclipnode_t *q1_dclipnodes;//[MAX_MAP_CLIPNODES];
int q1_numedges;
q1_dedge_t *q1_dedges;//[MAX_MAP_EDGES];
int q1_nummarksurfaces;
unsigned short *q1_dmarksurfaces;//[MAX_MAP_MARKSURFACES];
int q1_numsurfedges;
int *q1_dsurfedges;//[MAX_MAP_SURFEDGES];
//=============================================================================
int q1_bspallocated = false;
int q1_allocatedbspmem = 0;
void Q1_AllocMaxBSP(void)
{
//models
q1_nummodels = 0;
q1_dmodels = (q1_dmodel_t *) GetMemory(Q1_MAX_MAP_MODELS * sizeof(q1_dmodel_t));
q1_allocatedbspmem = Q1_MAX_MAP_MODELS * sizeof(q1_dmodel_t);
//visibility
q1_visdatasize = 0;
q1_dvisdata = (byte *) GetMemory(Q1_MAX_MAP_VISIBILITY * sizeof(byte));
q1_allocatedbspmem += Q1_MAX_MAP_VISIBILITY * sizeof(byte);
//light data
q1_lightdatasize = 0;
q1_dlightdata = (byte *) GetMemory(Q1_MAX_MAP_LIGHTING * sizeof(byte));
q1_allocatedbspmem += Q1_MAX_MAP_LIGHTING * sizeof(byte);
//texture data
q1_texdatasize = 0;
q1_dtexdata = (byte *) GetMemory(Q1_MAX_MAP_MIPTEX * sizeof(byte)); // (dmiptexlump_t)
q1_allocatedbspmem += Q1_MAX_MAP_MIPTEX * sizeof(byte);
//entities
q1_entdatasize = 0;
q1_dentdata = (char *) GetMemory(Q1_MAX_MAP_ENTSTRING * sizeof(char));
q1_allocatedbspmem += Q1_MAX_MAP_ENTSTRING * sizeof(char);
//leaves
q1_numleafs = 0;
q1_dleafs = (q1_dleaf_t *) GetMemory(Q1_MAX_MAP_LEAFS * sizeof(q1_dleaf_t));
q1_allocatedbspmem += Q1_MAX_MAP_LEAFS * sizeof(q1_dleaf_t);
//planes
q1_numplanes = 0;
q1_dplanes = (q1_dplane_t *) GetMemory(Q1_MAX_MAP_PLANES * sizeof(q1_dplane_t));
q1_allocatedbspmem += Q1_MAX_MAP_PLANES * sizeof(q1_dplane_t);
//vertexes
q1_numvertexes = 0;
q1_dvertexes = (q1_dvertex_t *) GetMemory(Q1_MAX_MAP_VERTS * sizeof(q1_dvertex_t));
q1_allocatedbspmem += Q1_MAX_MAP_VERTS * sizeof(q1_dvertex_t);
//nodes
q1_numnodes = 0;
q1_dnodes = (q1_dnode_t *) GetMemory(Q1_MAX_MAP_NODES * sizeof(q1_dnode_t));
q1_allocatedbspmem += Q1_MAX_MAP_NODES * sizeof(q1_dnode_t);
//texture info
q1_numtexinfo = 0;
q1_texinfo = (q1_texinfo_t *) GetMemory(Q1_MAX_MAP_TEXINFO * sizeof(q1_texinfo_t));
q1_allocatedbspmem += Q1_MAX_MAP_TEXINFO * sizeof(q1_texinfo_t);
//faces
q1_numfaces = 0;
q1_dfaces = (q1_dface_t *) GetMemory(Q1_MAX_MAP_FACES * sizeof(q1_dface_t));
q1_allocatedbspmem += Q1_MAX_MAP_FACES * sizeof(q1_dface_t);
//clip nodes
q1_numclipnodes = 0;
q1_dclipnodes = (q1_dclipnode_t *) GetMemory(Q1_MAX_MAP_CLIPNODES * sizeof(q1_dclipnode_t));
q1_allocatedbspmem += Q1_MAX_MAP_CLIPNODES * sizeof(q1_dclipnode_t);
//edges
q1_numedges = 0;
q1_dedges = (q1_dedge_t *) GetMemory(Q1_MAX_MAP_EDGES * sizeof(q1_dedge_t));
q1_allocatedbspmem += Q1_MAX_MAP_EDGES, sizeof(q1_dedge_t);
//mark surfaces
q1_nummarksurfaces = 0;
q1_dmarksurfaces = (unsigned short *) GetMemory(Q1_MAX_MAP_MARKSURFACES * sizeof(unsigned short));
q1_allocatedbspmem += Q1_MAX_MAP_MARKSURFACES * sizeof(unsigned short);
//surface edges
q1_numsurfedges = 0;
q1_dsurfedges = (int *) GetMemory(Q1_MAX_MAP_SURFEDGES * sizeof(int));
q1_allocatedbspmem += Q1_MAX_MAP_SURFEDGES * sizeof(int);
//print allocated memory
Log_Print("allocated ");
PrintMemorySize(q1_allocatedbspmem);
Log_Print(" of BSP memory\n");
} //end of the function Q1_AllocMaxBSP
void Q1_FreeMaxBSP(void)
{
//models
q1_nummodels = 0;
FreeMemory(q1_dmodels);
q1_dmodels = NULL;
//visibility
q1_visdatasize = 0;
FreeMemory(q1_dvisdata);
q1_dvisdata = NULL;
//light data
q1_lightdatasize = 0;
FreeMemory(q1_dlightdata);
q1_dlightdata = NULL;
//texture data
q1_texdatasize = 0;
FreeMemory(q1_dtexdata);
q1_dtexdata = NULL;
//entities
q1_entdatasize = 0;
FreeMemory(q1_dentdata);
q1_dentdata = NULL;
//leaves
q1_numleafs = 0;
FreeMemory(q1_dleafs);
q1_dleafs = NULL;
//planes
q1_numplanes = 0;
FreeMemory(q1_dplanes);
q1_dplanes = NULL;
//vertexes
q1_numvertexes = 0;
FreeMemory(q1_dvertexes);
q1_dvertexes = NULL;
//nodes
q1_numnodes = 0;
FreeMemory(q1_dnodes);
q1_dnodes = NULL;
//texture info
q1_numtexinfo = 0;
FreeMemory(q1_texinfo);
q1_texinfo = NULL;
//faces
q1_numfaces = 0;
FreeMemory(q1_dfaces);
q1_dfaces = NULL;
//clip nodes
q1_numclipnodes = 0;
FreeMemory(q1_dclipnodes);
q1_dclipnodes = NULL;
//edges
q1_numedges = 0;
FreeMemory(q1_dedges);
q1_dedges = NULL;
//mark surfaces
q1_nummarksurfaces = 0;
FreeMemory(q1_dmarksurfaces);
q1_dmarksurfaces = NULL;
//surface edges
q1_numsurfedges = 0;
FreeMemory(q1_dsurfedges);
q1_dsurfedges = NULL;
//
Log_Print("freed ");
PrintMemorySize(q1_allocatedbspmem);
Log_Print(" of BSP memory\n");
q1_allocatedbspmem = 0;
} //end of the function Q1_FreeMaxBSP
//#endif //ME
/*
=============
Q1_SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void Q1_SwapBSPFile (qboolean todisk)
{
int i, j, c;
q1_dmodel_t *d;
q1_dmiptexlump_t *mtl;
// models
for (i=0 ; i<q1_nummodels ; i++)
{
d = &q1_dmodels[i];
for (j=0 ; j<Q1_MAX_MAP_HULLS ; j++)
d->headnode[j] = LittleLong (d->headnode[j]);
d->visleafs = LittleLong (d->visleafs);
d->firstface = LittleLong (d->firstface);
d->numfaces = LittleLong (d->numfaces);
for (j=0 ; j<3 ; j++)
{
d->mins[j] = LittleFloat(d->mins[j]);
d->maxs[j] = LittleFloat(d->maxs[j]);
d->origin[j] = LittleFloat(d->origin[j]);
}
}
//
// vertexes
//
for (i=0 ; i<q1_numvertexes ; i++)
{
for (j=0 ; j<3 ; j++)
q1_dvertexes[i].point[j] = LittleFloat(q1_dvertexes[i].point[j]);
}
//
// planes
//
for (i=0 ; i<q1_numplanes ; i++)
{
for (j=0 ; j<3 ; j++)
q1_dplanes[i].normal[j] = LittleFloat(q1_dplanes[i].normal[j]);
q1_dplanes[i].dist = LittleFloat(q1_dplanes[i].dist);
q1_dplanes[i].type = LittleLong(q1_dplanes[i].type);
}
//
// texinfos
//
for (i=0 ; i<q1_numtexinfo ; i++)
{
for (j=0 ; j<8 ; j++)
q1_texinfo[i].vecs[0][j] = LittleFloat(q1_texinfo[i].vecs[0][j]);
q1_texinfo[i].miptex = LittleLong(q1_texinfo[i].miptex);
q1_texinfo[i].flags = LittleLong(q1_texinfo[i].flags);
}
//
// faces
//
for (i=0 ; i<q1_numfaces ; i++)
{
q1_dfaces[i].texinfo = LittleShort(q1_dfaces[i].texinfo);
q1_dfaces[i].planenum = LittleShort(q1_dfaces[i].planenum);
q1_dfaces[i].side = LittleShort(q1_dfaces[i].side);
q1_dfaces[i].lightofs = LittleLong(q1_dfaces[i].lightofs);
q1_dfaces[i].firstedge = LittleLong(q1_dfaces[i].firstedge);
q1_dfaces[i].numedges = LittleShort(q1_dfaces[i].numedges);
}
//
// nodes
//
for (i=0 ; i<q1_numnodes ; i++)
{
q1_dnodes[i].planenum = LittleLong(q1_dnodes[i].planenum);
for (j=0 ; j<3 ; j++)
{
q1_dnodes[i].mins[j] = LittleShort(q1_dnodes[i].mins[j]);
q1_dnodes[i].maxs[j] = LittleShort(q1_dnodes[i].maxs[j]);
}
q1_dnodes[i].children[0] = LittleShort(q1_dnodes[i].children[0]);
q1_dnodes[i].children[1] = LittleShort(q1_dnodes[i].children[1]);
q1_dnodes[i].firstface = LittleShort(q1_dnodes[i].firstface);
q1_dnodes[i].numfaces = LittleShort(q1_dnodes[i].numfaces);
}
//
// leafs
//
for (i=0 ; i<q1_numleafs ; i++)
{
q1_dleafs[i].contents = LittleLong(q1_dleafs[i].contents);
for (j=0 ; j<3 ; j++)
{
q1_dleafs[i].mins[j] = LittleShort(q1_dleafs[i].mins[j]);
q1_dleafs[i].maxs[j] = LittleShort(q1_dleafs[i].maxs[j]);
}
q1_dleafs[i].firstmarksurface = LittleShort(q1_dleafs[i].firstmarksurface);
q1_dleafs[i].nummarksurfaces = LittleShort(q1_dleafs[i].nummarksurfaces);
q1_dleafs[i].visofs = LittleLong(q1_dleafs[i].visofs);
}
//
// clipnodes
//
for (i=0 ; i<q1_numclipnodes ; i++)
{
q1_dclipnodes[i].planenum = LittleLong(q1_dclipnodes[i].planenum);
q1_dclipnodes[i].children[0] = LittleShort(q1_dclipnodes[i].children[0]);
q1_dclipnodes[i].children[1] = LittleShort(q1_dclipnodes[i].children[1]);
}
//
// miptex
//
if (q1_texdatasize)
{
mtl = (q1_dmiptexlump_t *)q1_dtexdata;
if (todisk)
c = mtl->nummiptex;
else
c = LittleLong(mtl->nummiptex);
mtl->nummiptex = LittleLong (mtl->nummiptex);
for (i=0 ; i<c ; i++)
mtl->dataofs[i] = LittleLong(mtl->dataofs[i]);
}
//
// marksurfaces
//
for (i=0 ; i<q1_nummarksurfaces ; i++)
q1_dmarksurfaces[i] = LittleShort(q1_dmarksurfaces[i]);
//
// surfedges
//
for (i=0 ; i<q1_numsurfedges ; i++)
q1_dsurfedges[i] = LittleLong(q1_dsurfedges[i]);
//
// edges
//
for (i=0 ; i<q1_numedges ; i++)
{
q1_dedges[i].v[0] = LittleShort(q1_dedges[i].v[0]);
q1_dedges[i].v[1] = LittleShort(q1_dedges[i].v[1]);
}
}
q1_dheader_t *q1_header;
int q1_fileLength;
int Q1_CopyLump (int lump, void *dest, int size, int maxsize)
{
int length, ofs;
length = q1_header->lumps[lump].filelen;
ofs = q1_header->lumps[lump].fileofs;
if (length % size) {
Error ("LoadBSPFile: odd lump size");
}
// somehow things got out of range
if ((length/size) > maxsize) {
printf("WARNING: exceeded max size for lump %d size %d > maxsize %d\n", lump, (length/size), maxsize);
length = maxsize * size;
}
if ( ofs + length > q1_fileLength ) {
printf("WARNING: exceeded file length for lump %d\n", lump);
length = q1_fileLength - ofs;
if ( length <= 0 ) {
return 0;
}
}
memcpy (dest, (byte *)q1_header + ofs, length);
return length / size;
}
/*
=============
Q1_LoadBSPFile
=============
*/
void Q1_LoadBSPFile(char *filename, int offset, int length)
{
int i;
//
// load the file header
//
q1_fileLength = LoadFile(filename, (void **)&q1_header, offset, length);
// swap the header
for (i=0 ; i< sizeof(q1_dheader_t)/4 ; i++)
((int *)q1_header)[i] = LittleLong ( ((int *)q1_header)[i]);
if (q1_header->version != Q1_BSPVERSION)
Error ("%s is version %i, not %i", filename, i, Q1_BSPVERSION);
q1_nummodels = Q1_CopyLump (Q1_LUMP_MODELS, q1_dmodels, sizeof(q1_dmodel_t), Q1_MAX_MAP_MODELS );
q1_numvertexes = Q1_CopyLump (Q1_LUMP_VERTEXES, q1_dvertexes, sizeof(q1_dvertex_t), Q1_MAX_MAP_VERTS );
q1_numplanes = Q1_CopyLump (Q1_LUMP_PLANES, q1_dplanes, sizeof(q1_dplane_t), Q1_MAX_MAP_PLANES );
q1_numleafs = Q1_CopyLump (Q1_LUMP_LEAFS, q1_dleafs, sizeof(q1_dleaf_t), Q1_MAX_MAP_LEAFS );
q1_numnodes = Q1_CopyLump (Q1_LUMP_NODES, q1_dnodes, sizeof(q1_dnode_t), Q1_MAX_MAP_NODES );
q1_numtexinfo = Q1_CopyLump (Q1_LUMP_TEXINFO, q1_texinfo, sizeof(q1_texinfo_t), Q1_MAX_MAP_TEXINFO );
q1_numclipnodes = Q1_CopyLump (Q1_LUMP_CLIPNODES, q1_dclipnodes, sizeof(q1_dclipnode_t), Q1_MAX_MAP_CLIPNODES );
q1_numfaces = Q1_CopyLump (Q1_LUMP_FACES, q1_dfaces, sizeof(q1_dface_t), Q1_MAX_MAP_FACES );
q1_nummarksurfaces = Q1_CopyLump (Q1_LUMP_MARKSURFACES, q1_dmarksurfaces, sizeof(q1_dmarksurfaces[0]), Q1_MAX_MAP_MARKSURFACES );
q1_numsurfedges = Q1_CopyLump (Q1_LUMP_SURFEDGES, q1_dsurfedges, sizeof(q1_dsurfedges[0]), Q1_MAX_MAP_SURFEDGES );
q1_numedges = Q1_CopyLump (Q1_LUMP_EDGES, q1_dedges, sizeof(q1_dedge_t), Q1_MAX_MAP_EDGES );
q1_texdatasize = Q1_CopyLump (Q1_LUMP_TEXTURES, q1_dtexdata, 1, Q1_MAX_MAP_MIPTEX );
q1_visdatasize = Q1_CopyLump (Q1_LUMP_VISIBILITY, q1_dvisdata, 1, Q1_MAX_MAP_VISIBILITY );
q1_lightdatasize = Q1_CopyLump (Q1_LUMP_LIGHTING, q1_dlightdata, 1, Q1_MAX_MAP_LIGHTING );
q1_entdatasize = Q1_CopyLump (Q1_LUMP_ENTITIES, q1_dentdata, 1, Q1_MAX_MAP_ENTSTRING );
FreeMemory(q1_header); // everything has been copied out
//
// swap everything
//
Q1_SwapBSPFile (false);
}
//============================================================================
FILE *q1_wadfile;
q1_dheader_t q1_outheader;
void Q1_AddLump (int lumpnum, void *data, int len)
{
q1_lump_t *lump;
lump = &q1_header->lumps[lumpnum];
lump->fileofs = LittleLong(ftell(q1_wadfile));
lump->filelen = LittleLong(len);
SafeWrite(q1_wadfile, data, (len+3)&~3);
}
/*
=============
Q1_WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void Q1_WriteBSPFile (char *filename)
{
q1_header = &q1_outheader;
memset (q1_header, 0, sizeof(q1_dheader_t));
Q1_SwapBSPFile (true);
q1_header->version = LittleLong (Q1_BSPVERSION);
q1_wadfile = SafeOpenWrite (filename);
SafeWrite (q1_wadfile, q1_header, sizeof(q1_dheader_t)); // overwritten later
Q1_AddLump (Q1_LUMP_PLANES, q1_dplanes, q1_numplanes*sizeof(q1_dplane_t));
Q1_AddLump (Q1_LUMP_LEAFS, q1_dleafs, q1_numleafs*sizeof(q1_dleaf_t));
Q1_AddLump (Q1_LUMP_VERTEXES, q1_dvertexes, q1_numvertexes*sizeof(q1_dvertex_t));
Q1_AddLump (Q1_LUMP_NODES, q1_dnodes, q1_numnodes*sizeof(q1_dnode_t));
Q1_AddLump (Q1_LUMP_TEXINFO, q1_texinfo, q1_numtexinfo*sizeof(q1_texinfo_t));
Q1_AddLump (Q1_LUMP_FACES, q1_dfaces, q1_numfaces*sizeof(q1_dface_t));
Q1_AddLump (Q1_LUMP_CLIPNODES, q1_dclipnodes, q1_numclipnodes*sizeof(q1_dclipnode_t));
Q1_AddLump (Q1_LUMP_MARKSURFACES, q1_dmarksurfaces, q1_nummarksurfaces*sizeof(q1_dmarksurfaces[0]));
Q1_AddLump (Q1_LUMP_SURFEDGES, q1_dsurfedges, q1_numsurfedges*sizeof(q1_dsurfedges[0]));
Q1_AddLump (Q1_LUMP_EDGES, q1_dedges, q1_numedges*sizeof(q1_dedge_t));
Q1_AddLump (Q1_LUMP_MODELS, q1_dmodels, q1_nummodels*sizeof(q1_dmodel_t));
Q1_AddLump (Q1_LUMP_LIGHTING, q1_dlightdata, q1_lightdatasize);
Q1_AddLump (Q1_LUMP_VISIBILITY, q1_dvisdata, q1_visdatasize);
Q1_AddLump (Q1_LUMP_ENTITIES, q1_dentdata, q1_entdatasize);
Q1_AddLump (Q1_LUMP_TEXTURES, q1_dtexdata, q1_texdatasize);
fseek (q1_wadfile, 0, SEEK_SET);
SafeWrite (q1_wadfile, q1_header, sizeof(q1_dheader_t));
fclose (q1_wadfile);
}
//============================================================================
/*
=============
Q1_PrintBSPFileSizes
Dumps info about current file
=============
*/
void Q1_PrintBSPFileSizes (void)
{
printf ("%5i planes %6i\n"
,q1_numplanes, (int)(q1_numplanes*sizeof(q1_dplane_t)));
printf ("%5i vertexes %6i\n"
,q1_numvertexes, (int)(q1_numvertexes*sizeof(q1_dvertex_t)));
printf ("%5i nodes %6i\n"
,q1_numnodes, (int)(q1_numnodes*sizeof(q1_dnode_t)));
printf ("%5i texinfo %6i\n"
,q1_numtexinfo, (int)(q1_numtexinfo*sizeof(q1_texinfo_t)));
printf ("%5i faces %6i\n"
,q1_numfaces, (int)(q1_numfaces*sizeof(q1_dface_t)));
printf ("%5i clipnodes %6i\n"
,q1_numclipnodes, (int)(q1_numclipnodes*sizeof(q1_dclipnode_t)));
printf ("%5i leafs %6i\n"
,q1_numleafs, (int)(q1_numleafs*sizeof(q1_dleaf_t)));
printf ("%5i marksurfaces %6i\n"
,q1_nummarksurfaces, (int)(q1_nummarksurfaces*sizeof(q1_dmarksurfaces[0])));
printf ("%5i surfedges %6i\n"
,q1_numsurfedges, (int)(q1_numsurfedges*sizeof(q1_dmarksurfaces[0])));
printf ("%5i edges %6i\n"
,q1_numedges, (int)(q1_numedges*sizeof(q1_dedge_t)));
if (!q1_texdatasize)
printf (" 0 textures 0\n");
else
printf ("%5i textures %6i\n",((q1_dmiptexlump_t*)q1_dtexdata)->nummiptex, q1_texdatasize);
printf (" lightdata %6i\n", q1_lightdatasize);
printf (" visdata %6i\n", q1_visdatasize);
printf (" entdata %6i\n", q1_entdatasize);
} //end of the function Q1_PrintBSPFileSizes
/*
================
Q1_ParseEntities
Parses the dentdata string into entities
================
*/
void Q1_ParseEntities (void)
{
script_t *script;
num_entities = 0;
script = LoadScriptMemory(q1_dentdata, q1_entdatasize, "*Quake1 bsp file");
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
SCFL_NOSTRINGESCAPECHARS);
while(ParseEntity(script))
{
} //end while
FreeScript(script);
} //end of the function Q1_ParseEntities
/*
================
Q1_UnparseEntities
Generates the dentdata string from all the entities
================
*/
void Q1_UnparseEntities (void)
{
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
buf = q1_dentdata;
end = buf;
*end = 0;
for (i=0 ; i<num_entities ; i++)
{
ep = entities[i].epairs;
if (!ep)
continue; // ent got removed
strcat (end,"{\n");
end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next)
{
sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
strcat (end, line);
end += strlen(line);
}
strcat (end,"}\n");
end += 2;
if (end > buf + Q1_MAX_MAP_ENTSTRING)
Error ("Entity text too long");
}
q1_entdatasize = end - buf + 1;
} //end of the function Q1_UnparseEntities

View File

@ -1,275 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// upper design bounds
#define Q1_MAX_MAP_HULLS 4
#define Q1_MAX_MAP_MODELS 256
#define Q1_MAX_MAP_BRUSHES 4096
#define Q1_MAX_MAP_ENTITIES 1024
#define Q1_MAX_MAP_ENTSTRING 65536
#define Q1_MAX_MAP_PLANES 8192
#define Q1_MAX_MAP_NODES 32767 // because negative shorts are contents
#define Q1_MAX_MAP_CLIPNODES 32767 //
#define Q1_MAX_MAP_LEAFS 32767 //
#define Q1_MAX_MAP_VERTS 65535
#define Q1_MAX_MAP_FACES 65535
#define Q1_MAX_MAP_MARKSURFACES 65535
#define Q1_MAX_MAP_TEXINFO 4096
#define Q1_MAX_MAP_EDGES 256000
#define Q1_MAX_MAP_SURFEDGES 512000
#define Q1_MAX_MAP_MIPTEX 0x200000
#define Q1_MAX_MAP_LIGHTING 0x100000
#define Q1_MAX_MAP_VISIBILITY 0x100000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
#define Q1_BSPVERSION 29
typedef struct
{
int fileofs, filelen;
} q1_lump_t;
#define Q1_LUMP_ENTITIES 0
#define Q1_LUMP_PLANES 1
#define Q1_LUMP_TEXTURES 2
#define Q1_LUMP_VERTEXES 3
#define Q1_LUMP_VISIBILITY 4
#define Q1_LUMP_NODES 5
#define Q1_LUMP_TEXINFO 6
#define Q1_LUMP_FACES 7
#define Q1_LUMP_LIGHTING 8
#define Q1_LUMP_CLIPNODES 9
#define Q1_LUMP_LEAFS 10
#define Q1_LUMP_MARKSURFACES 11
#define Q1_LUMP_EDGES 12
#define Q1_LUMP_SURFEDGES 13
#define Q1_LUMP_MODELS 14
#define Q1_HEADER_LUMPS 15
typedef struct
{
float mins[3], maxs[3];
float origin[3];
int headnode[Q1_MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} q1_dmodel_t;
typedef struct
{
int version;
q1_lump_t lumps[Q1_HEADER_LUMPS];
} q1_dheader_t;
typedef struct
{
int nummiptex;
int dataofs[4]; // [nummiptex]
} q1_dmiptexlump_t;
#define MIPLEVELS 4
typedef struct q1_miptex_s
{
char name[16];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
} q1_miptex_t;
typedef struct
{
float point[3];
} q1_dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} q1_dplane_t;
#define Q1_CONTENTS_EMPTY -1
#define Q1_CONTENTS_SOLID -2
#define Q1_CONTENTS_WATER -3
#define Q1_CONTENTS_SLIME -4
#define Q1_CONTENTS_LAVA -5
#define Q1_CONTENTS_SKY -6
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
int planenum;
short children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} q1_dnode_t;
typedef struct
{
int planenum;
short children[2]; // negative numbers are contents
} q1_dclipnode_t;
typedef struct q1_texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int miptex;
int flags;
} q1_texinfo_t;
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} q1_dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} q1_dface_t;
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
#define NUM_AMBIENTS 4 // automatic ambient sounds
// leaf 0 is the generic Q1_CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct
{
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
byte ambient_level[NUM_AMBIENTS];
} q1_dleaf_t;
//============================================================================
#ifndef QUAKE_GAME
// the utilities get to be lazy and just use large static arrays
extern int q1_nummodels;
extern q1_dmodel_t *q1_dmodels;//[MAX_MAP_MODELS];
extern int q1_visdatasize;
extern byte *q1_dvisdata;//[MAX_MAP_VISIBILITY];
extern int q1_lightdatasize;
extern byte *q1_dlightdata;//[MAX_MAP_LIGHTING];
extern int q1_texdatasize;
extern byte *q1_dtexdata;//[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
extern int q1_entdatasize;
extern char *q1_dentdata;//[MAX_MAP_ENTSTRING];
extern int q1_numleafs;
extern q1_dleaf_t *q1_dleafs;//[MAX_MAP_LEAFS];
extern int q1_numplanes;
extern q1_dplane_t *q1_dplanes;//[MAX_MAP_PLANES];
extern int q1_numvertexes;
extern q1_dvertex_t *q1_dvertexes;//[MAX_MAP_VERTS];
extern int q1_numnodes;
extern q1_dnode_t *q1_dnodes;//[MAX_MAP_NODES];
extern int q1_numtexinfo;
extern q1_texinfo_t *q1_texinfo;//[MAX_MAP_TEXINFO];
extern int q1_numfaces;
extern q1_dface_t *q1_dfaces;//[MAX_MAP_FACES];
extern int q1_numclipnodes;
extern q1_dclipnode_t *q1_dclipnodes;//[MAX_MAP_CLIPNODES];
extern int q1_numedges;
extern q1_dedge_t *q1_dedges;//[MAX_MAP_EDGES];
extern int q1_nummarksurfaces;
extern unsigned short *q1_dmarksurfaces;//[MAX_MAP_MARKSURFACES];
extern int q1_numsurfedges;
extern int *q1_dsurfedges;//[MAX_MAP_SURFEDGES];
void Q1_AllocMaxBSP(void);
void Q1_FreeMaxBSP(void);
void Q1_LoadBSPFile(char *filename, int offset, int length);
void Q1_WriteBSPFile(char *filename);
void Q1_PrintBSPFileSizes(void);
void Q1_ParseEntities(void);
void Q1_UnparseEntities(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,98 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef ME
#define ME
#endif //ME
extern int nummodels;
extern dmodel_t *dmodels;//[MAX_MAP_MODELS];
extern int visdatasize;
extern byte *dvisdata;//[MAX_MAP_VISIBILITY];
extern dvis_t *dvis;
extern int lightdatasize;
extern byte *dlightdata;//[MAX_MAP_LIGHTING];
extern int entdatasize;
extern char *dentdata;//[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t *dleafs;//[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t *dplanes;//[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t *dvertexes;//[MAX_MAP_VERTS];
extern int numnodes;
extern dnode_t *dnodes;//[MAX_MAP_NODES];
extern int numtexinfo;
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
extern int numfaces;
extern dface_t *dfaces;//[MAX_MAP_FACES];
extern int numedges;
extern dedge_t *dedges;//[MAX_MAP_EDGES];
extern int numleaffaces;
extern unsigned short *dleaffaces;//[MAX_MAP_LEAFFACES];
extern int numleafbrushes;
extern unsigned short *dleafbrushes;//[MAX_MAP_LEAFBRUSHES];
extern int numsurfedges;
extern int *dsurfedges;//[MAX_MAP_SURFEDGES];
extern int numareas;
extern darea_t *dareas;//[MAX_MAP_AREAS];
extern int numareaportals;
extern dareaportal_t *dareaportals;//[MAX_MAP_AREAPORTALS];
extern int numbrushes;
extern dbrush_t *dbrushes;//[MAX_MAP_BRUSHES];
extern int numbrushsides;
extern dbrushside_t *dbrushsides;//[MAX_MAP_BRUSHSIDES];
extern byte dpop[256];
extern char brushsidetextured[MAX_MAP_BRUSHSIDES];
void Q2_AllocMaxBSP(void);
void Q2_FreeMaxBSP(void);
void Q2_DecompressVis(byte *in, byte *decompressed);
int Q2_CompressVis(byte *vis, byte *dest);
void Q2_LoadBSPFile(char *filename, int offset, int length);
void Q2_LoadBSPFileTexinfo(char *filename); // just for qdata
void Q2_WriteBSPFile(char *filename);
void Q2_PrintBSPFileSizes(void);
void Q2_ParseEntities(void);
void Q2_UnparseEntities(void);

View File

@ -1,824 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "l_cmd.h"
#include "l_math.h"
#include "l_mem.h"
#include "l_log.h"
#include "l_poly.h"
#include "../botlib/l_script.h"
#include "l_qfiles.h"
#include "l_bsp_q3.h"
#include "l_bsp_ent.h"
void Q3_ParseEntities (void);
void Q3_PrintBSPFileSizes(void);
void GetLeafNums (void);
//=============================================================================
#define WCONVEX_EPSILON 0.5
int q3_nummodels;
q3_dmodel_t *q3_dmodels;//[MAX_MAP_MODELS];
int q3_numShaders;
q3_dshader_t *q3_dshaders;//[Q3_MAX_MAP_SHADERS];
int q3_entdatasize;
char *q3_dentdata;//[Q3_MAX_MAP_ENTSTRING];
int q3_numleafs;
q3_dleaf_t *q3_dleafs;//[Q3_MAX_MAP_LEAFS];
int q3_numplanes;
q3_dplane_t *q3_dplanes;//[Q3_MAX_MAP_PLANES];
int q3_numnodes;
q3_dnode_t *q3_dnodes;//[Q3_MAX_MAP_NODES];
int q3_numleafsurfaces;
int *q3_dleafsurfaces;//[Q3_MAX_MAP_LEAFFACES];
int q3_numleafbrushes;
int *q3_dleafbrushes;//[Q3_MAX_MAP_LEAFBRUSHES];
int q3_numbrushes;
q3_dbrush_t *q3_dbrushes;//[Q3_MAX_MAP_BRUSHES];
int q3_numbrushsides;
q3_dbrushside_t *q3_dbrushsides;//[Q3_MAX_MAP_BRUSHSIDES];
int q3_numLightBytes;
byte *q3_lightBytes;//[Q3_MAX_MAP_LIGHTING];
int q3_numGridPoints;
byte *q3_gridData;//[Q3_MAX_MAP_LIGHTGRID];
int q3_numVisBytes;
byte *q3_visBytes;//[Q3_MAX_MAP_VISIBILITY];
int q3_numDrawVerts;
q3_drawVert_t *q3_drawVerts;//[Q3_MAX_MAP_DRAW_VERTS];
int q3_numDrawIndexes;
int *q3_drawIndexes;//[Q3_MAX_MAP_DRAW_INDEXES];
int q3_numDrawSurfaces;
q3_dsurface_t *q3_drawSurfaces;//[Q3_MAX_MAP_DRAW_SURFS];
int q3_numFogs;
q3_dfog_t *q3_dfogs;//[Q3_MAX_MAP_FOGS];
char q3_dbrushsidetextured[Q3_MAX_MAP_BRUSHSIDES];
extern qboolean forcesidesvisible;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_FreeMaxBSP(void)
{
if (q3_dmodels) FreeMemory(q3_dmodels);
q3_dmodels = NULL;
q3_nummodels = 0;
if (q3_dshaders) FreeMemory(q3_dshaders);
q3_dshaders = NULL;
q3_numShaders = 0;
if (q3_dentdata) FreeMemory(q3_dentdata);
q3_dentdata = NULL;
q3_entdatasize = 0;
if (q3_dleafs) FreeMemory(q3_dleafs);
q3_dleafs = NULL;
q3_numleafs = 0;
if (q3_dplanes) FreeMemory(q3_dplanes);
q3_dplanes = NULL;
q3_numplanes = 0;
if (q3_dnodes) FreeMemory(q3_dnodes);
q3_dnodes = NULL;
q3_numnodes = 0;
if (q3_dleafsurfaces) FreeMemory(q3_dleafsurfaces);
q3_dleafsurfaces = NULL;
q3_numleafsurfaces = 0;
if (q3_dleafbrushes) FreeMemory(q3_dleafbrushes);
q3_dleafbrushes = NULL;
q3_numleafbrushes = 0;
if (q3_dbrushes) FreeMemory(q3_dbrushes);
q3_dbrushes = NULL;
q3_numbrushes = 0;
if (q3_dbrushsides) FreeMemory(q3_dbrushsides);
q3_dbrushsides = NULL;
q3_numbrushsides = 0;
if (q3_lightBytes) FreeMemory(q3_lightBytes);
q3_lightBytes = NULL;
q3_numLightBytes = 0;
if (q3_gridData) FreeMemory(q3_gridData);
q3_gridData = NULL;
q3_numGridPoints = 0;
if (q3_visBytes) FreeMemory(q3_visBytes);
q3_visBytes = NULL;
q3_numVisBytes = 0;
if (q3_drawVerts) FreeMemory(q3_drawVerts);
q3_drawVerts = NULL;
q3_numDrawVerts = 0;
if (q3_drawIndexes) FreeMemory(q3_drawIndexes);
q3_drawIndexes = NULL;
q3_numDrawIndexes = 0;
if (q3_drawSurfaces) FreeMemory(q3_drawSurfaces);
q3_drawSurfaces = NULL;
q3_numDrawSurfaces = 0;
if (q3_dfogs) FreeMemory(q3_dfogs);
q3_dfogs = NULL;
q3_numFogs = 0;
} //end of the function Q3_FreeMaxBSP
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_PlaneFromPoints(vec3_t p0, vec3_t p1, vec3_t p2, vec3_t normal, float *dist)
{
vec3_t t1, t2;
VectorSubtract(p0, p1, t1);
VectorSubtract(p2, p1, t2);
CrossProduct(t1, t2, normal);
VectorNormalize(normal);
*dist = DotProduct(p0, normal);
} //end of the function PlaneFromPoints
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist)
{
int i;
float *p0, *p1, *p2;
vec3_t t1, t2;
p0 = q3_drawVerts[surface->firstVert].xyz;
for (i = 1; i < surface->numVerts-1; i++)
{
p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
p2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
VectorSubtract(p0, p1, t1);
VectorSubtract(p2, p1, t2);
CrossProduct(t1, t2, normal);
VectorNormalize(normal);
if (VectorLength(normal)) break;
} //end for*/
/*
float dot;
for (i = 0; i < surface->numVerts; i++)
{
p0 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
p1 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
p2 = q3_drawVerts[surface->firstVert + ((i+2) % surface->numVerts)].xyz;
VectorSubtract(p0, p1, t1);
VectorSubtract(p2, p1, t2);
VectorNormalize(t1);
VectorNormalize(t2);
dot = DotProduct(t1, t2);
if (dot > -0.9 && dot < 0.9 &&
VectorLength(t1) > 0.1 && VectorLength(t2) > 0.1) break;
} //end for
CrossProduct(t1, t2, normal);
VectorNormalize(normal);
*/
if (VectorLength(normal) < 0.9)
{
printf("surface %d bogus normal vector %f %f %f\n", surface - q3_drawSurfaces, normal[0], normal[1], normal[2]);
printf("t1 = %f %f %f, t2 = %f %f %f\n", t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]);
for (i = 0; i < surface->numVerts; i++)
{
p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
Log_Print("p%d = %f %f %f\n", i, p1[0], p1[1], p1[2]);
} //end for
} //end if
*dist = DotProduct(p0, normal);
} //end of the function Q3_SurfacePlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
q3_dplane_t *q3_surfaceplanes;
void Q3_CreatePlanarSurfacePlanes(void)
{
int i;
q3_dsurface_t *surface;
Log_Print("creating planar surface planes...\n");
q3_surfaceplanes = (q3_dplane_t *) GetClearedMemory(q3_numDrawSurfaces * sizeof(q3_dplane_t));
for (i = 0; i < q3_numDrawSurfaces; i++)
{
surface = &q3_drawSurfaces[i];
if (surface->surfaceType != MST_PLANAR) continue;
Q3_SurfacePlane(surface, q3_surfaceplanes[i].normal, &q3_surfaceplanes[i].dist);
//Log_Print("normal = %f %f %f, dist = %f\n", q3_surfaceplanes[i].normal[0],
// q3_surfaceplanes[i].normal[1],
// q3_surfaceplanes[i].normal[2], q3_surfaceplanes[i].dist);
} //end for
} //end of the function Q3_CreatePlanarSurfacePlanes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
/*
void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist)
{
//take the plane information from the lightmap vector
//VectorCopy(surface->lightmapVecs[2], normal);
//calculate plane dist with first surface vertex
//*dist = DotProduct(q3_drawVerts[surface->firstVert].xyz, normal);
Q3_PlaneFromPoints(q3_drawVerts[surface->firstVert].xyz,
q3_drawVerts[surface->firstVert+1].xyz,
q3_drawVerts[surface->firstVert+2].xyz, normal, dist);
} //end of the function Q3_SurfacePlane*/
//===========================================================================
// returns the amount the face and the winding overlap
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float Q3_FaceOnWinding(q3_dsurface_t *surface, winding_t *winding)
{
int i;
float dist, area;
q3_dplane_t plane;
vec_t *v1, *v2;
vec3_t normal, edgevec;
winding_t *w;
//copy the winding before chopping
w = CopyWinding(winding);
//retrieve the surface plane
Q3_SurfacePlane(surface, plane.normal, &plane.dist);
//chop the winding with the surface edge planes
for (i = 0; i < surface->numVerts && w; i++)
{
v1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
v2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
//create a plane through the edge from v1 to v2, orthogonal to the
//surface plane and with the normal vector pointing inward
VectorSubtract(v2, v1, edgevec);
CrossProduct(edgevec, plane.normal, normal);
VectorNormalize(normal);
dist = DotProduct(normal, v1);
//
ChopWindingInPlace(&w, normal, dist, -0.1); //CLIP_EPSILON
} //end for
if (w)
{
area = WindingArea(w);
FreeWinding(w);
return area;
} //end if
return 0;
} //end of the function Q3_FaceOnWinding
//===========================================================================
// creates a winding for the given brush side on the given brush
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
winding_t *Q3_BrushSideWinding(q3_dbrush_t *brush, q3_dbrushside_t *baseside)
{
int i;
q3_dplane_t *baseplane, *plane;
winding_t *w;
q3_dbrushside_t *side;
//create a winding for the brush side with the given planenumber
baseplane = &q3_dplanes[baseside->planeNum];
w = BaseWindingForPlane(baseplane->normal, baseplane->dist);
for (i = 0; i < brush->numSides && w; i++)
{
side = &q3_dbrushsides[brush->firstSide + i];
//don't chop with the base plane
if (side->planeNum == baseside->planeNum) continue;
//also don't use planes that are almost equal
plane = &q3_dplanes[side->planeNum];
if (DotProduct(baseplane->normal, plane->normal) > 0.999
&& fabs(baseplane->dist - plane->dist) < 0.01) continue;
//
plane = &q3_dplanes[side->planeNum^1];
ChopWindingInPlace(&w, plane->normal, plane->dist, -0.1); //CLIP_EPSILON);
} //end for
return w;
} //end of the function Q3_BrushSideWinding
//===========================================================================
// fix screwed brush texture references
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WindingIsTiny(winding_t *w);
void Q3_FindVisibleBrushSides(void)
{
int i, j, k, we, numtextured, numsides;
float dot;
q3_dplane_t *plane;
q3_dbrushside_t *brushside;
q3_dbrush_t *brush;
q3_dsurface_t *surface;
winding_t *w;
memset(q3_dbrushsidetextured, false, Q3_MAX_MAP_BRUSHSIDES);
//
numsides = 0;
//create planes for the planar surfaces
Q3_CreatePlanarSurfacePlanes();
Log_Print("searching visible brush sides...\n");
Log_Print("%6d brush sides", numsides);
//go over all the brushes
for (i = 0; i < q3_numbrushes; i++)
{
brush = &q3_dbrushes[i];
//go over all the sides of the brush
for (j = 0; j < brush->numSides; j++)
{
qprintf("\r%6d", numsides++);
brushside = &q3_dbrushsides[brush->firstSide + j];
//
w = Q3_BrushSideWinding(brush, brushside);
if (!w)
{
q3_dbrushsidetextured[brush->firstSide + j] = true;
continue;
} //end if
else
{
//RemoveEqualPoints(w, 0.2);
if (WindingIsTiny(w))
{
FreeWinding(w);
q3_dbrushsidetextured[brush->firstSide + j] = true;
continue;
} //end if
else
{
we = WindingError(w);
if (we == WE_NOTENOUGHPOINTS
|| we == WE_SMALLAREA
|| we == WE_POINTBOGUSRANGE
// || we == WE_NONCONVEX
)
{
FreeWinding(w);
q3_dbrushsidetextured[brush->firstSide + j] = true;
continue;
} //end if
} //end else
} //end else
if (WindingArea(w) < 20)
{
q3_dbrushsidetextured[brush->firstSide + j] = true;
continue;
} //end if
//find a face for texturing this brush
for (k = 0; k < q3_numDrawSurfaces; k++)
{
surface = &q3_drawSurfaces[k];
if (surface->surfaceType != MST_PLANAR) continue;
//
//Q3_SurfacePlane(surface, plane.normal, &plane.dist);
plane = &q3_surfaceplanes[k];
//the surface plane and the brush side plane should be pretty much the same
if (fabs(fabs(plane->dist) - fabs(q3_dplanes[brushside->planeNum].dist)) > 5) continue;
dot = DotProduct(plane->normal, q3_dplanes[brushside->planeNum].normal);
if (dot > -0.9 && dot < 0.9) continue;
//if the face is partly or totally on the brush side
if (Q3_FaceOnWinding(surface, w))
{
q3_dbrushsidetextured[brush->firstSide + j] = true;
//Log_Write("Q3_FaceOnWinding");
break;
} //end if
} //end for
FreeWinding(w);
} //end for
} //end for
qprintf("\r%6d brush sides\n", numsides);
numtextured = 0;
for (i = 0; i < q3_numbrushsides; i++)
{
if (forcesidesvisible) q3_dbrushsidetextured[i] = true;
if (q3_dbrushsidetextured[i]) numtextured++;
} //end for
Log_Print("%d brush sides textured out of %d\n", numtextured, q3_numbrushsides);
} //end of the function Q3_FindVisibleBrushSides
/*
=============
Q3_SwapBlock
If all values are 32 bits, this can be used to swap everything
=============
*/
void Q3_SwapBlock( int *block, int sizeOfBlock ) {
int i;
sizeOfBlock >>= 2;
for ( i = 0 ; i < sizeOfBlock ; i++ ) {
block[i] = LittleLong( block[i] );
}
} //end of the function Q3_SwapBlock
/*
=============
Q3_SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void Q3_SwapBSPFile( void ) {
int i;
// models
Q3_SwapBlock( (int *)q3_dmodels, q3_nummodels * sizeof( q3_dmodels[0] ) );
// shaders (don't swap the name)
for ( i = 0 ; i < q3_numShaders ; i++ ) {
q3_dshaders[i].contentFlags = LittleLong( q3_dshaders[i].contentFlags );
q3_dshaders[i].surfaceFlags = LittleLong( q3_dshaders[i].surfaceFlags );
}
// planes
Q3_SwapBlock( (int *)q3_dplanes, q3_numplanes * sizeof( q3_dplanes[0] ) );
// nodes
Q3_SwapBlock( (int *)q3_dnodes, q3_numnodes * sizeof( q3_dnodes[0] ) );
// leafs
Q3_SwapBlock( (int *)q3_dleafs, q3_numleafs * sizeof( q3_dleafs[0] ) );
// leaffaces
Q3_SwapBlock( (int *)q3_dleafsurfaces, q3_numleafsurfaces * sizeof( q3_dleafsurfaces[0] ) );
// leafbrushes
Q3_SwapBlock( (int *)q3_dleafbrushes, q3_numleafbrushes * sizeof( q3_dleafbrushes[0] ) );
// brushes
Q3_SwapBlock( (int *)q3_dbrushes, q3_numbrushes * sizeof( q3_dbrushes[0] ) );
// brushsides
Q3_SwapBlock( (int *)q3_dbrushsides, q3_numbrushsides * sizeof( q3_dbrushsides[0] ) );
// vis
((int *)&q3_visBytes)[0] = LittleLong( ((int *)&q3_visBytes)[0] );
((int *)&q3_visBytes)[1] = LittleLong( ((int *)&q3_visBytes)[1] );
// drawverts (don't swap colors )
for ( i = 0 ; i < q3_numDrawVerts ; i++ ) {
q3_drawVerts[i].lightmap[0] = LittleFloat( q3_drawVerts[i].lightmap[0] );
q3_drawVerts[i].lightmap[1] = LittleFloat( q3_drawVerts[i].lightmap[1] );
q3_drawVerts[i].st[0] = LittleFloat( q3_drawVerts[i].st[0] );
q3_drawVerts[i].st[1] = LittleFloat( q3_drawVerts[i].st[1] );
q3_drawVerts[i].xyz[0] = LittleFloat( q3_drawVerts[i].xyz[0] );
q3_drawVerts[i].xyz[1] = LittleFloat( q3_drawVerts[i].xyz[1] );
q3_drawVerts[i].xyz[2] = LittleFloat( q3_drawVerts[i].xyz[2] );
q3_drawVerts[i].normal[0] = LittleFloat( q3_drawVerts[i].normal[0] );
q3_drawVerts[i].normal[1] = LittleFloat( q3_drawVerts[i].normal[1] );
q3_drawVerts[i].normal[2] = LittleFloat( q3_drawVerts[i].normal[2] );
}
// drawindexes
Q3_SwapBlock( (int *)q3_drawIndexes, q3_numDrawIndexes * sizeof( q3_drawIndexes[0] ) );
// drawsurfs
Q3_SwapBlock( (int *)q3_drawSurfaces, q3_numDrawSurfaces * sizeof( q3_drawSurfaces[0] ) );
// fogs
for ( i = 0 ; i < q3_numFogs ; i++ ) {
q3_dfogs[i].brushNum = LittleLong( q3_dfogs[i].brushNum );
}
}
/*
=============
Q3_CopyLump
=============
*/
int Q3_CopyLump( q3_dheader_t *header, int lump, void **dest, int size ) {
int length, ofs;
length = header->lumps[lump].filelen;
ofs = header->lumps[lump].fileofs;
if ( length % size ) {
Error ("Q3_LoadBSPFile: odd lump size");
}
*dest = GetMemory(length);
memcpy( *dest, (byte *)header + ofs, length );
return length / size;
}
/*
=============
CountTriangles
=============
*/
void CountTriangles( void ) {
int i, numTris, numPatchTris;
q3_dsurface_t *surface;
numTris = numPatchTris = 0;
for ( i = 0; i < q3_numDrawSurfaces; i++ ) {
surface = &q3_drawSurfaces[i];
numTris += surface->numIndexes / 3;
if ( surface->patchWidth ) {
numPatchTris += surface->patchWidth * surface->patchHeight * 2;
}
}
Log_Print( "%6d triangles\n", numTris );
Log_Print( "%6d patch tris\n", numPatchTris );
}
/*
=============
Q3_LoadBSPFile
=============
*/
void Q3_LoadBSPFile(struct quakefile_s *qf)
{
q3_dheader_t *header;
// load the file header
//LoadFile(filename, (void **)&header, offset, length);
//
LoadQuakeFile(qf, (void **)&header);
// swap the header
Q3_SwapBlock( (int *)header, sizeof(*header) );
if ( header->ident != Q3_BSP_IDENT ) {
Error( "%s is not a IBSP file", qf->filename );
}
if ( header->version != Q3_BSP_VERSION ) {
Error( "%s is version %i, not %i", qf->filename, header->version, Q3_BSP_VERSION );
}
q3_numShaders = Q3_CopyLump( header, Q3_LUMP_SHADERS, (void *) &q3_dshaders, sizeof(q3_dshader_t) );
q3_nummodels = Q3_CopyLump( header, Q3_LUMP_MODELS, (void *) &q3_dmodels, sizeof(q3_dmodel_t) );
q3_numplanes = Q3_CopyLump( header, Q3_LUMP_PLANES, (void *) &q3_dplanes, sizeof(q3_dplane_t) );
q3_numleafs = Q3_CopyLump( header, Q3_LUMP_LEAFS, (void *) &q3_dleafs, sizeof(q3_dleaf_t) );
q3_numnodes = Q3_CopyLump( header, Q3_LUMP_NODES, (void *) &q3_dnodes, sizeof(q3_dnode_t) );
q3_numleafsurfaces = Q3_CopyLump( header, Q3_LUMP_LEAFSURFACES, (void *) &q3_dleafsurfaces, sizeof(q3_dleafsurfaces[0]) );
q3_numleafbrushes = Q3_CopyLump( header, Q3_LUMP_LEAFBRUSHES, (void *) &q3_dleafbrushes, sizeof(q3_dleafbrushes[0]) );
q3_numbrushes = Q3_CopyLump( header, Q3_LUMP_BRUSHES, (void *) &q3_dbrushes, sizeof(q3_dbrush_t) );
q3_numbrushsides = Q3_CopyLump( header, Q3_LUMP_BRUSHSIDES, (void *) &q3_dbrushsides, sizeof(q3_dbrushside_t) );
q3_numDrawVerts = Q3_CopyLump( header, Q3_LUMP_DRAWVERTS, (void *) &q3_drawVerts, sizeof(q3_drawVert_t) );
q3_numDrawSurfaces = Q3_CopyLump( header, Q3_LUMP_SURFACES, (void *) &q3_drawSurfaces, sizeof(q3_dsurface_t) );
q3_numFogs = Q3_CopyLump( header, Q3_LUMP_FOGS, (void *) &q3_dfogs, sizeof(q3_dfog_t) );
q3_numDrawIndexes = Q3_CopyLump( header, Q3_LUMP_DRAWINDEXES, (void *) &q3_drawIndexes, sizeof(q3_drawIndexes[0]) );
q3_numVisBytes = Q3_CopyLump( header, Q3_LUMP_VISIBILITY, (void *) &q3_visBytes, 1 );
q3_numLightBytes = Q3_CopyLump( header, Q3_LUMP_LIGHTMAPS, (void *) &q3_lightBytes, 1 );
q3_entdatasize = Q3_CopyLump( header, Q3_LUMP_ENTITIES, (void *) &q3_dentdata, 1);
q3_numGridPoints = Q3_CopyLump( header, Q3_LUMP_LIGHTGRID, (void *) &q3_gridData, 8 );
CountTriangles();
FreeMemory( header ); // everything has been copied out
// swap everything
Q3_SwapBSPFile();
Q3_FindVisibleBrushSides();
//Q3_PrintBSPFileSizes();
}
//============================================================================
/*
=============
Q3_AddLump
=============
*/
void Q3_AddLump( FILE *bspfile, q3_dheader_t *header, int lumpnum, void *data, int len ) {
q3_lump_t *lump;
lump = &header->lumps[lumpnum];
lump->fileofs = LittleLong( ftell(bspfile) );
lump->filelen = LittleLong( len );
SafeWrite( bspfile, data, (len+3)&~3 );
}
/*
=============
Q3_WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void Q3_WriteBSPFile( char *filename )
{
q3_dheader_t outheader, *header;
FILE *bspfile;
header = &outheader;
memset( header, 0, sizeof(q3_dheader_t) );
Q3_SwapBSPFile();
header->ident = LittleLong( Q3_BSP_IDENT );
header->version = LittleLong( Q3_BSP_VERSION );
bspfile = SafeOpenWrite( filename );
SafeWrite( bspfile, header, sizeof(q3_dheader_t) ); // overwritten later
Q3_AddLump( bspfile, header, Q3_LUMP_SHADERS, q3_dshaders, q3_numShaders*sizeof(q3_dshader_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_PLANES, q3_dplanes, q3_numplanes*sizeof(q3_dplane_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_LEAFS, q3_dleafs, q3_numleafs*sizeof(q3_dleaf_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_NODES, q3_dnodes, q3_numnodes*sizeof(q3_dnode_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHES, q3_dbrushes, q3_numbrushes*sizeof(q3_dbrush_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHSIDES, q3_dbrushsides, q3_numbrushsides*sizeof(q3_dbrushside_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_LEAFSURFACES, q3_dleafsurfaces, q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0]) );
Q3_AddLump( bspfile, header, Q3_LUMP_LEAFBRUSHES, q3_dleafbrushes, q3_numleafbrushes*sizeof(q3_dleafbrushes[0]) );
Q3_AddLump( bspfile, header, Q3_LUMP_MODELS, q3_dmodels, q3_nummodels*sizeof(q3_dmodel_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_DRAWVERTS, q3_drawVerts, q3_numDrawVerts*sizeof(q3_drawVert_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_SURFACES, q3_drawSurfaces, q3_numDrawSurfaces*sizeof(q3_dsurface_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_VISIBILITY, q3_visBytes, q3_numVisBytes );
Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTMAPS, q3_lightBytes, q3_numLightBytes );
Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTGRID, q3_gridData, 8 * q3_numGridPoints );
Q3_AddLump( bspfile, header, Q3_LUMP_ENTITIES, q3_dentdata, q3_entdatasize );
Q3_AddLump( bspfile, header, Q3_LUMP_FOGS, q3_dfogs, q3_numFogs * sizeof(q3_dfog_t) );
Q3_AddLump( bspfile, header, Q3_LUMP_DRAWINDEXES, q3_drawIndexes, q3_numDrawIndexes * sizeof(q3_drawIndexes[0]) );
fseek (bspfile, 0, SEEK_SET);
SafeWrite (bspfile, header, sizeof(q3_dheader_t));
fclose (bspfile);
}
//============================================================================
/*
=============
Q3_PrintBSPFileSizes
Dumps info about current file
=============
*/
void Q3_PrintBSPFileSizes( void )
{
if ( !num_entities )
{
Q3_ParseEntities();
}
Log_Print ("%6i models %7i\n"
,q3_nummodels, (int)(q3_nummodels*sizeof(q3_dmodel_t)));
Log_Print ("%6i shaders %7i\n"
,q3_numShaders, (int)(q3_numShaders*sizeof(q3_dshader_t)));
Log_Print ("%6i brushes %7i\n"
,q3_numbrushes, (int)(q3_numbrushes*sizeof(q3_dbrush_t)));
Log_Print ("%6i brushsides %7i\n"
,q3_numbrushsides, (int)(q3_numbrushsides*sizeof(q3_dbrushside_t)));
Log_Print ("%6i fogs %7i\n"
,q3_numFogs, (int)(q3_numFogs*sizeof(q3_dfog_t)));
Log_Print ("%6i planes %7i\n"
,q3_numplanes, (int)(q3_numplanes*sizeof(q3_dplane_t)));
Log_Print ("%6i entdata %7i\n", num_entities, q3_entdatasize);
Log_Print ("\n");
Log_Print ("%6i nodes %7i\n"
,q3_numnodes, (int)(q3_numnodes*sizeof(q3_dnode_t)));
Log_Print ("%6i leafs %7i\n"
,q3_numleafs, (int)(q3_numleafs*sizeof(q3_dleaf_t)));
Log_Print ("%6i leafsurfaces %7i\n"
,q3_numleafsurfaces, (int)(q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0])));
Log_Print ("%6i leafbrushes %7i\n"
,q3_numleafbrushes, (int)(q3_numleafbrushes*sizeof(q3_dleafbrushes[0])));
Log_Print ("%6i drawverts %7i\n"
,q3_numDrawVerts, (int)(q3_numDrawVerts*sizeof(q3_drawVerts[0])));
Log_Print ("%6i drawindexes %7i\n"
,q3_numDrawIndexes, (int)(q3_numDrawIndexes*sizeof(q3_drawIndexes[0])));
Log_Print ("%6i drawsurfaces %7i\n"
,q3_numDrawSurfaces, (int)(q3_numDrawSurfaces*sizeof(q3_drawSurfaces[0])));
Log_Print ("%6i lightmaps %7i\n"
,q3_numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), q3_numLightBytes );
Log_Print (" visibility %7i\n"
, q3_numVisBytes );
}
/*
================
Q3_ParseEntities
Parses the q3_dentdata string into entities
================
*/
void Q3_ParseEntities (void)
{
script_t *script;
num_entities = 0;
script = LoadScriptMemory(q3_dentdata, q3_entdatasize, "*Quake3 bsp file");
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
SCFL_NOSTRINGESCAPECHARS);
while(ParseEntity(script))
{
} //end while
FreeScript(script);
} //end of the function Q3_ParseEntities
/*
================
Q3_UnparseEntities
Generates the q3_dentdata string from all the entities
================
*/
void Q3_UnparseEntities (void)
{
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
buf = q3_dentdata;
end = buf;
*end = 0;
for (i=0 ; i<num_entities ; i++)
{
ep = entities[i].epairs;
if (!ep)
continue; // ent got removed
strcat (end,"{\n");
end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next)
{
sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
strcat (end, line);
end += strlen(line);
}
strcat (end,"}\n");
end += 2;
if (end > buf + Q3_MAX_MAP_ENTSTRING)
Error ("Entity text too long");
}
q3_entdatasize = end - buf + 1;
} //end of the function Q3_UnparseEntities

View File

@ -1,81 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "q3files.h"
//#include "surfaceflags.h"
extern int q3_nummodels;
extern q3_dmodel_t *q3_dmodels;//[MAX_MAP_MODELS];
extern int q3_numShaders;
extern q3_dshader_t *q3_dshaders;//[Q3_MAX_MAP_SHADERS];
extern int q3_entdatasize;
extern char *q3_dentdata;//[Q3_MAX_MAP_ENTSTRING];
extern int q3_numleafs;
extern q3_dleaf_t *q3_dleafs;//[Q3_MAX_MAP_LEAFS];
extern int q3_numplanes;
extern q3_dplane_t *q3_dplanes;//[Q3_MAX_MAP_PLANES];
extern int q3_numnodes;
extern q3_dnode_t *q3_dnodes;//[Q3_MAX_MAP_NODES];
extern int q3_numleafsurfaces;
extern int *q3_dleafsurfaces;//[Q3_MAX_MAP_LEAFFACES];
extern int q3_numleafbrushes;
extern int *q3_dleafbrushes;//[Q3_MAX_MAP_LEAFBRUSHES];
extern int q3_numbrushes;
extern q3_dbrush_t *q3_dbrushes;//[Q3_MAX_MAP_BRUSHES];
extern int q3_numbrushsides;
extern q3_dbrushside_t *q3_dbrushsides;//[Q3_MAX_MAP_BRUSHSIDES];
extern int q3_numLightBytes;
extern byte *q3_lightBytes;//[Q3_MAX_MAP_LIGHTING];
extern int q3_numGridPoints;
extern byte *q3_gridData;//[Q3_MAX_MAP_LIGHTGRID];
extern int q3_numVisBytes;
extern byte *q3_visBytes;//[Q3_MAX_MAP_VISIBILITY];
extern int q3_numDrawVerts;
extern q3_drawVert_t *q3_drawVerts;//[Q3_MAX_MAP_DRAW_VERTS];
extern int q3_numDrawIndexes;
extern int *q3_drawIndexes;//[Q3_MAX_MAP_DRAW_INDEXES];
extern int q3_numDrawSurfaces;
extern q3_dsurface_t *q3_drawSurfaces;//[Q3_MAX_MAP_DRAW_SURFS];
extern int q3_numFogs;
extern q3_dfog_t *q3_dfogs;//[Q3_MAX_MAP_FOGS];
extern char q3_dbrushsidetextured[Q3_MAX_MAP_BRUSHSIDES];
void Q3_LoadBSPFile(struct quakefile_s *qf);
void Q3_FreeMaxBSP(void);
void Q3_ParseEntities (void);

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "sinfiles.h"
#define SINGAME_BSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'R') //RBSP
#define SINGAME_BSPVERSION 1
#define SIN_BSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') //IBSP
#define SIN_BSPVERSION 41
extern int sin_nummodels;
extern sin_dmodel_t *sin_dmodels;//[MAX_MAP_MODELS];
extern int sin_visdatasize;
extern byte *sin_dvisdata;//[MAX_MAP_VISIBILITY];
extern sin_dvis_t *sin_dvis;// = (dvis_t *)sin_sin_dvisdata;
extern int sin_lightdatasize;
extern byte *sin_dlightdata;//[MAX_MAP_LIGHTING];
extern int sin_entdatasize;
extern char *sin_dentdata;//[MAX_MAP_ENTSTRING];
extern int sin_numleafs;
extern sin_dleaf_t *sin_dleafs;//[MAX_MAP_LEAFS];
extern int sin_numplanes;
extern sin_dplane_t *sin_dplanes;//[MAX_MAP_PLANES];
extern int sin_numvertexes;
extern sin_dvertex_t *sin_dvertexes;//[MAX_MAP_VERTS];
extern int sin_numnodes;
extern sin_dnode_t *sin_dnodes;//[MAX_MAP_NODES];
extern int sin_numtexinfo;
extern sin_texinfo_t *sin_texinfo;//[MAX_MAP_sin_texinfo];
extern int sin_numfaces;
extern sin_dface_t *sin_dfaces;//[MAX_MAP_FACES];
extern int sin_numedges;
extern sin_dedge_t *sin_dedges;//[MAX_MAP_EDGES];
extern int sin_numleaffaces;
extern unsigned short *sin_dleaffaces;//[MAX_MAP_LEAFFACES];
extern int sin_numleafbrushes;
extern unsigned short *sin_dleafbrushes;//[MAX_MAP_LEAFBRUSHES];
extern int sin_numsurfedges;
extern int *sin_dsurfedges;//[MAX_MAP_SURFEDGES];
extern int sin_numbrushes;
extern sin_dbrush_t *sin_dbrushes;//[MAX_MAP_BRUSHES];
extern int sin_numbrushsides;
extern sin_dbrushside_t *sin_dbrushsides;//[MAX_MAP_BRUSHSIDES];
extern int sin_numareas;
extern sin_darea_t *sin_dareas;//[MAX_MAP_AREAS];
extern int sin_numareaportals;
extern sin_dareaportal_t *sin_dareaportals;//[MAX_MAP_AREAPORTALS];
extern int sin_numlightinfo;
extern sin_lightvalue_t *sin_lightinfo;//[MAX_MAP_LIGHTINFO];
extern byte sin_dpop[256];
extern char sin_dbrushsidetextured[SIN_MAX_MAP_BRUSHSIDES];
void Sin_AllocMaxBSP(void);
void Sin_FreeMaxBSP(void);
void Sin_DecompressVis(byte *in, byte *decompressed);
int Sin_CompressVis(byte *vis, byte *dest);
void Sin_LoadBSPFile (char *filename, int offset, int length);
void Sin_LoadBSPFileTexinfo (char *filename); // just for qdata
void Sin_WriteBSPFile (char *filename);
void Sin_PrintBSPFileSizes (void);
void Sin_ParseEntities(void);
void Sin_UnparseEntities(void);

File diff suppressed because it is too large Load Diff

View File

@ -1,157 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// cmdlib.h
#ifndef SIN
#define SIN
#endif //SIN
#ifndef __CMDLIB__
#define __CMDLIB__
#ifdef _WIN32
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#pragma warning(disable : 4018) // signed/unsigned mismatch
#pragma warning(disable : 4305) // truncate from double to float
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
typedef enum {false, true} qboolean;
typedef unsigned char byte;
#endif
// the dec offsetof macro doesnt work very well...
#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
// set these before calling CheckParm
extern int myargc;
extern char **myargv;
char *strupr (char *in);
char *strlower (char *in);
int Q_strncasecmp (char *s1, char *s2, int n);
int Q_strcasecmp (char *s1, char *s2);
void Q_getwd (char *out);
int Q_filelength (FILE *f);
int FileTime (char *path);
void Q_mkdir (char *path);
extern char qdir[1024];
extern char gamedir[1024];
void SetQdirFromPath (char *path);
char *ExpandArg (char *path); // from cmd line
char *ExpandPath (char *path); // from scripts
char *ExpandPathAndArchive (char *path);
double I_FloatTime (void);
void Error(char *error, ...);
void Warning(char *warning, ...);
int CheckParm (char *check);
FILE *SafeOpenWrite (char *filename);
FILE *SafeOpenRead (char *filename);
void SafeRead (FILE *f, void *buffer, int count);
void SafeWrite (FILE *f, void *buffer, int count);
int LoadFile (char *filename, void **bufferptr, int offset, int length);
int TryLoadFile (char *filename, void **bufferptr);
void SaveFile (char *filename, void *buffer, int count);
qboolean FileExists (char *filename);
void DefaultExtension (char *path, char *extension);
void DefaultPath (char *path, char *basepath);
void StripFilename (char *path);
void StripExtension (char *path);
void ExtractFilePath (char *path, char *dest);
void ExtractFileBase (char *path, char *dest);
void ExtractFileExtension (char *path, char *dest);
int ParseNum (char *str);
short BigShort (short l);
short LittleShort (short l);
int BigLong (int l);
int LittleLong (int l);
float BigFloat (float l);
float LittleFloat (float l);
#ifdef SIN
unsigned short BigUnsignedShort (unsigned short l);
unsigned short LittleUnsignedShort (unsigned short l);
unsigned BigUnsigned (unsigned l);
unsigned LittleUnsigned (unsigned l);
#endif
char *COM_Parse (char *data);
extern char com_token[1024];
extern qboolean com_eof;
char *copystring(char *s);
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
void CreatePath (char *path);
void QCopyFile (char *from, char *to);
extern qboolean archive;
extern char archivedir[1024];
extern qboolean verbose;
void qprintf (char *format, ...);
void ExpandWildcards (int *argc, char ***argv);
// for compression routines
typedef struct
{
byte *data;
int count;
} cblock_t;
#endif

View File

@ -1,215 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "qbsp.h"
#define MAX_LOGFILENAMESIZE 1024
typedef struct logfile_s
{
char filename[MAX_LOGFILENAMESIZE];
FILE *fp;
int numwrites;
} logfile_t;
logfile_t logfile;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Open(char *filename)
{
if (!filename || !strlen(filename))
{
printf("openlog <filename>\n");
return;
} //end if
if (logfile.fp)
{
printf("log file %s is already opened\n", logfile.filename);
return;
} //end if
logfile.fp = fopen(filename, "wb");
if (!logfile.fp)
{
printf("can't open the log file %s\n", filename);
return;
} //end if
strncpy(logfile.filename, filename, MAX_LOGFILENAMESIZE);
printf("Opened log %s\n", logfile.filename);
} //end of the function Log_Create
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Close(void)
{
if (!logfile.fp)
{
printf("no log file to close\n");
return;
} //end if
if (fclose(logfile.fp))
{
printf("can't close log file %s\n", logfile.filename);
return;
} //end if
logfile.fp = NULL;
printf("Closed log %s\n", logfile.filename);
} //end of the function Log_Close
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Shutdown(void)
{
if (logfile.fp) Log_Close();
} //end of the function Log_Shutdown
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_UnifyEndOfLine(char *buf)
{
int i;
for (i = 0; buf[i]; i++)
{
if (buf[i] == '\n')
{
if (i <= 0 || buf[i-1] != '\r')
{
memmove(&buf[i+1], &buf[i], strlen(&buf[i])+1);
buf[i] = '\r';
i++;
} //end if
} //end if
} //end for
} //end of the function Log_UnifyEndOfLine
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Print(char *fmt, ...)
{
va_list ap;
char buf[2048];
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
if (verbose)
{
#ifdef WINBSPC
WinBSPCPrint(buf);
#else
printf("%s", buf);
#endif //WINBSPS
} //end if
if (logfile.fp)
{
Log_UnifyEndOfLine(buf);
fprintf(logfile.fp, "%s", buf);
fflush(logfile.fp);
} //end if
} //end of the function Log_Print
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Write(char *fmt, ...)
{
va_list ap;
char buf[2048];
if (!logfile.fp) return;
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
Log_UnifyEndOfLine(buf);
fprintf(logfile.fp, "%s", buf);
fflush(logfile.fp);
} //end of the function Log_Write
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_WriteTimeStamped(char *fmt, ...)
{
va_list ap;
if (!logfile.fp) return;
/* fprintf(logfile.fp, "%d %02d:%02d:%02d:%02d ",
logfile.numwrites,
(int) (botlibglobals.time / 60 / 60),
(int) (botlibglobals.time / 60),
(int) (botlibglobals.time),
(int) ((int) (botlibglobals.time * 100)) -
((int) botlibglobals.time) * 100);*/
va_start(ap, fmt);
vfprintf(logfile.fp, fmt, ap);
va_end(ap);
logfile.numwrites++;
fflush(logfile.fp);
} //end of the function Log_Write
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
FILE *Log_FileStruct(void)
{
return logfile.fp;
} //end of the function Log_FileStruct
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Flush(void)
{
if (logfile.fp) fflush(logfile.fp);
} //end of the function Log_Flush

View File

@ -1,42 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//open a log file
void Log_Open(char *filename);
//close the current log file
void Log_Close(void);
//close log file if present
void Log_Shutdown(void);
//print on stdout and write to the current opened log file
void Log_Print(char *fmt, ...);
//write to the current opened log file
void Log_Write(char *fmt, ...);
//write to the current opened log file with a time stamp
void Log_WriteTimeStamped(char *fmt, ...);
//returns the log file structure
FILE *Log_FileStruct(void);
//flush log file
void Log_Flush(void);
#ifdef WINBSPC
void WinBSPCPrint(char *str);
#endif //WINBSPC

View File

@ -1,289 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// mathlib.c -- math primitives
#include "l_cmd.h"
#include "l_math.h"
vec3_t vec3_origin = {0,0,0};
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
{
float angle;
static float sr, sp, sy, cr, cp, cy;
// static to help MS compiler fp bugs
angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
if (forward)
{
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
}
if (right)
{
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
right[1] = (-1*sr*sp*sy+-1*cr*cy);
right[2] = -1*sr*cp;
}
if (up)
{
up[0] = (cr*sp*cy+-sr*-sy);
up[1] = (cr*sp*sy+-sr*cy);
up[2] = cr*cp;
}
}
/*
=================
RadiusFromBounds
=================
*/
float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
int i;
vec3_t corner;
float a, b;
for (i=0 ; i<3 ; i++) {
a = fabs( mins[i] );
b = fabs( maxs[i] );
corner[i] = a > b ? a : b;
}
return VectorLength (corner);
}
/*
================
R_ConcatRotations
================
*/
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
}
void AxisClear( vec3_t axis[3] ) {
axis[0][0] = 1;
axis[0][1] = 0;
axis[0][2] = 0;
axis[1][0] = 0;
axis[1][1] = 1;
axis[1][2] = 0;
axis[2][0] = 0;
axis[2][1] = 0;
axis[2][2] = 1;
}
float VectorLengthSquared(vec3_t v) {
return DotProduct(v, v);
}
double VectorLength(vec3_t v)
{
int i;
double length;
length = 0;
for (i=0 ; i< 3 ; i++)
length += v[i]*v[i];
length = sqrt (length); // FIXME
return length;
}
qboolean VectorCompare (vec3_t v1, vec3_t v2)
{
int i;
for (i=0 ; i<3 ; i++)
if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
return false;
return true;
}
vec_t Q_rint (vec_t in)
{
return floor(in + 0.5);
}
void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross)
{
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
void _VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
{
vc[0] = va[0] + scale*vb[0];
vc[1] = va[1] + scale*vb[1];
vc[2] = va[2] + scale*vb[2];
}
vec_t _DotProduct (vec3_t v1, vec3_t v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]-vb[0];
out[1] = va[1]-vb[1];
out[2] = va[2]-vb[2];
}
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]+vb[0];
out[1] = va[1]+vb[1];
out[2] = va[2]+vb[2];
}
void _VectorCopy (vec3_t in, vec3_t out)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
{
out[0] = v[0] * scale;
out[1] = v[1] * scale;
out[2] = v[2] * scale;
}
vec_t VectorNormalize(vec3_t inout)
{
vec_t length, ilength;
length = sqrt (inout[0]*inout[0] + inout[1]*inout[1] + inout[2]*inout[2]);
if (length == 0)
{
VectorClear (inout);
return 0;
}
ilength = 1.0/length;
inout[0] = inout[0]*ilength;
inout[1] = inout[1]*ilength;
inout[2] = inout[2]*ilength;
return length;
}
vec_t VectorNormalize2(const vec3_t in, vec3_t out)
{
vec_t length, ilength;
length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
if (length == 0)
{
VectorClear (out);
return 0;
}
ilength = 1.0/length;
out[0] = in[0]*ilength;
out[1] = in[1]*ilength;
out[2] = in[2]*ilength;
return length;
}
vec_t ColorNormalize (vec3_t in, vec3_t out)
{
float max, scale;
max = in[0];
if (in[1] > max)
max = in[1];
if (in[2] > max)
max = in[2];
if (max == 0)
return 0;
scale = 1.0 / max;
VectorScale (in, scale, out);
return max;
}
void VectorInverse (vec3_t v)
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void ClearBounds(vec3_t mins, vec3_t maxs)
{
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
}
void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs)
{
int i;
vec_t val;
for (i=0 ; i<3 ; i++)
{
val = v[i];
if (val < mins[i])
mins[i] = val;
if (val > maxs[i])
maxs[i] = val;
}
}

View File

@ -1,93 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __MATHLIB__
#define __MATHLIB__
// mathlib.h
#include <math.h>
#ifdef DOUBLEVEC_T
typedef double vec_t;
#else
typedef float vec_t;
#endif
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
#define SIDE_FRONT 0
#define SIDE_ON 2
#define SIDE_BACK 1
#define SIDE_CROSS -2
#define PITCH 0
#define YAW 1
#define ROLL 2
#define Q_PI 3.14159265358979323846
#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
extern vec3_t vec3_origin;
#define EQUAL_EPSILON 0.001
qboolean VectorCompare (vec3_t v1, vec3_t v2);
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
#define Vector4Copy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];}
#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
#define VectorNegate(x, y) {y[0]=-x[0];y[1]=-x[1];y[2]=-x[2];}
#define VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
vec_t Q_rint (vec_t in);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
void _VectorCopy (vec3_t in, vec3_t out);
void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
void _VectorMA(vec3_t va, double scale, vec3_t vb, vec3_t vc);
double VectorLength(vec3_t v);
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross);
vec_t VectorNormalize(vec3_t inout);
vec_t ColorNormalize(vec3_t in, vec3_t out);
vec_t VectorNormalize2(const vec3_t v, vec3_t out);
void VectorInverse (vec3_t v);
void ClearBounds (vec3_t mins, vec3_t maxs);
void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs);
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
void RotatePoint(vec3_t point, float matrix[3][3]);
void CreateRotationMatrix(vec3_t angles, float matrix[3][3]);
#endif

View File

@ -1,441 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "l_log.h"
int allocedmemory;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintMemorySize(unsigned long size)
{
unsigned long number1, number2, number3;
number1 = size >> 20;
number2 = (size & 0xFFFFF) >> 10;
number3 = (size & 0x3FF);
if (number1) Log_Print("%ld MB", number1);
if (number1 && number2) Log_Print(" and ");
if (number2) Log_Print("%ld KB", number2);
if (number2 && number3) Log_Print(" and ");
if (number3) Log_Print("%ld bytes", number3);
} //end of the function PrintFileSize
#ifndef MEMDEBUG
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int MemorySize(void *ptr)
{
#if defined(WIN32) || defined(_WIN32)
#ifdef __WATCOMC__
//Intel 32 bits memory addressing, 16 bytes aligned
return (_msize(ptr) + 15) >> 4 << 4;
#else
return _msize(ptr);
#endif
#else
return 0;
#endif
} //end of the function MemorySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *GetClearedMemory(int size)
{
void *ptr;
ptr = (void *) malloc(size);
if (!ptr) Error("out of memory");
memset(ptr, 0, size);
allocedmemory += MemorySize(ptr);
return ptr;
} //end of the function GetClearedMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *GetMemory(unsigned long size)
{
void *ptr;
ptr = malloc(size);
if (!ptr) Error("out of memory");
allocedmemory += MemorySize(ptr);
return ptr;
} //end of the function GetMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeMemory(void *ptr)
{
allocedmemory -= MemorySize(ptr);
free(ptr);
} //end of the function FreeMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int TotalAllocatedMemory(void)
{
return allocedmemory;
} //end of the function TotalAllocatedMemory
#else
#define MEM_ID 0x12345678l
int totalmemorysize;
int numblocks;
typedef struct memoryblock_s
{
unsigned long int id;
void *ptr;
int size;
#ifdef MEMDEBUG
char *label;
char *file;
int line;
#endif //MEMDEBUG
struct memoryblock_s *prev, *next;
} memoryblock_t;
memoryblock_t *memory;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LinkMemoryBlock(memoryblock_t *block)
{
block->prev = NULL;
block->next = memory;
if (memory) memory->prev = block;
memory = block;
} //end of the function LinkMemoryBlock
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void UnlinkMemoryBlock(memoryblock_t *block)
{
if (block->prev) block->prev->next = block->next;
else memory = block->next;
if (block->next) block->next->prev = block->prev;
} //end of the function UnlinkMemoryBlock
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
#else
void *GetMemory(unsigned long size)
#endif //MEMDEBUG
{
void *ptr;
memoryblock_t *block;
ptr = malloc(size + sizeof(memoryblock_t));
block = (memoryblock_t *) ptr;
block->id = MEM_ID;
block->ptr = (char *) ptr + sizeof(memoryblock_t);
block->size = size + sizeof(memoryblock_t);
#ifdef MEMDEBUG
block->label = label;
block->file = file;
block->line = line;
#endif //MEMDEBUG
LinkMemoryBlock(block);
totalmemorysize += block->size;
numblocks++;
return block->ptr;
} //end of the function GetMemoryDebug
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
#else
void *GetClearedMemory(unsigned long size)
#endif //MEMDEBUG
{
void *ptr;
#ifdef MEMDEBUG
ptr = GetMemoryDebug(size, label, file, line);
#else
ptr = GetMemory(size);
#endif //MEMDEBUG
memset(ptr, 0, size);
return ptr;
} //end of the function GetClearedMemoryLabelled
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *GetClearedHunkMemory(unsigned long size)
{
return GetClearedMemory(size);
} //end of the function GetClearedHunkMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *GetHunkMemory(unsigned long size)
{
return GetMemory(size);
} //end of the function GetHunkMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
memoryblock_t *BlockFromPointer(void *ptr, char *str)
{
memoryblock_t *block;
if (!ptr)
{
#ifdef MEMDEBUG
//char *crash = (char *) NULL;
//crash[0] = 1;
Error("%s: NULL pointer\n", str);
#endif MEMDEBUG
return NULL;
} //end if
block = (memoryblock_t *) ((char *) ptr - sizeof(memoryblock_t));
if (block->id != MEM_ID)
{
Error("%s: invalid memory block\n", str);
} //end if
if (block->ptr != ptr)
{
Error("%s: memory block pointer invalid\n", str);
} //end if
return block;
} //end of the function BlockFromPointer
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeMemory(void *ptr)
{
memoryblock_t *block;
block = BlockFromPointer(ptr, "FreeMemory");
if (!block) return;
UnlinkMemoryBlock(block);
totalmemorysize -= block->size;
numblocks--;
//
free(block);
} //end of the function FreeMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int MemoryByteSize(void *ptr)
{
memoryblock_t *block;
block = BlockFromPointer(ptr, "MemoryByteSize");
if (!block) return 0;
return block->size;
} //end of the function MemoryByteSize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int MemorySize(void *ptr)
{
return MemoryByteSize(ptr);
} //end of the function MemorySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintUsedMemorySize(void)
{
printf("total botlib memory: %d KB\n", totalmemorysize >> 10);
printf("total memory blocks: %d\n", numblocks);
} //end of the function PrintUsedMemorySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintMemoryLabels(void)
{
memoryblock_t *block;
int i;
PrintUsedMemorySize();
i = 0;
for (block = memory; block; block = block->next)
{
#ifdef MEMDEBUG
Log_Write("%6d, %p, %8d: %24s line %6d: %s", i, block->ptr, block->size, block->file, block->line, block->label);
#endif //MEMDEBUG
i++;
} //end for
} //end of the function PrintMemoryLabels
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void DumpMemory(void)
{
memoryblock_t *block;
for (block = memory; block; block = memory)
{
FreeMemory(block->ptr);
} //end for
totalmemorysize = 0;
} //end of the function DumpMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int TotalAllocatedMemory(void)
{
return totalmemorysize;
} //end of the function TotalAllocatedMemory
#endif
//===========================================================================
// Q3 Hunk and Z_ memory management
//===========================================================================
typedef struct memhunk_s
{
void *ptr;
struct memhunk_s *next;
} memhunk_t;
memhunk_t *memhunk_high;
memhunk_t *memhunk_low;
int memhunk_high_size = 16 * 1024 * 1024;
int memhunk_low_size = 0;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Hunk_ClearHigh(void)
{
memhunk_t *h, *nexth;
for (h = memhunk_high; h; h = nexth)
{
nexth = h->next;
FreeMemory(h);
} //end for
memhunk_high = NULL;
memhunk_high_size = 16 * 1024 * 1024;
} //end of the function Hunk_ClearHigh
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *Hunk_Alloc(int size)
{
memhunk_t *h;
if (!size) return (void *) memhunk_high_size;
//
h = GetClearedMemory(size + sizeof(memhunk_t));
h->ptr = (char *) h + sizeof(memhunk_t);
h->next = memhunk_high;
memhunk_high = h;
memhunk_high_size -= size;
return h->ptr;
} //end of the function Hunk_Alloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *Z_Malloc(int size)
{
return GetClearedMemory(size);
} //end of the function Z_Malloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Z_Free (void *ptr)
{
FreeMemory(ptr);
} //end of the function Z_Free

View File

@ -1,51 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//=============================================================================
// memory.h
//#define MEMDEBUG
#undef MEMDEBUG
#ifndef MEMDEBUG
void *GetClearedMemory(int size);
void *GetMemory(unsigned long size);
#else
#define GetMemory(size) GetMemoryDebug(size, #size, __FILE__, __LINE__);
#define GetClearedMemory(size) GetClearedMemoryDebug(size, #size, __FILE__, __LINE__);
//allocate a memory block of the given size
void *GetMemoryDebug(unsigned long size, char *label, char *file, int line);
//allocate a memory block of the given size and clear it
void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line);
//
void PrintMemoryLabels(void);
#endif //MEMDEBUG
void FreeMemory(void *ptr);
int MemorySize(void *ptr);
void PrintMemorySize(unsigned long size);
int TotalAllocatedMemory(void);

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//a winding gives the bounding points of a convex polygon
typedef struct
{
int numpoints;
vec3_t p[4]; //variable sized
} winding_t;
#define MAX_POINTS_ON_WINDING 96
//you can define on_epsilon in the makefile as tighter
#ifndef ON_EPSILON
#define ON_EPSILON 0.1
#endif
//winding errors
#define WE_NONE 0
#define WE_NOTENOUGHPOINTS 1
#define WE_SMALLAREA 2
#define WE_POINTBOGUSRANGE 3
#define WE_POINTOFFPLANE 4
#define WE_DEGENERATEEDGE 5
#define WE_NONCONVEX 6
//allocates a winding
winding_t *AllocWinding (int points);
//returns the area of the winding
vec_t WindingArea (winding_t *w);
//gives the center of the winding
void WindingCenter (winding_t *w, vec3_t center);
//clips the given winding to the given plane and gives the front
//and back part of the clipped winding
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back);
//returns the fragment of the given winding that is on the front
//side of the cliping plane. The original is freed.
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
//returns a copy of the given winding
winding_t *CopyWinding (winding_t *w);
//returns the reversed winding of the given one
winding_t *ReverseWinding (winding_t *w);
//returns a base winding for the given plane
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
//checks the winding for errors
void CheckWinding (winding_t *w);
//returns the plane normal and dist the winding is in
void WindingPlane(winding_t *w, vec3_t normal, vec_t *dist);
//removes colinear points from the winding
void RemoveColinearPoints(winding_t *w);
//returns on which side of the plane the winding is situated
int WindingOnPlaneSide(winding_t *w, vec3_t normal, vec_t dist);
//frees the winding
void FreeWinding(winding_t *w);
//gets the bounds of the winding
void WindingBounds(winding_t *w, vec3_t mins, vec3_t maxs);
//chops the winding with the given plane, the original winding is freed if clipped
void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
//prints the winding points on STDOUT
void pw(winding_t *w);
//try to merge the two windings which are in the given plane
//the original windings are undisturbed
//the merged winding is returned when merging was possible
//NULL is returned otherwise
winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal);
//brute force winding merging... creates a convex winding out of
//the two whatsoever
winding_t *MergeWindings(winding_t *w1, winding_t *w2, vec3_t planenormal);
//#ifdef ME
void ResetWindings(void);
//returns the amount of winding memory
int WindingMemory(void);
int WindingPeakMemory(void);
int ActiveWindings(void);
//returns the winding error string
char *WindingErrorString(void);
//returns one of the WE_ flags when the winding has errors
int WindingError(winding_t *w);
//removes equal points from the winding
void RemoveEqualPoints(winding_t *w, float epsilon);
//returns a winding with a point added at the given spot to the
//given winding, original winding is NOT freed
winding_t *AddWindingPoint(winding_t *w, vec3_t point, int spot);
//returns true if the point is on one of the winding 'edges'
//when the point is on one of the edged the number of the first
//point of the edge is stored in 'spot'
int PointOnWinding(winding_t *w, vec3_t normal, float dist, vec3_t point, int *spot);
//find a plane seperating the two windings
//true is returned when the windings area adjacent
//the seperating plane normal and distance area stored in 'normal' and 'dist'
//this plane will contain both the piece of common edge of the two windings
//and the vector 'dir'
int FindPlaneSeperatingWindings(winding_t *w1, winding_t *w2, vec3_t dir,
vec3_t normal, float *dist);
//
int WindingsNonConvex(winding_t *w1, winding_t *w2,
vec3_t normal1, vec3_t normal2,
float dist1, float dist2);
//#endif //ME

View File

@ -1,663 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if defined(WIN32)|defined(_WIN32)
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <glob.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include "qbsp.h"
//file extensions with their type
typedef struct qfile_exttype_s
{
char *extension;
int type;
} qfile_exttyp_t;
qfile_exttyp_t quakefiletypes[] =
{
{QFILEEXT_UNKNOWN, QFILETYPE_UNKNOWN},
{QFILEEXT_PAK, QFILETYPE_PAK},
{QFILEEXT_PK3, QFILETYPE_PK3},
{QFILEEXT_SIN, QFILETYPE_PAK},
{QFILEEXT_BSP, QFILETYPE_BSP},
{QFILEEXT_MAP, QFILETYPE_MAP},
{QFILEEXT_MDL, QFILETYPE_MDL},
{QFILEEXT_MD2, QFILETYPE_MD2},
{QFILEEXT_MD3, QFILETYPE_MD3},
{QFILEEXT_WAL, QFILETYPE_WAL},
{QFILEEXT_WAV, QFILETYPE_WAV},
{QFILEEXT_AAS, QFILETYPE_AAS},
{NULL, 0}
};
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int QuakeFileExtensionType(char *extension)
{
int i;
for (i = 0; quakefiletypes[i].extension; i++)
{
if (!stricmp(extension, quakefiletypes[i].extension))
{
return quakefiletypes[i].type;
} //end if
} //end for
return QFILETYPE_UNKNOWN;
} //end of the function QuakeFileExtensionType
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *QuakeFileTypeExtension(int type)
{
int i;
for (i = 0; quakefiletypes[i].extension; i++)
{
if (quakefiletypes[i].type == type)
{
return quakefiletypes[i].extension;
} //end if
} //end for
return QFILEEXT_UNKNOWN;
} //end of the function QuakeFileExtension
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int QuakeFileType(char *filename)
{
char ext[_MAX_PATH] = ".";
ExtractFileExtension(filename, ext+1);
return QuakeFileExtensionType(ext);
} //end of the function QuakeFileTypeFromFileName
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *StringContains(char *str1, char *str2, int casesensitive)
{
int len, i, j;
len = strlen(str1) - strlen(str2);
for (i = 0; i <= len; i++, str1++)
{
for (j = 0; str2[j]; j++)
{
if (casesensitive)
{
if (str1[j] != str2[j]) break;
} //end if
else
{
if (toupper(str1[j]) != toupper(str2[j])) break;
} //end else
} //end for
if (!str2[j]) return str1;
} //end for
return NULL;
} //end of the function StringContains
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int FileFilter(char *filter, char *filename, int casesensitive)
{
char buf[1024];
char *ptr;
int i, found;
while(*filter)
{
if (*filter == '*')
{
filter++;
for (i = 0; *filter; i++)
{
if (*filter == '*' || *filter == '?') break;
buf[i] = *filter;
filter++;
} //end for
buf[i] = '\0';
if (strlen(buf))
{
ptr = StringContains(filename, buf, casesensitive);
if (!ptr) return false;
filename = ptr + strlen(buf);
} //end if
} //end if
else if (*filter == '?')
{
filter++;
filename++;
} //end else if
else if (*filter == '[' && *(filter+1) == '[')
{
filter++;
} //end if
else if (*filter == '[')
{
filter++;
found = false;
while(*filter && !found)
{
if (*filter == ']' && *(filter+1) != ']') break;
if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']'))
{
if (casesensitive)
{
if (*filename >= *filter && *filename <= *(filter+2)) found = true;
} //end if
else
{
if (toupper(*filename) >= toupper(*filter) &&
toupper(*filename) <= toupper(*(filter+2))) found = true;
} //end else
filter += 3;
} //end if
else
{
if (casesensitive)
{
if (*filter == *filename) found = true;
} //end if
else
{
if (toupper(*filter) == toupper(*filename)) found = true;
} //end else
filter++;
} //end else
} //end while
if (!found) return false;
while(*filter)
{
if (*filter == ']' && *(filter+1) != ']') break;
filter++;
} //end while
filter++;
filename++;
} //end else if
else
{
if (casesensitive)
{
if (*filter != *filename) return false;
} //end if
else
{
if (toupper(*filter) != toupper(*filename)) return false;
} //end else
filter++;
filename++;
} //end else
} //end while
return true;
} //end of the function FileFilter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *FindQuakeFilesInZip(char *zipfile, char *filter)
{
unzFile uf;
int err;
unz_global_info gi;
char filename_inzip[MAX_PATH];
unz_file_info file_info;
int i;
quakefile_t *qfiles, *lastqf, *qf;
uf = unzOpen(zipfile);
err = unzGetGlobalInfo(uf, &gi);
if (err != UNZ_OK) return NULL;
unzGoToFirstFile(uf);
qfiles = NULL;
lastqf = NULL;
for (i = 0; i < gi.number_entry; i++)
{
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL,0,NULL,0);
if (err != UNZ_OK) break;
ConvertPath(filename_inzip);
if (FileFilter(filter, filename_inzip, false))
{
qf = malloc(sizeof(quakefile_t));
if (!qf) Error("out of memory");
memset(qf, 0, sizeof(quakefile_t));
strcpy(qf->pakfile, zipfile);
strcpy(qf->filename, zipfile);
strcpy(qf->origname, filename_inzip);
qf->zipfile = true;
//memcpy( &buildBuffer[i].zipfileinfo, (unz_s*)uf, sizeof(unz_s));
memcpy(&qf->zipinfo, (unz_s*)uf, sizeof(unz_s));
qf->offset = 0;
qf->length = file_info.uncompressed_size;
qf->type = QuakeFileType(filename_inzip);
//add the file ot the list
qf->next = NULL;
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
} //end if
unzGoToNextFile(uf);
} //end for
unzClose(uf);
return qfiles;
} //end of the function FindQuakeFilesInZip
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *FindQuakeFilesInPak(char *pakfile, char *filter)
{
FILE *fp;
dpackheader_t packheader;
dsinpackfile_t *packfiles;
dpackfile_t *idpackfiles;
quakefile_t *qfiles, *lastqf, *qf;
int numpackdirs, i;
qfiles = NULL;
lastqf = NULL;
//open the pak file
fp = fopen(pakfile, "rb");
if (!fp)
{
Warning("can't open pak file %s", pakfile);
return NULL;
} //end if
//read pak header, check for valid pak id and seek to the dir entries
if ((fread(&packheader, 1, sizeof(dpackheader_t), fp) != sizeof(dpackheader_t))
|| (packheader.ident != IDPAKHEADER && packheader.ident != SINPAKHEADER)
|| (fseek(fp, LittleLong(packheader.dirofs), SEEK_SET))
)
{
fclose(fp);
Warning("invalid pak file %s", pakfile);
return NULL;
} //end if
//if it is a pak file from id software
if (packheader.ident == IDPAKHEADER)
{
//number of dir entries in the pak file
numpackdirs = LittleLong(packheader.dirlen) / sizeof(dpackfile_t);
idpackfiles = (dpackfile_t *) malloc(numpackdirs * sizeof(dpackfile_t));
if (!idpackfiles) Error("out of memory");
//read the dir entry
if (fread(idpackfiles, sizeof(dpackfile_t), numpackdirs, fp) != numpackdirs)
{
fclose(fp);
free(idpackfiles);
Warning("can't read the Quake pak file dir entries from %s", pakfile);
return NULL;
} //end if
fclose(fp);
//convert to sin pack files
packfiles = (dsinpackfile_t *) malloc(numpackdirs * sizeof(dsinpackfile_t));
if (!packfiles) Error("out of memory");
for (i = 0; i < numpackdirs; i++)
{
strcpy(packfiles[i].name, idpackfiles[i].name);
packfiles[i].filepos = LittleLong(idpackfiles[i].filepos);
packfiles[i].filelen = LittleLong(idpackfiles[i].filelen);
} //end for
free(idpackfiles);
} //end if
else //its a Sin pack file
{
//number of dir entries in the pak file
numpackdirs = LittleLong(packheader.dirlen) / sizeof(dsinpackfile_t);
packfiles = (dsinpackfile_t *) malloc(numpackdirs * sizeof(dsinpackfile_t));
if (!packfiles) Error("out of memory");
//read the dir entry
if (fread(packfiles, sizeof(dsinpackfile_t), numpackdirs, fp) != numpackdirs)
{
fclose(fp);
free(packfiles);
Warning("can't read the Sin pak file dir entries from %s", pakfile);
return NULL;
} //end if
fclose(fp);
for (i = 0; i < numpackdirs; i++)
{
packfiles[i].filepos = LittleLong(packfiles[i].filepos);
packfiles[i].filelen = LittleLong(packfiles[i].filelen);
} //end for
} //end else
//
for (i = 0; i < numpackdirs; i++)
{
ConvertPath(packfiles[i].name);
if (FileFilter(filter, packfiles[i].name, false))
{
qf = malloc(sizeof(quakefile_t));
if (!qf) Error("out of memory");
memset(qf, 0, sizeof(quakefile_t));
strcpy(qf->pakfile, pakfile);
strcpy(qf->filename, pakfile);
strcpy(qf->origname, packfiles[i].name);
qf->zipfile = false;
qf->offset = packfiles[i].filepos;
qf->length = packfiles[i].filelen;
qf->type = QuakeFileType(packfiles[i].name);
//add the file ot the list
qf->next = NULL;
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
} //end if
} //end for
free(packfiles);
return qfiles;
} //end of the function FindQuakeFilesInPak
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *FindQuakeFilesWithPakFilter(char *pakfilter, char *filter)
{
#if defined(WIN32)|defined(_WIN32)
WIN32_FIND_DATA filedata;
HWND handle;
struct _stat statbuf;
#else
glob_t globbuf;
struct stat statbuf;
int j;
#endif
quakefile_t *qfiles, *lastqf, *qf;
char pakfile[_MAX_PATH], filename[_MAX_PATH], *str;
int done;
qfiles = NULL;
lastqf = NULL;
if (pakfilter && strlen(pakfilter))
{
#if defined(WIN32)|defined(_WIN32)
handle = FindFirstFile(pakfilter, &filedata);
done = (handle == INVALID_HANDLE_VALUE);
while(!done)
{
_splitpath(pakfilter, pakfile, NULL, NULL, NULL);
_splitpath(pakfilter, NULL, &pakfile[strlen(pakfile)], NULL, NULL);
AppendPathSeperator(pakfile, _MAX_PATH);
strcat(pakfile, filedata.cFileName);
_stat(pakfile, &statbuf);
#else
glob(pakfilter, 0, NULL, &globbuf);
for (j = 0; j < globbuf.gl_pathc; j++)
{
strcpy(pakfile, globbuf.gl_pathv[j]);
stat(pakfile, &statbuf);
#endif
//if the file with .pak or .pk3 is a folder
if (statbuf.st_mode & S_IFDIR)
{
strcpy(filename, pakfilter);
AppendPathSeperator(filename, _MAX_PATH);
strcat(filename, filter);
qf = FindQuakeFilesWithPakFilter(NULL, filename);
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
while(lastqf->next) lastqf = lastqf->next;
} //end if
else
{
#if defined(WIN32)|defined(_WIN32)
str = StringContains(pakfile, ".pk3", false);
#else
str = StringContains(pakfile, ".pk3", true);
#endif
if (str && str == pakfile + strlen(pakfile) - strlen(".pk3"))
{
qf = FindQuakeFilesInZip(pakfile, filter);
} //end if
else
{
qf = FindQuakeFilesInPak(pakfile, filter);
} //end else
//
if (qf)
{
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
while(lastqf->next) lastqf = lastqf->next;
} //end if
} //end else
//
#if defined(WIN32)|defined(_WIN32)
//find the next file
done = !FindNextFile(handle, &filedata);
} //end while
#else
} //end for
globfree(&globbuf);
#endif
} //end if
else
{
#if defined(WIN32)|defined(_WIN32)
handle = FindFirstFile(filter, &filedata);
done = (handle == INVALID_HANDLE_VALUE);
while(!done)
{
_splitpath(filter, filename, NULL, NULL, NULL);
_splitpath(filter, NULL, &filename[strlen(filename)], NULL, NULL);
AppendPathSeperator(filename, _MAX_PATH);
strcat(filename, filedata.cFileName);
#else
glob(filter, 0, NULL, &globbuf);
for (j = 0; j < globbuf.gl_pathc; j++)
{
strcpy(filename, globbuf.gl_pathv[j]);
#endif
//
qf = malloc(sizeof(quakefile_t));
if (!qf) Error("out of memory");
memset(qf, 0, sizeof(quakefile_t));
strcpy(qf->pakfile, "");
strcpy(qf->filename, filename);
strcpy(qf->origname, filename);
qf->offset = 0;
qf->length = 0;
qf->type = QuakeFileType(filename);
//add the file ot the list
qf->next = NULL;
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
#if defined(WIN32)|defined(_WIN32)
//find the next file
done = !FindNextFile(handle, &filedata);
} //end while
#else
} //end for
globfree(&globbuf);
#endif
} //end else
return qfiles;
} //end of the function FindQuakeFilesWithPakFilter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *FindQuakeFiles(char *filter)
{
char *str;
char newfilter[_MAX_PATH];
char pakfilter[_MAX_PATH];
char filefilter[_MAX_PATH];
strcpy(newfilter, filter);
ConvertPath(newfilter);
strcpy(pakfilter, newfilter);
str = StringContains(pakfilter, ".pak", false);
if (!str) str = StringContains(pakfilter, ".pk3", false);
if (str)
{
str += strlen(".pak");
if (*str)
{
*str++ = '\0';
while(*str == '\\' || *str == '/') str++;
strcpy(filefilter, str);
return FindQuakeFilesWithPakFilter(pakfilter, filefilter);
} //end if
} //end else
return FindQuakeFilesWithPakFilter(NULL, newfilter);
} //end of the function FindQuakeFiles
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int LoadQuakeFile(quakefile_t *qf, void **bufferptr)
{
FILE *fp;
void *buffer;
int length;
unzFile zf;
if (qf->zipfile)
{
//open the zip file
zf = unzOpen(qf->pakfile);
//set the file pointer
qf->zipinfo.file = ((unz_s *) zf)->file;
//open the Quake file in the zip file
unzOpenCurrentFile(&qf->zipinfo);
//allocate memory for the buffer
length = qf->length;
buffer = GetMemory(length+1);
//read the Quake file from the zip file
length = unzReadCurrentFile(&qf->zipinfo, buffer, length);
//close the Quake file in the zip file
unzCloseCurrentFile(&qf->zipinfo);
//close the zip file
unzClose(zf);
*bufferptr = buffer;
return length;
} //end if
else
{
fp = SafeOpenRead(qf->filename);
if (qf->offset) fseek(fp, qf->offset, SEEK_SET);
length = qf->length;
if (!length) length = Q_filelength(fp);
buffer = GetMemory(length+1);
((char *)buffer)[length] = 0;
SafeRead(fp, buffer, length);
fclose(fp);
*bufferptr = buffer;
return length;
} //end else
} //end of the function LoadQuakeFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int ReadQuakeFile(quakefile_t *qf, void *buffer, int offset, int length)
{
FILE *fp;
int read;
unzFile zf;
char tmpbuf[1024];
if (qf->zipfile)
{
//open the zip file
zf = unzOpen(qf->pakfile);
//set the file pointer
qf->zipinfo.file = ((unz_s *) zf)->file;
//open the Quake file in the zip file
unzOpenCurrentFile(&qf->zipinfo);
//
while(offset > 0)
{
read = offset;
if (read > sizeof(tmpbuf)) read = sizeof(tmpbuf);
unzReadCurrentFile(&qf->zipinfo, tmpbuf, read);
offset -= read;
} //end while
//read the Quake file from the zip file
length = unzReadCurrentFile(&qf->zipinfo, buffer, length);
//close the Quake file in the zip file
unzCloseCurrentFile(&qf->zipinfo);
//close the zip file
unzClose(zf);
return length;
} //end if
else
{
fp = SafeOpenRead(qf->filename);
if (qf->offset) fseek(fp, qf->offset, SEEK_SET);
if (offset) fseek(fp, offset, SEEK_CUR);
SafeRead(fp, buffer, length);
fclose(fp);
return length;
} //end else
} //end of the function ReadQuakeFile

View File

@ -1,91 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/unzip.h"
#define QFILETYPE_UNKNOWN 0x8000
#define QFILETYPE_PAK 0x0001
#define QFILETYPE_PK3 0x0002
#define QFILETYPE_BSP 0x0004
#define QFILETYPE_MAP 0x0008
#define QFILETYPE_MDL 0x0010
#define QFILETYPE_MD2 0x0020
#define QFILETYPE_MD3 0x0040
#define QFILETYPE_WAL 0x0080
#define QFILETYPE_WAV 0x0100
#define QFILETYPE_AAS 0x4000
#define QFILEEXT_UNKNOWN ""
#define QFILEEXT_PAK ".PAK"
#define QFILEEXT_PK3 ".PK3"
#define QFILEEXT_SIN ".SIN"
#define QFILEEXT_BSP ".BSP"
#define QFILEEXT_MAP ".MAP"
#define QFILEEXT_MDL ".MDL"
#define QFILEEXT_MD2 ".MD2"
#define QFILEEXT_MD3 ".MD3"
#define QFILEEXT_WAL ".WAL"
#define QFILEEXT_WAV ".WAV"
#define QFILEEXT_AAS ".AAS"
//maximum path length
#ifndef _MAX_PATH
#define _MAX_PATH 1024
#endif
//for Sin packs
#define MAX_PAK_FILENAME_LENGTH 120
#define SINPAKHEADER (('K'<<24)+('A'<<16)+('P'<<8)+'S')
typedef struct
{
char name[MAX_PAK_FILENAME_LENGTH];
int filepos, filelen;
} dsinpackfile_t;
typedef struct quakefile_s
{
char pakfile[_MAX_PATH];
char filename[_MAX_PATH];
char origname[_MAX_PATH];
int zipfile;
int type;
int offset;
int length;
unz_s zipinfo;
struct quakefile_s *next;
} quakefile_t;
//returns the file extension for the given type
char *QuakeFileTypeExtension(int type);
//returns the file type for the given extension
int QuakeFileExtensionType(char *extension);
//return the Quake file type for the given file
int QuakeFileType(char *filename);
//returns true if the filename complies to the filter
int FileFilter(char *filter, char *filename, int casesensitive);
//find Quake files using the given filter
quakefile_t *FindQuakeFiles(char *filter);
//load the given Quake file, returns the length of the file
int LoadQuakeFile(quakefile_t *qf, void **bufferptr);
//read part of a Quake file into the buffer
int ReadQuakeFile(quakefile_t *qf, void *buffer, int offset, int length);

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
extern int numthreads;
void ThreadSetDefault (void);
int GetThreadWork (void);
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
//mutex
void ThreadSetupLock(void);
void ThreadShutdownLock(void);
void ThreadLock (void);
void ThreadUnlock (void);
//semaphore
void ThreadSetupSemaphore(void);
void ThreadShutdownSemaphore(void);
void ThreadSemaphoreWait(void);
void ThreadSemaphoreIncrease(int count);
//add/remove threads
void AddThread(void (*func)(int));
void RemoveThread(int threadid);
void WaitForAllThreadsFinished(void);
int GetNumThreads(void);

View File

@ -1,259 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//#ifndef BOTLIB
//#define BOTLIB
//#endif //BOTLIB
#ifdef BOTLIB
#include "q_shared.h"
#include "qfiles.h"
#include "botlib.h"
#include "l_log.h"
#include "l_libvar.h"
#include "l_memory.h"
//#include "l_utils.h"
#include "be_interface.h"
#else //BOTLIB
#include "qbsp.h"
#include "l_mem.h"
#endif //BOTLIB
#ifdef BOTLIB
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void Vector2Angles(vec3_t value1, vec3_t angles)
{
float forward;
float yaw, pitch;
if (value1[1] == 0 && value1[0] == 0)
{
yaw = 0;
if (value1[2] > 0) pitch = 90;
else pitch = 270;
} //end if
else
{
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
if (yaw < 0) yaw += 360;
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0) pitch += 360;
} //end else
angles[PITCH] = -pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
} //end of the function Vector2Angles
#endif //BOTLIB
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ConvertPath(char *path)
{
while(*path)
{
if (*path == '/' || *path == '\\') *path = PATHSEPERATOR_CHAR;
path++;
} //end while
} //end of the function ConvertPath
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AppendPathSeperator(char *path, int length)
{
int pathlen = strlen(path);
if (strlen(path) && length-pathlen > 1 && path[pathlen-1] != '/' && path[pathlen-1] != '\\')
{
path[pathlen] = PATHSEPERATOR_CHAR;
path[pathlen+1] = '\0';
} //end if
} //end of the function AppenPathSeperator
#if 0
//===========================================================================
// returns pointer to file handle
// sets offset to and length of 'filename' in the pak file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean FindFileInPak(char *pakfile, char *filename, foundfile_t *file)
{
FILE *fp;
dpackheader_t packheader;
dpackfile_t *packfiles;
int numdirs, i;
char path[MAX_PATH];
//open the pak file
fp = fopen(pakfile, "rb");
if (!fp)
{
return false;
} //end if
//read pak header, check for valid pak id and seek to the dir entries
if ((fread(&packheader, 1, sizeof(dpackheader_t), fp) != sizeof(dpackheader_t))
|| (packheader.ident != IDPAKHEADER)
|| (fseek(fp, LittleLong(packheader.dirofs), SEEK_SET))
)
{
fclose(fp);
return false;
} //end if
//number of dir entries in the pak file
numdirs = LittleLong(packheader.dirlen) / sizeof(dpackfile_t);
packfiles = (dpackfile_t *) GetMemory(numdirs * sizeof(dpackfile_t));
//read the dir entry
if (fread(packfiles, sizeof(dpackfile_t), numdirs, fp) != numdirs)
{
fclose(fp);
FreeMemory(packfiles);
return false;
} //end if
fclose(fp);
//
strcpy(path, filename);
ConvertPath(path);
//find the dir entry in the pak file
for (i = 0; i < numdirs; i++)
{
//convert the dir entry name
ConvertPath(packfiles[i].name);
//compare the dir entry name with the filename
if (Q_strcasecmp(packfiles[i].name, path) == 0)
{
strcpy(file->filename, pakfile);
file->offset = LittleLong(packfiles[i].filepos);
file->length = LittleLong(packfiles[i].filelen);
FreeMemory(packfiles);
return true;
} //end if
} //end for
FreeMemory(packfiles);
return false;
} //end of the function FindFileInPak
//===========================================================================
// find a Quake2 file
// returns full path in 'filename'
// sets offset and length of the file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean FindQuakeFile2(char *basedir, char *gamedir, char *filename, foundfile_t *file)
{
int dir, i;
//NOTE: 3 is necessary (LCC bug???)
char gamedirs[3][MAX_PATH] = {"","",""};
char filedir[MAX_PATH] = "";
//
if (gamedir) strncpy(gamedirs[0], gamedir, MAX_PATH);
strncpy(gamedirs[1], "baseq2", MAX_PATH);
//
//find the file in the two game directories
for (dir = 0; dir < 2; dir++)
{
//check if the file is in a directory
filedir[0] = 0;
if (basedir && strlen(basedir))
{
strncpy(filedir, basedir, MAX_PATH);
AppendPathSeperator(filedir, MAX_PATH);
} //end if
if (strlen(gamedirs[dir]))
{
strncat(filedir, gamedirs[dir], MAX_PATH - strlen(filedir));
AppendPathSeperator(filedir, MAX_PATH);
} //end if
strncat(filedir, filename, MAX_PATH - strlen(filedir));
ConvertPath(filedir);
Log_Write("accessing %s", filedir);
if (!access(filedir, 0x04))
{
strcpy(file->filename, filedir);
file->length = 0;
file->offset = 0;
return true;
} //end if
//check if the file is in a pak?.pak
for (i = 0; i < 10; i++)
{
filedir[0] = 0;
if (basedir && strlen(basedir))
{
strncpy(filedir, basedir, MAX_PATH);
AppendPathSeperator(filedir, MAX_PATH);
} //end if
if (strlen(gamedirs[dir]))
{
strncat(filedir, gamedirs[dir], MAX_PATH - strlen(filedir));
AppendPathSeperator(filedir, MAX_PATH);
} //end if
sprintf(&filedir[strlen(filedir)], "pak%d.pak\0", i);
if (!access(filedir, 0x04))
{
Log_Write("searching %s in %s", filename, filedir);
if (FindFileInPak(filedir, filename, file)) return true;
} //end if
} //end for
} //end for
file->offset = 0;
file->length = 0;
return false;
} //end of the function FindQuakeFile2
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef BOTLIB
qboolean FindQuakeFile(char *filename, foundfile_t *file)
{
return FindQuakeFile2(LibVarGetString("basedir"),
LibVarGetString("gamedir"), filename, file);
} //end of the function FindQuakeFile
#else //BOTLIB
qboolean FindQuakeFile(char *basedir, char *gamedir, char *filename, foundfile_t *file)
{
return FindQuakeFile2(basedir, gamedir, filename, file);
} //end of the function FindQuakeFile
#endif //BOTLIB
#endif

View File

@ -1,79 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef MAX_PATH
#define MAX_PATH 64
#endif
#ifndef PATH_SEPERATORSTR
#if defined(WIN32)|defined(_WIN32)|defined(__NT__)|defined(__WINDOWS__)|defined(__WINDOWS_386__)
#define PATHSEPERATOR_STR "\\"
#else
#define PATHSEPERATOR_STR "/"
#endif
#endif
#ifndef PATH_SEPERATORCHAR
#if defined(WIN32)|defined(_WIN32)|defined(__NT__)|defined(__WINDOWS__)|defined(__WINDOWS_386__)
#define PATHSEPERATOR_CHAR '\\'
#else
#define PATHSEPERATOR_CHAR '/'
#endif
#endif
//random in the range [0, 1]
#define random() ((rand () & 0x7fff) / ((float)0x7fff))
//random in the range [-1, 1]
#define crandom() (2.0 * (random() - 0.5))
//min and max
#define Maximum(x,y) (x > y ? x : y)
#define Minimum(x,y) (x < y ? x : y)
//absolute value
#define FloatAbs(x) (*(float *) &((* (int *) &(x)) & 0x7FFFFFFF))
#define IntAbs(x) (~(x))
//coordinates
#define _X 0
#define _Y 1
#define _Z 2
typedef struct foundfile_s
{
int offset;
int length;
char filename[MAX_PATH]; //screw LCC, array must be at end of struct
} foundfile_t;
void Vector2Angles(vec3_t value1, vec3_t angles);
//set the correct path seperators
void ConvertPath(char *path);
//append a path seperator to the given path not exceeding the length
void AppendPathSeperator(char *path, int length);
//find a file in a pak file
qboolean FindFileInPak(char *pakfile, char *filename, foundfile_t *file);
//find a quake file
#ifdef BOTLIB
qboolean FindQuakeFile(char *filename, foundfile_t *file);
#else //BOTLIB
qboolean FindQuakeFile(char *basedir, char *gamedir, char *filename, foundfile_t *file);
#endif //BOTLIB

View File

@ -1,61 +0,0 @@
#
# Makefile for the BSPC tool for the Gladiator Bot
# Intended for LCC-Win32
#
CC=lcc
CFLAGS=-DC_ONLY -o
OBJS= _files.obj\
aas_areamerging.obj\
aas_cfg.obj\
aas_create.obj\
aas_edgemelting.obj\
aas_facemerging.obj\
aas_file.obj\
aas_gsubdiv.obj\
aas_map.obj\
aas_prunenodes.obj\
aas_store.obj\
brushbsp.obj\
bspc.obj\
csg.obj\
faces.obj\
glfile.obj\
l_bsp_hl.obj\
l_bsp_q1.obj\
l_bsp_q2.obj\
l_bsp_sin.obj\
l_cmd.obj\
l_log.obj\
l_math.obj\
l_mem.obj\
l_poly.obj\
l_qfiles.obj\
l_script.obj\
l_threads.obj\
l_utils.obj\
leakfile.obj\
map.obj\
map_hl.obj\
map_q1.obj\
map_q2.obj\
map_q2_new.obj\
map_sin.obj\
nodraw.obj\
portals.obj\
prtfile.obj\
textures.obj\
tree.obj\
writebsp.obj
all: bspc.exe
bspc.exe: $(OBJS)
lcclnk
clean:
del *.obj bspc.exe
%.obj: %.c
$(CC) $(CFLAGS) $<

View File

@ -1,101 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
/*
==============================================================================
LEAF FILE GENERATION
Save out name.line for qe3 to read
==============================================================================
*/
/*
=============
LeakFile
Finds the shortest possible chain of portals
that leads from the outside leaf to a specifically
occupied leaf
=============
*/
void LeakFile (tree_t *tree)
{
vec3_t mid;
FILE *linefile;
char filename[1024];
node_t *node;
int count;
if (!tree->outside_node.occupied)
return;
qprintf ("--- LeakFile ---\n");
//
// write the points to the file
//
sprintf (filename, "%s.lin", source);
qprintf ("%s\n", filename);
linefile = fopen (filename, "w");
if (!linefile)
Error ("Couldn't open %s\n", filename);
count = 0;
node = &tree->outside_node;
while (node->occupied > 1)
{
int next;
portal_t *p, *nextportal;
node_t *nextnode;
int s;
// find the best portal exit
next = node->occupied;
for (p=node->portals ; p ; p = p->next[!s])
{
s = (p->nodes[0] == node);
if (p->nodes[s]->occupied
&& p->nodes[s]->occupied < next)
{
nextportal = p;
nextnode = p->nodes[s];
next = nextnode->occupied;
}
}
node = nextnode;
WindingCenter (nextportal->winding, mid);
fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
count++;
}
// add the occupant center
GetVectorForKey (node->occupant, "origin", mid);
fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
qprintf ("%5i point linefile\n", count+1);
fclose (linefile);
}

View File

@ -1,109 +0,0 @@
#
# Makefile for the BSPC tool for the Gladiator Bot
# Intended for gcc/Linux
#
ARCH=i386
CC=gcc
BASE_CFLAGS=-Dstricmp=strcasecmp
#use these cflags to optimize it
CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
-malign-jumps=2 -malign-functions=2 -DLINUX -DBSPC
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-ldl -lm -lpthread
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
#############################################################################
# SETUP AND BUILD BSPC
#############################################################################
.c.o:
$(DO_CC)
GAME_OBJS = \
_files.o\
aas_areamerging.o\
aas_cfg.o\
aas_create.o\
aas_edgemelting.o\
aas_facemerging.o\
aas_file.o\
aas_gsubdiv.o\
aas_map.o\
aas_prunenodes.o\
aas_store.o\
be_aas_bspc.o\
../botlib/be_aas_bspq3.o\
../botlib/be_aas_cluster.o\
../botlib/be_aas_move.o\
../botlib/be_aas_optimize.o\
../botlib/be_aas_reach.o\
../botlib/be_aas_sample.o\
brushbsp.o\
bspc.o\
../qcommon/cm_load.o\
../qcommon/cm_patch.o\
../qcommon/cm_test.o\
../qcommon/cm_trace.o\
csg.o\
glfile.o\
l_bsp_ent.o\
l_bsp_hl.o\
l_bsp_q1.o\
l_bsp_q2.o\
l_bsp_q3.o\
l_bsp_sin.o\
l_cmd.o\
../botlib/l_libvar.o\
l_log.o\
l_math.o\
l_mem.o\
l_poly.o\
../botlib/l_precomp.o\
l_qfiles.o\
../botlib/l_script.o\
../botlib/l_struct.o\
l_threads.o\
l_utils.o\
leakfile.o\
map.o\
map_hl.o\
map_q1.o\
map_q2.o\
map_q3.o\
map_sin.o\
../qcommon/md4.o\
nodraw.o\
portals.o\
tetrahedron.o\
textures.o\
tree.o\
../qcommon/unzip.o
bspc$(ARCH) : $(GAME_OBJS)
$(CC) $(CFLAGS) -o $@ $(GAME_OBJS) $(LDFLAGS)
#############################################################################
# MISC
#############################################################################
clean:
-rm -f $(GAME_OBJS)
depend:
gcc -MM $(GAME_OBJS:.o=.c)
install:
cp bspci386 ..
#
# From "make depend"
#

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,681 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h" //aas_bbox_t
#include "aas_store.h" //AAS_MAX_BBOXES
#include "aas_cfg.h"
#include "aas_map.h" //AAS_CreateMapBrushes
#include "l_bsp_q3.h"
#include "../qcommon/cm_patch.h"
#include "../qcommon/surfaceflags.h"
#define NODESTACKSIZE 1024
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintContents(int contents);
int Q3_BrushContents(mapbrush_t *b)
{
int contents, i, mixed, hint;
side_t *s;
s = &b->original_sides[0];
contents = s->contents;
//
mixed = false;
hint = false;
for (i = 1; i < b->numsides; i++)
{
s = &b->original_sides[i];
if (s->contents != contents) mixed = true;
if (s->surf & (SURF_HINT|SURF_SKIP)) hint = true;
contents |= s->contents;
} //end for
//
if (hint)
{
if (contents)
{
Log_Write("WARNING: hint brush with contents: ");
PrintContents(contents);
Log_Write("\r\n");
//
Log_Write("brush contents is: ");
PrintContents(b->contents);
Log_Write("\r\n");
} //end if
return 0;
} //end if
//Log_Write("brush %d contents ", nummapbrushes);
//PrintContents(contents);
//Log_Write("\r\n");
//remove ladder and fog contents
contents &= ~(CONTENTS_LADDER|CONTENTS_FOG);
//
if (mixed)
{
Log_Write("Entity %i, Brush %i: mixed face contents "
, b->entitynum, b->brushnum);
PrintContents(contents);
Log_Write("\r\n");
//
Log_Write("brush contents is: ");
PrintContents(b->contents);
Log_Write("\r\n");
//
if (contents & CONTENTS_DONOTENTER) return CONTENTS_DONOTENTER;//Log_Print("mixed contents with donotenter\n");
/*
Log_Print("contents:"); PrintContents(contents);
Log_Print("\ncontents:"); PrintContents(s->contents);
Log_Print("\n");
Log_Print("texture name = %s\n", texinfo[s->texinfo].texture);
*/
//if liquid brush
if (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER))
{
return (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER));
} //end if
if (contents & CONTENTS_PLAYERCLIP) return (contents & CONTENTS_PLAYERCLIP);
return (contents & CONTENTS_SOLID);
} //end if
/*
if (contents & CONTENTS_AREAPORTAL)
{
static int num;
Log_Write("Entity %i, Brush %i: area portal %d\r\n", b->entitynum, b->brushnum, num++);
} //end if*/
if (contents == (contents & CONTENTS_STRUCTURAL))
{
//Log_Print("brush %i is only structural\n", b->brushnum);
contents = 0;
} //end if
if (contents & CONTENTS_DONOTENTER)
{
Log_Print("brush %i is a donotenter brush, c = %X\n", b->brushnum, contents);
} //end if
return contents;
} //end of the function Q3_BrushContents
#define BBOX_NORMAL_EPSILON 0.0001
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_DPlanes2MapPlanes(void)
{
int i;
for (i = 0; i < q3_numplanes; i++)
{
dplanes2mapplanes[i] = FindFloatPlane(q3_dplanes[i].normal, q3_dplanes[i].dist);
} //end for
} //end of the function Q3_DPlanes2MapPlanes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_BSPBrushToMapBrush(q3_dbrush_t *bspbrush, entity_t *mapent)
{
mapbrush_t *b;
int i, k, n;
side_t *side, *s2;
int planenum;
q3_dbrushside_t *bspbrushside;
q3_dplane_t *bspplane;
if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
b = &mapbrushes[nummapbrushes];
b->original_sides = &brushsides[nummapbrushsides];
b->entitynum = mapent-entities;
b->brushnum = nummapbrushes - mapent->firstbrush;
b->leafnum = dbrushleafnums[bspbrush - q3_dbrushes];
for (n = 0; n < bspbrush->numSides; n++)
{
//pointer to the bsp brush side
bspbrushside = &q3_dbrushsides[bspbrush->firstSide + n];
if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
{
Error ("MAX_MAPFILE_BRUSHSIDES");
} //end if
//pointer to the map brush side
side = &brushsides[nummapbrushsides];
//if the BSP brush side is textured
if (q3_dbrushsidetextured[bspbrush->firstSide + n]) side->flags |= SFL_TEXTURED|SFL_VISIBLE;
else side->flags &= ~SFL_TEXTURED;
//NOTE: all Quake3 sides are assumed textured
//side->flags |= SFL_TEXTURED|SFL_VISIBLE;
//
if (bspbrushside->shaderNum < 0)
{
side->contents = 0;
side->surf = 0;
} //end if
else
{
side->contents = q3_dshaders[bspbrushside->shaderNum].contentFlags;
side->surf = q3_dshaders[bspbrushside->shaderNum].surfaceFlags;
if (strstr(q3_dshaders[bspbrushside->shaderNum].shader, "common/hint"))
{
//Log_Print("found hint side\n");
side->surf |= SURF_HINT;
} //end if
} //end else
//
if (side->surf & SURF_NODRAW)
{
side->flags |= SFL_TEXTURED|SFL_VISIBLE;
} //end if
/*
if (side->contents & (CONTENTS_TRANSLUCENT|CONTENTS_STRUCTURAL))
{
side->flags |= SFL_TEXTURED|SFL_VISIBLE;
} //end if*/
// hints and skips are never detail, and have no content
if (side->surf & (SURF_HINT|SURF_SKIP) )
{
side->contents = 0;
//Log_Print("found hint brush side\n");
}
/*
if ((side->surf & SURF_NODRAW) && (side->surf & SURF_NOIMPACT))
{
side->contents = 0;
side->surf &= ~CONTENTS_DETAIL;
Log_Print("probably found hint brush in a BSP without hints being used\n");
} //end if*/
//ME: get a plane for this side
bspplane = &q3_dplanes[bspbrushside->planeNum];
planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
//
// see if the plane has been used already
//
//ME: this really shouldn't happen!!!
//ME: otherwise the bsp file is corrupted??
//ME: still it seems to happen, maybe Johny Boy's
//ME: brush bevel adding is crappy ?
for (k = 0; k < b->numsides; k++)
{
s2 = b->original_sides + k;
// if (DotProduct (mapplanes[s2->planenum].normal, mapplanes[planenum].normal) > 0.999
// && fabs(mapplanes[s2->planenum].dist - mapplanes[planenum].dist) < 0.01 )
if (s2->planenum == planenum)
{
Log_Print("Entity %i, Brush %i: duplicate plane\n"
, b->entitynum, b->brushnum);
break;
}
if ( s2->planenum == (planenum^1) )
{
Log_Print("Entity %i, Brush %i: mirrored plane\n"
, b->entitynum, b->brushnum);
break;
}
}
if (k != b->numsides)
continue; // duplicated
//
// keep this side
//
//ME: reset pointer to side, why? hell I dunno (pointer is set above already)
side = b->original_sides + b->numsides;
//ME: store the plane number
side->planenum = planenum;
//ME: texinfo is already stored when bsp is loaded
//NOTE: check for TEXINFO_NODE, otherwise crash in Q3_BrushContents
//if (bspbrushside->texinfo < 0) side->texinfo = 0;
//else side->texinfo = bspbrushside->texinfo;
// save the td off in case there is an origin brush and we
// have to recalculate the texinfo
// ME: don't need to recalculate because it's already done
// (for non-world entities) in the BSP file
// side_brushtextures[nummapbrushsides] = td;
nummapbrushsides++;
b->numsides++;
} //end for
// get the content for the entire brush
b->contents = q3_dshaders[bspbrush->shaderNum].contentFlags;
b->contents &= ~(CONTENTS_LADDER|CONTENTS_FOG|CONTENTS_STRUCTURAL);
// b->contents = Q3_BrushContents(b);
//
if (BrushExists(b))
{
c_squattbrushes++;
b->numsides = 0;
return;
} //end if
//if we're creating AAS
if (create_aas)
{
//create the AAS brushes from this brush, don't add brush bevels
AAS_CreateMapBrushes(b, mapent, false);
return;
} //end if
// allow detail brushes to be removed
if (nodetail && (b->contents & CONTENTS_DETAIL) )
{
b->numsides = 0;
return;
} //end if
// allow water brushes to be removed
if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
{
b->numsides = 0;
return;
} //end if
// create windings for sides and bounds for brush
MakeBrushWindings(b);
//mark brushes without winding or with a tiny window as bevels
MarkBrushBevels(b);
// brushes that will not be visible at all will never be
// used as bsp splitters
if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
{
c_clipbrushes++;
for (i = 0; i < b->numsides; i++)
b->original_sides[i].texinfo = TEXINFO_NODE;
} //end for
//
// origin brushes are removed, but they set
// the rotation origin for the rest of the brushes
// in the entity. After the entire entity is parsed,
// the planenums and texinfos will be adjusted for
// the origin brush
//
//ME: not needed because the entities in the BSP file already
// have an origin set
// if (b->contents & CONTENTS_ORIGIN)
// {
// char string[32];
// vec3_t origin;
//
// if (num_entities == 1)
// {
// Error ("Entity %i, Brush %i: origin brushes not allowed in world"
// , b->entitynum, b->brushnum);
// return;
// }
//
// VectorAdd (b->mins, b->maxs, origin);
// VectorScale (origin, 0.5, origin);
//
// sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
// SetKeyValue (&entities[b->entitynum], "origin", string);
//
// VectorCopy (origin, entities[b->entitynum].origin);
//
// // don't keep this brush
// b->numsides = 0;
//
// return;
// }
//ME: the bsp brushes already have bevels, so we won't try to
// add them again (especially since Johny Boy's bevel adding might
// be crappy)
// AddBrushBevels(b);
nummapbrushes++;
mapent->numbrushes++;
} //end of the function Q3_BSPBrushToMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_ParseBSPBrushes(entity_t *mapent)
{
int i;
for (i = 0; i < q3_dmodels[mapent->modelnum].numBrushes; i++)
{
Q3_BSPBrushToMapBrush(&q3_dbrushes[q3_dmodels[mapent->modelnum].firstBrush + i], mapent);
} //end for
} //end of the function Q3_ParseBSPBrushes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean Q3_ParseBSPEntity(int entnum)
{
entity_t *mapent;
char *model;
int startbrush, startsides;
startbrush = nummapbrushes;
startsides = nummapbrushsides;
mapent = &entities[entnum];//num_entities];
mapent->firstbrush = nummapbrushes;
mapent->numbrushes = 0;
mapent->modelnum = -1; //-1 = no BSP model
model = ValueForKey(mapent, "model");
if (model && strlen(model))
{
if (*model == '*')
{
//get the model number of this entity (skip the leading *)
mapent->modelnum = atoi(&model[1]);
} //end if
} //end if
GetVectorForKey(mapent, "origin", mapent->origin);
//if this is the world entity it has model number zero
//the world entity has no model key
if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
{
mapent->modelnum = 0;
} //end if
//if the map entity has a BSP model (a modelnum of -1 is used for
//entities that aren't using a BSP model)
if (mapent->modelnum >= 0)
{
//parse the bsp brushes
Q3_ParseBSPBrushes(mapent);
} //end if
//
//the origin of the entity is already taken into account
//
//func_group entities can't be in the bsp file
//
//check out the func_areaportal entities
if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
{
c_areaportals++;
mapent->areaportalnum = c_areaportals;
return true;
} //end if
return true;
} //end of the function Q3_ParseBSPEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#define MAX_PATCH_VERTS 1024
void AAS_CreateCurveBrushes(void)
{
int i, j, n, planenum, numcurvebrushes = 0;
q3_dsurface_t *surface;
q3_drawVert_t *dv_p;
vec3_t points[MAX_PATCH_VERTS];
int width, height, c;
patchCollide_t *pc;
facet_t *facet;
mapbrush_t *brush;
side_t *side;
entity_t *mapent;
winding_t *winding;
qprintf("nummapbrushsides = %d\n", nummapbrushsides);
mapent = &entities[0];
for (i = 0; i < q3_numDrawSurfaces; i++)
{
surface = &q3_drawSurfaces[i];
if ( ! surface->patchWidth ) continue;
// if the curve is not solid
if (!(q3_dshaders[surface->shaderNum].contentFlags & (CONTENTS_SOLID|CONTENTS_PLAYERCLIP)))
{
//Log_Print("skipped non-solid curve\n");
continue;
} //end if
// if this curve should not be used for AAS
if ( q3_dshaders[surface->shaderNum].contentFlags & CONTENTS_NOBOTCLIP ) {
continue;
}
//
width = surface->patchWidth;
height = surface->patchHeight;
c = width * height;
if (c > MAX_PATCH_VERTS)
{
Error("ParseMesh: MAX_PATCH_VERTS");
} //end if
dv_p = q3_drawVerts + surface->firstVert;
for ( j = 0 ; j < c ; j++, dv_p++ )
{
points[j][0] = dv_p->xyz[0];
points[j][1] = dv_p->xyz[1];
points[j][2] = dv_p->xyz[2];
} //end for
// create the internal facet structure
pc = CM_GeneratePatchCollide(width, height, points);
//
for (j = 0; j < pc->numFacets; j++)
{
facet = &pc->facets[j];
//
brush = &mapbrushes[nummapbrushes];
brush->original_sides = &brushsides[nummapbrushsides];
brush->entitynum = 0;
brush->brushnum = nummapbrushes - mapent->firstbrush;
//
brush->numsides = facet->numBorders + 2;
nummapbrushsides += brush->numsides;
brush->contents = CONTENTS_SOLID;
//
//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
qprintf("\r%6d curve brushes", ++numcurvebrushes);
//
planenum = FindFloatPlane(pc->planes[facet->surfacePlane].plane, pc->planes[facet->surfacePlane].plane[3]);
//
side = &brush->original_sides[0];
side->planenum = planenum;
side->contents = CONTENTS_SOLID;
side->flags |= SFL_TEXTURED|SFL_VISIBLE|SFL_CURVE;
side->surf = 0;
//
side = &brush->original_sides[1];
if (create_aas)
{
//the plane is expanded later so it's not a problem that
//these first two opposite sides are coplanar
side->planenum = planenum ^ 1;
} //end if
else
{
side->planenum = FindFloatPlane(mapplanes[planenum^1].normal, mapplanes[planenum^1].dist + 1);
side->flags |= SFL_TEXTURED|SFL_VISIBLE;
} //end else
side->contents = CONTENTS_SOLID;
side->flags |= SFL_CURVE;
side->surf = 0;
//
winding = BaseWindingForPlane(mapplanes[side->planenum].normal, mapplanes[side->planenum].dist);
for (n = 0; n < facet->numBorders; n++)
{
//never use the surface plane as a border
if (facet->borderPlanes[n] == facet->surfacePlane) continue;
//
side = &brush->original_sides[2 + n];
side->planenum = FindFloatPlane(pc->planes[facet->borderPlanes[n]].plane, pc->planes[facet->borderPlanes[n]].plane[3]);
if (facet->borderInward[n]) side->planenum ^= 1;
side->contents = CONTENTS_SOLID;
side->flags |= SFL_TEXTURED|SFL_CURVE;
side->surf = 0;
//chop the winding in place
if (winding) ChopWindingInPlace(&winding, mapplanes[side->planenum^1].normal, mapplanes[side->planenum^1].dist, 0.1); //CLIP_EPSILON);
} //end for
//VectorCopy(pc->bounds[0], brush->mins);
//VectorCopy(pc->bounds[1], brush->maxs);
if (!winding)
{
Log_Print("WARNING: AAS_CreateCurveBrushes: no winding\n");
brush->numsides = 0;
continue;
} //end if
brush->original_sides[0].winding = winding;
WindingBounds(winding, brush->mins, brush->maxs);
for (n = 0; n < 3; n++)
{
//IDBUG: all the indexes into the mins and maxs were zero (not using i)
if (brush->mins[n] < -MAX_MAP_BOUNDS || brush->maxs[n] > MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: bounds out of range\n", brush->entitynum, brush->brushnum);
Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
brush->numsides = 0; //remove the brush
break;
} //end if
if (brush->mins[n] > MAX_MAP_BOUNDS || brush->maxs[n] < -MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
brush->numsides = 0; //remove the brush
break;
} //end if
} //end for
if (create_aas)
{
//NOTE: brush bevels now already added
//AddBrushBevels(brush);
AAS_CreateMapBrushes(brush, mapent, false);
} //end if
else
{
// create windings for sides and bounds for brush
MakeBrushWindings(brush);
AddBrushBevels(brush);
nummapbrushes++;
mapent->numbrushes++;
} //end else
} //end for
} //end for
//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
qprintf("\r%6d curve brushes\n", numcurvebrushes);
} //end of the function AAS_CreateCurveBrushes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ExpandMapBrush(mapbrush_t *brush, vec3_t mins, vec3_t maxs);
void Q3_LoadMapFromBSP(struct quakefile_s *qf)
{
int i;
vec3_t mins = {-1,-1,-1}, maxs = {1, 1, 1};
Log_Print("-- Q3_LoadMapFromBSP --\n");
//loaded map type
loadedmaptype = MAPTYPE_QUAKE3;
Log_Print("Loading map from %s...\n", qf->filename);
//load the bsp file
Q3_LoadBSPFile(qf);
//create an index from bsp planes to map planes
//DPlanes2MapPlanes();
//clear brush model numbers
for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
brushmodelnumbers[i] = -1;
nummapbrushsides = 0;
num_entities = 0;
Q3_ParseEntities();
//
for (i = 0; i < num_entities; i++)
{
Q3_ParseBSPEntity(i);
} //end for
AAS_CreateCurveBrushes();
//get the map mins and maxs from the world model
ClearBounds(map_mins, map_maxs);
for (i = 0; i < entities[0].numbrushes; i++)
{
if (mapbrushes[i].numsides <= 0)
continue;
AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
} //end for
/*/
for (i = 0; i < nummapbrushes; i++)
{
//if (!mapbrushes[i].original_sides) continue;
//AddBrushBevels(&mapbrushes[i]);
//AAS_ExpandMapBrush(&mapbrushes[i], mins, maxs);
} //end for*/
/*
for (i = 0; i < nummapbrushsides; i++)
{
Log_Write("side %d flags = %d", i, brushsides[i].flags);
} //end for
for (i = 0; i < nummapbrushes; i++)
{
Log_Write("brush contents: ");
PrintContents(mapbrushes[i].contents);
Log_Print("\n");
} //end for*/
} //end of the function Q3_LoadMapFromBSP
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Q3_ResetMapLoading(void)
{
//reset for map loading from bsp
memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
nodestackptr = NULL;
nodestacksize = 0;
memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
} //end of the function Q3_ResetMapLoading

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
vec3_t draw_mins, draw_maxs;
qboolean drawflag;
void Draw_ClearWindow (void)
{
}
//============================================================
#define GLSERV_PORT 25001
void GLS_BeginScene (void)
{
}
void GLS_Winding (winding_t *w, int code)
{
}
void GLS_EndScene (void)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -1,287 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
/*
==============================================================================
PORTAL FILE GENERATION
Save out name.prt for qvis to read
==============================================================================
*/
#define PORTALFILE "PRT1"
FILE *pf;
int num_visclusters; // clusters the player can be in
int num_visportals;
void WriteFloat2 (FILE *f, vec_t v)
{
if ( fabs(v - Q_rint(v)) < 0.001 )
fprintf (f,"%i ",(int)Q_rint(v));
else
fprintf (f,"%f ",v);
}
/*
=================
WritePortalFile_r
=================
*/
void WritePortalFile_r (node_t *node)
{
int i, s;
portal_t *p;
winding_t *w;
vec3_t normal;
vec_t dist;
// decision node
if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
{
WritePortalFile_r (node->children[0]);
WritePortalFile_r (node->children[1]);
return;
}
if (node->contents & CONTENTS_SOLID)
return;
for (p = node->portals ; p ; p=p->next[s])
{
w = p->winding;
s = (p->nodes[1] == node);
if (w && p->nodes[0] == node)
{
if (!Portal_VisFlood (p))
continue;
// 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
// FIXME: is this still relevent?
WindingPlane (w, normal, &dist);
if ( DotProduct (p->plane.normal, normal) < 0.99 )
{ // backwards...
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
}
else
fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
for (i=0 ; i<w->numpoints ; i++)
{
fprintf (pf,"(");
WriteFloat2 (pf, w->p[i][0]);
WriteFloat2 (pf, w->p[i][1]);
WriteFloat2 (pf, w->p[i][2]);
fprintf (pf,") ");
}
fprintf (pf,"\n");
}
}
}
/*
================
FillLeafNumbers_r
All of the leafs under node will have the same cluster
================
*/
void FillLeafNumbers_r (node_t *node, int num)
{
if (node->planenum == PLANENUM_LEAF)
{
if (node->contents & CONTENTS_SOLID)
node->cluster = -1;
else
node->cluster = num;
return;
}
node->cluster = num;
FillLeafNumbers_r (node->children[0], num);
FillLeafNumbers_r (node->children[1], num);
}
/*
================
NumberLeafs_r
================
*/
void NumberLeafs_r (node_t *node)
{
portal_t *p;
if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
{ // decision node
node->cluster = -99;
NumberLeafs_r (node->children[0]);
NumberLeafs_r (node->children[1]);
return;
}
// either a leaf or a detail cluster
if ( node->contents & CONTENTS_SOLID )
{ // solid block, viewpoint never inside
node->cluster = -1;
return;
}
FillLeafNumbers_r (node, num_visclusters);
num_visclusters++;
// count the portals
for (p = node->portals ; p ; )
{
if (p->nodes[0] == node) // only write out from first leaf
{
if (Portal_VisFlood (p))
num_visportals++;
p = p->next[0];
}
else
p = p->next[1];
}
}
/*
================
CreateVisPortals_r
================
*/
void CreateVisPortals_r (node_t *node)
{
// stop as soon as we get to a detail_seperator, which
// means that everything below is in a single cluster
if (node->planenum == PLANENUM_LEAF || node->detail_seperator )
return;
MakeNodePortal (node);
SplitNodePortals (node);
CreateVisPortals_r (node->children[0]);
CreateVisPortals_r (node->children[1]);
}
/*
================
FinishVisPortals_r
================
*/
void FinishVisPortals2_r (node_t *node)
{
if (node->planenum == PLANENUM_LEAF)
return;
MakeNodePortal (node);
SplitNodePortals (node);
FinishVisPortals2_r (node->children[0]);
FinishVisPortals2_r (node->children[1]);
}
void FinishVisPortals_r (node_t *node)
{
if (node->planenum == PLANENUM_LEAF)
return;
if (node->detail_seperator)
{
FinishVisPortals2_r (node);
return;
}
FinishVisPortals_r (node->children[0]);
FinishVisPortals_r (node->children[1]);
}
int clusterleaf;
void SaveClusters_r (node_t *node)
{
if (node->planenum == PLANENUM_LEAF)
{
dleafs[clusterleaf++].cluster = node->cluster;
return;
}
SaveClusters_r (node->children[0]);
SaveClusters_r (node->children[1]);
}
/*
================
WritePortalFile
================
*/
void WritePortalFile (tree_t *tree)
{
char filename[1024];
node_t *headnode;
qprintf ("--- WritePortalFile ---\n");
headnode = tree->headnode;
num_visclusters = 0;
num_visportals = 0;
Tree_FreePortals_r (headnode);
MakeHeadnodePortals (tree);
CreateVisPortals_r (headnode);
// set the cluster field in every leaf and count the total number of portals
NumberLeafs_r (headnode);
// write the file
sprintf (filename, "%s.prt", source);
printf ("writing %s\n", filename);
pf = fopen (filename, "w");
if (!pf)
Error ("Error opening %s", filename);
fprintf (pf, "%s\n", PORTALFILE);
fprintf (pf, "%i\n", num_visclusters);
fprintf (pf, "%i\n", num_visportals);
qprintf ("%5i visclusters\n", num_visclusters);
qprintf ("%5i visportals\n", num_visportals);
WritePortalFile_r (headnode);
fclose (pf);
// we need to store the clusters out now because ordering
// issues made us do this after writebsp...
clusterleaf = 1;
SaveClusters_r (headnode);
}

View File

@ -1,487 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
/*
========================================================================
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P')
typedef struct
{
char name[56];
int filepos, filelen;
} dpackfile_t;
typedef struct
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
} dpackheader_t;
#define MAX_FILES_IN_PACK 4096
/*
========================================================================
PCX files are used for as many images as possible
========================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
.MD2 triangle model file format
========================================================================
*/
#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define ALIAS_VERSION 8
#define MAX_TRIANGLES 4096
#define MAX_VERTS 2048
#define MAX_FRAMES 512
#define MAX_MD2SKINS 32
#define MAX_SKINNAME 64
typedef struct
{
short s;
short t;
} dstvert_t;
typedef struct
{
short index_xyz[3];
short index_st[3];
} dtriangle_t;
typedef struct
{
byte v[3]; // scaled byte to fit in frame mins/maxs
byte lightnormalindex;
} dtrivertx_t;
#define DTRIVERTX_V0 0
#define DTRIVERTX_V1 1
#define DTRIVERTX_V2 2
#define DTRIVERTX_LNI 3
#define DTRIVERTX_SIZE 4
typedef struct
{
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
dtrivertx_t verts[1]; // variable sized
} daliasframe_t;
// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.
typedef struct
{
int ident;
int version;
int skinwidth;
int skinheight;
int framesize; // byte size of each frame
int num_skins;
int num_xyz;
int num_st; // greater than num_xyz for seams
int num_tris;
int num_glcmds; // dwords in strip/fan command list
int num_frames;
int ofs_skins; // each skin is a MAX_SKINNAME string
int ofs_st; // byte offset from start for stverts
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
int ofs_end; // end of file
} dmdl_t;
/*
========================================================================
.SP2 sprite file format
========================================================================
*/
#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I')
// little-endian "IDS2"
#define SPRITE_VERSION 2
typedef struct
{
int width, height;
int origin_x, origin_y; // raster coordinates inside pic
char name[MAX_SKINNAME]; // name of pcx file
} dsprframe_t;
typedef struct {
int ident;
int version;
int numframes;
dsprframe_t frames[1]; // variable sized
} dsprite_t;
/*
==============================================================================
.WAL texture file format
==============================================================================
*/
#define MIPLEVELS 4
typedef struct miptex_s
{
char name[32];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
char animname[32]; // next frame in animation chain
int flags;
int contents;
int value;
} miptex_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I')
// little-endian "IBSP"
#define BSPVERSION 38
// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
#define MAX_MAP_ENTITIES 2048
#define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_TEXINFO 8192
#define MAX_MAP_AREAS 256
#define MAX_MAP_AREAPORTALS 1024
#define MAX_MAP_PLANES 65536
#define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536
#define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536
#define MAX_MAP_FACES 65536
#define MAX_MAP_LEAFFACES 65536
#define MAX_MAP_LEAFBRUSHES 65536
#define MAX_MAP_PORTALS 65536
#define MAX_MAP_EDGES 128000
#define MAX_MAP_SURFEDGES 256000
#define MAX_MAP_LIGHTING 0x320000
#define MAX_MAP_VISIBILITY 0x280000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
typedef struct
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_VERTEXES 2
#define LUMP_VISIBILITY 3
#define LUMP_NODES 4
#define LUMP_TEXINFO 5
#define LUMP_FACES 6
#define LUMP_LIGHTING 7
#define LUMP_LEAFS 8
#define LUMP_LEAFFACES 9
#define LUMP_LEAFBRUSHES 10
#define LUMP_EDGES 11
#define LUMP_SURFEDGES 12
#define LUMP_MODELS 13
#define LUMP_BRUSHES 14
#define LUMP_BRUSHSIDES 15
#define LUMP_POP 16
#define LUMP_AREAS 17
#define LUMP_AREAPORTALS 18
#define HEADER_LUMPS 19
typedef struct
{
int ident;
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3]; // for sounds or lights
int headnode;
int firstface, numfaces; // submodels just draw faces
// without walking the bsp tree
} dmodel_t;
typedef struct
{
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planes (x&~1) and (x&~1)+1 are allways opposites
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
#define CONTENTS_WINDOW 2 // translucent, but not watery
#define CONTENTS_AUX 4
#define CONTENTS_LAVA 8
#define CONTENTS_SLIME 16
#define CONTENTS_WATER 32
#define CONTENTS_MIST 64
#define LAST_VISIBLE_CONTENTS 64
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x40000
#define CONTENTS_CURRENT_90 0x80000
#define CONTENTS_CURRENT_180 0x100000
#define CONTENTS_CURRENT_270 0x200000
#define CONTENTS_CURRENT_UP 0x400000
#define CONTENTS_CURRENT_DOWN 0x800000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEADMONSTER 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
//renamed because it's in conflict with the Q3A translucent contents
#define CONTENTS_Q2TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define SURF_LIGHT 0x1 // value will hold the light strength
#define SURF_SLICK 0x2 // effects game physics
#define SURF_SKY 0x4 // don't draw, but add to skybox
#define SURF_WARP 0x8 // turbulent water warp
#define SURF_TRANS33 0x10
#define SURF_TRANS66 0x20
#define SURF_FLOWING 0x40 // scroll towards angle
#define SURF_NODRAW 0x80 // don't bother referencing the texture
#define SURF_HINT 0x100 // make a primary bsp splitter
#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for frustom culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
int value; // light emission, etc
char texture[32]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
} texinfo_t;
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
typedef struct
{
int contents; // OR of all brushes (not needed?)
short cluster;
short area;
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} dleaf_t;
typedef struct
{
unsigned short planenum; // facing out of the leaf
short texinfo;
} dbrushside_t;
typedef struct
{
int firstside;
int numsides;
int contents;
} dbrush_t;
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the visibility lump consists of a header with a count, then
// byte offsets for the PVS and PHS of each cluster, then the raw
// compressed bit vectors
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef struct
{
int numclusters;
int bitofs[8][2]; // bitofs[numclusters][2]
} dvis_t;
// each area has a list of portals that lead into other areas
// when portals are closed, other areas may not be visible or
// hearable even if the vis info says that it should be
typedef struct
{
int portalnum;
int otherarea;
} dareaportal_t;
typedef struct
{
int numareaportals;
int firstareaportal;
} darea_t;

View File

@ -1,374 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __QFILES_H__
#define __QFILES_H__
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
// surface geometry should not exceed these limits
#define SHADER_MAX_VERTEXES 1000
#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
// the maximum size of game reletive pathnames
#define MAX_QPATH 64
/*
========================================================================
PCX files are used for 8 bit images
========================================================================
*
typedef struct {
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
TGA files are used for 24/32 bit images
========================================================================
*
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
*/
/*
========================================================================
.MD3 triangle model file format
========================================================================
*/
#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
#define MD3_VERSION 15
// limits
#define MD3_MAX_LODS 4
#define MD3_MAX_TRIANGLES 8192 // per surface
#define MD3_MAX_VERTS 4096 // per surface
#define MD3_MAX_SHADERS 256 // per surface
#define MD3_MAX_FRAMES 1024 // per model
#define MD3_MAX_SURFACES 32 // per model
#define MD3_MAX_TAGS 16 // per frame
// vertex scales
#define MD3_XYZ_SCALE (1.0/64)
typedef struct md3Frame_s {
vec3_t bounds[2];
vec3_t localOrigin;
float radius;
char name[16];
} md3Frame_t;
typedef struct md3Tag_s {
char name[MAX_QPATH]; // tag name
vec3_t origin;
vec3_t axis[3];
} md3Tag_t;
/*
** md3Surface_t
**
** CHUNK SIZE
** header sizeof( md3Surface_t )
** shaders sizeof( md3Shader_t ) * numShaders
** triangles[0] sizeof( md3Triangle_t ) * numTriangles
** st sizeof( md3St_t ) * numVerts
** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
*/
typedef struct {
int ident; //
char name[MAX_QPATH]; // polyset name
int flags;
int numFrames; // all surfaces in a model should have the same
int numShaders; // all surfaces in a model should have the same
int numVerts;
int numTriangles;
int ofsTriangles;
int ofsShaders; // offset from start of md3Surface_t
int ofsSt; // texture coords are common for all frames
int ofsXyzNormals; // numVerts * numFrames
int ofsEnd; // next surface follows
} md3Surface_t;
typedef struct {
char name[MAX_QPATH];
int shaderIndex; // for in-game use
} md3Shader_t;
typedef struct {
int indexes[3];
} md3Triangle_t;
typedef struct {
float st[2];
} md3St_t;
typedef struct {
short xyz[3];
short normal;
} md3XyzNormal_t;
typedef struct {
int ident;
int version;
char name[MAX_QPATH]; // model name
int flags;
int numFrames;
int numTags;
int numSurfaces;
int numSkins;
int ofsFrames; // offset for first frame
int ofsTags; // numFrames * numTags
int ofsSurfaces; // first surface, others follow
int ofsEnd; // end of file
} md3Header_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define Q3_BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
// little-endian "IBSP"
#define Q3_BSP_VERSION 46
// there shouldn't be any problem with increasing these values at the
// expense of more memory allocation in the utilities
#define Q3_MAX_MAP_MODELS 0x400
#define Q3_MAX_MAP_BRUSHES 0x8000
#define Q3_MAX_MAP_ENTITIES 0x800
#define Q3_MAX_MAP_ENTSTRING 0x10000
#define Q3_MAX_MAP_SHADERS 0x400
#define Q3_MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
#define Q3_MAX_MAP_FOGS 0x100
#define Q3_MAX_MAP_PLANES 0x10000
#define Q3_MAX_MAP_NODES 0x10000
#define Q3_MAX_MAP_BRUSHSIDES 0x10000
#define Q3_MAX_MAP_LEAFS 0x10000
#define Q3_MAX_MAP_LEAFFACES 0x10000
#define Q3_MAX_MAP_LEAFBRUSHES 0x10000
#define Q3_MAX_MAP_PORTALS 0x10000
#define Q3_MAX_MAP_LIGHTING 0x400000
#define Q3_MAX_MAP_LIGHTGRID 0x400000
#define Q3_MAX_MAP_VISIBILITY 0x200000
#define Q3_MAX_MAP_DRAW_SURFS 0x20000
#define Q3_MAX_MAP_DRAW_VERTS 0x80000
#define Q3_MAX_MAP_DRAW_INDEXES 0x80000
// key / value pair sizes in the entities lump
#define Q3_MAX_KEY 32
#define Q3_MAX_VALUE 1024
// the editor uses these predefined yaw angles to orient entities up or down
#define ANGLE_UP -1
#define ANGLE_DOWN -2
#define LIGHTMAP_WIDTH 128
#define LIGHTMAP_HEIGHT 128
//=============================================================================
typedef struct {
int fileofs, filelen;
} q3_lump_t;
#define Q3_LUMP_ENTITIES 0
#define Q3_LUMP_SHADERS 1
#define Q3_LUMP_PLANES 2
#define Q3_LUMP_NODES 3
#define Q3_LUMP_LEAFS 4
#define Q3_LUMP_LEAFSURFACES 5
#define Q3_LUMP_LEAFBRUSHES 6
#define Q3_LUMP_MODELS 7
#define Q3_LUMP_BRUSHES 8
#define Q3_LUMP_BRUSHSIDES 9
#define Q3_LUMP_DRAWVERTS 10
#define Q3_LUMP_DRAWINDEXES 11
#define Q3_LUMP_FOGS 12
#define Q3_LUMP_SURFACES 13
#define Q3_LUMP_LIGHTMAPS 14
#define Q3_LUMP_LIGHTGRID 15
#define Q3_LUMP_VISIBILITY 16
#define Q3_HEADER_LUMPS 17
typedef struct {
int ident;
int version;
q3_lump_t lumps[Q3_HEADER_LUMPS];
} q3_dheader_t;
typedef struct {
float mins[3], maxs[3];
int firstSurface, numSurfaces;
int firstBrush, numBrushes;
} q3_dmodel_t;
typedef struct {
char shader[MAX_QPATH];
int surfaceFlags;
int contentFlags;
} q3_dshader_t;
// planes (x&~1) and (x&~1)+1 are allways opposites
typedef struct {
float normal[3];
float dist;
} q3_dplane_t;
typedef struct {
int planeNum;
int children[2]; // negative numbers are -(leafs+1), not nodes
int mins[3]; // for frustom culling
int maxs[3];
} q3_dnode_t;
typedef struct {
int cluster; // -1 = opaque cluster (do I still store these?)
int area;
int mins[3]; // for frustum culling
int maxs[3];
int firstLeafSurface;
int numLeafSurfaces;
int firstLeafBrush;
int numLeafBrushes;
} q3_dleaf_t;
typedef struct {
int planeNum; // positive plane side faces out of the leaf
int shaderNum;
} q3_dbrushside_t;
typedef struct {
int firstSide;
int numSides;
int shaderNum; // the shader that determines the contents flags
} q3_dbrush_t;
typedef struct {
char shader[MAX_QPATH];
int brushNum;
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
} q3_dfog_t;
typedef struct {
vec3_t xyz;
float st[2];
float lightmap[2];
vec3_t normal;
byte color[4];
} q3_drawVert_t;
typedef enum {
MST_BAD,
MST_PLANAR,
MST_PATCH,
MST_TRIANGLE_SOUP,
MST_FLARE
} q3_mapSurfaceType_t;
typedef struct {
int shaderNum;
int fogNum;
int surfaceType;
int firstVert;
int numVerts;
int firstIndex;
int numIndexes;
int lightmapNum;
int lightmapX, lightmapY;
int lightmapWidth, lightmapHeight;
vec3_t lightmapOrigin;
vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
int patchWidth;
int patchHeight;
} q3_dsurface_t;
#endif

View File

@ -1,477 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if defined(WIN32) || defined(_WIN32)
#include <io.h>
#endif
#include <malloc.h>
#include "l_cmd.h"
#include "l_math.h"
#include "l_poly.h"
#include "l_threads.h"
#include "../botlib/l_script.h"
#include "l_bsp_ent.h"
#include "q2files.h"
#include "l_mem.h"
#include "l_utils.h"
#include "l_log.h"
#include "l_qfiles.h"
#define BSPC_VERSION "2.1h"
#define ME
#define DEBUG
#define NODELIST
#define SIN
#define MAX_BRUSH_SIDES 128 //maximum number of sides per brush
#define CLIP_EPSILON 0.1
#define MAX_MAP_BOUNDS 65535
#define BOGUS_RANGE (MAX_MAP_BOUNDS+128) //somewhere outside the map
#define TEXINFO_NODE -1 //side is allready on a node
#define PLANENUM_LEAF -1 //used for leaf nodes
#define MAXEDGES 20 //maximum number of face edges
#define MAX_NODE_BRUSHES 8 //maximum brushes in a node
//side flags
#define SFL_TESTED 1
#define SFL_VISIBLE 2
#define SFL_BEVEL 4
#define SFL_TEXTURED 8
#define SFL_CURVE 16
//map plane
typedef struct plane_s
{
vec3_t normal;
vec_t dist;
int type;
int signbits;
struct plane_s *hash_chain;
} plane_t;
//brush texture
typedef struct
{
vec_t shift[2];
vec_t rotate;
vec_t scale[2];
char name[32];
int flags;
int value;
} brush_texture_t;
//brush side
typedef struct side_s
{
int planenum; // map plane this side is in
int texinfo; // texture reference
winding_t *winding; // winding of this side
struct side_s *original; // bspbrush_t sides will reference the mapbrush_t sides
int lightinfo; // for SIN only
int contents; // from miptex
int surf; // from miptex
unsigned short flags; // side flags
} side_t; //sizeof(side_t) = 36
//map brush
typedef struct mapbrush_s
{
int entitynum;
int brushnum;
int contents;
#ifdef ME
int expansionbbox; //bbox used for expansion of the brush
int leafnum;
int modelnum;
#endif
vec3_t mins, maxs;
int numsides;
side_t *original_sides;
} mapbrush_t;
//bsp face
typedef struct face_s
{
struct face_s *next; // on node
// the chain of faces off of a node can be merged or split,
// but each face_t along the way will remain in the chain
// until the entire tree is freed
struct face_s *merged; // if set, this face isn't valid anymore
struct face_s *split[2]; // if set, this face isn't valid anymore
struct portal_s *portal;
int texinfo;
#ifdef SIN
int lightinfo;
#endif
int planenum;
int contents; // faces in different contents can't merge
int outputnumber;
winding_t *w;
int numpoints;
qboolean badstartvert; // tjunctions cannot be fixed without a midpoint vertex
int vertexnums[MAXEDGES];
} face_t;
//bsp brush
typedef struct bspbrush_s
{
struct bspbrush_s *next;
vec3_t mins, maxs;
int side, testside; // side of node during construction
mapbrush_t *original;
int numsides;
side_t sides[6]; // variably sized
} bspbrush_t; //sizeof(bspbrush_t) = 44 + numsides * sizeof(side_t)
//bsp node
typedef struct node_s
{
//both leafs and nodes
int planenum; // -1 = leaf node
struct node_s *parent;
vec3_t mins, maxs; // valid after portalization
bspbrush_t *volume; // one for each leaf/node
// nodes only
qboolean detail_seperator; // a detail brush caused the split
side_t *side; // the side that created the node
struct node_s *children[2];
face_t *faces;
// leafs only
bspbrush_t *brushlist; // fragments of all brushes in this leaf
int contents; // OR of all brush contents
int occupied; // 1 or greater can reach entity
entity_t *occupant; // for leak file testing
int cluster; // for portalfile writing
int area; // for areaportals
struct portal_s *portals; // also on nodes during construction
#ifdef NODELIST
struct node_s *next; //next node in the nodelist
#endif
#ifdef ME
int expansionbboxes; //OR of all bboxes used for expansion of the brushes
int modelnum;
#endif
} node_t; //sizeof(node_t) = 80 bytes
//bsp portal
typedef struct portal_s
{
plane_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;
qboolean sidefound; // false if ->side hasn't been checked
side_t *side; // NULL = non-visible
face_t *face[2]; // output face in bsp file
#ifdef ME
struct tmp_face_s *tmpface; //pointer to the tmpface created for this portal
int planenum; //number of the map plane used by the portal
#endif
} portal_t;
//bsp tree
typedef struct
{
node_t *headnode;
node_t outside_node;
vec3_t mins, maxs;
} tree_t;
//=============================================================================
// bspc.c
//=============================================================================
extern qboolean noprune;
extern qboolean nodetail;
extern qboolean fulldetail;
extern qboolean nomerge;
extern qboolean nosubdiv;
extern qboolean nowater;
extern qboolean noweld;
extern qboolean noshare;
extern qboolean notjunc;
extern qboolean onlyents;
#ifdef ME
extern qboolean nocsg;
extern qboolean create_aas;
extern qboolean freetree;
extern qboolean lessbrushes;
extern qboolean nobrushmerge;
extern qboolean cancelconversion;
extern qboolean noliquids;
extern qboolean capsule_collision;
#endif //ME
extern float subdivide_size;
extern vec_t microvolume;
extern char outbase[32];
extern char source[1024];
//=============================================================================
// map.c
//=============================================================================
#define MAX_MAPFILE_PLANES 256000
#define MAX_MAPFILE_BRUSHES 65535
#define MAX_MAPFILE_BRUSHSIDES (MAX_MAPFILE_BRUSHES*8)
#define MAX_MAPFILE_TEXINFO 8192
extern int entity_num;
extern plane_t mapplanes[MAX_MAPFILE_PLANES];
extern int nummapplanes;
extern int mapplaneusers[MAX_MAPFILE_PLANES];
extern int nummapbrushes;
extern mapbrush_t mapbrushes[MAX_MAPFILE_BRUSHES];
extern vec3_t map_mins, map_maxs;
extern int nummapbrushsides;
extern side_t brushsides[MAX_MAPFILE_BRUSHSIDES];
extern brush_texture_t side_brushtextures[MAX_MAPFILE_BRUSHSIDES];
#ifdef ME
typedef struct
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
int value;
char texture[64]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
} map_texinfo_t;
extern map_texinfo_t map_texinfo[MAX_MAPFILE_TEXINFO];
extern int map_numtexinfo;
#define NODESTACKSIZE 1024
#define MAPTYPE_QUAKE1 1
#define MAPTYPE_QUAKE2 2
#define MAPTYPE_QUAKE3 3
#define MAPTYPE_HALFLIFE 4
#define MAPTYPE_SIN 5
extern int nodestack[NODESTACKSIZE];
extern int *nodestackptr;
extern int nodestacksize;
extern int brushmodelnumbers[MAX_MAPFILE_BRUSHES];
extern int dbrushleafnums[MAX_MAPFILE_BRUSHES];
extern int dplanes2mapplanes[MAX_MAPFILE_PLANES];
extern int loadedmaptype;
#endif //ME
extern int c_boxbevels;
extern int c_edgebevels;
extern int c_areaportals;
extern int c_clipbrushes;
extern int c_squattbrushes;
//finds a float plane for the given normal and distance
int FindFloatPlane(vec3_t normal, vec_t dist);
//returns the plane type for the given normal
int PlaneTypeForNormal(vec3_t normal);
//returns the plane defined by the three given points
int PlaneFromPoints(int *p0, int *p1, int *p2);
//add bevels to the map brush
void AddBrushBevels(mapbrush_t *b);
//makes brush side windings for the brush
qboolean MakeBrushWindings(mapbrush_t *ob);
//marks brush bevels of the brush as bevel
void MarkBrushBevels(mapbrush_t *brush);
//returns true if the map brush already exists
int BrushExists(mapbrush_t *brush);
//loads a map from a bsp file
int LoadMapFromBSP(struct quakefile_s *qf);
//resets map loading
void ResetMapLoading(void);
//print some map info
void PrintMapInfo(void);
//writes a map file (type depending on loaded map type)
void WriteMapFile(char *filename);
//=============================================================================
// map_q2.c
//=============================================================================
void Q2_ResetMapLoading(void);
//loads a Quake2 map file
void Q2_LoadMapFile(char *filename);
//loads a map from a Quake2 bsp file
void Q2_LoadMapFromBSP(char *filename, int offset, int length);
//=============================================================================
// map_q1.c
//=============================================================================
void Q1_ResetMapLoading(void);
//loads a Quake2 map file
void Q1_LoadMapFile(char *filename);
//loads a map from a Quake1 bsp file
void Q1_LoadMapFromBSP(char *filename, int offset, int length);
//=============================================================================
// map_q3.c
//=============================================================================
void Q3_ResetMapLoading(void);
//loads a map from a Quake3 bsp file
void Q3_LoadMapFromBSP(struct quakefile_s *qf);
//=============================================================================
// map_sin.c
//=============================================================================
void Sin_ResetMapLoading(void);
//loads a Sin map file
void Sin_LoadMapFile(char *filename);
//loads a map from a Sin bsp file
void Sin_LoadMapFromBSP(char *filename, int offset, int length);
//=============================================================================
// map_hl.c
//=============================================================================
void HL_ResetMapLoading(void);
//loads a Half-Life map file
void HL_LoadMapFile(char *filename);
//loads a map from a Half-Life bsp file
void HL_LoadMapFromBSP(char *filename, int offset, int length);
//=============================================================================
// textures.c
//=============================================================================
typedef struct
{
char name[64];
int flags;
int value;
int contents;
char animname[64];
} textureref_t;
#define MAX_MAP_TEXTURES 1024
extern textureref_t textureref[MAX_MAP_TEXTURES];
int FindMiptex(char *name);
int TexinfoForBrushTexture(plane_t *plane, brush_texture_t *bt, vec3_t origin);
void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv);
//=============================================================================
// csg
//=============================================================================
bspbrush_t *MakeBspBrushList(int startbrush, int endbrush, vec3_t clipmins, vec3_t clipmaxs);
bspbrush_t *ChopBrushes(bspbrush_t *head);
bspbrush_t *InitialBrushList(bspbrush_t *list);
bspbrush_t *OptimizedBrushList(bspbrush_t *list);
void WriteBrushMap(char *name, bspbrush_t *list);
void CheckBSPBrush(bspbrush_t *brush);
void BSPBrushWindings(bspbrush_t *brush);
bspbrush_t *TryMergeBrushes(bspbrush_t *brush1, bspbrush_t *brush2);
tree_t *ProcessWorldBrushes(int brush_start, int brush_end);
//=============================================================================
// brushbsp
//=============================================================================
#define PSIDE_FRONT 1
#define PSIDE_BACK 2
#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK)
#define PSIDE_FACING 4
void WriteBrushList(char *name, bspbrush_t *brush, qboolean onlyvis);
bspbrush_t *CopyBrush(bspbrush_t *brush);
void SplitBrush(bspbrush_t *brush, int planenum, bspbrush_t **front, bspbrush_t **back);
node_t *AllocNode(void);
bspbrush_t *AllocBrush(int numsides);
int CountBrushList(bspbrush_t *brushes);
void FreeBrush(bspbrush_t *brushes);
vec_t BrushVolume(bspbrush_t *brush);
void BoundBrush(bspbrush_t *brush);
void FreeBrushList(bspbrush_t *brushes);
tree_t *BrushBSP(bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
bspbrush_t *BrushFromBounds(vec3_t mins, vec3_t maxs);
int BrushMostlyOnSide(bspbrush_t *brush, plane_t *plane);
qboolean WindingIsHuge(winding_t *w);
qboolean WindingIsTiny(winding_t *w);
void ResetBrushBSP(void);
//=============================================================================
// portals.c
//=============================================================================
int VisibleContents (int contents);
void MakeHeadnodePortals (tree_t *tree);
void MakeNodePortal (node_t *node);
void SplitNodePortals (node_t *node);
qboolean Portal_VisFlood (portal_t *p);
qboolean FloodEntities (tree_t *tree);
void FillOutside (node_t *headnode);
void FloodAreas (tree_t *tree);
void MarkVisibleSides (tree_t *tree, int start, int end);
void FreePortal (portal_t *p);
void EmitAreaPortals (node_t *headnode);
void MakeTreePortals (tree_t *tree);
//=============================================================================
// glfile.c
//=============================================================================
void OutputWinding(winding_t *w, FILE *glview);
void WriteGLView(tree_t *tree, char *source);
//=============================================================================
// gldraw.c
//=============================================================================
extern vec3_t draw_mins, draw_maxs;
extern qboolean drawflag;
void Draw_ClearWindow (void);
void DrawWinding (winding_t *w);
void GLS_BeginScene (void);
void GLS_Winding (winding_t *w, int code);
void GLS_EndScene (void);
//=============================================================================
// leakfile.c
//=============================================================================
void LeakFile (tree_t *tree);
//=============================================================================
// tree.c
//=============================================================================
tree_t *Tree_Alloc(void);
void Tree_Free(tree_t *tree);
void Tree_Free_r(node_t *node);
void Tree_Print_r(node_t *node, int depth);
void Tree_FreePortals_r(node_t *node);
void Tree_PruneNodes_r(node_t *node);
void Tree_PruneNodes(node_t *node);

View File

@ -1,487 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
/*
========================================================================
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P')
typedef struct
{
char name[56];
int filepos, filelen;
} dpackfile_t;
typedef struct
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
} dpackheader_t;
#define MAX_FILES_IN_PACK 4096
/*
========================================================================
PCX files are used for as many images as possible
========================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
.MD2 triangle model file format
========================================================================
*/
#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define ALIAS_VERSION 8
#define MAX_TRIANGLES 4096
#define MAX_VERTS 2048
#define MAX_FRAMES 512
#define MAX_MD2SKINS 32
#define MAX_SKINNAME 64
typedef struct
{
short s;
short t;
} dstvert_t;
typedef struct
{
short index_xyz[3];
short index_st[3];
} dtriangle_t;
typedef struct
{
byte v[3]; // scaled byte to fit in frame mins/maxs
byte lightnormalindex;
} dtrivertx_t;
#define DTRIVERTX_V0 0
#define DTRIVERTX_V1 1
#define DTRIVERTX_V2 2
#define DTRIVERTX_LNI 3
#define DTRIVERTX_SIZE 4
typedef struct
{
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
dtrivertx_t verts[1]; // variable sized
} daliasframe_t;
// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.
typedef struct
{
int ident;
int version;
int skinwidth;
int skinheight;
int framesize; // byte size of each frame
int num_skins;
int num_xyz;
int num_st; // greater than num_xyz for seams
int num_tris;
int num_glcmds; // dwords in strip/fan command list
int num_frames;
int ofs_skins; // each skin is a MAX_SKINNAME string
int ofs_st; // byte offset from start for stverts
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
int ofs_end; // end of file
} dmdl_t;
/*
========================================================================
.SP2 sprite file format
========================================================================
*/
#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I')
// little-endian "IDS2"
#define SPRITE_VERSION 2
typedef struct
{
int width, height;
int origin_x, origin_y; // raster coordinates inside pic
char name[MAX_SKINNAME]; // name of pcx file
} dsprframe_t;
typedef struct {
int ident;
int version;
int numframes;
dsprframe_t frames[1]; // variable sized
} dsprite_t;
/*
==============================================================================
.WAL texture file format
==============================================================================
*/
#define MIPLEVELS 4
typedef struct miptex_s
{
char name[32];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
char animname[32]; // next frame in animation chain
int flags;
int contents;
int value;
} miptex_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I')
// little-endian "IBSP"
#define BSPVERSION 38
// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
#define MAX_MAP_ENTITIES 2048
#define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_TEXINFO 8192
#define MAX_MAP_AREAS 256
#define MAX_MAP_AREAPORTALS 1024
#define MAX_MAP_PLANES 65536
#define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536
#define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536
#define MAX_MAP_FACES 65536
#define MAX_MAP_LEAFFACES 65536
#define MAX_MAP_LEAFBRUSHES 65536
#define MAX_MAP_PORTALS 65536
#define MAX_MAP_EDGES 128000
#define MAX_MAP_SURFEDGES 256000
#define MAX_MAP_LIGHTING 0x320000
#define MAX_MAP_VISIBILITY 0x280000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
typedef struct
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_VERTEXES 2
#define LUMP_VISIBILITY 3
#define LUMP_NODES 4
#define LUMP_TEXINFO 5
#define LUMP_FACES 6
#define LUMP_LIGHTING 7
#define LUMP_LEAFS 8
#define LUMP_LEAFFACES 9
#define LUMP_LEAFBRUSHES 10
#define LUMP_EDGES 11
#define LUMP_SURFEDGES 12
#define LUMP_MODELS 13
#define LUMP_BRUSHES 14
#define LUMP_BRUSHSIDES 15
#define LUMP_POP 16
#define LUMP_AREAS 17
#define LUMP_AREAPORTALS 18
#define HEADER_LUMPS 19
typedef struct
{
int ident;
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3]; // for sounds or lights
int headnode;
int firstface, numfaces; // submodels just draw faces
// without walking the bsp tree
} dmodel_t;
typedef struct
{
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planes (x&~1) and (x&~1)+1 are allways opposites
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
#define CONTENTS_WINDOW 2 // translucent, but not watery
#define CONTENTS_AUX 4
#define CONTENTS_LAVA 8
#define CONTENTS_SLIME 16
#define CONTENTS_WATER 32
#define CONTENTS_MIST 64
#define LAST_VISIBLE_CONTENTS 64
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x40000
#define CONTENTS_CURRENT_90 0x80000
#define CONTENTS_CURRENT_180 0x100000
#define CONTENTS_CURRENT_270 0x200000
#define CONTENTS_CURRENT_UP 0x400000
#define CONTENTS_CURRENT_DOWN 0x800000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEADMONSTER 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
//renamed because it's in conflict with the Q3A translucent contents
#define CONTENTS_Q2TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define SURF_LIGHT 0x1 // value will hold the light strength
#define SURF_SLICK 0x2 // effects game physics
#define SURF_SKY 0x4 // don't draw, but add to skybox
#define SURF_WARP 0x8 // turbulent water warp
#define SURF_TRANS33 0x10
#define SURF_TRANS66 0x20
#define SURF_FLOWING 0x40 // scroll towards angle
#define SURF_NODRAW 0x80 // don't bother referencing the texture
#define SURF_HINT 0x100 // make a primary bsp splitter
#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for frustom culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
int value; // light emission, etc
char texture[32]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
} texinfo_t;
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
typedef struct
{
int contents; // OR of all brushes (not needed?)
short cluster;
short area;
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} dleaf_t;
typedef struct
{
unsigned short planenum; // facing out of the leaf
short texinfo;
} dbrushside_t;
typedef struct
{
int firstside;
int numsides;
int contents;
} dbrush_t;
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the visibility lump consists of a header with a count, then
// byte offsets for the PVS and PHS of each cluster, then the raw
// compressed bit vectors
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef struct
{
int numclusters;
int bitofs[8][2]; // bitofs[numclusters][2]
} dvis_t;
// each area has a list of portals that lead into other areas
// when portals are closed, other areas may not be visible or
// hearable even if the vis info says that it should be
typedef struct
{
int portalnum;
int otherarea;
} dareaportal_t;
typedef struct
{
int numareaportals;
int firstareaportal;
} darea_t;

View File

@ -1,365 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define SIN
#define SINBSPVERSION 41
// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define SIN_MAX_MAP_MODELS 1024
#define SIN_MAX_MAP_BRUSHES 8192
#define SIN_MAX_MAP_ENTITIES 2048
#define SIN_MAX_MAP_ENTSTRING 0x40000
#define SIN_MAX_MAP_TEXINFO 8192
#define SIN_MAX_MAP_AREAS 256
#define SIN_MAX_MAP_AREAPORTALS 1024
#define SIN_MAX_MAP_PLANES 65536
#define SIN_MAX_MAP_NODES 65536
#define SIN_MAX_MAP_BRUSHSIDES 65536
#define SIN_MAX_MAP_LEAFS 65536
#define SIN_MAX_MAP_VERTS 65536
#define SIN_MAX_MAP_FACES 65536
#define SIN_MAX_MAP_LEAFFACES 65536
#define SIN_MAX_MAP_LEAFBRUSHES 65536
#define SIN_MAX_MAP_PORTALS 65536
#define SIN_MAX_MAP_EDGES 128000
#define SIN_MAX_MAP_SURFEDGES 256000
#define SIN_MAX_MAP_LIGHTING 0x320000
#define SIN_MAX_MAP_VISIBILITY 0x280000
#ifdef SIN
#define SIN_MAX_MAP_LIGHTINFO 8192
#endif
#ifdef SIN
#undef SIN_MAX_MAP_LIGHTING //undef the Quake2 bsp version
#define SIN_MAX_MAP_LIGHTING 0x300000
#endif
#ifdef SIN
#undef SIN_MAX_MAP_VISIBILITY //undef the Quake2 bsp version
#define SIN_MAX_MAP_VISIBILITY 0x280000
#endif
//=============================================================================
typedef struct
{
int fileofs, filelen;
} sin_lump_t;
#define SIN_LUMP_ENTITIES 0
#define SIN_LUMP_PLANES 1
#define SIN_LUMP_VERTEXES 2
#define SIN_LUMP_VISIBILITY 3
#define SIN_LUMP_NODES 4
#define SIN_LUMP_TEXINFO 5
#define SIN_LUMP_FACES 6
#define SIN_LUMP_LIGHTING 7
#define SIN_LUMP_LEAFS 8
#define SIN_LUMP_LEAFFACES 9
#define SIN_LUMP_LEAFBRUSHES 10
#define SIN_LUMP_EDGES 11
#define SIN_LUMP_SURFEDGES 12
#define SIN_LUMP_MODELS 13
#define SIN_LUMP_BRUSHES 14
#define SIN_LUMP_BRUSHSIDES 15
#define SIN_LUMP_POP 16
#define SIN_LUMP_AREAS 17
#define SIN_LUMP_AREAPORTALS 18
#ifdef SIN
#define SIN_LUMP_LIGHTINFO 19
#define SINHEADER_LUMPS 20
#endif
typedef struct
{
int ident;
int version;
sin_lump_t lumps[SINHEADER_LUMPS];
} sin_dheader_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3]; // for sounds or lights
int headnode;
int firstface, numfaces; // submodels just draw faces
// without walking the bsp tree
} sin_dmodel_t;
typedef struct
{
float point[3];
} sin_dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planes (x&~1) and (x&~1)+1 are allways opposites
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} sin_dplane_t;
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#ifdef SIN
#define CONTENTS_FENCE 4
#endif
// remaining contents are non-visible, and don't eat brushes
#ifdef SIN
#define CONTENTS_DUMMYFENCE 0x1000
#endif
#ifdef SIN
#define SURF_MASKED 0x2 // surface texture is masked
#endif
#define SURF_SKY 0x4 // don't draw, but add to skybox
#define SURF_WARP 0x8 // turbulent water warp
#ifdef SIN
#define SURF_NONLIT 0x10 // surface is not lit
#define SURF_NOFILTER 0x20 // surface is not bi-linear filtered
#endif
#define SURF_FLOWING 0x40 // scroll towards angle
#define SURF_NODRAW 0x80 // don't bother referencing the texture
#define SURF_HINT 0x100 // make a primary bsp splitter
#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
#ifdef SIN
#define SURF_CONVEYOR 0x40 // surface is not lit
#endif
#ifdef SIN
#define SURF_WAVY 0x400 // surface has waves
#define SURF_RICOCHET 0x800 // projectiles bounce literally bounce off this surface
#define SURF_PRELIT 0x1000 // surface has intensity information for pre-lighting
#define SURF_MIRROR 0x2000 // surface is a mirror
#define SURF_CONSOLE 0x4000 // surface is a console
#define SURF_USECOLOR 0x8000 // surface is lit with non-lit * color
#define SURF_HARDWAREONLY 0x10000 // surface has been damaged
#define SURF_DAMAGE 0x20000 // surface can be damaged
#define SURF_WEAK 0x40000 // surface has weak hit points
#define SURF_NORMAL 0x80000 // surface has normal hit points
#define SURF_ADD 0x100000 // surface will be additive
#define SURF_ENVMAPPED 0x200000 // surface is envmapped
#define SURF_RANDOMANIMATE 0x400000 // surface start animating on a random frame
#define SURF_ANIMATE 0x800000 // surface animates
#define SURF_RNDTIME 0x1000000 // time between animations is random
#define SURF_TRANSLATE 0x2000000 // surface translates
#define SURF_NOMERGE 0x4000000 // surface is not merged in csg phase
#define SURF_TYPE_BIT0 0x8000000 // 0 bit of surface type
#define SURF_TYPE_BIT1 0x10000000 // 1 bit of surface type
#define SURF_TYPE_BIT2 0x20000000 // 2 bit of surface type
#define SURF_TYPE_BIT3 0x40000000 // 3 bit of surface type
#define SURF_START_BIT 27
#define SURFACETYPE_FROM_FLAGS( x ) ( ( x >> (SURF_START_BIT) ) & 0xf )
#define SURF_TYPE_SHIFT(x) ( (x) << (SURF_START_BIT) ) // macro for getting proper bit mask
#define SURF_TYPE_NONE SURF_TYPE_SHIFT(0)
#define SURF_TYPE_WOOD SURF_TYPE_SHIFT(1)
#define SURF_TYPE_METAL SURF_TYPE_SHIFT(2)
#define SURF_TYPE_STONE SURF_TYPE_SHIFT(3)
#define SURF_TYPE_CONCRETE SURF_TYPE_SHIFT(4)
#define SURF_TYPE_DIRT SURF_TYPE_SHIFT(5)
#define SURF_TYPE_FLESH SURF_TYPE_SHIFT(6)
#define SURF_TYPE_GRILL SURF_TYPE_SHIFT(7)
#define SURF_TYPE_GLASS SURF_TYPE_SHIFT(8)
#define SURF_TYPE_FABRIC SURF_TYPE_SHIFT(9)
#define SURF_TYPE_MONITOR SURF_TYPE_SHIFT(10)
#define SURF_TYPE_GRAVEL SURF_TYPE_SHIFT(11)
#define SURF_TYPE_VEGETATION SURF_TYPE_SHIFT(12)
#define SURF_TYPE_PAPER SURF_TYPE_SHIFT(13)
#define SURF_TYPE_DUCT SURF_TYPE_SHIFT(14)
#define SURF_TYPE_WATER SURF_TYPE_SHIFT(15)
#endif
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for frustom culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} sin_dnode_t;
#ifdef SIN
typedef struct sin_lightvalue_s
{
int value; // light emission, etc
vec3_t color;
float direct;
float directangle;
float directstyle;
char directstylename[32];
} sin_lightvalue_t;
typedef struct sin_texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
char texture[64]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
float trans_mag;
int trans_angle;
int base_angle;
float animtime;
float nonlit;
float translucence;
float friction;
float restitution;
vec3_t color;
char groupname[32];
} sin_texinfo_t;
#endif //SIN
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} sin_dedge_t;
#ifdef MAXLIGHTMAPS
#undef MAXLIGHTMAPS
#endif
#define MAXLIGHTMAPS 16
typedef struct
{
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
#ifdef SIN
int lightinfo;
#endif
} sin_dface_t;
typedef struct
{
int contents; // OR of all brushes (not needed?)
short cluster;
short area;
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} sin_dleaf_t;
typedef struct
{
unsigned short planenum; // facing out of the leaf
short texinfo;
#ifdef SIN
int lightinfo;
#endif
} sin_dbrushside_t;
typedef struct
{
int firstside;
int numsides;
int contents;
} sin_dbrush_t;
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the visibility lump consists of a header with a count, then
// byte offsets for the PVS and PHS of each cluster, then the raw
// compressed bit vectors
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef struct
{
int numclusters;
int bitofs[8][2]; // bitofs[numclusters][2]
} sin_dvis_t;
// each area has a list of portals that lead into other areas
// when portals are closed, other areas may not be visible or
// hearable even if the vis info says that it should be
typedef struct
{
int portalnum;
int otherarea;
} sin_dareaportal_t;
typedef struct
{
int numareaportals;
int firstareaportal;
} sin_darea_t;

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void TH_AASToTetrahedrons(char *filename);

View File

@ -1,228 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
#include "l_bsp_q2.h"
int nummiptex;
textureref_t textureref[MAX_MAP_TEXTURES];
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int FindMiptex (char *name)
{
int i;
char path[1024];
miptex_t *mt;
for (i = 0; i < nummiptex; i++)
{
if (!strcmp (name, textureref[i].name))
{
return i;
} //end if
} //end for
if (nummiptex == MAX_MAP_TEXTURES)
Error ("MAX_MAP_TEXTURES");
strcpy (textureref[i].name, name);
// load the miptex to get the flags and values
sprintf (path, "%stextures/%s.wal", gamedir, name);
if (TryLoadFile (path, (void **)&mt) != -1)
{
textureref[i].value = LittleLong (mt->value);
textureref[i].flags = LittleLong (mt->flags);
textureref[i].contents = LittleLong (mt->contents);
strcpy (textureref[i].animname, mt->animname);
FreeMemory(mt);
} //end if
nummiptex++;
if (textureref[i].animname[0])
FindMiptex (textureref[i].animname);
return i;
} //end of the function FindMipTex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec3_t baseaxis[18] =
{
{0,0,1}, {1,0,0}, {0,-1,0}, // floor
{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling
{1,0,0}, {0,1,0}, {0,0,-1}, // west wall
{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall
{0,1,0}, {1,0,0}, {0,0,-1}, // south wall
{0,-1,0}, {1,0,0}, {0,0,-1} // north wall
};
void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
{
int bestaxis;
vec_t dot,best;
int i;
best = 0;
bestaxis = 0;
for (i=0 ; i<6 ; i++)
{
dot = DotProduct (pln->normal, baseaxis[i*3]);
if (dot > best)
{
best = dot;
bestaxis = i;
}
}
VectorCopy (baseaxis[bestaxis*3+1], xv);
VectorCopy (baseaxis[bestaxis*3+2], yv);
} //end of the function TextureAxisFromPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int TexinfoForBrushTexture(plane_t *plane, brush_texture_t *bt, vec3_t origin)
{
vec3_t vecs[2];
int sv, tv;
vec_t ang, sinv, cosv;
vec_t ns, nt;
texinfo_t tx, *tc;
int i, j, k;
float shift[2];
brush_texture_t anim;
int mt;
if (!bt->name[0])
return 0;
memset (&tx, 0, sizeof(tx));
strcpy (tx.texture, bt->name);
TextureAxisFromPlane(plane, vecs[0], vecs[1]);
shift[0] = DotProduct (origin, vecs[0]);
shift[1] = DotProduct (origin, vecs[1]);
if (!bt->scale[0])
bt->scale[0] = 1;
if (!bt->scale[1])
bt->scale[1] = 1;
// rotate axis
if (bt->rotate == 0)
{ sinv = 0 ; cosv = 1; }
else if (bt->rotate == 90)
{ sinv = 1 ; cosv = 0; }
else if (bt->rotate == 180)
{ sinv = 0 ; cosv = -1; }
else if (bt->rotate == 270)
{ sinv = -1 ; cosv = 0; }
else
{
ang = bt->rotate / 180 * Q_PI;
sinv = sin(ang);
cosv = cos(ang);
}
if (vecs[0][0])
sv = 0;
else if (vecs[0][1])
sv = 1;
else
sv = 2;
if (vecs[1][0])
tv = 0;
else if (vecs[1][1])
tv = 1;
else
tv = 2;
for (i=0 ; i<2 ; i++)
{
ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
vecs[i][sv] = ns;
vecs[i][tv] = nt;
}
for (i=0 ; i<2 ; i++)
for (j=0 ; j<3 ; j++)
tx.vecs[i][j] = vecs[i][j] / bt->scale[i];
tx.vecs[0][3] = bt->shift[0] + shift[0];
tx.vecs[1][3] = bt->shift[1] + shift[1];
tx.flags = bt->flags;
tx.value = bt->value;
//
// find the texinfo
//
tc = texinfo;
for (i=0 ; i<numtexinfo ; i++, tc++)
{
if (tc->flags != tx.flags)
continue;
if (tc->value != tx.value)
continue;
for (j=0 ; j<2 ; j++)
{
if (strcmp (tc->texture, tx.texture))
goto skip;
for (k=0 ; k<4 ; k++)
{
if (tc->vecs[j][k] != tx.vecs[j][k])
goto skip;
}
}
return i;
skip:;
}
*tc = tx;
numtexinfo++;
// load the next animation
mt = FindMiptex (bt->name);
if (textureref[mt].animname[0])
{
anim = *bt;
strcpy (anim.name, textureref[mt].animname);
tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin);
}
else
tc->nexttexinfo = -1;
return i;
} //end of the function TexinfoForBrushTexture

View File

@ -1,283 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
extern int c_nodes;
int c_pruned;
int freedtreemem = 0;
void RemovePortalFromNode (portal_t *portal, node_t *l);
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
node_t *NodeForPoint (node_t *node, vec3_t origin)
{
plane_t *plane;
vec_t d;
while (node->planenum != PLANENUM_LEAF)
{
plane = &mapplanes[node->planenum];
d = DotProduct (origin, plane->normal) - plane->dist;
if (d >= 0)
node = node->children[0];
else
node = node->children[1];
}
return node;
} //end of the function NodeForPoint
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_FreePortals_r (node_t *node)
{
portal_t *p, *nextp;
int s;
// free children
if (node->planenum != PLANENUM_LEAF)
{
Tree_FreePortals_r(node->children[0]);
Tree_FreePortals_r(node->children[1]);
}
// free portals
for (p = node->portals; p; p = nextp)
{
s = (p->nodes[1] == node);
nextp = p->next[s];
RemovePortalFromNode (p, p->nodes[!s]);
#ifdef ME
if (p->winding) freedtreemem += MemorySize(p->winding);
freedtreemem += MemorySize(p);
#endif //ME
FreePortal(p);
}
node->portals = NULL;
} //end of the function Tree_FreePortals_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_Free_r (node_t *node)
{
// face_t *f, *nextf;
bspbrush_t *brush, *nextbrush;
//free children
if (node->planenum != PLANENUM_LEAF)
{
Tree_Free_r (node->children[0]);
Tree_Free_r (node->children[1]);
} //end if
//free bspbrushes
// FreeBrushList (node->brushlist);
for (brush = node->brushlist; brush; brush = nextbrush)
{
nextbrush = brush->next;
#ifdef ME
freedtreemem += MemorySize(brush);
#endif //ME
FreeBrush(brush);
} //end for
node->brushlist = NULL;
/*
NOTE: only used when creating Q2 bsp
// free faces
for (f = node->faces; f; f = nextf)
{
nextf = f->next;
#ifdef ME
if (f->w) freedtreemem += MemorySize(f->w);
freedtreemem += sizeof(face_t);
#endif //ME
FreeFace(f);
} //end for
*/
// free the node
if (node->volume)
{
#ifdef ME
freedtreemem += MemorySize(node->volume);
#endif //ME
FreeBrush (node->volume);
} //end if
if (numthreads == 1) c_nodes--;
#ifdef ME
freedtreemem += MemorySize(node);
#endif //ME
FreeMemory(node);
} //end of the function Tree_Free_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_Free(tree_t *tree)
{
//if no tree just return
if (!tree) return;
//
freedtreemem = 0;
//
Tree_FreePortals_r(tree->headnode);
Tree_Free_r(tree->headnode);
#ifdef ME
freedtreemem += MemorySize(tree);
#endif //ME
FreeMemory(tree);
#ifdef ME
Log_Print("freed ");
PrintMemorySize(freedtreemem);
Log_Print(" of tree memory\n");
#endif //ME
} //end of the function Tree_Free
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tree_t *Tree_Alloc(void)
{
tree_t *tree;
tree = GetMemory(sizeof(*tree));
memset (tree, 0, sizeof(*tree));
ClearBounds (tree->mins, tree->maxs);
return tree;
} //end of the function Tree_Alloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_Print_r (node_t *node, int depth)
{
int i;
plane_t *plane;
bspbrush_t *bb;
for (i=0 ; i<depth ; i++)
printf (" ");
if (node->planenum == PLANENUM_LEAF)
{
if (!node->brushlist)
printf ("NULL\n");
else
{
for (bb=node->brushlist ; bb ; bb=bb->next)
printf ("%i ", bb->original->brushnum);
printf ("\n");
}
return;
}
plane = &mapplanes[node->planenum];
printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
plane->normal[0], plane->normal[1], plane->normal[2],
plane->dist);
Tree_Print_r (node->children[0], depth+1);
Tree_Print_r (node->children[1], depth+1);
} //end of the function Tree_Print_r
//===========================================================================
// NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_PruneNodes_r (node_t *node)
{
bspbrush_t *b, *next;
if (node->planenum == PLANENUM_LEAF) return;
Tree_PruneNodes_r (node->children[0]);
Tree_PruneNodes_r (node->children[1]);
if (create_aas)
{
if ((node->children[0]->contents & CONTENTS_LADDER) ||
(node->children[1]->contents & CONTENTS_LADDER)) return;
}
if ((node->children[0]->contents & CONTENTS_SOLID)
&& (node->children[1]->contents & CONTENTS_SOLID))
{
if (node->faces)
Error ("node->faces seperating CONTENTS_SOLID");
if (node->children[0]->faces || node->children[1]->faces)
Error ("!node->faces with children");
// FIXME: free stuff
node->planenum = PLANENUM_LEAF;
node->contents = CONTENTS_SOLID;
node->detail_seperator = false;
if (node->brushlist)
Error ("PruneNodes: node->brushlist");
// combine brush lists
node->brushlist = node->children[1]->brushlist;
for (b = node->children[0]->brushlist; b; b = next)
{
next = b->next;
b->next = node->brushlist;
node->brushlist = b;
} //end for
//free the child nodes
FreeMemory(node->children[0]);
FreeMemory(node->children[1]);
//two nodes are cut away
c_pruned += 2;
} //end if
} //end of the function Tree_PruneNodes_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Tree_PruneNodes(node_t *node)
{
Log_Print("------- Prune Nodes --------\n");
c_pruned = 0;
Tree_PruneNodes_r(node);
Log_Print("%5i pruned nodes\n", c_pruned);
} //end of the function Tree_PruneNodes

View File

@ -1,595 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "qbsp.h"
int c_nofaces;
int c_facenodes;
/*
=========================================================
ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
=========================================================
*/
int planeused[MAX_MAP_PLANES];
/*
============
EmitPlanes
There is no oportunity to discard planes, because all of the original
brushes will be saved in the map.
============
*/
void EmitPlanes (void)
{
int i;
dplane_t *dp;
plane_t *mp;
//ME: this causes a crash??
// int planetranslate[MAX_MAP_PLANES];
mp = mapplanes;
for (i=0 ; i<nummapplanes ; i++, mp++)
{
dp = &dplanes[numplanes];
// planetranslate[i] = numplanes;
VectorCopy ( mp->normal, dp->normal);
dp->dist = mp->dist;
dp->type = mp->type;
numplanes++;
if (numplanes >= MAX_MAP_PLANES)
Error("MAX_MAP_PLANES");
}
}
//========================================================
void EmitMarkFace (dleaf_t *leaf_p, face_t *f)
{
int i;
int facenum;
while (f->merged)
f = f->merged;
if (f->split[0])
{
EmitMarkFace (leaf_p, f->split[0]);
EmitMarkFace (leaf_p, f->split[1]);
return;
}
facenum = f->outputnumber;
if (facenum == -1)
return; // degenerate face
if (facenum < 0 || facenum >= numfaces)
Error ("Bad leafface");
for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)
if (dleaffaces[i] == facenum)
break; // merged out face
if (i == numleaffaces)
{
if (numleaffaces >= MAX_MAP_LEAFFACES)
Error ("MAX_MAP_LEAFFACES");
dleaffaces[numleaffaces] = facenum;
numleaffaces++;
}
}
/*
==================
EmitLeaf
==================
*/
void EmitLeaf (node_t *node)
{
dleaf_t *leaf_p;
portal_t *p;
int s;
face_t *f;
bspbrush_t *b;
int i;
int brushnum;
// emit a leaf
if (numleafs >= MAX_MAP_LEAFS)
Error ("MAX_MAP_LEAFS");
leaf_p = &dleafs[numleafs];
numleafs++;
leaf_p->contents = node->contents;
leaf_p->cluster = node->cluster;
leaf_p->area = node->area;
//
// write bounding box info
//
VectorCopy (node->mins, leaf_p->mins);
VectorCopy (node->maxs, leaf_p->maxs);
//
// write the leafbrushes
//
leaf_p->firstleafbrush = numleafbrushes;
for (b=node->brushlist ; b ; b=b->next)
{
if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
Error ("MAX_MAP_LEAFBRUSHES");
brushnum = b->original - mapbrushes;
for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)
if (dleafbrushes[i] == brushnum)
break;
if (i == numleafbrushes)
{
dleafbrushes[numleafbrushes] = brushnum;
numleafbrushes++;
}
}
leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
//
// write the leaffaces
//
if (leaf_p->contents & CONTENTS_SOLID)
return; // no leaffaces in solids
leaf_p->firstleafface = numleaffaces;
for (p = node->portals ; p ; p = p->next[s])
{
s = (p->nodes[1] == node);
f = p->face[s];
if (!f)
continue; // not a visible portal
EmitMarkFace (leaf_p, f);
}
leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
}
/*
==================
EmitFace
==================
*/
void EmitFace (face_t *f)
{
dface_t *df;
int i;
int e;
f->outputnumber = -1;
if (f->numpoints < 3)
{
return; // degenerated
}
if (f->merged || f->split[0] || f->split[1])
{
return; // not a final face
}
// save output number so leaffaces can use
f->outputnumber = numfaces;
if (numfaces >= MAX_MAP_FACES)
Error ("numfaces == MAX_MAP_FACES");
df = &dfaces[numfaces];
numfaces++;
// planenum is used by qlight, but not quake
df->planenum = f->planenum & (~1);
df->side = f->planenum & 1;
df->firstedge = numsurfedges;
df->numedges = f->numpoints;
df->texinfo = f->texinfo;
for (i=0 ; i<f->numpoints ; i++)
{
// e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);
if (numsurfedges >= MAX_MAP_SURFEDGES)
Error ("numsurfedges == MAX_MAP_SURFEDGES");
dsurfedges[numsurfedges] = e;
numsurfedges++;
}
}
/*
============
EmitDrawingNode_r
============
*/
int EmitDrawNode_r (node_t *node)
{
dnode_t *n;
face_t *f;
int i;
if (node->planenum == PLANENUM_LEAF)
{
EmitLeaf (node);
return -numleafs;
}
// emit a node
if (numnodes == MAX_MAP_NODES)
Error ("MAX_MAP_NODES");
n = &dnodes[numnodes];
numnodes++;
VectorCopy (node->mins, n->mins);
VectorCopy (node->maxs, n->maxs);
planeused[node->planenum]++;
planeused[node->planenum^1]++;
if (node->planenum & 1)
Error ("WriteDrawNodes_r: odd planenum");
n->planenum = node->planenum;
n->firstface = numfaces;
if (!node->faces)
c_nofaces++;
else
c_facenodes++;
for (f=node->faces ; f ; f=f->next)
EmitFace (f);
n->numfaces = numfaces - n->firstface;
//
// recursively output the other nodes
//
for (i=0 ; i<2 ; i++)
{
if (node->children[i]->planenum == PLANENUM_LEAF)
{
n->children[i] = -(numleafs + 1);
EmitLeaf (node->children[i]);
}
else
{
n->children[i] = numnodes;
EmitDrawNode_r (node->children[i]);
}
}
return n - dnodes;
}
//=========================================================
/*
============
WriteBSP
============
*/
void WriteBSP (node_t *headnode)
{
int oldfaces;
c_nofaces = 0;
c_facenodes = 0;
qprintf ("--- WriteBSP ---\n");
oldfaces = numfaces;
dmodels[nummodels].headnode = EmitDrawNode_r (headnode);
EmitAreaPortals (headnode);
qprintf ("%5i nodes with faces\n", c_facenodes);
qprintf ("%5i nodes without faces\n", c_nofaces);
qprintf ("%5i faces\n", numfaces-oldfaces);
}
//===========================================================
/*
============
SetModelNumbers
============
*/
void SetModelNumbers (void)
{
int i;
int models;
char value[10];
models = 1;
for (i=1 ; i<num_entities ; i++)
{
if (entities[i].numbrushes)
{
sprintf (value, "*%i", models);
models++;
SetKeyValue (&entities[i], "model", value);
}
}
}
/*
============
SetLightStyles
============
*/
#define MAX_SWITCHED_LIGHTS 32
void SetLightStyles (void)
{
int stylenum;
char *t;
entity_t *e;
int i, j;
char value[10];
char lighttargets[MAX_SWITCHED_LIGHTS][64];
// any light that is controlled (has a targetname)
// must have a unique style number generated for it
stylenum = 0;
for (i=1 ; i<num_entities ; i++)
{
e = &entities[i];
t = ValueForKey (e, "classname");
if (Q_strncasecmp (t, "light", 5))
continue;
t = ValueForKey (e, "targetname");
if (!t[0])
continue;
// find this targetname
for (j=0 ; j<stylenum ; j++)
if (!strcmp (lighttargets[j], t))
break;
if (j == stylenum)
{
if (stylenum == MAX_SWITCHED_LIGHTS)
Error ("stylenum == MAX_SWITCHED_LIGHTS");
strcpy (lighttargets[j], t);
stylenum++;
}
sprintf (value, "%i", 32 + j);
SetKeyValue (e, "style", value);
}
}
//===========================================================
/*
============
EmitBrushes
============
*/
void EmitBrushes (void)
{
int i, j, bnum, s, x;
dbrush_t *db;
mapbrush_t *b;
dbrushside_t *cp;
vec3_t normal;
vec_t dist;
int planenum;
numbrushsides = 0;
numbrushes = nummapbrushes;
for (bnum=0 ; bnum<nummapbrushes ; bnum++)
{
b = &mapbrushes[bnum];
db = &dbrushes[bnum];
db->contents = b->contents;
db->firstside = numbrushsides;
db->numsides = b->numsides;
for (j=0 ; j<b->numsides ; j++)
{
if (numbrushsides == MAX_MAP_BRUSHSIDES)
Error ("MAX_MAP_BRUSHSIDES");
cp = &dbrushsides[numbrushsides];
numbrushsides++;
cp->planenum = b->original_sides[j].planenum;
cp->texinfo = b->original_sides[j].texinfo;
}
#ifdef ME
//for collision detection, bounding boxes are axial :)
//brushes are convex so just add dot or line touching planes on the sides of
//the brush parallell to the axis planes
#endif
// add any axis planes not contained in the brush to bevel off corners
for (x=0 ; x<3 ; x++)
for (s=-1 ; s<=1 ; s+=2)
{
// add the plane
VectorCopy (vec3_origin, normal);
normal[x] = s;
if (s == -1)
dist = -b->mins[x];
else
dist = b->maxs[x];
planenum = FindFloatPlane (normal, dist);
for (i=0 ; i<b->numsides ; i++)
if (b->original_sides[i].planenum == planenum)
break;
if (i == b->numsides)
{
if (numbrushsides >= MAX_MAP_BRUSHSIDES)
Error ("MAX_MAP_BRUSHSIDES");
dbrushsides[numbrushsides].planenum = planenum;
dbrushsides[numbrushsides].texinfo =
dbrushsides[numbrushsides-1].texinfo;
numbrushsides++;
db->numsides++;
}
}
}
}
//===========================================================
/*
==================
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;
numbrushsides = 0;
numvertexes = 0;
numleaffaces = 0;
numleafbrushes = 0;
numsurfedges = 0;
// edge 0 is not used, because 0 can't be negated
numedges = 1;
// leave vertex 0 as an error
numvertexes = 1;
// leave leaf 0 as an error
numleafs = 1;
dleafs[0].contents = CONTENTS_SOLID;
}
/*
============
EndBSPFile
============
*/
void EndBSPFile (void)
{
#if 0
char path[1024];
int len;
byte *buf;
#endif
EmitBrushes ();
EmitPlanes ();
Q2_UnparseEntities ();
// load the pop
#if 0
sprintf (path, "%s/pics/pop.lmp", gamedir);
len = LoadFile (path, &buf);
memcpy (dpop, buf, sizeof(dpop));
FreeMemory(buf);
#endif
}
/*
==================
BeginModel
==================
*/
int firstmodleaf;
extern int firstmodeledge;
extern int firstmodelface;
void BeginModel (void)
{
dmodel_t *mod;
int start, end;
mapbrush_t *b;
int j;
entity_t *e;
vec3_t mins, maxs;
if (nummodels == MAX_MAP_MODELS)
Error ("MAX_MAP_MODELS");
mod = &dmodels[nummodels];
mod->firstface = numfaces;
firstmodleaf = numleafs;
firstmodeledge = numedges;
firstmodelface = numfaces;
//
// bound the brushes
//
e = &entities[entity_num];
start = e->firstbrush;
end = start + e->numbrushes;
ClearBounds (mins, maxs);
for (j=start ; j<end ; j++)
{
b = &mapbrushes[j];
if (!b->numsides)
continue; // not a real brush (origin brush)
AddPointToBounds (b->mins, mins, maxs);
AddPointToBounds (b->maxs, mins, maxs);
}
VectorCopy (mins, mod->mins);
VectorCopy (maxs, mod->maxs);
}
/*
==================
EndModel
==================
*/
void EndModel (void)
{
dmodel_t *mod;
mod = &dmodels[nummodels];
mod->numfaces = numfaces - mod->firstface;
nummodels++;
}

View File

@ -435,8 +435,6 @@ void CG_ColorForHealth( vec4_t hcolor ) {
// bk001205 - code below duplicated in q3_ui/ui-atoms.c
// bk001205 - FIXME: does this belong in ui_shared.c?
// bk001205 - FIXME: HARD_LINKED flags not visible here
#ifndef Q3_STATIC // bk001205 - q_shared defines not visible here
/*
=================
UI_DrawProportionalString2
@ -821,4 +819,3 @@ void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t
UI_DrawProportionalString2( x, y, str, color, sizeScale, cgs.media.charsetProp );
}
#endif // Q3STATIC

View File

@ -438,9 +438,6 @@ void QDECL CG_Error( const char *msg, ... ) {
trap_Error( text );
}
#ifndef CGAME_HARD_LINKED
// this is only here so the functions in q_shared.c and bg_*.c can link (FIXME)
void QDECL Com_Error( int level, const char *error, ... ) {
va_list argptr;
char text[1024];
@ -463,8 +460,6 @@ void QDECL Com_Printf( const char *msg, ... ) {
CG_Printf ("%s", text);
}
#endif
/*
================
CG_Argv

View File

@ -248,7 +248,7 @@ If the line width has changed, reformat the buffer.
void Con_CheckResize (void)
{
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
MAC_STATIC short tbuf[CON_TEXTSIZE];
short tbuf[CON_TEXTSIZE];
width = (SCREEN_WIDTH / SMALLCHAR_WIDTH) - 2;

View File

@ -1257,7 +1257,7 @@ reswitch:
break;
case 'f':
AddFloat( &buf_p, *(double *)arg, width, prec );
#ifdef __LCC__
#ifdef Q3_VM
arg += 1; // everything is 32 bit in my compiler
#else
arg += 2;

View File

@ -536,9 +536,6 @@ void G_ShutdownGame( int restart ) {
//===================================================================
#ifndef GAME_HARD_LINKED
// this is only here so the functions in q_shared.c and bg_*.c can link
void QDECL Com_Error ( int level, const char *error, ... ) {
va_list argptr;
char text[1024];
@ -561,8 +558,6 @@ void QDECL Com_Printf( const char *msg, ... ) {
G_Printf ("%s", text);
}
#endif
/*
========================================================================

View File

@ -30,9 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
uiStatic_t uis;
qboolean m_entersound; // after a frame, so caching won't disrupt the sound
// these are here so the functions in q_shared.c can link
#ifndef UI_HARD_LINKED
void QDECL Com_Error( int level, const char *error, ... ) {
va_list argptr;
char text[1024];
@ -55,8 +52,6 @@ void QDECL Com_Printf( const char *msg, ... ) {
trap_Print( va("%s", text) );
}
#endif
/*
=================
UI_ClampCvar

View File

@ -980,7 +980,7 @@ CM_PatchCollideFromGrid
static void CM_PatchCollideFromGrid( cGrid_t *grid, patchCollide_t *pf ) {
int i, j;
float *p1, *p2, *p3;
MAC_STATIC int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2];
int gridPlanes[MAX_GRID_SIZE][MAX_GRID_SIZE][2];
facet_t *facet;
int borders[4];
int noAdjust[4];
@ -1147,7 +1147,7 @@ Points is packed as concatenated rows.
*/
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ) {
patchCollide_t *pf;
MAC_STATIC cGrid_t grid;
cGrid_t grid;
int i, j;
if ( width <= 2 || height <= 2 || !points ) {

View File

@ -153,7 +153,7 @@ float Q_crandom( int *seed ) {
return 2.0 * ( Q_random( seed ) - 0.5 );
}
#ifdef __LCC__
#ifdef Q3_VM
int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
@ -739,7 +739,7 @@ int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
// if not GNU x86 and configured to use asm
#if !( (defined __GNUC__) && (defined __i386__) && (!defined C_ONLY))
#if defined __LCC__ || defined C_ONLY || !id386 || defined __VECTORC
#if defined Q3_VM || defined C_ONLY || !id386 || defined __VECTORC
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
{

View File

@ -105,7 +105,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// this is the define for determining if we have an asm version of a C function
#if (defined _M_IX86 || defined __i386__) && !defined __sun && !defined __LCC__
#if (defined _M_IX86 || defined __i386__) && !defined __sun && !defined Q3_VM
#define id386 1
#else
#define id386 0
@ -135,8 +135,6 @@ float FloatSwap (const float *f);
#ifdef WIN32
#define MAC_STATIC
#undef QDECL
#define QDECL __cdecl
@ -184,7 +182,6 @@ static ID_INLINE float BigFloat(const float l) { return FloatSwap(&l); }
#if defined(MACOS_X)
#define MAC_STATIC
#define __cdecl
#define __declspec(x)
#define stricmp strcasecmp
@ -239,7 +236,6 @@ static inline float LittleFloat (const float l) { return FloatSwap(&l); }
#ifdef __MACOS__
#include <MacTypes.h>
#define MAC_STATIC
#define ID_INLINE inline
#define CPUSTRING "MacOS-PPC"
@ -266,7 +262,6 @@ static inline float LittleFloat (const float l) { return FloatSwap(&l); }
// bk001205 - from Makefile
#define stricmp strcasecmp
#define MAC_STATIC // bk: FIXME
#define ID_INLINE inline
#ifdef __i386__
@ -291,14 +286,6 @@ static inline float LittleFloat (const float l) { return FloatSwap(&l); }
#define PATH_SEP '/'
// bk001205 - try
#ifdef Q3_STATIC
#define GAME_HARD_LINKED
#define CGAME_HARD_LINKED
#define UI_HARD_LINKED
#define BOTLIB_HARD_LINKED
#endif
#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
inline static short BigShort( short l) { return ShortSwap(l); }
#define LittleShort
@ -322,7 +309,6 @@ inline static float LittleFloat (const float l) { return FloatSwap(&l); }
#define stricmp strcasecmp
#define MAC_STATIC
#define ID_INLINE inline
#ifdef __i386__
@ -364,7 +350,6 @@ static float LittleFloat (const float l) { return FloatSwap(&l); }
// bk001205 - from Makefile
#define stricmp strcasecmp
#define MAC_STATIC
#define ID_INLINE inline
#ifdef __i386__
@ -375,14 +360,6 @@ static float LittleFloat (const float l) { return FloatSwap(&l); }
#define PATH_SEP '/'
// bk001205 - try
#ifdef Q3_STATIC
#define GAME_HARD_LINKED
#define CGAME_HARD_LINKED
#define UI_HARD_LINKED
#define BOTLIB_HARD_LINKED
#endif
#if defined(_LITTLE_ENDIAN)
inline static short BigShort( short l) { return ShortSwap(l); }
#define LittleShort
@ -703,7 +680,7 @@ void ByteToDir( int b, vec3_t dir );
#endif
#ifdef __LCC__
#ifdef Q3_VM
#ifdef VectorCopy
#undef VectorCopy
// this is a little hack to get more efficient copies in our interpreter
@ -738,7 +715,7 @@ float RadiusFromBounds( const vec3_t mins, const vec3_t maxs );
void ClearBounds( vec3_t mins, vec3_t maxs );
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
#ifndef __LCC__
#ifndef Q3_VM
static ID_INLINE int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
return 0;

View File

@ -135,7 +135,7 @@ R_LoadLightmaps
static void R_LoadLightmaps( lump_t *l ) {
byte *buf, *buf_p;
int len;
MAC_STATIC byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4];
byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4];
int i, j;
float maxIntensity = 0;
double sumIntensity = 0;
@ -379,7 +379,7 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
srfGridMesh_t *grid;
int i, j;
int width, height, numPoints;
MAC_STATIC drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
int lightmapNum;
vec3_t bounds[2];
vec3_t tmpVec;

View File

@ -366,7 +366,7 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
float len, maxLen;
int dir;
int t;
MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
for ( i = 0 ; i < width ; i++ ) {
@ -525,7 +525,7 @@ R_GridInsertColumn
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
int i, j;
int width, height, oldwidth;
MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
@ -579,7 +579,7 @@ R_GridInsertRow
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
int i, j;
int width, height, oldheight;
MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;

View File

@ -422,7 +422,7 @@ static void ProjectDlightTexture( void ) {
float *texCoords;
byte *colors;
byte clipBits[SHADER_MAX_VERTEXES];
MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2];
float texCoordsArray[SHADER_MAX_VERTEXES][2];
byte colorArray[SHADER_MAX_VERTEXES][4];
unsigned hitIndexes[SHADER_MAX_INDEXES];
int numIndexes;

View File

@ -231,7 +231,7 @@ void SV_DirectConnect( netadr_t from ) {
char userinfo[MAX_INFO_STRING];
int i;
client_t *cl, *newcl;
MAC_STATIC client_t temp;
client_t temp;
sharedEntity_t *ent;
int clientNum;
int version;

View File

@ -1,296 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Splines"
SccProjectName="&quot;$/MissionPack/code/Splines&quot;, WJNAAAAA"
SccLocalPath=".">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
StringPooling="TRUE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Release/Splines.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Release\Splines.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Debug/Splines.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Debug\Splines.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<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">
<File
RelativePath="math_angles.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="math_matrix.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="math_quaternion.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="math_vector.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="q_parse.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="q_shared.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="splines.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
<File
RelativePath="util_str.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
<File
RelativePath="math_angles.h">
</File>
<File
RelativePath="math_matrix.h">
</File>
<File
RelativePath="math_quaternion.h">
</File>
<File
RelativePath="math_vector.h">
</File>
<File
RelativePath="q_shared.h">
</File>
<File
RelativePath="splines.h">
</File>
<File
RelativePath="util_list.h">
</File>
<File
RelativePath="util_str.h">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,150 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "q_shared.h"
#include <float.h>
angles_t ang_zero( 0.0f, 0.0f, 0.0f );
void toAngles( mat3_t &src, angles_t &dst ) {
double theta;
double cp;
double sp;
sp = src[ 0 ][ 2 ];
// cap off our sin value so that we don't get any NANs
if ( sp > 1.0 ) {
sp = 1.0;
} else if ( sp < -1.0 ) {
sp = -1.0;
}
theta = -asin( sp );
cp = cos( theta );
if ( cp > 8192 * FLT_EPSILON ) {
dst.pitch = theta * 180 / M_PI;
dst.yaw = atan2( src[ 0 ][ 1 ], src[ 0 ][ 0 ] ) * 180 / M_PI;
dst.roll = atan2( src[ 1 ][ 2 ], src[ 2 ][ 2 ] ) * 180 / M_PI;
} else {
dst.pitch = theta * 180 / M_PI;
dst.yaw = -atan2( src[ 1 ][ 0 ], src[ 1 ][ 1 ] ) * 180 / M_PI;
dst.roll = 0;
}
}
void toAngles( quat_t &src, angles_t &dst ) {
mat3_t temp;
toMatrix( src, temp );
toAngles( temp, dst );
}
void toAngles( idVec3_t &src, angles_t &dst ) {
dst.pitch = src[ 0 ];
dst.yaw = src[ 1 ];
dst.roll = src[ 2 ];
}
void angles_t::toVectors( idVec3_t *forward, idVec3_t *right, idVec3_t *up ) {
float angle;
static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
angle = yaw * ( M_PI * 2 / 360 );
sy = sin( angle );
cy = cos( angle );
angle = pitch * ( M_PI * 2 / 360 );
sp = sin( angle );
cp = cos( angle );
angle = roll * ( M_PI * 2 / 360 );
sr = sin( angle );
cr = cos( angle );
if ( forward ) {
forward->set( cp * cy, cp * sy, -sp );
}
if ( right ) {
right->set( -sr * sp * cy + cr * sy, -sr * sp * sy + -cr * cy, -sr * cp );
}
if ( up ) {
up->set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
}
}
idVec3_t angles_t::toForward( void ) {
float angle;
static float sp, sy, cp, cy; // static to help MS compiler fp bugs
angle = yaw * ( M_PI * 2 / 360 );
sy = sin( angle );
cy = cos( angle );
angle = pitch * ( M_PI * 2 / 360 );
sp = sin( angle );
cp = cos( angle );
return idVec3_t( cp * cy, cp * sy, -sp );
}
/*
=================
Normalize360
returns angles normalized to the range [0 <= angle < 360]
=================
*/
angles_t& angles_t::Normalize360( void ) {
pitch = (360.0 / 65536) * ( ( int )( pitch * ( 65536 / 360.0 ) ) & 65535 );
yaw = (360.0 / 65536) * ( ( int )( yaw * ( 65536 / 360.0 ) ) & 65535 );
roll = (360.0 / 65536) * ( ( int )( roll * ( 65536 / 360.0 ) ) & 65535 );
return *this;
}
/*
=================
Normalize180
returns angles normalized to the range [-180 < angle <= 180]
=================
*/
angles_t& angles_t::Normalize180( void ) {
Normalize360();
if ( pitch > 180.0 ) {
pitch -= 360.0;
}
if ( yaw > 180.0 ) {
yaw -= 360.0;
}
if ( roll > 180.0 ) {
roll -= 360.0;
}
return *this;
}

View File

@ -1,195 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __MATH_ANGLES_H__
#define __MATH_ANGLES_H__
#include <stdlib.h>
#include <assert.h>
#include "math_vector.h"
class mat3_t;
class quat_t;
class idVec3_t;
typedef idVec3_t &vec3_p;
class angles_t {
public:
float pitch;
float yaw;
float roll;
angles_t();
angles_t( float pitch, float yaw, float roll );
angles_t( const idVec3_t &vec );
friend void toAngles( idVec3_t &src, angles_t &dst );
friend void toAngles( quat_t &src, angles_t &dst );
friend void toAngles( mat3_t &src, angles_t &dst );
operator vec3_p();
float operator[]( int index ) const;
float& operator[]( int index );
void set( float pitch, float yaw, float roll );
void operator=( angles_t const &a );
void operator=( idVec3_t const &a );
friend angles_t operator+( const angles_t &a, const angles_t &b );
angles_t &operator+=( angles_t const &a );
angles_t &operator+=( idVec3_t const &a );
friend angles_t operator-( angles_t &a, angles_t &b );
angles_t &operator-=( angles_t &a );
friend angles_t operator*( const angles_t &a, float b );
friend angles_t operator*( float a, const angles_t &b );
angles_t &operator*=( float a );
friend int operator==( angles_t &a, angles_t &b );
friend int operator!=( angles_t &a, angles_t &b );
void toVectors( idVec3_t *forward, idVec3_t *right = NULL, idVec3_t *up = NULL );
idVec3_t toForward( void );
angles_t &Zero( void );
angles_t &Normalize360( void );
angles_t &Normalize180( void );
};
extern angles_t ang_zero;
inline angles_t::angles_t() {}
inline angles_t::angles_t( float pitch, float yaw, float roll ) {
this->pitch = pitch;
this->yaw = yaw;
this->roll = roll;
}
inline angles_t::angles_t( const idVec3_t &vec ) {
this->pitch = vec.x;
this->yaw = vec.y;
this->roll = vec.z;
}
inline float angles_t::operator[]( int index ) const {
assert( ( index >= 0 ) && ( index < 3 ) );
return ( &pitch )[ index ];
}
inline float& angles_t::operator[]( int index ) {
assert( ( index >= 0 ) && ( index < 3 ) );
return ( &pitch )[ index ];
}
inline angles_t::operator vec3_p( void ) {
return *( idVec3_t * )&pitch;
}
inline void angles_t::set( float pitch, float yaw, float roll ) {
this->pitch = pitch;
this->yaw = yaw;
this->roll = roll;
}
inline void angles_t::operator=( angles_t const &a ) {
pitch = a.pitch;
yaw = a.yaw;
roll = a.roll;
}
inline void angles_t::operator=( idVec3_t const &a ) {
pitch = a[ 0 ];
yaw = a[ 1 ];
roll = a[ 2 ];
}
inline angles_t operator+( const angles_t &a, const angles_t &b ) {
return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
}
inline angles_t& angles_t::operator+=( angles_t const &a ) {
pitch += a.pitch;
yaw += a.yaw;
roll += a.roll;
return *this;
}
inline angles_t& angles_t::operator+=( idVec3_t const &a ) {
pitch += a.x;
yaw += a.y;
roll += a.z;
return *this;
}
inline angles_t operator-( angles_t &a, angles_t &b ) {
return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
}
inline angles_t& angles_t::operator-=( angles_t &a ) {
pitch -= a.pitch;
yaw -= a.yaw;
roll -= a.roll;
return *this;
}
inline angles_t operator*( const angles_t &a, float b ) {
return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
}
inline angles_t operator*( float a, const angles_t &b ) {
return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
}
inline angles_t& angles_t::operator*=( float a ) {
pitch *= a;
yaw *= a;
roll *= a;
return *this;
}
inline int operator==( angles_t &a, angles_t &b ) {
return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
}
inline int operator!=( angles_t &a, angles_t &b ) {
return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
}
inline angles_t& angles_t::Zero( void ) {
pitch = 0.0f;
yaw = 0.0f;
roll = 0.0f;
return *this;
}
#endif /* !__MATH_ANGLES_H__ */

Some files were not shown because too many files have changed in this diff Show More