mirror of
https://github.com/id-Software/RTCW-MP.git
synced 2026-03-20 00:49:40 +01:00
The Return to Castle Wolfenstein Multiplayer sources as originally released under the GPL license on August 12, 2010.
This commit is contained in:
90
src/bspc/_files.c
Normal file
90
src/bspc/_files.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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_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
|
||||
|
||||
*/
|
||||
424
src/bspc/aas_areamerging.c
Normal file
424
src/bspc/aas_areamerging.c
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_areamerging.c
|
||||
// Function: Merging of Areas
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
40
src/bspc/aas_areamerging.h
Normal file
40
src/bspc/aas_areamerging.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_areamerging.h
|
||||
// Function: Merging of Areas
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
|
||||
void AAS_MergeAreas( void );
|
||||
|
||||
312
src/bspc/aas_cfg.c
Normal file
312
src/bspc/aas_cfg.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: cfg.c
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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"
|
||||
|
||||
///////////////////////////////////
|
||||
extern void LibVarSet( char *var_name, char *value );
|
||||
///////////////////////////////////
|
||||
|
||||
//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},
|
||||
// Ridah, calculated from velocity and gravity
|
||||
// {"sv_maxbarrier", CFG_OFS(sv_maxbarrier), FT_FLOAT},
|
||||
// {"sv_jumpvel", CFG_OFS(sv_jumpvel), 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;
|
||||
|
||||
#if 0
|
||||
//===========================================================================
|
||||
// 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] = -18;
|
||||
cfg.bboxes[0].mins[1] = -18;
|
||||
cfg.bboxes[0].mins[2] = -24;
|
||||
cfg.bboxes[0].maxs[0] = 18;
|
||||
cfg.bboxes[0].maxs[1] = 18;
|
||||
cfg.bboxes[0].maxs[2] = 48;
|
||||
//bbox 1
|
||||
cfg.bboxes[1].presencetype = PRESENCE_CROUCH;
|
||||
cfg.bboxes[1].flags = 1;
|
||||
cfg.bboxes[1].mins[0] = -18;
|
||||
cfg.bboxes[1].mins[1] = -18;
|
||||
cfg.bboxes[1].mins[2] = -24;
|
||||
cfg.bboxes[1].maxs[0] = 18;
|
||||
cfg.bboxes[1].maxs[1] = 18;
|
||||
cfg.bboxes[1].maxs[2] = 24;
|
||||
//
|
||||
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;
|
||||
|
||||
// cfg.phys_maxbarrier = -999;//32; // RIDAH: this is calculated at run-time now, from the gravity and jump velocity settings
|
||||
} //end of the function DefaultCfg
|
||||
#else
|
||||
//===========================================================================
|
||||
// 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;
|
||||
|
||||
// cfg.phys_maxbarrier = -999;//32; // RIDAH: this is calculated at run-time now, from the gravity and jump velocity settings
|
||||
} //end of the function DefaultCfg
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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
|
||||
88
src/bspc/aas_cfg.h
Normal file
88
src/bspc/aas_cfg.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: cfg.h
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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 );
|
||||
1182
src/bspc/aas_create.c
Normal file
1182
src/bspc/aas_create.c
Normal file
File diff suppressed because it is too large
Load Diff
153
src/bspc/aas_create.h
Normal file
153
src/bspc/aas_create.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_create.h
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
// Ridah, steepness
|
||||
float groundsteepness;
|
||||
} 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 );
|
||||
125
src/bspc/aas_edgemelting.c
Normal file
125
src/bspc/aas_edgemelting.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_edgemelting.c
|
||||
// Function: Melting of Edges
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
|
||||
40
src/bspc/aas_edgemelting.h
Normal file
40
src/bspc/aas_edgemelting.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_edgemelting.h
|
||||
// Function: Melting of Edges
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
|
||||
void AAS_MeltAreaFaceWindings( void );
|
||||
|
||||
312
src/bspc/aas_facemerging.c
Normal file
312
src/bspc/aas_facemerging.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_facemerging.c
|
||||
// Function: Merging of Faces
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
39
src/bspc/aas_facemerging.h
Normal file
39
src/bspc/aas_facemerging.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_facemerging.h
|
||||
// Function: Merging of Faces
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
void AAS_MergeAreaFaces( void );
|
||||
void AAS_MergeAreaPlaneFaces( void );
|
||||
603
src/bspc/aas_file.c
Normal file
603
src/bspc/aas_file.c
Normal file
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_file.c
|
||||
// Function: AAS file loading and writing
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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 );
|
||||
// Ridah
|
||||
( *aasworld ).areasettings[i].groundsteepness = LittleFloat( ( *aasworld ).areasettings[i].groundsteepness );
|
||||
} //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 ) {
|
||||
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
|
||||
|
||||
40
src/bspc/aas_file.h
Normal file
40
src/bspc/aas_file.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_write.h
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
qboolean AAS_WriteAASFile( char *filename );
|
||||
qboolean AAS_LoadAASFile( char *filename, int fpoffset, int fplength );
|
||||
|
||||
688
src/bspc/aas_gsubdiv.c
Normal file
688
src/bspc/aas_gsubdiv.c
Normal file
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_gsubdiv.c
|
||||
// Function: Gravitational Subdivision
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
|
||||
40
src/bspc/aas_gsubdiv.h
Normal file
40
src/bspc/aas_gsubdiv.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_gsubdiv.h
|
||||
// Function: Gravitational subdivision
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
//works with the global tmpaasworld
|
||||
void AAS_GravitationalSubdivision( void );
|
||||
void AAS_LadderSubdivision( void );
|
||||
838
src/bspc/aas_map.c
Normal file
838
src/bspc/aas_map.c
Normal file
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_map.c
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-03
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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 "..\game\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_DONOTENTER_LARGE
|
||||
| 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 AAS_AlwaysTriggered( 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;
|
||||
} //end if
|
||||
//check for possible trigger_always entities activating this entity
|
||||
if ( AAS_AlwaysTriggered( ValueForKey( &entities[i], "targetname" ) ) ) {
|
||||
return true;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end if
|
||||
} //end for
|
||||
return false;
|
||||
} //end of the function AAS_AlwaysTriggered
|
||||
//===========================================================================
|
||||
//
|
||||
// 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" ) ) ||
|
||||
!strcmp( "func_door", ValueForKey( mapent, "classname" ) ) ||
|
||||
!strcmp( "func_invisible_user", 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" ) ) ) {
|
||||
// RF, spawnflag & 1 is for delayed spawn, so ignore it
|
||||
if ( atoi( ValueForKey( mapent, "spawnflags" ) ) & 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//"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_tramcar", ValueForKey( mapent, "classname" ) ) ) {
|
||||
return true;
|
||||
} //end else if
|
||||
else if ( !strcmp( "func_invisible_user", ValueForKey( mapent, "classname" ) ) ) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
else if (!strcmp("func_static", ValueForKey(mapent, "classname")))
|
||||
{
|
||||
//FIXME: easy/medium/hard/deathmatch specific?
|
||||
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;
|
||||
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" ) ) ) {
|
||||
//set the lava contents
|
||||
brush->contents |= CONTENTS_LAVA;
|
||||
//Log_Print("found trigger_hurt brush\n");
|
||||
} //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
|
||||
else if ( !strcmp( "func_invisible_user", ValueForKey( mapent, "classname" ) ) ) {
|
||||
//set mover contents
|
||||
brush->contents = CONTENTS_TRIGGER;
|
||||
} //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
|
||||
//
|
||||
// Rafael TBD: no flag to support CONTENTS_BOTCLIP
|
||||
/*
|
||||
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_DONOTENTER_LARGE
|
||||
| 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_DONOTENTER_LARGE
|
||||
| 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
|
||||
38
src/bspc/aas_map.h
Normal file
38
src/bspc/aas_map.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_map.h
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
void AAS_CreateMapBrushes( mapbrush_t *brush, entity_t *mapent, int addbevels );
|
||||
103
src/bspc/aas_prunenodes.c
Normal file
103
src/bspc/aas_prunenodes.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_prunenodes.c
|
||||
// Function: Prune Nodes
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
39
src/bspc/aas_prunenodes.h
Normal file
39
src/bspc/aas_prunenodes.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_prunenodes.h
|
||||
// Function: Prune Nodes
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
void AAS_PruneNodes( void );
|
||||
|
||||
1121
src/bspc/aas_store.c
Normal file
1121
src/bspc/aas_store.c
Normal file
File diff suppressed because it is too large
Load Diff
125
src/bspc/aas_store.h
Normal file
125
src/bspc/aas_store.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: aas_store.h
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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;
|
||||
//*/
|
||||
|
||||
// Ridah
|
||||
extern aas_t aasworlds[1];
|
||||
extern aas_t *aasworld;
|
||||
// done.
|
||||
|
||||
//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 );
|
||||
314
src/bspc/be_aas_bspc.c
Normal file
314
src/bspc/be_aas_bspc.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: b_aas_bspc.c
|
||||
// Function: Area Awareness System
|
||||
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
|
||||
// Last update: 1999-09-14
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#include "../game/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;
|
||||
|
||||
//#define AAS_MOVE_DEBUG
|
||||
|
||||
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
|
||||
|
||||
// Ridah
|
||||
void AAS_SetWorldPointer( aas_t *newaasworld ) {
|
||||
aasworld = newaasworld;
|
||||
}
|
||||
// done.
|
||||
42
src/bspc/be_aas_bspc.h
Normal file
42
src/bspc/be_aas_bspc.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: b_aas_bspc.h
|
||||
// Function: Area Awareness System
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1999-02-28
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
void AAS_CalcReachAndClusters( struct quakefile_s *qf );
|
||||
|
||||
// Ridah
|
||||
void AAS_SetWorldPointer( aas_t *newaasworld );
|
||||
// done.
|
||||
1923
src/bspc/brushbsp.c
Normal file
1923
src/bspc/brushbsp.c
Normal file
File diff suppressed because it is too large
Load Diff
1101
src/bspc/bspc.c
Normal file
1101
src/bspc/bspc.c
Normal file
File diff suppressed because it is too large
Load Diff
1053
src/bspc/csg.c
Normal file
1053
src/bspc/csg.c
Normal file
File diff suppressed because it is too large
Load Diff
1002
src/bspc/faces.c
Normal file
1002
src/bspc/faces.c
Normal file
File diff suppressed because it is too large
Load Diff
157
src/bspc/glfile.c
Normal file
157
src/bspc/glfile.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
}
|
||||
|
||||
195
src/bspc/l_bsp_ent.c
Normal file
195
src/bspc/l_bsp_ent.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_bsp_ent.c
|
||||
// Function: bsp entity parsing
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1999-04-05
|
||||
// Tab Size: 3
|
||||
// Notes: -
|
||||
//===========================================================================
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
65
src/bspc/l_bsp_ent.h
Normal file
65
src/bspc/l_bsp_ent.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
|
||||
608
src/bspc/l_bsp_q1.c
Normal file
608
src/bspc/l_bsp_q1.c
Normal file
@@ -0,0 +1,608 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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_CopyLump( int lump, void *dest, int size ) {
|
||||
int length, ofs;
|
||||
|
||||
length = q1_header->lumps[lump].filelen;
|
||||
ofs = q1_header->lumps[lump].fileofs;
|
||||
|
||||
if ( length % size ) {
|
||||
Error( "Q1_LoadBSPFile: odd lump size" );
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
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_numvertexes = Q1_CopyLump( Q1_LUMP_VERTEXES, q1_dvertexes, sizeof( q1_dvertex_t ) );
|
||||
q1_numplanes = Q1_CopyLump( Q1_LUMP_PLANES, q1_dplanes, sizeof( q1_dplane_t ) );
|
||||
q1_numleafs = Q1_CopyLump( Q1_LUMP_LEAFS, q1_dleafs, sizeof( q1_dleaf_t ) );
|
||||
q1_numnodes = Q1_CopyLump( Q1_LUMP_NODES, q1_dnodes, sizeof( q1_dnode_t ) );
|
||||
q1_numtexinfo = Q1_CopyLump( Q1_LUMP_TEXINFO, q1_texinfo, sizeof( q1_texinfo_t ) );
|
||||
q1_numclipnodes = Q1_CopyLump( Q1_LUMP_CLIPNODES, q1_dclipnodes, sizeof( q1_dclipnode_t ) );
|
||||
q1_numfaces = Q1_CopyLump( Q1_LUMP_FACES, q1_dfaces, sizeof( q1_dface_t ) );
|
||||
q1_nummarksurfaces = Q1_CopyLump( Q1_LUMP_MARKSURFACES, q1_dmarksurfaces, sizeof( q1_dmarksurfaces[0] ) );
|
||||
q1_numsurfedges = Q1_CopyLump( Q1_LUMP_SURFEDGES, q1_dsurfedges, sizeof( q1_dsurfedges[0] ) );
|
||||
q1_numedges = Q1_CopyLump( Q1_LUMP_EDGES, q1_dedges, sizeof( q1_dedge_t ) );
|
||||
|
||||
q1_texdatasize = Q1_CopyLump( Q1_LUMP_TEXTURES, q1_dtexdata, 1 );
|
||||
q1_visdatasize = Q1_CopyLump( Q1_LUMP_VISIBILITY, q1_dvisdata, 1 );
|
||||
q1_lightdatasize = Q1_CopyLump( Q1_LUMP_LIGHTING, q1_dlightdata, 1 );
|
||||
q1_entdatasize = Q1_CopyLump( Q1_LUMP_ENTITIES, q1_dentdata, 1 );
|
||||
|
||||
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
|
||||
282
src/bspc/l_bsp_q1.h
Normal file
282
src/bspc/l_bsp_q1.h
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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
|
||||
1137
src/bspc/l_bsp_q2.c
Normal file
1137
src/bspc/l_bsp_q2.c
Normal file
File diff suppressed because it is too large
Load Diff
104
src/bspc/l_bsp_q2.h
Normal file
104
src/bspc/l_bsp_q2.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
|
||||
838
src/bspc/l_bsp_q3.c
Normal file
838
src/bspc/l_bsp_q3.c
Normal file
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
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 );
|
||||
|
||||
|
||||
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
|
||||
|
||||
88
src/bspc/l_bsp_q3.h
Normal file
88
src/bspc/l_bsp_q3.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
1186
src/bspc/l_bsp_sin.c
Normal file
1186
src/bspc/l_bsp_sin.c
Normal file
File diff suppressed because it is too large
Load Diff
113
src/bspc/l_bsp_sin.h
Normal file
113
src/bspc/l_bsp_sin.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
|
||||
1182
src/bspc/l_cmd.c
Normal file
1182
src/bspc/l_cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
164
src/bspc/l_cmd.h
Normal file
164
src/bspc/l_cmd.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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
|
||||
|
||||
220
src/bspc/l_log.c
Normal file
220
src/bspc/l_log.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_log.c
|
||||
// Function: log file stuff
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-31
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
|
||||
57
src/bspc/l_log.h
Normal file
57
src/bspc/l_log.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_log.h
|
||||
// Function: log file stuff
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-31
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
//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
|
||||
279
src/bspc/l_math.c
Normal file
279
src/bspc/l_math.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
float VectorLengthSquared( vec3_t v ) {
|
||||
return DotProduct( v, v );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/bspc/l_math.h
Normal file
100
src/bspc/l_math.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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
|
||||
484
src/bspc/l_mem.c
Normal file
484
src/bspc/l_mem.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_mem.c
|
||||
// Function:
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1999-06-02
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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: -
|
||||
//===========================================================================
|
||||
int fmemsize;
|
||||
void FreeMemory( void *ptr ) {
|
||||
// RF, modified this for better memory trash testing
|
||||
fmemsize = MemorySize( ptr );
|
||||
allocedmemory -= fmemsize;
|
||||
|
||||
// RF, somehow this crashes windows if size is less than or equal 8
|
||||
if ( fmemsize <= 8 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// RF, set this memory to something that will cause problems if accessed again
|
||||
memset( ptr, 0xAA, fmemsize );
|
||||
|
||||
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
|
||||
58
src/bspc/l_mem.h
Normal file
58
src/bspc/l_mem.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
|
||||
1433
src/bspc/l_poly.c
Normal file
1433
src/bspc/l_poly.c
Normal file
File diff suppressed because it is too large
Load Diff
136
src/bspc/l_poly.h
Normal file
136
src/bspc/l_poly.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_poly.h
|
||||
// Function:
|
||||
// Programmer: id Sofware
|
||||
// Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-04
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
//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
|
||||
|
||||
701
src/bspc/l_qfiles.c
Normal file
701
src/bspc/l_qfiles.c
Normal file
@@ -0,0 +1,701 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_qfiles.h
|
||||
// Function: -
|
||||
// Programmer: Mr Elusive
|
||||
// Last update: 1999-11-29
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
106
src/bspc/l_qfiles.h
Normal file
106
src/bspc/l_qfiles.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_qfiles.h
|
||||
// Function: -
|
||||
// Programmer: Mr Elusive
|
||||
// Last update: 1999-12-01
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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 );
|
||||
1528
src/bspc/l_threads.c
Normal file
1528
src/bspc/l_threads.c
Normal file
File diff suppressed because it is too large
Load Diff
52
src/bspc/l_threads.h
Normal file
52
src/bspc/l_threads.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
|
||||
262
src/bspc/l_utils.c
Normal file
262
src/bspc/l_utils.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_utils.c
|
||||
// Function: several utils
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-31
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
//#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
|
||||
//===========================================================================
|
||||
// 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
|
||||
94
src/bspc/l_utils.h
Normal file
94
src/bspc/l_utils.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: l_utils.h
|
||||
// Function: several utils
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-31
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
108
src/bspc/leakfile.c
Normal file
108
src/bspc/leakfile.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 );
|
||||
}
|
||||
|
||||
1351
src/bspc/map.c
Normal file
1351
src/bspc/map.c
Normal file
File diff suppressed because it is too large
Load Diff
1205
src/bspc/map_q1.c
Normal file
1205
src/bspc/map_q1.c
Normal file
File diff suppressed because it is too large
Load Diff
1149
src/bspc/map_q2.c
Normal file
1149
src/bspc/map_q2.c
Normal file
File diff suppressed because it is too large
Load Diff
711
src/bspc/map_q3.c
Normal file
711
src/bspc/map_q3.c
Normal file
@@ -0,0 +1,711 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: map_q3.c
|
||||
// Function: map loading
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1999-07-02
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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 "..\game\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;
|
||||
int contentFlags = 0;
|
||||
|
||||
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
|
||||
|
||||
// Ridah, mark ladder brushes
|
||||
if ( strstr( q3_dshaders[bspbrushside->shaderNum].shader, "common/ladder" ) ) {
|
||||
//Log_Print("found ladder side\n");
|
||||
side->contents |= CONTENTS_LADDER;
|
||||
contentFlags |= CONTENTS_LADDER;
|
||||
} //end if
|
||||
// done.
|
||||
|
||||
} //end else
|
||||
//
|
||||
|
||||
if ( !( strstr( q3_dshaders[bspbrushside->shaderNum].shader, "common/slip" ) ) ) {
|
||||
side->flags |= SFL_VISIBLE;
|
||||
} 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
|
||||
//Quake3 bsp brushes don't have a contents
|
||||
b->contents = q3_dshaders[bspbrush->shaderNum].contentFlags | contentFlags;
|
||||
// Ridah, Wolf has ladders (if we call Q3_BrushContents(), we'll get the solid area bug
|
||||
b->contents &= ~( /*CONTENTS_LADDER|*/ CONTENTS_FOG | CONTENTS_STRUCTURAL );
|
||||
//b->contents = Q3_BrushContents(b);
|
||||
//
|
||||
// Ridah, CONTENTS_MOSTERCLIP should prevent AAS from being created, but not clip players/AI in the game
|
||||
if ( b->contents & CONTENTS_MONSTERCLIP ) {
|
||||
b->contents |= CONTENTS_PLAYERCLIP;
|
||||
}
|
||||
|
||||
// func_explosive's not solid
|
||||
if ( !strcmp( "func_explosive", ValueForKey( &entities[b->entitynum], "classname" ) ) ||
|
||||
!strcmp( "func_invisible_user", ValueForKey( &entities[b->entitynum], "classname" ) ) ||
|
||||
!strcmp( "func_static", ValueForKey( &entities[b->entitynum], "classname" ) ) ) {
|
||||
Log_Print( "Ignoring %s brush..\n", ValueForKey( &entities[b->entitynum], "classname" ) );
|
||||
b->numsides = 0;
|
||||
b->contents = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
//===========================================================================
|
||||
//===========================================================================
|
||||
void Q3_ParseBSPBrushes( entity_t *mapent ) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
//give all the brushes that belong to this entity the number of the
|
||||
//BSP model used by this entity
|
||||
Q3_SetBrushModelNumbers(mapent);
|
||||
//now parse all the brushes with the correct mapent->modelnum
|
||||
for (i = 0; i < q3_numbrushes; i++)
|
||||
{
|
||||
if (brushmodelnumbers[i] == mapent->modelnum)
|
||||
{
|
||||
Q3_BSPBrushToMapBrush(&q3_dbrushes[i], mapent);
|
||||
} //end if
|
||||
} //end for
|
||||
*/
|
||||
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
|
||||
//===========================================================================
|
||||
//===========================================================================
|
||||
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
|
||||
//
|
||||
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;
|
||||
}
|
||||
if ( mapbrushes[i].mins[0] > 4096 ) {
|
||||
continue; //no valid points
|
||||
}
|
||||
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
|
||||
|
||||
1199
src/bspc/map_sin.c
Normal file
1199
src/bspc/map_sin.c
Normal file
File diff suppressed because it is too large
Load Diff
50
src/bspc/nodraw.c
Normal file
50
src/bspc/nodraw.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 ) {
|
||||
}
|
||||
1308
src/bspc/portals.c
Normal file
1308
src/bspc/portals.c
Normal file
File diff suppressed because it is too large
Load Diff
287
src/bspc/prtfile.c
Normal file
287
src/bspc/prtfile.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// NO LONGER USED
|
||||
#if 0
|
||||
#include "qbsp.h"
|
||||
|
||||
extern dleaf_t dleafs[MAX_MAP_LEAFS];
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 );
|
||||
}
|
||||
#endif
|
||||
494
src/bspc/q2files.h
Normal file
494
src/bspc/q2files.h
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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;
|
||||
381
src/bspc/q3files.h
Normal file
381
src/bspc/q3files.h
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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 47
|
||||
|
||||
|
||||
// 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
|
||||
496
src/bspc/qbsp.h
Normal file
496
src/bspc/qbsp.h
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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"
|
||||
|
||||
//Mr Elusive shit
|
||||
#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 128000
|
||||
#define MAX_MAPFILE_BRUSHES 65535 //16384
|
||||
#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 );
|
||||
|
||||
//=============================================================================
|
||||
// faces.c
|
||||
//=============================================================================
|
||||
|
||||
face_t *AllocFace( void );
|
||||
void FreeFace( face_t *f );
|
||||
void MakeFaces( node_t *headnode );
|
||||
void FixTjuncs( node_t *headnode );
|
||||
int GetEdge2( int v1, int v2, face_t *f );
|
||||
void MergeNodeFaces( node_t *node );
|
||||
495
src/bspc/qfiles.h
Normal file
495
src/bspc/qfiles.h
Normal file
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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
|
||||
|
||||
#define SURF_MONSTERSLICK 0x4000000 // slick surf that only affects ai's
|
||||
|
||||
|
||||
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;
|
||||
372
src/bspc/sinfiles.h
Normal file
372
src/bspc/sinfiles.h
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 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;
|
||||
249
src/bspc/textures.c
Normal file
249
src/bspc/textures.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: textures.c
|
||||
// Function: textures
|
||||
// Programmer: Mr Elusive (MrElusive@worldentity.com)
|
||||
// Last update: 1999-08-10
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
//===========================================================================
|
||||
//textureAxisFromPlane
|
||||
//
|
||||
// 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
|
||||
298
src/bspc/tree.c
Normal file
298
src/bspc/tree.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Name: textures.c
|
||||
// Function: textures
|
||||
// Programmer: Mr Elusive (MrElusive@worldentity.com)
|
||||
// Last update: 1999-08-10
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
#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
|
||||
632
src/bspc/writebsp.c
Normal file
632
src/bspc/writebsp.c
Normal file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||||
|
||||
RTCW MP 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// NO LONGER IN PROJECT
|
||||
#if 0
|
||||
#include "qbsp.h"
|
||||
|
||||
int c_nofaces;
|
||||
int c_facenodes;
|
||||
|
||||
|
||||
extern int numplanes;
|
||||
extern int numfaces;
|
||||
extern int numleaffaces;
|
||||
extern int numleafs;
|
||||
extern int numleafbrushes;
|
||||
extern int numsurfedges;
|
||||
extern int numnodes;
|
||||
|
||||
extern int nummodels;
|
||||
extern int numbrushsides;
|
||||
extern int numbrushes;
|
||||
extern int numvertexes;
|
||||
extern int numedges;
|
||||
|
||||
extern dplane_t dplanes[MAX_MAP_PLANES];
|
||||
extern dleaf_t dleafs[MAX_MAP_LEAFS];
|
||||
extern dleaf_t dleafs[MAX_MAP_LEAFS];
|
||||
extern dface_t dfaces[MAX_MAP_FACES];
|
||||
extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
|
||||
extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
|
||||
extern int dsurfedges[MAX_MAP_SURFEDGES];
|
||||
extern dnode_t dnodes[MAX_MAP_NODES];
|
||||
extern dmodel_t dmodels[MAX_MAP_MODELS];
|
||||
extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
|
||||
extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
|
||||
|
||||
/*
|
||||
=========================================================
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user