mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2025-01-18 21:51:37 +00:00
* 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:
parent
63fdc74843
commit
c41483634c
116 changed files with 16 additions and 48383 deletions
|
@ -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"
|
||||
#
|
||||
|
|
@ -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
|
||||
|
||||
*/
|
|
@ -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
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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);
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
@ -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);
|
|
@ -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
|
||||
*/
|
|
@ -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
|
|
@ -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);
|
1871
code/bspc/brushbsp.c
1871
code/bspc/brushbsp.c
File diff suppressed because it is too large
Load diff
991
code/bspc/bspc.c
991
code/bspc/bspc.c
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
1005
code/bspc/csg.c
1005
code/bspc/csg.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
} //*/
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
1134
code/bspc/l_bsp_q2.c
1134
code/bspc/l_bsp_q2.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
@ -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);
|
||||
|
1230
code/bspc/l_cmd.c
1230
code/bspc/l_cmd.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
1411
code/bspc/l_poly.c
1411
code/bspc/l_poly.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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) $<
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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"
|
||||
#
|
||||
|
1267
code/bspc/map.c
1267
code/bspc/map.c
File diff suppressed because it is too large
Load diff
1114
code/bspc/map_hl.c
1114
code/bspc/map_hl.c
File diff suppressed because it is too large
Load diff
1174
code/bspc/map_q1.c
1174
code/bspc/map_q1.c
File diff suppressed because it is too large
Load diff
1162
code/bspc/map_q2.c
1162
code/bspc/map_q2.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
1211
code/bspc/map_sin.c
1211
code/bspc/map_sin.c
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
}
|
1297
code/bspc/portals.c
1297
code/bspc/portals.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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
|
477
code/bspc/qbsp.h
477
code/bspc/qbsp.h
|
@ -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);
|
|
@ -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;
|
|
@ -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
|
@ -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);
|
||||
|
|
@ -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
|
283
code/bspc/tree.c
283
code/bspc/tree.c
|
@ -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
|
|
@ -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++;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="Splines"
|
||||
SccProjectName=""$/MissionPack/code/Splines", 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>
|
|
@ -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;
|
||||
}
|
|
@ -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
Loading…
Reference in a new issue