Itsa me, quake3io!
This commit is contained in:
parent
dbe4ddb103
commit
5b755058f5
1409 changed files with 798983 additions and 798983 deletions
1680
q3map/brush.c
Normal file → Executable file
1680
q3map/brush.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
62
q3map/brush_primit.c
Normal file → Executable file
62
q3map/brush_primit.c
Normal file → Executable file
|
@ -19,34 +19,34 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
// global flag
|
||||
int g_bBrushPrimit;
|
||||
|
||||
// NOTE : ComputeAxisBase here and in editor code must always BE THE SAME !
|
||||
// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0
|
||||
// rotation by (0,RotY,RotZ) assigns X to normal
|
||||
void ComputeAxisBase(vec3_t normal,vec3_t texX,vec3_t texY)
|
||||
{
|
||||
vec_t RotY,RotZ;
|
||||
// do some cleaning
|
||||
if (fabs(normal[0])<1e-6)
|
||||
normal[0]=0.0f;
|
||||
if (fabs(normal[1])<1e-6)
|
||||
normal[1]=0.0f;
|
||||
if (fabs(normal[2])<1e-6)
|
||||
normal[2]=0.0f;
|
||||
// compute the two rotations around Y and Z to rotate X to normal
|
||||
RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0]));
|
||||
RotZ=atan2(normal[1],normal[0]);
|
||||
// rotate (0,1,0) and (0,0,1) to compute texX and texY
|
||||
texX[0]=-sin(RotZ);
|
||||
texX[1]=cos(RotZ);
|
||||
texX[2]=0;
|
||||
// the texY vector is along -Z ( T texture coorinates axis )
|
||||
texY[0]=-sin(RotY)*cos(RotZ);
|
||||
texY[1]=-sin(RotY)*sin(RotZ);
|
||||
texY[2]=-cos(RotY);
|
||||
}
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
// global flag
|
||||
int g_bBrushPrimit;
|
||||
|
||||
// NOTE : ComputeAxisBase here and in editor code must always BE THE SAME !
|
||||
// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0
|
||||
// rotation by (0,RotY,RotZ) assigns X to normal
|
||||
void ComputeAxisBase(vec3_t normal,vec3_t texX,vec3_t texY)
|
||||
{
|
||||
vec_t RotY,RotZ;
|
||||
// do some cleaning
|
||||
if (fabs(normal[0])<1e-6)
|
||||
normal[0]=0.0f;
|
||||
if (fabs(normal[1])<1e-6)
|
||||
normal[1]=0.0f;
|
||||
if (fabs(normal[2])<1e-6)
|
||||
normal[2]=0.0f;
|
||||
// compute the two rotations around Y and Z to rotate X to normal
|
||||
RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0]));
|
||||
RotZ=atan2(normal[1],normal[0]);
|
||||
// rotate (0,1,0) and (0,0,1) to compute texX and texY
|
||||
texX[0]=-sin(RotZ);
|
||||
texX[1]=cos(RotZ);
|
||||
texX[2]=0;
|
||||
// the texY vector is along -Z ( T texture coorinates axis )
|
||||
texY[0]=-sin(RotY)*cos(RotZ);
|
||||
texY[1]=-sin(RotY)*sin(RotZ);
|
||||
texY[2]=-cos(RotY);
|
||||
}
|
||||
|
|
1168
q3map/bsp.c
Normal file → Executable file
1168
q3map/bsp.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
716
q3map/facebsp.c
Normal file → Executable file
716
q3map/facebsp.c
Normal file → Executable file
|
@ -19,361 +19,361 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
int c_faceLeafs;
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
AllocBspFace
|
||||
================
|
||||
*/
|
||||
bspface_t *AllocBspFace( void ) {
|
||||
bspface_t *f;
|
||||
|
||||
f = malloc(sizeof(*f));
|
||||
memset( f, 0, sizeof(*f) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FreeBspFace
|
||||
================
|
||||
*/
|
||||
void FreeBspFace( bspface_t *f ) {
|
||||
if ( f->w ) {
|
||||
FreeWinding( f->w );
|
||||
}
|
||||
free( f );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SelectSplitPlaneNum
|
||||
================
|
||||
*/
|
||||
int hintsplit;
|
||||
|
||||
#define BLOCK_SIZE 1024
|
||||
int SelectSplitPlaneNum( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *check;
|
||||
bspface_t *bestSplit;
|
||||
int splits, facing, front, back;
|
||||
int side;
|
||||
plane_t *plane;
|
||||
int value, bestValue;
|
||||
int i;
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
int planenum;
|
||||
|
||||
hintsplit = qfalse;
|
||||
// if it is crossing a 1k block boundary, force a split
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
dist = BLOCK_SIZE * ( floor( node->mins[i] / BLOCK_SIZE ) + 1 );
|
||||
if ( node->maxs[i] > dist ) {
|
||||
VectorClear( normal );
|
||||
normal[i] = 1;
|
||||
planenum = FindFloatPlane( normal, dist );
|
||||
return planenum;
|
||||
}
|
||||
}
|
||||
|
||||
// pick one of the face planes
|
||||
bestValue = -99999;
|
||||
bestSplit = list;
|
||||
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
split->checked = qfalse;
|
||||
}
|
||||
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
if ( split->checked ) {
|
||||
continue;
|
||||
}
|
||||
plane = &mapplanes[ split->planenum ];
|
||||
splits = 0;
|
||||
facing = 0;
|
||||
front = 0;
|
||||
back = 0;
|
||||
for ( check = list ; check ; check = check->next ) {
|
||||
if ( check->planenum == split->planenum ) {
|
||||
facing++;
|
||||
check->checked = qtrue; // won't need to test this plane again
|
||||
continue;
|
||||
}
|
||||
side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
|
||||
if ( side == SIDE_CROSS ) {
|
||||
splits++;
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
front++;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
back++;
|
||||
}
|
||||
}
|
||||
value = 5*facing - 5*splits; // - abs(front-back);
|
||||
if ( plane->type < 3 ) {
|
||||
value+=5; // axial is better
|
||||
}
|
||||
value += split->priority; // prioritize hints higher
|
||||
|
||||
if ( value > bestValue ) {
|
||||
bestValue = value;
|
||||
bestSplit = split;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestValue == -99999 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bestSplit->hint)
|
||||
hintsplit = qtrue;
|
||||
|
||||
return bestSplit->planenum;
|
||||
}
|
||||
|
||||
int CountFaceList( bspface_t *list ) {
|
||||
int c;
|
||||
c = 0;
|
||||
for ( ; list ; list = list->next ) {
|
||||
c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BuildFaceTree_r
|
||||
================
|
||||
*/
|
||||
void BuildFaceTree_r( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *next;
|
||||
int side;
|
||||
plane_t *plane;
|
||||
bspface_t *newFace;
|
||||
bspface_t *childLists[2];
|
||||
winding_t *frontWinding, *backWinding;
|
||||
int i;
|
||||
int splitPlaneNum;
|
||||
|
||||
i = CountFaceList( list );
|
||||
|
||||
splitPlaneNum = SelectSplitPlaneNum( node, list );
|
||||
// if we don't have any more faces, this is a node
|
||||
if ( splitPlaneNum == -1 ) {
|
||||
node->planenum = PLANENUM_LEAF;
|
||||
c_faceLeafs++;
|
||||
return;
|
||||
}
|
||||
|
||||
// partition the list
|
||||
node->planenum = splitPlaneNum;
|
||||
node->hint = hintsplit;
|
||||
plane = &mapplanes[ splitPlaneNum ];
|
||||
childLists[0] = NULL;
|
||||
childLists[1] = NULL;
|
||||
for ( split = list ; split ; split = next ) {
|
||||
next = split->next;
|
||||
|
||||
if ( split->planenum == node->planenum ) {
|
||||
FreeBspFace( split );
|
||||
continue;
|
||||
}
|
||||
|
||||
side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
|
||||
|
||||
if ( side == SIDE_CROSS ) {
|
||||
ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
|
||||
&frontWinding, &backWinding );
|
||||
if ( frontWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = frontWinding;
|
||||
newFace->next = childLists[0];
|
||||
newFace->planenum = split->planenum;
|
||||
newFace->priority = split->priority;
|
||||
newFace->hint = split->hint;
|
||||
childLists[0] = newFace;
|
||||
}
|
||||
if ( backWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = backWinding;
|
||||
newFace->next = childLists[1];
|
||||
newFace->planenum = split->planenum;
|
||||
newFace->priority = split->priority;
|
||||
newFace->hint = split->hint;
|
||||
childLists[1] = newFace;
|
||||
}
|
||||
FreeBspFace( split );
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
split->next = childLists[0];
|
||||
childLists[0] = split;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
split->next = childLists[1];
|
||||
childLists[1] = split;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// recursively process children
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
node->children[i] = AllocNode();
|
||||
node->children[i]->parent = node;
|
||||
VectorCopy( node->mins, node->children[i]->mins );
|
||||
VectorCopy( node->maxs, node->children[i]->maxs );
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( plane->normal[i] == 1 ) {
|
||||
node->children[0]->mins[i] = plane->dist;
|
||||
node->children[1]->maxs[i] = plane->dist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
BuildFaceTree_r ( node->children[i], childLists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
FaceBSP
|
||||
|
||||
List will be freed before returning
|
||||
================
|
||||
*/
|
||||
tree_t *FaceBSP( bspface_t *list ) {
|
||||
tree_t *tree;
|
||||
bspface_t *face;
|
||||
int i;
|
||||
int count;
|
||||
|
||||
qprintf( "--- FaceBSP ---\n" );
|
||||
|
||||
tree = AllocTree ();
|
||||
|
||||
count = 0;
|
||||
for ( face = list ; face ; face = face->next ) {
|
||||
count++;
|
||||
for ( i = 0 ; i < face->w->numpoints ; i++ ) {
|
||||
AddPointToBounds( face->w->p[i], tree->mins, tree->maxs);
|
||||
}
|
||||
}
|
||||
qprintf( "%5i faces\n", count );
|
||||
|
||||
tree->headnode = AllocNode();
|
||||
VectorCopy( tree->mins, tree->headnode->mins );
|
||||
VectorCopy( tree->maxs, tree->headnode->maxs );
|
||||
c_faceLeafs = 0;
|
||||
|
||||
BuildFaceTree_r ( tree->headnode, list );
|
||||
|
||||
qprintf( "%5i leafs\n", c_faceLeafs );
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
BspFaceForPortal
|
||||
=================
|
||||
*/
|
||||
bspface_t *BspFaceForPortal( portal_t *p ) {
|
||||
bspface_t *f;
|
||||
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( p->winding );
|
||||
f->planenum = p->onnode->planenum & ~1;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeStructuralBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ) {
|
||||
bspbrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
winding_t *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( b = list ; b ; b = b->next ) {
|
||||
if ( b->detail ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->winding;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( w );
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
if (s->surfaceFlags & SURF_HINT) {
|
||||
//f->priority = HINT_PRIORITY;
|
||||
f->hint = qtrue;
|
||||
}
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeVisibleBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ) {
|
||||
bspbrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
winding_t *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( b = list ; b ; b = b->next ) {
|
||||
if ( b->detail ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->visibleHull;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( w );
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
if (s->surfaceFlags & SURF_HINT) {
|
||||
//f->priority = HINT_PRIORITY;
|
||||
f->hint = qtrue;
|
||||
}
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
int c_faceLeafs;
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
AllocBspFace
|
||||
================
|
||||
*/
|
||||
bspface_t *AllocBspFace( void ) {
|
||||
bspface_t *f;
|
||||
|
||||
f = malloc(sizeof(*f));
|
||||
memset( f, 0, sizeof(*f) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FreeBspFace
|
||||
================
|
||||
*/
|
||||
void FreeBspFace( bspface_t *f ) {
|
||||
if ( f->w ) {
|
||||
FreeWinding( f->w );
|
||||
}
|
||||
free( f );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SelectSplitPlaneNum
|
||||
================
|
||||
*/
|
||||
int hintsplit;
|
||||
|
||||
#define BLOCK_SIZE 1024
|
||||
int SelectSplitPlaneNum( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *check;
|
||||
bspface_t *bestSplit;
|
||||
int splits, facing, front, back;
|
||||
int side;
|
||||
plane_t *plane;
|
||||
int value, bestValue;
|
||||
int i;
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
int planenum;
|
||||
|
||||
hintsplit = qfalse;
|
||||
// if it is crossing a 1k block boundary, force a split
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
dist = BLOCK_SIZE * ( floor( node->mins[i] / BLOCK_SIZE ) + 1 );
|
||||
if ( node->maxs[i] > dist ) {
|
||||
VectorClear( normal );
|
||||
normal[i] = 1;
|
||||
planenum = FindFloatPlane( normal, dist );
|
||||
return planenum;
|
||||
}
|
||||
}
|
||||
|
||||
// pick one of the face planes
|
||||
bestValue = -99999;
|
||||
bestSplit = list;
|
||||
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
split->checked = qfalse;
|
||||
}
|
||||
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
if ( split->checked ) {
|
||||
continue;
|
||||
}
|
||||
plane = &mapplanes[ split->planenum ];
|
||||
splits = 0;
|
||||
facing = 0;
|
||||
front = 0;
|
||||
back = 0;
|
||||
for ( check = list ; check ; check = check->next ) {
|
||||
if ( check->planenum == split->planenum ) {
|
||||
facing++;
|
||||
check->checked = qtrue; // won't need to test this plane again
|
||||
continue;
|
||||
}
|
||||
side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
|
||||
if ( side == SIDE_CROSS ) {
|
||||
splits++;
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
front++;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
back++;
|
||||
}
|
||||
}
|
||||
value = 5*facing - 5*splits; // - abs(front-back);
|
||||
if ( plane->type < 3 ) {
|
||||
value+=5; // axial is better
|
||||
}
|
||||
value += split->priority; // prioritize hints higher
|
||||
|
||||
if ( value > bestValue ) {
|
||||
bestValue = value;
|
||||
bestSplit = split;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestValue == -99999 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bestSplit->hint)
|
||||
hintsplit = qtrue;
|
||||
|
||||
return bestSplit->planenum;
|
||||
}
|
||||
|
||||
int CountFaceList( bspface_t *list ) {
|
||||
int c;
|
||||
c = 0;
|
||||
for ( ; list ; list = list->next ) {
|
||||
c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BuildFaceTree_r
|
||||
================
|
||||
*/
|
||||
void BuildFaceTree_r( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *next;
|
||||
int side;
|
||||
plane_t *plane;
|
||||
bspface_t *newFace;
|
||||
bspface_t *childLists[2];
|
||||
winding_t *frontWinding, *backWinding;
|
||||
int i;
|
||||
int splitPlaneNum;
|
||||
|
||||
i = CountFaceList( list );
|
||||
|
||||
splitPlaneNum = SelectSplitPlaneNum( node, list );
|
||||
// if we don't have any more faces, this is a node
|
||||
if ( splitPlaneNum == -1 ) {
|
||||
node->planenum = PLANENUM_LEAF;
|
||||
c_faceLeafs++;
|
||||
return;
|
||||
}
|
||||
|
||||
// partition the list
|
||||
node->planenum = splitPlaneNum;
|
||||
node->hint = hintsplit;
|
||||
plane = &mapplanes[ splitPlaneNum ];
|
||||
childLists[0] = NULL;
|
||||
childLists[1] = NULL;
|
||||
for ( split = list ; split ; split = next ) {
|
||||
next = split->next;
|
||||
|
||||
if ( split->planenum == node->planenum ) {
|
||||
FreeBspFace( split );
|
||||
continue;
|
||||
}
|
||||
|
||||
side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
|
||||
|
||||
if ( side == SIDE_CROSS ) {
|
||||
ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
|
||||
&frontWinding, &backWinding );
|
||||
if ( frontWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = frontWinding;
|
||||
newFace->next = childLists[0];
|
||||
newFace->planenum = split->planenum;
|
||||
newFace->priority = split->priority;
|
||||
newFace->hint = split->hint;
|
||||
childLists[0] = newFace;
|
||||
}
|
||||
if ( backWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = backWinding;
|
||||
newFace->next = childLists[1];
|
||||
newFace->planenum = split->planenum;
|
||||
newFace->priority = split->priority;
|
||||
newFace->hint = split->hint;
|
||||
childLists[1] = newFace;
|
||||
}
|
||||
FreeBspFace( split );
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
split->next = childLists[0];
|
||||
childLists[0] = split;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
split->next = childLists[1];
|
||||
childLists[1] = split;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// recursively process children
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
node->children[i] = AllocNode();
|
||||
node->children[i]->parent = node;
|
||||
VectorCopy( node->mins, node->children[i]->mins );
|
||||
VectorCopy( node->maxs, node->children[i]->maxs );
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( plane->normal[i] == 1 ) {
|
||||
node->children[0]->mins[i] = plane->dist;
|
||||
node->children[1]->maxs[i] = plane->dist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
BuildFaceTree_r ( node->children[i], childLists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
FaceBSP
|
||||
|
||||
List will be freed before returning
|
||||
================
|
||||
*/
|
||||
tree_t *FaceBSP( bspface_t *list ) {
|
||||
tree_t *tree;
|
||||
bspface_t *face;
|
||||
int i;
|
||||
int count;
|
||||
|
||||
qprintf( "--- FaceBSP ---\n" );
|
||||
|
||||
tree = AllocTree ();
|
||||
|
||||
count = 0;
|
||||
for ( face = list ; face ; face = face->next ) {
|
||||
count++;
|
||||
for ( i = 0 ; i < face->w->numpoints ; i++ ) {
|
||||
AddPointToBounds( face->w->p[i], tree->mins, tree->maxs);
|
||||
}
|
||||
}
|
||||
qprintf( "%5i faces\n", count );
|
||||
|
||||
tree->headnode = AllocNode();
|
||||
VectorCopy( tree->mins, tree->headnode->mins );
|
||||
VectorCopy( tree->maxs, tree->headnode->maxs );
|
||||
c_faceLeafs = 0;
|
||||
|
||||
BuildFaceTree_r ( tree->headnode, list );
|
||||
|
||||
qprintf( "%5i leafs\n", c_faceLeafs );
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
BspFaceForPortal
|
||||
=================
|
||||
*/
|
||||
bspface_t *BspFaceForPortal( portal_t *p ) {
|
||||
bspface_t *f;
|
||||
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( p->winding );
|
||||
f->planenum = p->onnode->planenum & ~1;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeStructuralBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ) {
|
||||
bspbrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
winding_t *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( b = list ; b ; b = b->next ) {
|
||||
if ( b->detail ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->winding;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( w );
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
if (s->surfaceFlags & SURF_HINT) {
|
||||
//f->priority = HINT_PRIORITY;
|
||||
f->hint = qtrue;
|
||||
}
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeVisibleBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ) {
|
||||
bspbrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
winding_t *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( b = list ; b ; b = b->next ) {
|
||||
if ( b->detail ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->visibleHull;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
f->w = CopyWinding( w );
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
if (s->surfaceFlags & SURF_HINT) {
|
||||
//f->priority = HINT_PRIORITY;
|
||||
f->hint = qtrue;
|
||||
}
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
|
|
1066
q3map/fog.c
Normal file → Executable file
1066
q3map/fog.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
422
q3map/gldraw.c
Normal file → Executable file
422
q3map/gldraw.c
Normal file → Executable file
|
@ -19,214 +19,214 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glaux.h>
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
// can't use the glvertex3fv functions, because the vec3_t fields
|
||||
// could be either floats or doubles, depending on DOUBLEVEC_T
|
||||
|
||||
qboolean drawflag;
|
||||
vec3_t draw_mins, draw_maxs;
|
||||
|
||||
|
||||
#define WIN_SIZE 512
|
||||
|
||||
void InitWindow (void)
|
||||
{
|
||||
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
|
||||
auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
|
||||
auxInitWindow ("qcsg");
|
||||
}
|
||||
|
||||
void Draw_ClearWindow (void)
|
||||
{
|
||||
static int init;
|
||||
int w, h, g;
|
||||
vec_t mx, my;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
init = qtrue;
|
||||
InitWindow ();
|
||||
}
|
||||
|
||||
glClearColor (1,0.8,0.8,0);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
w = (draw_maxs[0] - draw_mins[0]);
|
||||
h = (draw_maxs[1] - draw_mins[1]);
|
||||
|
||||
mx = draw_mins[0] + w/2;
|
||||
my = draw_mins[1] + h/2;
|
||||
|
||||
g = w > h ? w : h;
|
||||
|
||||
glLoadIdentity ();
|
||||
gluPerspective (90, 1, 2, 16384);
|
||||
gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0);
|
||||
|
||||
glColor3f (0,0,0);
|
||||
// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 0
|
||||
glColor4f (1,0,0,0.5);
|
||||
glBegin (GL_POLYGON);
|
||||
|
||||
glVertex3f (0, 500, 0);
|
||||
glVertex3f (0, 900, 0);
|
||||
glVertex3f (0, 900, 100);
|
||||
glVertex3f (0, 500, 100);
|
||||
|
||||
glEnd ();
|
||||
#endif
|
||||
|
||||
glFlush ();
|
||||
|
||||
}
|
||||
|
||||
void Draw_SetRed (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (1,0,0);
|
||||
}
|
||||
|
||||
void Draw_SetGrey (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0.5,0.5,0.5);
|
||||
}
|
||||
|
||||
void Draw_SetBlack (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0,0,0);
|
||||
}
|
||||
|
||||
void DrawWinding (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor4f (0,0,0,0.5);
|
||||
glBegin (GL_LINE_LOOP);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glColor4f (0,1,0,0.3);
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
void DrawAuxWinding (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor4f (0,0,0,0.5);
|
||||
glBegin (GL_LINE_LOOP);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glColor4f (1,0,0,0.3);
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
#define GLSERV_PORT 25001
|
||||
|
||||
qboolean wins_init;
|
||||
int draw_socket;
|
||||
|
||||
void GLS_BeginScene (void)
|
||||
{
|
||||
WSADATA winsockdata;
|
||||
WORD wVersionRequested;
|
||||
struct sockaddr_in address;
|
||||
int r;
|
||||
|
||||
if (!wins_init)
|
||||
{
|
||||
wins_init = qtrue;
|
||||
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
|
||||
r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
|
||||
|
||||
if (r)
|
||||
Error ("Winsock initialization failed.");
|
||||
|
||||
}
|
||||
|
||||
// connect a socket to the server
|
||||
|
||||
draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (draw_socket == -1)
|
||||
Error ("draw_socket failed");
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
address.sin_port = GLSERV_PORT;
|
||||
r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address));
|
||||
if (r == -1)
|
||||
{
|
||||
closesocket (draw_socket);
|
||||
draw_socket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GLS_Winding (winding_t *w, int code)
|
||||
{
|
||||
byte buf[1024];
|
||||
int i, j;
|
||||
|
||||
if (!draw_socket)
|
||||
return;
|
||||
|
||||
((int *)buf)[0] = w->numpoints;
|
||||
((int *)buf)[1] = code;
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
for (j=0 ; j<3 ; j++)
|
||||
((float *)buf)[2+i*3+j] = w->p[i][j];
|
||||
|
||||
send (draw_socket, buf, w->numpoints*12+8, 0);
|
||||
}
|
||||
|
||||
void GLS_EndScene (void)
|
||||
{
|
||||
closesocket (draw_socket);
|
||||
draw_socket = 0;
|
||||
}
|
||||
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glaux.h>
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
// can't use the glvertex3fv functions, because the vec3_t fields
|
||||
// could be either floats or doubles, depending on DOUBLEVEC_T
|
||||
|
||||
qboolean drawflag;
|
||||
vec3_t draw_mins, draw_maxs;
|
||||
|
||||
|
||||
#define WIN_SIZE 512
|
||||
|
||||
void InitWindow (void)
|
||||
{
|
||||
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
|
||||
auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
|
||||
auxInitWindow ("qcsg");
|
||||
}
|
||||
|
||||
void Draw_ClearWindow (void)
|
||||
{
|
||||
static int init;
|
||||
int w, h, g;
|
||||
vec_t mx, my;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
init = qtrue;
|
||||
InitWindow ();
|
||||
}
|
||||
|
||||
glClearColor (1,0.8,0.8,0);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
w = (draw_maxs[0] - draw_mins[0]);
|
||||
h = (draw_maxs[1] - draw_mins[1]);
|
||||
|
||||
mx = draw_mins[0] + w/2;
|
||||
my = draw_mins[1] + h/2;
|
||||
|
||||
g = w > h ? w : h;
|
||||
|
||||
glLoadIdentity ();
|
||||
gluPerspective (90, 1, 2, 16384);
|
||||
gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0);
|
||||
|
||||
glColor3f (0,0,0);
|
||||
// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 0
|
||||
glColor4f (1,0,0,0.5);
|
||||
glBegin (GL_POLYGON);
|
||||
|
||||
glVertex3f (0, 500, 0);
|
||||
glVertex3f (0, 900, 0);
|
||||
glVertex3f (0, 900, 100);
|
||||
glVertex3f (0, 500, 100);
|
||||
|
||||
glEnd ();
|
||||
#endif
|
||||
|
||||
glFlush ();
|
||||
|
||||
}
|
||||
|
||||
void Draw_SetRed (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (1,0,0);
|
||||
}
|
||||
|
||||
void Draw_SetGrey (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0.5,0.5,0.5);
|
||||
}
|
||||
|
||||
void Draw_SetBlack (void)
|
||||
{
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor3f (0,0,0);
|
||||
}
|
||||
|
||||
void DrawWinding (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor4f (0,0,0,0.5);
|
||||
glBegin (GL_LINE_LOOP);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glColor4f (0,1,0,0.3);
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
void DrawAuxWinding (winding_t *w)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!drawflag)
|
||||
return;
|
||||
|
||||
glColor4f (0,0,0,0.5);
|
||||
glBegin (GL_LINE_LOOP);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glColor4f (1,0,0,0.3);
|
||||
glBegin (GL_POLYGON);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
|
||||
glEnd ();
|
||||
|
||||
glFlush ();
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
#define GLSERV_PORT 25001
|
||||
|
||||
qboolean wins_init;
|
||||
int draw_socket;
|
||||
|
||||
void GLS_BeginScene (void)
|
||||
{
|
||||
WSADATA winsockdata;
|
||||
WORD wVersionRequested;
|
||||
struct sockaddr_in address;
|
||||
int r;
|
||||
|
||||
if (!wins_init)
|
||||
{
|
||||
wins_init = qtrue;
|
||||
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
|
||||
r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
|
||||
|
||||
if (r)
|
||||
Error ("Winsock initialization failed.");
|
||||
|
||||
}
|
||||
|
||||
// connect a socket to the server
|
||||
|
||||
draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (draw_socket == -1)
|
||||
Error ("draw_socket failed");
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
address.sin_port = GLSERV_PORT;
|
||||
r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address));
|
||||
if (r == -1)
|
||||
{
|
||||
closesocket (draw_socket);
|
||||
draw_socket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GLS_Winding (winding_t *w, int code)
|
||||
{
|
||||
byte buf[1024];
|
||||
int i, j;
|
||||
|
||||
if (!draw_socket)
|
||||
return;
|
||||
|
||||
((int *)buf)[0] = w->numpoints;
|
||||
((int *)buf)[1] = code;
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
for (j=0 ; j<3 ; j++)
|
||||
((float *)buf)[2+i*3+j] = w->p[i][j];
|
||||
|
||||
send (draw_socket, buf, w->numpoints*12+8, 0);
|
||||
}
|
||||
|
||||
void GLS_EndScene (void)
|
||||
{
|
||||
closesocket (draw_socket);
|
||||
draw_socket = 0;
|
||||
}
|
||||
|
|
254
q3map/glfile.c
Normal file → Executable file
254
q3map/glfile.c
Normal file → Executable file
|
@ -19,130 +19,130 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
int c_glfaces;
|
||||
|
||||
int PortalVisibleSides (portal_t *p)
|
||||
{
|
||||
int fcon, bcon;
|
||||
|
||||
if (!p->onnode)
|
||||
return 0; // outside
|
||||
|
||||
fcon = p->nodes[0]->opaque;
|
||||
bcon = p->nodes[1]->opaque;
|
||||
|
||||
// same contents never create a face
|
||||
if (fcon == bcon)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
int c_glfaces;
|
||||
|
||||
int PortalVisibleSides (portal_t *p)
|
||||
{
|
||||
int fcon, bcon;
|
||||
|
||||
if (!p->onnode)
|
||||
return 0; // outside
|
||||
|
||||
fcon = p->nodes[0]->opaque;
|
||||
bcon = p->nodes[1]->opaque;
|
||||
|
||||
// same contents never create a face
|
||||
if (fcon == bcon)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
158
q3map/leakfile.c
Normal file → Executable file
158
q3map/leakfile.c
Normal file → Executable file
|
@ -19,82 +19,82 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
LEAF FILE GENERATION
|
||||
|
||||
Save out name.line for qe3 to read
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
LeakFile
|
||||
|
||||
Finds the shortest possible chain of portals
|
||||
that leads from the outside leaf to a specifically
|
||||
occupied leaf
|
||||
=============
|
||||
*/
|
||||
void LeakFile (tree_t *tree)
|
||||
{
|
||||
vec3_t mid;
|
||||
FILE *linefile;
|
||||
char filename[1024];
|
||||
node_t *node;
|
||||
int count;
|
||||
|
||||
if (!tree->outside_node.occupied)
|
||||
return;
|
||||
|
||||
qprintf ("--- LeakFile ---\n");
|
||||
|
||||
//
|
||||
// write the points to the file
|
||||
//
|
||||
sprintf (filename, "%s.lin", source);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
4256
q3map/light.c
Normal file → Executable file
4256
q3map/light.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
260
q3map/light.h
Normal file → Executable file
260
q3map/light.h
Normal file → Executable file
|
@ -19,133 +19,133 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
#include "polylib.h"
|
||||
#include "imagelib.h"
|
||||
#include "threads.h"
|
||||
#include "scriplib.h"
|
||||
|
||||
#include "shaders.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
emit_point,
|
||||
emit_area,
|
||||
emit_spotlight,
|
||||
emit_sun
|
||||
} emittype_t;
|
||||
|
||||
#define MAX_LIGHT_EDGES 8
|
||||
typedef struct light_s
|
||||
{
|
||||
struct light_s *next;
|
||||
emittype_t type;
|
||||
struct shaderInfo_s *si;
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t normal; // for surfaces, spotlights, and suns
|
||||
float dist; // plane location along normal
|
||||
|
||||
qboolean linearLight;
|
||||
int photons;
|
||||
int style;
|
||||
vec3_t color;
|
||||
float radiusByDist; // for spotlights
|
||||
|
||||
qboolean twosided; // fog lights both sides
|
||||
|
||||
winding_t *w;
|
||||
vec3_t emitColor; // full out-of-gamut value
|
||||
} light_t;
|
||||
|
||||
|
||||
extern float lightscale;
|
||||
extern float ambient;
|
||||
extern float maxlight;
|
||||
extern float direct_scale;
|
||||
extern float entity_scale;
|
||||
|
||||
extern qboolean noSurfaces;
|
||||
|
||||
//===============================================================
|
||||
|
||||
// light_trace.c
|
||||
|
||||
// a facet is a subdivided element of a patch aproximation or model
|
||||
typedef struct cFacet_s {
|
||||
float surface[4];
|
||||
int numBoundaries; // either 3 or 4, anything less is degenerate
|
||||
float boundaries[4][4]; // positive is outside the bounds
|
||||
|
||||
vec3_t points[4]; // needed for area light subdivision
|
||||
|
||||
float textureMatrix[2][4]; // compute texture coordinates at point of impact for translucency
|
||||
} cFacet_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t mins, maxs;
|
||||
vec3_t origin;
|
||||
float radius;
|
||||
|
||||
qboolean patch;
|
||||
|
||||
int numFacets;
|
||||
cFacet_t *facets;
|
||||
|
||||
shaderInfo_t *shader; // for translucency
|
||||
} surfaceTest_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
vec3_t filter; // starts out 1.0, 1.0, 1.0, may be reduced if
|
||||
// transparent surfaces are crossed
|
||||
|
||||
vec3_t hit; // the impact point of a completely opaque surface
|
||||
float hitFraction; // 0 = at start, 1.0 = at end
|
||||
qboolean passSolid;
|
||||
} trace_t;
|
||||
|
||||
extern surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS];
|
||||
|
||||
void InitTrace( void );
|
||||
|
||||
// traceWork_t is only a parameter to crutch up poor large local allocations on
|
||||
// winNT and macOS. It should be allocated in the worker function, but never
|
||||
// looked at.
|
||||
typedef struct {
|
||||
vec3_t start, end;
|
||||
int numOpenLeafs;
|
||||
int openLeafNumbers[MAX_MAP_LEAFS];
|
||||
trace_t *trace;
|
||||
int patchshadows;
|
||||
} traceWork_t;
|
||||
|
||||
void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace,
|
||||
qboolean testAll, traceWork_t *tw );
|
||||
qboolean PointInSolid( vec3_t start );
|
||||
|
||||
//===============================================================
|
||||
|
||||
//===============================================================
|
||||
|
||||
|
||||
typedef struct {
|
||||
int textureNum;
|
||||
int x, y, width, height;
|
||||
|
||||
// for patches
|
||||
qboolean patch;
|
||||
mesh_t mesh;
|
||||
|
||||
// for faces
|
||||
vec3_t origin;
|
||||
vec3_t vecs[3];
|
||||
} lightmap_t;
|
||||
|
||||
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
#include "polylib.h"
|
||||
#include "imagelib.h"
|
||||
#include "threads.h"
|
||||
#include "scriplib.h"
|
||||
|
||||
#include "shaders.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
emit_point,
|
||||
emit_area,
|
||||
emit_spotlight,
|
||||
emit_sun
|
||||
} emittype_t;
|
||||
|
||||
#define MAX_LIGHT_EDGES 8
|
||||
typedef struct light_s
|
||||
{
|
||||
struct light_s *next;
|
||||
emittype_t type;
|
||||
struct shaderInfo_s *si;
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t normal; // for surfaces, spotlights, and suns
|
||||
float dist; // plane location along normal
|
||||
|
||||
qboolean linearLight;
|
||||
int photons;
|
||||
int style;
|
||||
vec3_t color;
|
||||
float radiusByDist; // for spotlights
|
||||
|
||||
qboolean twosided; // fog lights both sides
|
||||
|
||||
winding_t *w;
|
||||
vec3_t emitColor; // full out-of-gamut value
|
||||
} light_t;
|
||||
|
||||
|
||||
extern float lightscale;
|
||||
extern float ambient;
|
||||
extern float maxlight;
|
||||
extern float direct_scale;
|
||||
extern float entity_scale;
|
||||
|
||||
extern qboolean noSurfaces;
|
||||
|
||||
//===============================================================
|
||||
|
||||
// light_trace.c
|
||||
|
||||
// a facet is a subdivided element of a patch aproximation or model
|
||||
typedef struct cFacet_s {
|
||||
float surface[4];
|
||||
int numBoundaries; // either 3 or 4, anything less is degenerate
|
||||
float boundaries[4][4]; // positive is outside the bounds
|
||||
|
||||
vec3_t points[4]; // needed for area light subdivision
|
||||
|
||||
float textureMatrix[2][4]; // compute texture coordinates at point of impact for translucency
|
||||
} cFacet_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t mins, maxs;
|
||||
vec3_t origin;
|
||||
float radius;
|
||||
|
||||
qboolean patch;
|
||||
|
||||
int numFacets;
|
||||
cFacet_t *facets;
|
||||
|
||||
shaderInfo_t *shader; // for translucency
|
||||
} surfaceTest_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
vec3_t filter; // starts out 1.0, 1.0, 1.0, may be reduced if
|
||||
// transparent surfaces are crossed
|
||||
|
||||
vec3_t hit; // the impact point of a completely opaque surface
|
||||
float hitFraction; // 0 = at start, 1.0 = at end
|
||||
qboolean passSolid;
|
||||
} trace_t;
|
||||
|
||||
extern surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS];
|
||||
|
||||
void InitTrace( void );
|
||||
|
||||
// traceWork_t is only a parameter to crutch up poor large local allocations on
|
||||
// winNT and macOS. It should be allocated in the worker function, but never
|
||||
// looked at.
|
||||
typedef struct {
|
||||
vec3_t start, end;
|
||||
int numOpenLeafs;
|
||||
int openLeafNumbers[MAX_MAP_LEAFS];
|
||||
trace_t *trace;
|
||||
int patchshadows;
|
||||
} traceWork_t;
|
||||
|
||||
void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace,
|
||||
qboolean testAll, traceWork_t *tw );
|
||||
qboolean PointInSolid( vec3_t start );
|
||||
|
||||
//===============================================================
|
||||
|
||||
//===============================================================
|
||||
|
||||
|
||||
typedef struct {
|
||||
int textureNum;
|
||||
int x, y, width, height;
|
||||
|
||||
// for patches
|
||||
qboolean patch;
|
||||
mesh_t mesh;
|
||||
|
||||
// for faces
|
||||
vec3_t origin;
|
||||
vec3_t vecs[3];
|
||||
} lightmap_t;
|
||||
|
||||
|
||||
|
|
1846
q3map/light_trace.c
Normal file → Executable file
1846
q3map/light_trace.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
748
q3map/lightmaps.c
Normal file → Executable file
748
q3map/lightmaps.c
Normal file → Executable file
|
@ -19,377 +19,377 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Lightmap allocation has to be done after all flood filling and
|
||||
visible surface determination.
|
||||
|
||||
*/
|
||||
|
||||
int numSortShaders;
|
||||
mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS];
|
||||
|
||||
|
||||
int allocated[LIGHTMAP_WIDTH];
|
||||
|
||||
int numLightmaps = 1;
|
||||
int c_exactLightmap;
|
||||
|
||||
|
||||
void PrepareNewLightmap( void ) {
|
||||
memset( allocated, 0, sizeof( allocated ) );
|
||||
numLightmaps++;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
AllocLMBlock
|
||||
|
||||
returns a texture number and the position inside it
|
||||
===============
|
||||
*/
|
||||
qboolean AllocLMBlock (int w, int h, int *x, int *y)
|
||||
{
|
||||
int i, j;
|
||||
int best, best2;
|
||||
|
||||
best = LIGHTMAP_HEIGHT;
|
||||
|
||||
for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
|
||||
best2 = 0;
|
||||
|
||||
for (j=0 ; j<w ; j++) {
|
||||
if (allocated[i+j] >= best) {
|
||||
break;
|
||||
}
|
||||
if (allocated[i+j] > best2) {
|
||||
best2 = allocated[i+j];
|
||||
}
|
||||
}
|
||||
if (j == w) { // this is a valid spot
|
||||
*x = i;
|
||||
*y = best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
if (best + h > LIGHTMAP_HEIGHT) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
for (i=0 ; i<w ; i++) {
|
||||
allocated[*x + i] = best + h;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmapForPatch
|
||||
===================
|
||||
*/
|
||||
//#define LIGHTMAP_PATCHSHIFT
|
||||
|
||||
void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
|
||||
int i, j, k;
|
||||
drawVert_t *verts;
|
||||
int w, h;
|
||||
int x, y;
|
||||
float s, t;
|
||||
mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh;
|
||||
int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
|
||||
|
||||
verts = ds->verts;
|
||||
|
||||
mesh.width = ds->patchWidth;
|
||||
mesh.height = ds->patchHeight;
|
||||
mesh.verts = verts;
|
||||
newmesh = SubdivideMesh( mesh, 8, 999 );
|
||||
|
||||
PutMeshOnCurve( *newmesh );
|
||||
tempMesh = RemoveLinearMeshColumnsRows( newmesh );
|
||||
FreeMesh(newmesh);
|
||||
|
||||
ssize = samplesize;
|
||||
if (ds->shaderInfo->lightmapSampleSize)
|
||||
ssize = ds->shaderInfo->lightmapSampleSize;
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
|
||||
#else
|
||||
subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
|
||||
#endif
|
||||
|
||||
w = subdividedMesh->width;
|
||||
h = subdividedMesh->height;
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
w++;
|
||||
h++;
|
||||
#endif
|
||||
|
||||
FreeMesh(subdividedMesh);
|
||||
|
||||
// allocate the lightmap
|
||||
c_exactLightmap += w * h;
|
||||
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
PrepareNewLightmap();
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
Error("Entity %i, brush %i: Lightmap allocation failed",
|
||||
ds->mapBrush->entitynum, ds->mapBrush->brushnum );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
w--;
|
||||
h--;
|
||||
#endif
|
||||
|
||||
// set the lightmap texture coordinates in the drawVerts
|
||||
ds->lightmapNum = numLightmaps - 1;
|
||||
ds->lightmapWidth = w;
|
||||
ds->lightmapHeight = h;
|
||||
ds->lightmapX = x;
|
||||
ds->lightmapY = y;
|
||||
|
||||
for ( i = 0 ; i < ds->patchWidth ; i++ ) {
|
||||
for ( k = 0 ; k < w ; k++ ) {
|
||||
if ( originalWidths[k] >= i ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k >= w)
|
||||
k = w-1;
|
||||
s = x + k;
|
||||
for ( j = 0 ; j < ds->patchHeight ; j++ ) {
|
||||
for ( k = 0 ; k < h ; k++ ) {
|
||||
if ( originalHeights[k] >= j ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k >= h)
|
||||
k = h-1;
|
||||
t = y + k;
|
||||
verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
|
||||
verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmapForSurface
|
||||
===================
|
||||
*/
|
||||
//#define LIGHTMAP_BLOCK 16
|
||||
void AllocateLightmapForSurface( mapDrawSurface_t *ds ) {
|
||||
vec3_t mins, maxs, size, exactSize, delta;
|
||||
int i;
|
||||
drawVert_t *verts;
|
||||
int w, h;
|
||||
int x, y, ssize;
|
||||
int axis;
|
||||
vec3_t vecs[2];
|
||||
float s, t;
|
||||
vec3_t origin;
|
||||
plane_t *plane;
|
||||
float d;
|
||||
vec3_t planeNormal;
|
||||
|
||||
if ( ds->patch ) {
|
||||
AllocateLightmapForPatch( ds );
|
||||
return;
|
||||
}
|
||||
|
||||
ssize = samplesize;
|
||||
if (ds->shaderInfo->lightmapSampleSize)
|
||||
ssize = ds->shaderInfo->lightmapSampleSize;
|
||||
|
||||
plane = &mapplanes[ ds->side->planenum ];
|
||||
|
||||
// bound the surface
|
||||
ClearBounds( mins, maxs );
|
||||
verts = ds->verts;
|
||||
for ( i = 0 ; i < ds->numVerts ; i++ ) {
|
||||
AddPointToBounds( verts[i].xyz, mins, maxs );
|
||||
}
|
||||
|
||||
// round to the lightmap resolution
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
exactSize[i] = maxs[i] - mins[i];
|
||||
mins[i] = ssize * floor( mins[i] / ssize );
|
||||
maxs[i] = ssize * ceil( maxs[i] / ssize );
|
||||
size[i] = (maxs[i] - mins[i]) / ssize + 1;
|
||||
}
|
||||
|
||||
// the two largest axis will be the lightmap size
|
||||
memset( vecs, 0, sizeof( vecs ) );
|
||||
|
||||
planeNormal[0] = fabs( plane->normal[0] );
|
||||
planeNormal[1] = fabs( plane->normal[1] );
|
||||
planeNormal[2] = fabs( plane->normal[2] );
|
||||
|
||||
if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
|
||||
w = size[1];
|
||||
h = size[2];
|
||||
axis = 0;
|
||||
vecs[0][1] = 1.0 / ssize;
|
||||
vecs[1][2] = 1.0 / ssize;
|
||||
} else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
|
||||
w = size[0];
|
||||
h = size[2];
|
||||
axis = 1;
|
||||
vecs[0][0] = 1.0 / ssize;
|
||||
vecs[1][2] = 1.0 / ssize;
|
||||
} else {
|
||||
w = size[0];
|
||||
h = size[1];
|
||||
axis = 2;
|
||||
vecs[0][0] = 1.0 / ssize;
|
||||
vecs[1][1] = 1.0 / ssize;
|
||||
}
|
||||
|
||||
if ( !plane->normal[axis] ) {
|
||||
Error( "Chose a 0 valued axis" );
|
||||
}
|
||||
|
||||
if ( w > LIGHTMAP_WIDTH ) {
|
||||
VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] );
|
||||
w = LIGHTMAP_WIDTH;
|
||||
}
|
||||
|
||||
if ( h > LIGHTMAP_HEIGHT ) {
|
||||
VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] );
|
||||
h = LIGHTMAP_HEIGHT;
|
||||
}
|
||||
|
||||
c_exactLightmap += w * h;
|
||||
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
PrepareNewLightmap();
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
Error("Entity %i, brush %i: Lightmap allocation failed",
|
||||
ds->mapBrush->entitynum, ds->mapBrush->brushnum );
|
||||
}
|
||||
}
|
||||
|
||||
// set the lightmap texture coordinates in the drawVerts
|
||||
ds->lightmapNum = numLightmaps - 1;
|
||||
ds->lightmapWidth = w;
|
||||
ds->lightmapHeight = h;
|
||||
ds->lightmapX = x;
|
||||
ds->lightmapY = y;
|
||||
|
||||
for ( i = 0 ; i < ds->numVerts ; i++ ) {
|
||||
VectorSubtract( verts[i].xyz, mins, delta );
|
||||
s = DotProduct( delta, vecs[0] ) + x + 0.5;
|
||||
t = DotProduct( delta, vecs[1] ) + y + 0.5;
|
||||
verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
|
||||
verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
|
||||
}
|
||||
|
||||
// calculate the world coordinates of the lightmap samples
|
||||
|
||||
// project mins onto plane to get origin
|
||||
d = DotProduct( mins, plane->normal ) - plane->dist;
|
||||
d /= plane->normal[ axis ];
|
||||
VectorCopy( mins, origin );
|
||||
origin[axis] -= d;
|
||||
|
||||
// project stepped lightmap blocks and subtract to get planevecs
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
vec3_t normalized;
|
||||
float len;
|
||||
|
||||
len = VectorNormalize( vecs[i], normalized );
|
||||
VectorScale( normalized, (1.0/len), vecs[i] );
|
||||
d = DotProduct( vecs[i], plane->normal );
|
||||
d /= plane->normal[ axis ];
|
||||
vecs[i][axis] -= d;
|
||||
}
|
||||
|
||||
VectorCopy( origin, ds->lightmapOrigin );
|
||||
VectorCopy( vecs[0], ds->lightmapVecs[0] );
|
||||
VectorCopy( vecs[1], ds->lightmapVecs[1] );
|
||||
VectorCopy( plane->normal, ds->lightmapVecs[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmaps
|
||||
===================
|
||||
*/
|
||||
void AllocateLightmaps( entity_t *e ) {
|
||||
int i, j;
|
||||
mapDrawSurface_t *ds;
|
||||
shaderInfo_t *si;
|
||||
|
||||
qprintf ("--- AllocateLightmaps ---\n");
|
||||
|
||||
|
||||
// sort all surfaces by shader so common shaders will usually
|
||||
// be in the same lightmap
|
||||
numSortShaders = 0;
|
||||
|
||||
for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
|
||||
ds = &mapDrawSurfs[i];
|
||||
if ( !ds->numVerts ) {
|
||||
continue; // leftover from a surface subdivision
|
||||
}
|
||||
if ( ds->miscModel ) {
|
||||
continue;
|
||||
}
|
||||
if ( !ds->patch ) {
|
||||
VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] );
|
||||
}
|
||||
|
||||
// search for this shader
|
||||
for ( j = 0 ; j < numSortShaders ; j++ ) {
|
||||
if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) {
|
||||
ds->nextOnShader = surfsOnShader[j];
|
||||
surfsOnShader[j] = ds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == numSortShaders ) {
|
||||
if ( numSortShaders >= MAX_MAP_SHADERS ) {
|
||||
Error( "MAX_MAP_SHADERS" );
|
||||
}
|
||||
surfsOnShader[j] = ds;
|
||||
numSortShaders++;
|
||||
}
|
||||
}
|
||||
qprintf( "%5i unique shaders\n", numSortShaders );
|
||||
|
||||
// for each shader, allocate lightmaps for each surface
|
||||
|
||||
// numLightmaps = 0;
|
||||
// PrepareNewLightmap();
|
||||
|
||||
for ( i = 0 ; i < numSortShaders ; i++ ) {
|
||||
si = surfsOnShader[i]->shaderInfo;
|
||||
|
||||
for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) {
|
||||
// some surfaces don't need lightmaps allocated for them
|
||||
if ( si->surfaceFlags & SURF_NOLIGHTMAP ) {
|
||||
ds->lightmapNum = -1;
|
||||
} else if ( si->surfaceFlags & SURF_POINTLIGHT ) {
|
||||
ds->lightmapNum = -3;
|
||||
} else {
|
||||
AllocateLightmapForSurface( ds );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qprintf( "%7i exact lightmap texels\n", c_exactLightmap );
|
||||
qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Lightmap allocation has to be done after all flood filling and
|
||||
visible surface determination.
|
||||
|
||||
*/
|
||||
|
||||
int numSortShaders;
|
||||
mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS];
|
||||
|
||||
|
||||
int allocated[LIGHTMAP_WIDTH];
|
||||
|
||||
int numLightmaps = 1;
|
||||
int c_exactLightmap;
|
||||
|
||||
|
||||
void PrepareNewLightmap( void ) {
|
||||
memset( allocated, 0, sizeof( allocated ) );
|
||||
numLightmaps++;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
AllocLMBlock
|
||||
|
||||
returns a texture number and the position inside it
|
||||
===============
|
||||
*/
|
||||
qboolean AllocLMBlock (int w, int h, int *x, int *y)
|
||||
{
|
||||
int i, j;
|
||||
int best, best2;
|
||||
|
||||
best = LIGHTMAP_HEIGHT;
|
||||
|
||||
for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
|
||||
best2 = 0;
|
||||
|
||||
for (j=0 ; j<w ; j++) {
|
||||
if (allocated[i+j] >= best) {
|
||||
break;
|
||||
}
|
||||
if (allocated[i+j] > best2) {
|
||||
best2 = allocated[i+j];
|
||||
}
|
||||
}
|
||||
if (j == w) { // this is a valid spot
|
||||
*x = i;
|
||||
*y = best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
if (best + h > LIGHTMAP_HEIGHT) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
for (i=0 ; i<w ; i++) {
|
||||
allocated[*x + i] = best + h;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmapForPatch
|
||||
===================
|
||||
*/
|
||||
//#define LIGHTMAP_PATCHSHIFT
|
||||
|
||||
void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
|
||||
int i, j, k;
|
||||
drawVert_t *verts;
|
||||
int w, h;
|
||||
int x, y;
|
||||
float s, t;
|
||||
mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh;
|
||||
int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
|
||||
|
||||
verts = ds->verts;
|
||||
|
||||
mesh.width = ds->patchWidth;
|
||||
mesh.height = ds->patchHeight;
|
||||
mesh.verts = verts;
|
||||
newmesh = SubdivideMesh( mesh, 8, 999 );
|
||||
|
||||
PutMeshOnCurve( *newmesh );
|
||||
tempMesh = RemoveLinearMeshColumnsRows( newmesh );
|
||||
FreeMesh(newmesh);
|
||||
|
||||
ssize = samplesize;
|
||||
if (ds->shaderInfo->lightmapSampleSize)
|
||||
ssize = ds->shaderInfo->lightmapSampleSize;
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
|
||||
#else
|
||||
subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
|
||||
#endif
|
||||
|
||||
w = subdividedMesh->width;
|
||||
h = subdividedMesh->height;
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
w++;
|
||||
h++;
|
||||
#endif
|
||||
|
||||
FreeMesh(subdividedMesh);
|
||||
|
||||
// allocate the lightmap
|
||||
c_exactLightmap += w * h;
|
||||
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
PrepareNewLightmap();
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
Error("Entity %i, brush %i: Lightmap allocation failed",
|
||||
ds->mapBrush->entitynum, ds->mapBrush->brushnum );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIGHTMAP_PATCHSHIFT
|
||||
w--;
|
||||
h--;
|
||||
#endif
|
||||
|
||||
// set the lightmap texture coordinates in the drawVerts
|
||||
ds->lightmapNum = numLightmaps - 1;
|
||||
ds->lightmapWidth = w;
|
||||
ds->lightmapHeight = h;
|
||||
ds->lightmapX = x;
|
||||
ds->lightmapY = y;
|
||||
|
||||
for ( i = 0 ; i < ds->patchWidth ; i++ ) {
|
||||
for ( k = 0 ; k < w ; k++ ) {
|
||||
if ( originalWidths[k] >= i ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k >= w)
|
||||
k = w-1;
|
||||
s = x + k;
|
||||
for ( j = 0 ; j < ds->patchHeight ; j++ ) {
|
||||
for ( k = 0 ; k < h ; k++ ) {
|
||||
if ( originalHeights[k] >= j ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k >= h)
|
||||
k = h-1;
|
||||
t = y + k;
|
||||
verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
|
||||
verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmapForSurface
|
||||
===================
|
||||
*/
|
||||
//#define LIGHTMAP_BLOCK 16
|
||||
void AllocateLightmapForSurface( mapDrawSurface_t *ds ) {
|
||||
vec3_t mins, maxs, size, exactSize, delta;
|
||||
int i;
|
||||
drawVert_t *verts;
|
||||
int w, h;
|
||||
int x, y, ssize;
|
||||
int axis;
|
||||
vec3_t vecs[2];
|
||||
float s, t;
|
||||
vec3_t origin;
|
||||
plane_t *plane;
|
||||
float d;
|
||||
vec3_t planeNormal;
|
||||
|
||||
if ( ds->patch ) {
|
||||
AllocateLightmapForPatch( ds );
|
||||
return;
|
||||
}
|
||||
|
||||
ssize = samplesize;
|
||||
if (ds->shaderInfo->lightmapSampleSize)
|
||||
ssize = ds->shaderInfo->lightmapSampleSize;
|
||||
|
||||
plane = &mapplanes[ ds->side->planenum ];
|
||||
|
||||
// bound the surface
|
||||
ClearBounds( mins, maxs );
|
||||
verts = ds->verts;
|
||||
for ( i = 0 ; i < ds->numVerts ; i++ ) {
|
||||
AddPointToBounds( verts[i].xyz, mins, maxs );
|
||||
}
|
||||
|
||||
// round to the lightmap resolution
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
exactSize[i] = maxs[i] - mins[i];
|
||||
mins[i] = ssize * floor( mins[i] / ssize );
|
||||
maxs[i] = ssize * ceil( maxs[i] / ssize );
|
||||
size[i] = (maxs[i] - mins[i]) / ssize + 1;
|
||||
}
|
||||
|
||||
// the two largest axis will be the lightmap size
|
||||
memset( vecs, 0, sizeof( vecs ) );
|
||||
|
||||
planeNormal[0] = fabs( plane->normal[0] );
|
||||
planeNormal[1] = fabs( plane->normal[1] );
|
||||
planeNormal[2] = fabs( plane->normal[2] );
|
||||
|
||||
if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
|
||||
w = size[1];
|
||||
h = size[2];
|
||||
axis = 0;
|
||||
vecs[0][1] = 1.0 / ssize;
|
||||
vecs[1][2] = 1.0 / ssize;
|
||||
} else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
|
||||
w = size[0];
|
||||
h = size[2];
|
||||
axis = 1;
|
||||
vecs[0][0] = 1.0 / ssize;
|
||||
vecs[1][2] = 1.0 / ssize;
|
||||
} else {
|
||||
w = size[0];
|
||||
h = size[1];
|
||||
axis = 2;
|
||||
vecs[0][0] = 1.0 / ssize;
|
||||
vecs[1][1] = 1.0 / ssize;
|
||||
}
|
||||
|
||||
if ( !plane->normal[axis] ) {
|
||||
Error( "Chose a 0 valued axis" );
|
||||
}
|
||||
|
||||
if ( w > LIGHTMAP_WIDTH ) {
|
||||
VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] );
|
||||
w = LIGHTMAP_WIDTH;
|
||||
}
|
||||
|
||||
if ( h > LIGHTMAP_HEIGHT ) {
|
||||
VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] );
|
||||
h = LIGHTMAP_HEIGHT;
|
||||
}
|
||||
|
||||
c_exactLightmap += w * h;
|
||||
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
PrepareNewLightmap();
|
||||
if ( !AllocLMBlock( w, h, &x, &y ) ) {
|
||||
Error("Entity %i, brush %i: Lightmap allocation failed",
|
||||
ds->mapBrush->entitynum, ds->mapBrush->brushnum );
|
||||
}
|
||||
}
|
||||
|
||||
// set the lightmap texture coordinates in the drawVerts
|
||||
ds->lightmapNum = numLightmaps - 1;
|
||||
ds->lightmapWidth = w;
|
||||
ds->lightmapHeight = h;
|
||||
ds->lightmapX = x;
|
||||
ds->lightmapY = y;
|
||||
|
||||
for ( i = 0 ; i < ds->numVerts ; i++ ) {
|
||||
VectorSubtract( verts[i].xyz, mins, delta );
|
||||
s = DotProduct( delta, vecs[0] ) + x + 0.5;
|
||||
t = DotProduct( delta, vecs[1] ) + y + 0.5;
|
||||
verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
|
||||
verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
|
||||
}
|
||||
|
||||
// calculate the world coordinates of the lightmap samples
|
||||
|
||||
// project mins onto plane to get origin
|
||||
d = DotProduct( mins, plane->normal ) - plane->dist;
|
||||
d /= plane->normal[ axis ];
|
||||
VectorCopy( mins, origin );
|
||||
origin[axis] -= d;
|
||||
|
||||
// project stepped lightmap blocks and subtract to get planevecs
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
vec3_t normalized;
|
||||
float len;
|
||||
|
||||
len = VectorNormalize( vecs[i], normalized );
|
||||
VectorScale( normalized, (1.0/len), vecs[i] );
|
||||
d = DotProduct( vecs[i], plane->normal );
|
||||
d /= plane->normal[ axis ];
|
||||
vecs[i][axis] -= d;
|
||||
}
|
||||
|
||||
VectorCopy( origin, ds->lightmapOrigin );
|
||||
VectorCopy( vecs[0], ds->lightmapVecs[0] );
|
||||
VectorCopy( vecs[1], ds->lightmapVecs[1] );
|
||||
VectorCopy( plane->normal, ds->lightmapVecs[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
AllocateLightmaps
|
||||
===================
|
||||
*/
|
||||
void AllocateLightmaps( entity_t *e ) {
|
||||
int i, j;
|
||||
mapDrawSurface_t *ds;
|
||||
shaderInfo_t *si;
|
||||
|
||||
qprintf ("--- AllocateLightmaps ---\n");
|
||||
|
||||
|
||||
// sort all surfaces by shader so common shaders will usually
|
||||
// be in the same lightmap
|
||||
numSortShaders = 0;
|
||||
|
||||
for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
|
||||
ds = &mapDrawSurfs[i];
|
||||
if ( !ds->numVerts ) {
|
||||
continue; // leftover from a surface subdivision
|
||||
}
|
||||
if ( ds->miscModel ) {
|
||||
continue;
|
||||
}
|
||||
if ( !ds->patch ) {
|
||||
VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] );
|
||||
}
|
||||
|
||||
// search for this shader
|
||||
for ( j = 0 ; j < numSortShaders ; j++ ) {
|
||||
if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) {
|
||||
ds->nextOnShader = surfsOnShader[j];
|
||||
surfsOnShader[j] = ds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == numSortShaders ) {
|
||||
if ( numSortShaders >= MAX_MAP_SHADERS ) {
|
||||
Error( "MAX_MAP_SHADERS" );
|
||||
}
|
||||
surfsOnShader[j] = ds;
|
||||
numSortShaders++;
|
||||
}
|
||||
}
|
||||
qprintf( "%5i unique shaders\n", numSortShaders );
|
||||
|
||||
// for each shader, allocate lightmaps for each surface
|
||||
|
||||
// numLightmaps = 0;
|
||||
// PrepareNewLightmap();
|
||||
|
||||
for ( i = 0 ; i < numSortShaders ; i++ ) {
|
||||
si = surfsOnShader[i]->shaderInfo;
|
||||
|
||||
for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) {
|
||||
// some surfaces don't need lightmaps allocated for them
|
||||
if ( si->surfaceFlags & SURF_NOLIGHTMAP ) {
|
||||
ds->lightmapNum = -1;
|
||||
} else if ( si->surfaceFlags & SURF_POINTLIGHT ) {
|
||||
ds->lightmapNum = -3;
|
||||
} else {
|
||||
AllocateLightmapForSurface( ds );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qprintf( "%7i exact lightmap texels\n", c_exactLightmap );
|
||||
qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
11452
q3map/lightv.c
Normal file → Executable file
11452
q3map/lightv.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
296
q3map/makefile
Normal file → Executable file
296
q3map/makefile
Normal file → Executable file
|
@ -1,148 +1,148 @@
|
|||
|
||||
CFLAGS = -c
|
||||
LDFLAGS =
|
||||
ODIR = /q3/q3map
|
||||
|
||||
EXEBASE = q3map
|
||||
EXE = $(ODIR)/$(EXEBASE)
|
||||
all: $(EXE)
|
||||
|
||||
_irix:
|
||||
make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../common -Xcpluscomm " "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3 -g"
|
||||
|
||||
_irixdebug:
|
||||
make "CFLAGS = -c -O2 -g -I../common -Xcpluscomm" "LDFLAGS = -g"
|
||||
|
||||
_irixinst:
|
||||
make "_irix"
|
||||
make "install"
|
||||
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o $(EXE)
|
||||
|
||||
install:
|
||||
cp $(EXE) /quake3_bin
|
||||
chmod 0777 /quake3_bin/$(EXEBASE)
|
||||
|
||||
installtest:
|
||||
cp $(EXE) /quake3_bin/$(EXEBASE)_test
|
||||
chmod 0777 /quake3_bin/$(EXEBASE)_test
|
||||
|
||||
|
||||
FILES = $(ODIR)/fog.o $(ODIR)/brush.o $(ODIR)/tjunction.o $(ODIR)/vis.o $(ODIR)/visflow.o \
|
||||
$(ODIR)/light.o $(ODIR)/lightmaps.o $(ODIR)/bspfile.o \
|
||||
$(ODIR)/cmdlib.o $(ODIR)/patch.o $(ODIR)/mesh.o $(ODIR)/nodraw.o $(ODIR)/glfile.o \
|
||||
$(ODIR)/leakfile.o $(ODIR)/map.o $(ODIR)/mathlib.o $(ODIR)/polylib.o $(ODIR)/aselib.o \
|
||||
$(ODIR)/imagelib.o $(ODIR)/portals.o $(ODIR)/prtfile.o $(ODIR)/bsp.o $(ODIR)/surface.o \
|
||||
$(ODIR)/scriplib.o $(ODIR)/shaders.o $(ODIR)/threads.o $(ODIR)/tree.o \
|
||||
$(ODIR)/writebsp.o $(ODIR)/facebsp.o $(ODIR)/misc_model.o $(ODIR)/light_trace.o
|
||||
|
||||
$(EXE) : $(FILES)
|
||||
cc -o $(EXE) $(LDFLAGS) $(FILES) -lm
|
||||
|
||||
$(ODIR)/surface.o : surface.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/fog.o : fog.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/brush.o : brush.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/tjunction.o : tjunction.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/lightmaps.o : lightmaps.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/brushbsp.o : brushbsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/facebsp.o : facebsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/patch.o : patch.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/mesh.o : mesh.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/misc_model.o : misc_model.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/nodraw.o : nodraw.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/glfile.o : glfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/leakfile.o : leakfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/map.o : map.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/portals.o : portals.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/prtfile.o : prtfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/bsp.o : bsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/tree.o : tree.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/shaders.o : shaders.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/writebsp.o : writebsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/csg.o : csg.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
$(ODIR)/vis.o : vis.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/visflow.o : visflow.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
$(ODIR)/light.o : light.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/light_trace.o : light_trace.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
$(ODIR)/cmdlib.o : ../common/cmdlib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/mathlib.o : ../common/mathlib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/polylib.o : ../common/polylib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/aselib.o : ../common/aselib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/imagelib.o : ../common/imagelib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/scriplib.o : ../common/scriplib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/threads.o : ../common/threads.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/bspfile.o : ../common/bspfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
|
||||
CFLAGS = -c
|
||||
LDFLAGS =
|
||||
ODIR = /q3/q3map
|
||||
|
||||
EXEBASE = q3map
|
||||
EXE = $(ODIR)/$(EXEBASE)
|
||||
all: $(EXE)
|
||||
|
||||
_irix:
|
||||
make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../common -Xcpluscomm " "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3 -g"
|
||||
|
||||
_irixdebug:
|
||||
make "CFLAGS = -c -O2 -g -I../common -Xcpluscomm" "LDFLAGS = -g"
|
||||
|
||||
_irixinst:
|
||||
make "_irix"
|
||||
make "install"
|
||||
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o $(EXE)
|
||||
|
||||
install:
|
||||
cp $(EXE) /quake3_bin
|
||||
chmod 0777 /quake3_bin/$(EXEBASE)
|
||||
|
||||
installtest:
|
||||
cp $(EXE) /quake3_bin/$(EXEBASE)_test
|
||||
chmod 0777 /quake3_bin/$(EXEBASE)_test
|
||||
|
||||
|
||||
FILES = $(ODIR)/fog.o $(ODIR)/brush.o $(ODIR)/tjunction.o $(ODIR)/vis.o $(ODIR)/visflow.o \
|
||||
$(ODIR)/light.o $(ODIR)/lightmaps.o $(ODIR)/bspfile.o \
|
||||
$(ODIR)/cmdlib.o $(ODIR)/patch.o $(ODIR)/mesh.o $(ODIR)/nodraw.o $(ODIR)/glfile.o \
|
||||
$(ODIR)/leakfile.o $(ODIR)/map.o $(ODIR)/mathlib.o $(ODIR)/polylib.o $(ODIR)/aselib.o \
|
||||
$(ODIR)/imagelib.o $(ODIR)/portals.o $(ODIR)/prtfile.o $(ODIR)/bsp.o $(ODIR)/surface.o \
|
||||
$(ODIR)/scriplib.o $(ODIR)/shaders.o $(ODIR)/threads.o $(ODIR)/tree.o \
|
||||
$(ODIR)/writebsp.o $(ODIR)/facebsp.o $(ODIR)/misc_model.o $(ODIR)/light_trace.o
|
||||
|
||||
$(EXE) : $(FILES)
|
||||
cc -o $(EXE) $(LDFLAGS) $(FILES) -lm
|
||||
|
||||
$(ODIR)/surface.o : surface.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/fog.o : fog.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/brush.o : brush.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/tjunction.o : tjunction.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/lightmaps.o : lightmaps.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/brushbsp.o : brushbsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/facebsp.o : facebsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/patch.o : patch.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/mesh.o : mesh.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/misc_model.o : misc_model.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/nodraw.o : nodraw.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/glfile.o : glfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/leakfile.o : leakfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/map.o : map.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/portals.o : portals.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/prtfile.o : prtfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/bsp.o : bsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/tree.o : tree.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/shaders.o : shaders.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/writebsp.o : writebsp.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/csg.o : csg.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
$(ODIR)/vis.o : vis.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/visflow.o : visflow.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
$(ODIR)/light.o : light.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/light_trace.o : light_trace.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
$(ODIR)/cmdlib.o : ../common/cmdlib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/mathlib.o : ../common/mathlib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/polylib.o : ../common/polylib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/aselib.o : ../common/aselib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/imagelib.o : ../common/imagelib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/scriplib.o : ../common/scriplib.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/threads.o : ../common/threads.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
$(ODIR)/bspfile.o : ../common/bspfile.c
|
||||
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
|
||||
cc $(CFLAGS) -o $@ /tmp/temp.i
|
||||
|
||||
|
||||
|
|
2460
q3map/map.c
Normal file → Executable file
2460
q3map/map.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1322
q3map/mesh.c
Normal file → Executable file
1322
q3map/mesh.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
54
q3map/mesh.h
Normal file → Executable file
54
q3map/mesh.h
Normal file → Executable file
|
@ -19,30 +19,30 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// mesh.h
|
||||
|
||||
|
||||
typedef struct {
|
||||
int width, height;
|
||||
drawVert_t *verts;
|
||||
} mesh_t;
|
||||
|
||||
#define MAX_EXPANDED_AXIS 128
|
||||
|
||||
extern int originalWidths[MAX_EXPANDED_AXIS];
|
||||
extern int originalHeights[MAX_EXPANDED_AXIS];
|
||||
|
||||
void FreeMesh( mesh_t *m );
|
||||
mesh_t *CopyMesh( mesh_t *mesh );
|
||||
void PrintMesh( mesh_t *m );
|
||||
mesh_t *TransposeMesh( mesh_t *in );
|
||||
void InvertMesh( mesh_t *m );
|
||||
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
|
||||
mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]);
|
||||
mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in );
|
||||
void MakeMeshNormals( mesh_t in );
|
||||
void PutMeshOnCurve( mesh_t in );
|
||||
|
||||
|
||||
void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
|
||||
|
||||
// mesh.h
|
||||
|
||||
|
||||
typedef struct {
|
||||
int width, height;
|
||||
drawVert_t *verts;
|
||||
} mesh_t;
|
||||
|
||||
#define MAX_EXPANDED_AXIS 128
|
||||
|
||||
extern int originalWidths[MAX_EXPANDED_AXIS];
|
||||
extern int originalHeights[MAX_EXPANDED_AXIS];
|
||||
|
||||
void FreeMesh( mesh_t *m );
|
||||
mesh_t *CopyMesh( mesh_t *mesh );
|
||||
void PrintMesh( mesh_t *m );
|
||||
mesh_t *TransposeMesh( mesh_t *in );
|
||||
void InvertMesh( mesh_t *m );
|
||||
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
|
||||
mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]);
|
||||
mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in );
|
||||
void MakeMeshNormals( mesh_t in );
|
||||
void PutMeshOnCurve( mesh_t in );
|
||||
|
||||
|
||||
void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
|
||||
|
|
902
q3map/misc_model.c
Normal file → Executable file
902
q3map/misc_model.c
Normal file → Executable file
|
@ -19,454 +19,454 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
#include "aselib.h"
|
||||
#ifdef _WIN32
|
||||
#ifdef _TTIMOBUILD
|
||||
#include "pakstuff.h"
|
||||
#else
|
||||
#include "../libs/pakstuff.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
char modelName[1024];
|
||||
md3Header_t *header;
|
||||
} loadedModel_t;
|
||||
|
||||
int c_triangleModels;
|
||||
int c_triangleSurfaces;
|
||||
int c_triangleVertexes;
|
||||
int c_triangleIndexes;
|
||||
|
||||
|
||||
#define MAX_LOADED_MODELS 1024
|
||||
loadedModel_t loadedModels[MAX_LOADED_MODELS];
|
||||
int numLoadedModels;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadMD3
|
||||
=================
|
||||
*/
|
||||
#define LL(x) x=LittleLong(x)
|
||||
md3Header_t *R_LoadMD3( const char *mod_name ) {
|
||||
int i, j;
|
||||
md3Header_t *md3;
|
||||
md3Frame_t *frame;
|
||||
md3Surface_t *surf;
|
||||
md3Triangle_t *tri;
|
||||
md3St_t *st;
|
||||
md3XyzNormal_t *xyz;
|
||||
int version;
|
||||
char filename[1024];
|
||||
int len;
|
||||
|
||||
sprintf( filename, "%s%s", gamedir, mod_name );
|
||||
len = TryLoadFile( filename, (void **)&md3 );
|
||||
#ifdef _WIN32
|
||||
if ( len <= 0 ) {
|
||||
len = PakLoadAnyFile(filename, (void **)&md3);
|
||||
}
|
||||
#endif
|
||||
if ( len <= 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
version = LittleLong (md3->version);
|
||||
if (version != MD3_VERSION) {
|
||||
_printf( "R_LoadMD3: %s has wrong version (%i should be %i)\n",
|
||||
mod_name, version, MD3_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LL(md3->ident);
|
||||
LL(md3->version);
|
||||
LL(md3->numFrames);
|
||||
LL(md3->numTags);
|
||||
LL(md3->numSurfaces);
|
||||
LL(md3->numSkins);
|
||||
LL(md3->ofsFrames);
|
||||
LL(md3->ofsTags);
|
||||
LL(md3->ofsSurfaces);
|
||||
LL(md3->ofsEnd);
|
||||
|
||||
if ( md3->numFrames < 1 ) {
|
||||
_printf( "R_LoadMD3: %s has no frames\n", mod_name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// we don't need to swap tags in the renderer, they aren't used
|
||||
|
||||
// swap all the frames
|
||||
frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames );
|
||||
for ( i = 0 ; i < md3->numFrames ; i++, frame++) {
|
||||
frame->radius = LittleFloat( frame->radius );
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
|
||||
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
|
||||
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
|
||||
}
|
||||
}
|
||||
|
||||
// swap all the surfaces
|
||||
surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
|
||||
for ( i = 0 ; i < md3->numSurfaces ; i++) {
|
||||
|
||||
LL(surf->ident);
|
||||
LL(surf->flags);
|
||||
LL(surf->numFrames);
|
||||
LL(surf->numShaders);
|
||||
LL(surf->numTriangles);
|
||||
LL(surf->ofsTriangles);
|
||||
LL(surf->numVerts);
|
||||
LL(surf->ofsShaders);
|
||||
LL(surf->ofsSt);
|
||||
LL(surf->ofsXyzNormals);
|
||||
LL(surf->ofsEnd);
|
||||
|
||||
if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
|
||||
Error ("R_LoadMD3: %s has more than %i verts on a surface (%i)",
|
||||
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
|
||||
}
|
||||
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
|
||||
Error ("R_LoadMD3: %s has more than %i triangles on a surface (%i)",
|
||||
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
|
||||
}
|
||||
|
||||
// swap all the triangles
|
||||
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
|
||||
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
|
||||
LL(tri->indexes[0]);
|
||||
LL(tri->indexes[1]);
|
||||
LL(tri->indexes[2]);
|
||||
}
|
||||
|
||||
// swap all the ST
|
||||
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
|
||||
for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
|
||||
st->st[0] = LittleFloat( st->st[0] );
|
||||
st->st[1] = LittleFloat( st->st[1] );
|
||||
}
|
||||
|
||||
// swap all the XyzNormals
|
||||
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
|
||||
for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
|
||||
{
|
||||
xyz->xyz[0] = LittleShort( xyz->xyz[0] );
|
||||
xyz->xyz[1] = LittleShort( xyz->xyz[1] );
|
||||
xyz->xyz[2] = LittleShort( xyz->xyz[2] );
|
||||
|
||||
xyz->normal = LittleShort( xyz->normal );
|
||||
}
|
||||
|
||||
|
||||
// find the next surface
|
||||
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
|
||||
}
|
||||
|
||||
return md3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
LoadModel
|
||||
================
|
||||
*/
|
||||
md3Header_t *LoadModel( const char *modelName ) {
|
||||
int i;
|
||||
loadedModel_t *lm;
|
||||
|
||||
// see if we already have it loaded
|
||||
for ( i = 0, lm = loadedModels ; i < numLoadedModels ; i++, lm++ ) {
|
||||
if ( !strcmp( modelName, lm->modelName ) ) {
|
||||
return lm->header;
|
||||
}
|
||||
}
|
||||
|
||||
// load it
|
||||
if ( numLoadedModels == MAX_LOADED_MODELS ) {
|
||||
Error( "MAX_LOADED_MODELS" );
|
||||
}
|
||||
numLoadedModels++;
|
||||
|
||||
strcpy( lm->modelName, modelName );
|
||||
|
||||
lm->header = R_LoadMD3( modelName );
|
||||
|
||||
return lm->header;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
InsertMD3Model
|
||||
|
||||
Convert a model entity to raw geometry surfaces and insert it in the tree
|
||||
============
|
||||
*/
|
||||
void InsertMD3Model( const char *modelName, vec3_t origin, float angle, tree_t *tree ) {
|
||||
int i, j;
|
||||
md3Header_t *md3;
|
||||
md3Surface_t *surf;
|
||||
md3Shader_t *shader;
|
||||
md3Triangle_t *tri;
|
||||
md3St_t *st;
|
||||
md3XyzNormal_t *xyz;
|
||||
drawVert_t *outv;
|
||||
float lat, lng;
|
||||
float angleCos, angleSin;
|
||||
mapDrawSurface_t *out;
|
||||
vec3_t temp;
|
||||
|
||||
angle = angle / 180 * Q_PI;
|
||||
angleCos = cos( angle );
|
||||
angleSin = sin( angle );
|
||||
|
||||
// load the model
|
||||
md3 = LoadModel( modelName );
|
||||
if ( !md3 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// each md3 surface will become a new bsp surface
|
||||
|
||||
c_triangleModels++;
|
||||
c_triangleSurfaces += md3->numSurfaces;
|
||||
|
||||
// expand, translate, and rotate the vertexes
|
||||
// swap all the surfaces
|
||||
surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
|
||||
for ( i = 0 ; i < md3->numSurfaces ; i++) {
|
||||
// allocate a surface
|
||||
out = AllocDrawSurf();
|
||||
out->miscModel = qtrue;
|
||||
|
||||
shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
|
||||
|
||||
out->shaderInfo = ShaderInfoForShader( shader->name );
|
||||
|
||||
out->numVerts = surf->numVerts;
|
||||
out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) );
|
||||
|
||||
out->numIndexes = surf->numTriangles * 3;
|
||||
out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) );
|
||||
|
||||
out->lightmapNum = -1;
|
||||
out->fogNum = -1;
|
||||
|
||||
// emit the indexes
|
||||
c_triangleIndexes += surf->numTriangles * 3;
|
||||
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
|
||||
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
|
||||
out->indexes[j*3+0] = tri->indexes[0];
|
||||
out->indexes[j*3+1] = tri->indexes[1];
|
||||
out->indexes[j*3+2] = tri->indexes[2];
|
||||
}
|
||||
|
||||
// emit the vertexes
|
||||
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
|
||||
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
|
||||
|
||||
c_triangleVertexes += surf->numVerts;
|
||||
for ( j = 0 ; j < surf->numVerts ; j++, st++, xyz++ ) {
|
||||
outv = &out->verts[ j ];
|
||||
|
||||
outv->st[0] = st->st[0];
|
||||
outv->st[1] = st->st[1];
|
||||
|
||||
outv->lightmap[0] = 0;
|
||||
outv->lightmap[1] = 0;
|
||||
|
||||
// the colors will be set by the lighting pass
|
||||
outv->color[0] = 255;
|
||||
outv->color[1] = 255;
|
||||
outv->color[2] = 255;
|
||||
outv->color[3] = 255;
|
||||
|
||||
outv->xyz[0] = origin[0] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleCos - xyz->xyz[1] * angleSin );
|
||||
outv->xyz[1] = origin[1] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleSin + xyz->xyz[1] * angleCos );
|
||||
outv->xyz[2] = origin[2] + MD3_XYZ_SCALE * ( xyz->xyz[2] );
|
||||
|
||||
// decode the lat/lng normal to a 3 float normal
|
||||
lat = ( xyz->normal >> 8 ) & 0xff;
|
||||
lng = ( xyz->normal & 0xff );
|
||||
lat *= Q_PI/128;
|
||||
lng *= Q_PI/128;
|
||||
|
||||
temp[0] = cos(lat) * sin(lng);
|
||||
temp[1] = sin(lat) * sin(lng);
|
||||
temp[2] = cos(lng);
|
||||
|
||||
// rotate the normal
|
||||
outv->normal[0] = temp[0] * angleCos - temp[1] * angleSin;
|
||||
outv->normal[1] = temp[0] * angleSin + temp[1] * angleCos;
|
||||
outv->normal[2] = temp[2];
|
||||
}
|
||||
|
||||
// find the next surface
|
||||
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
InsertASEModel
|
||||
|
||||
Convert a model entity to raw geometry surfaces and insert it in the tree
|
||||
============
|
||||
*/
|
||||
void InsertASEModel( const char *modelName, vec3_t origin, float angle, tree_t *tree ) {
|
||||
int i, j;
|
||||
drawVert_t *outv;
|
||||
float angleCos, angleSin;
|
||||
mapDrawSurface_t *out;
|
||||
int numSurfaces;
|
||||
const char *name;
|
||||
polyset_t *pset;
|
||||
int numFrames;
|
||||
char filename[1024];
|
||||
|
||||
sprintf( filename, "%s%s", gamedir, modelName );
|
||||
|
||||
angle = angle / 180 * Q_PI;
|
||||
angleCos = cos( angle );
|
||||
angleSin = sin( angle );
|
||||
|
||||
// load the model
|
||||
ASE_Load( filename, qfalse, qfalse );
|
||||
|
||||
// each ase surface will become a new bsp surface
|
||||
numSurfaces = ASE_GetNumSurfaces();
|
||||
|
||||
c_triangleModels++;
|
||||
c_triangleSurfaces += numSurfaces;
|
||||
|
||||
// expand, translate, and rotate the vertexes
|
||||
// swap all the surfaces
|
||||
for ( i = 0 ; i < numSurfaces ; i++) {
|
||||
name = ASE_GetSurfaceName( i );
|
||||
|
||||
pset = ASE_GetSurfaceAnimation( i, &numFrames, -1, -1, -1 );
|
||||
if ( !name || !pset ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate a surface
|
||||
out = AllocDrawSurf();
|
||||
out->miscModel = qtrue;
|
||||
|
||||
out->shaderInfo = ShaderInfoForShader( pset->materialname );
|
||||
|
||||
out->numVerts = 3 * pset->numtriangles;
|
||||
out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) );
|
||||
|
||||
out->numIndexes = 3 * pset->numtriangles;
|
||||
out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) );
|
||||
|
||||
out->lightmapNum = -1;
|
||||
out->fogNum = -1;
|
||||
|
||||
// emit the indexes
|
||||
c_triangleIndexes += out->numIndexes;
|
||||
for ( j = 0 ; j < out->numIndexes ; j++ ) {
|
||||
out->indexes[j] = j;
|
||||
}
|
||||
|
||||
// emit the vertexes
|
||||
c_triangleVertexes += out->numVerts;
|
||||
for ( j = 0 ; j < out->numVerts ; j++ ) {
|
||||
int index;
|
||||
triangle_t *tri;
|
||||
|
||||
index = j % 3;
|
||||
tri = &pset->triangles[ j / 3 ];
|
||||
|
||||
outv = &out->verts[ j ];
|
||||
|
||||
outv->st[0] = tri->texcoords[index][0];
|
||||
outv->st[1] = tri->texcoords[index][1];
|
||||
|
||||
outv->lightmap[0] = 0;
|
||||
outv->lightmap[1] = 0;
|
||||
|
||||
// the colors will be set by the lighting pass
|
||||
outv->color[0] = 255;
|
||||
outv->color[1] = 255;
|
||||
outv->color[2] = 255;
|
||||
outv->color[3] = 255;
|
||||
|
||||
outv->xyz[0] = origin[0] + tri->verts[index][0];
|
||||
outv->xyz[1] = origin[1] + tri->verts[index][1];
|
||||
outv->xyz[2] = origin[2] + tri->verts[index][2];
|
||||
|
||||
// rotate the normal
|
||||
outv->normal[0] = tri->normals[index][0];
|
||||
outv->normal[1] = tri->normals[index][1];
|
||||
outv->normal[2] = tri->normals[index][2];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
AddTriangleModels
|
||||
=====================
|
||||
*/
|
||||
void AddTriangleModels( tree_t *tree ) {
|
||||
int entity_num;
|
||||
entity_t *entity;
|
||||
|
||||
qprintf("----- AddTriangleModels -----\n");
|
||||
|
||||
for ( entity_num=1 ; entity_num< num_entities ; entity_num++ ) {
|
||||
entity = &entities[entity_num];
|
||||
|
||||
// convert misc_models into raw geometry
|
||||
if ( !Q_stricmp( "misc_model", ValueForKey( entity, "classname" ) ) ) {
|
||||
const char *model;
|
||||
vec3_t origin;
|
||||
float angle;
|
||||
|
||||
// get the angle for rotation FIXME: support full matrix positioning
|
||||
angle = FloatForKey( entity, "angle" );
|
||||
|
||||
GetVectorForKey( entity, "origin", origin );
|
||||
|
||||
model = ValueForKey( entity, "model" );
|
||||
if ( !model[0] ) {
|
||||
_printf("WARNING: misc_model at %i %i %i without a model key\n", (int)origin[0],
|
||||
(int)origin[1], (int)origin[2] );
|
||||
continue;
|
||||
}
|
||||
if ( strstr( model, ".md3" ) || strstr( model, ".MD3" ) ) {
|
||||
InsertMD3Model( model, origin, angle, tree );
|
||||
continue;
|
||||
}
|
||||
if ( strstr( model, ".ase" ) || strstr( model, ".ASE" ) ) {
|
||||
InsertASEModel( model, origin, angle, tree );
|
||||
continue;
|
||||
}
|
||||
_printf( "Unknown misc_model type: %s\n", model );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
qprintf( "%5i triangle models\n", c_triangleModels );
|
||||
qprintf( "%5i triangle surfaces\n", c_triangleSurfaces );
|
||||
qprintf( "%5i triangle vertexes\n", c_triangleVertexes );
|
||||
qprintf( "%5i triangle indexes\n", c_triangleIndexes );
|
||||
}
|
||||
|
||||
|
||||
#include "qbsp.h"
|
||||
#include "aselib.h"
|
||||
#ifdef _WIN32
|
||||
#ifdef _TTIMOBUILD
|
||||
#include "pakstuff.h"
|
||||
#else
|
||||
#include "../libs/pakstuff.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
char modelName[1024];
|
||||
md3Header_t *header;
|
||||
} loadedModel_t;
|
||||
|
||||
int c_triangleModels;
|
||||
int c_triangleSurfaces;
|
||||
int c_triangleVertexes;
|
||||
int c_triangleIndexes;
|
||||
|
||||
|
||||
#define MAX_LOADED_MODELS 1024
|
||||
loadedModel_t loadedModels[MAX_LOADED_MODELS];
|
||||
int numLoadedModels;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadMD3
|
||||
=================
|
||||
*/
|
||||
#define LL(x) x=LittleLong(x)
|
||||
md3Header_t *R_LoadMD3( const char *mod_name ) {
|
||||
int i, j;
|
||||
md3Header_t *md3;
|
||||
md3Frame_t *frame;
|
||||
md3Surface_t *surf;
|
||||
md3Triangle_t *tri;
|
||||
md3St_t *st;
|
||||
md3XyzNormal_t *xyz;
|
||||
int version;
|
||||
char filename[1024];
|
||||
int len;
|
||||
|
||||
sprintf( filename, "%s%s", gamedir, mod_name );
|
||||
len = TryLoadFile( filename, (void **)&md3 );
|
||||
#ifdef _WIN32
|
||||
if ( len <= 0 ) {
|
||||
len = PakLoadAnyFile(filename, (void **)&md3);
|
||||
}
|
||||
#endif
|
||||
if ( len <= 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
version = LittleLong (md3->version);
|
||||
if (version != MD3_VERSION) {
|
||||
_printf( "R_LoadMD3: %s has wrong version (%i should be %i)\n",
|
||||
mod_name, version, MD3_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LL(md3->ident);
|
||||
LL(md3->version);
|
||||
LL(md3->numFrames);
|
||||
LL(md3->numTags);
|
||||
LL(md3->numSurfaces);
|
||||
LL(md3->numSkins);
|
||||
LL(md3->ofsFrames);
|
||||
LL(md3->ofsTags);
|
||||
LL(md3->ofsSurfaces);
|
||||
LL(md3->ofsEnd);
|
||||
|
||||
if ( md3->numFrames < 1 ) {
|
||||
_printf( "R_LoadMD3: %s has no frames\n", mod_name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// we don't need to swap tags in the renderer, they aren't used
|
||||
|
||||
// swap all the frames
|
||||
frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames );
|
||||
for ( i = 0 ; i < md3->numFrames ; i++, frame++) {
|
||||
frame->radius = LittleFloat( frame->radius );
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
|
||||
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
|
||||
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
|
||||
}
|
||||
}
|
||||
|
||||
// swap all the surfaces
|
||||
surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
|
||||
for ( i = 0 ; i < md3->numSurfaces ; i++) {
|
||||
|
||||
LL(surf->ident);
|
||||
LL(surf->flags);
|
||||
LL(surf->numFrames);
|
||||
LL(surf->numShaders);
|
||||
LL(surf->numTriangles);
|
||||
LL(surf->ofsTriangles);
|
||||
LL(surf->numVerts);
|
||||
LL(surf->ofsShaders);
|
||||
LL(surf->ofsSt);
|
||||
LL(surf->ofsXyzNormals);
|
||||
LL(surf->ofsEnd);
|
||||
|
||||
if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
|
||||
Error ("R_LoadMD3: %s has more than %i verts on a surface (%i)",
|
||||
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
|
||||
}
|
||||
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
|
||||
Error ("R_LoadMD3: %s has more than %i triangles on a surface (%i)",
|
||||
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
|
||||
}
|
||||
|
||||
// swap all the triangles
|
||||
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
|
||||
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
|
||||
LL(tri->indexes[0]);
|
||||
LL(tri->indexes[1]);
|
||||
LL(tri->indexes[2]);
|
||||
}
|
||||
|
||||
// swap all the ST
|
||||
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
|
||||
for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
|
||||
st->st[0] = LittleFloat( st->st[0] );
|
||||
st->st[1] = LittleFloat( st->st[1] );
|
||||
}
|
||||
|
||||
// swap all the XyzNormals
|
||||
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
|
||||
for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )
|
||||
{
|
||||
xyz->xyz[0] = LittleShort( xyz->xyz[0] );
|
||||
xyz->xyz[1] = LittleShort( xyz->xyz[1] );
|
||||
xyz->xyz[2] = LittleShort( xyz->xyz[2] );
|
||||
|
||||
xyz->normal = LittleShort( xyz->normal );
|
||||
}
|
||||
|
||||
|
||||
// find the next surface
|
||||
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
|
||||
}
|
||||
|
||||
return md3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
LoadModel
|
||||
================
|
||||
*/
|
||||
md3Header_t *LoadModel( const char *modelName ) {
|
||||
int i;
|
||||
loadedModel_t *lm;
|
||||
|
||||
// see if we already have it loaded
|
||||
for ( i = 0, lm = loadedModels ; i < numLoadedModels ; i++, lm++ ) {
|
||||
if ( !strcmp( modelName, lm->modelName ) ) {
|
||||
return lm->header;
|
||||
}
|
||||
}
|
||||
|
||||
// load it
|
||||
if ( numLoadedModels == MAX_LOADED_MODELS ) {
|
||||
Error( "MAX_LOADED_MODELS" );
|
||||
}
|
||||
numLoadedModels++;
|
||||
|
||||
strcpy( lm->modelName, modelName );
|
||||
|
||||
lm->header = R_LoadMD3( modelName );
|
||||
|
||||
return lm->header;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
InsertMD3Model
|
||||
|
||||
Convert a model entity to raw geometry surfaces and insert it in the tree
|
||||
============
|
||||
*/
|
||||
void InsertMD3Model( const char *modelName, vec3_t origin, float angle, tree_t *tree ) {
|
||||
int i, j;
|
||||
md3Header_t *md3;
|
||||
md3Surface_t *surf;
|
||||
md3Shader_t *shader;
|
||||
md3Triangle_t *tri;
|
||||
md3St_t *st;
|
||||
md3XyzNormal_t *xyz;
|
||||
drawVert_t *outv;
|
||||
float lat, lng;
|
||||
float angleCos, angleSin;
|
||||
mapDrawSurface_t *out;
|
||||
vec3_t temp;
|
||||
|
||||
angle = angle / 180 * Q_PI;
|
||||
angleCos = cos( angle );
|
||||
angleSin = sin( angle );
|
||||
|
||||
// load the model
|
||||
md3 = LoadModel( modelName );
|
||||
if ( !md3 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// each md3 surface will become a new bsp surface
|
||||
|
||||
c_triangleModels++;
|
||||
c_triangleSurfaces += md3->numSurfaces;
|
||||
|
||||
// expand, translate, and rotate the vertexes
|
||||
// swap all the surfaces
|
||||
surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces );
|
||||
for ( i = 0 ; i < md3->numSurfaces ; i++) {
|
||||
// allocate a surface
|
||||
out = AllocDrawSurf();
|
||||
out->miscModel = qtrue;
|
||||
|
||||
shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
|
||||
|
||||
out->shaderInfo = ShaderInfoForShader( shader->name );
|
||||
|
||||
out->numVerts = surf->numVerts;
|
||||
out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) );
|
||||
|
||||
out->numIndexes = surf->numTriangles * 3;
|
||||
out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) );
|
||||
|
||||
out->lightmapNum = -1;
|
||||
out->fogNum = -1;
|
||||
|
||||
// emit the indexes
|
||||
c_triangleIndexes += surf->numTriangles * 3;
|
||||
tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
|
||||
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
|
||||
out->indexes[j*3+0] = tri->indexes[0];
|
||||
out->indexes[j*3+1] = tri->indexes[1];
|
||||
out->indexes[j*3+2] = tri->indexes[2];
|
||||
}
|
||||
|
||||
// emit the vertexes
|
||||
st = (md3St_t *) ( (byte *)surf + surf->ofsSt );
|
||||
xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals );
|
||||
|
||||
c_triangleVertexes += surf->numVerts;
|
||||
for ( j = 0 ; j < surf->numVerts ; j++, st++, xyz++ ) {
|
||||
outv = &out->verts[ j ];
|
||||
|
||||
outv->st[0] = st->st[0];
|
||||
outv->st[1] = st->st[1];
|
||||
|
||||
outv->lightmap[0] = 0;
|
||||
outv->lightmap[1] = 0;
|
||||
|
||||
// the colors will be set by the lighting pass
|
||||
outv->color[0] = 255;
|
||||
outv->color[1] = 255;
|
||||
outv->color[2] = 255;
|
||||
outv->color[3] = 255;
|
||||
|
||||
outv->xyz[0] = origin[0] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleCos - xyz->xyz[1] * angleSin );
|
||||
outv->xyz[1] = origin[1] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleSin + xyz->xyz[1] * angleCos );
|
||||
outv->xyz[2] = origin[2] + MD3_XYZ_SCALE * ( xyz->xyz[2] );
|
||||
|
||||
// decode the lat/lng normal to a 3 float normal
|
||||
lat = ( xyz->normal >> 8 ) & 0xff;
|
||||
lng = ( xyz->normal & 0xff );
|
||||
lat *= Q_PI/128;
|
||||
lng *= Q_PI/128;
|
||||
|
||||
temp[0] = cos(lat) * sin(lng);
|
||||
temp[1] = sin(lat) * sin(lng);
|
||||
temp[2] = cos(lng);
|
||||
|
||||
// rotate the normal
|
||||
outv->normal[0] = temp[0] * angleCos - temp[1] * angleSin;
|
||||
outv->normal[1] = temp[0] * angleSin + temp[1] * angleCos;
|
||||
outv->normal[2] = temp[2];
|
||||
}
|
||||
|
||||
// find the next surface
|
||||
surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
InsertASEModel
|
||||
|
||||
Convert a model entity to raw geometry surfaces and insert it in the tree
|
||||
============
|
||||
*/
|
||||
void InsertASEModel( const char *modelName, vec3_t origin, float angle, tree_t *tree ) {
|
||||
int i, j;
|
||||
drawVert_t *outv;
|
||||
float angleCos, angleSin;
|
||||
mapDrawSurface_t *out;
|
||||
int numSurfaces;
|
||||
const char *name;
|
||||
polyset_t *pset;
|
||||
int numFrames;
|
||||
char filename[1024];
|
||||
|
||||
sprintf( filename, "%s%s", gamedir, modelName );
|
||||
|
||||
angle = angle / 180 * Q_PI;
|
||||
angleCos = cos( angle );
|
||||
angleSin = sin( angle );
|
||||
|
||||
// load the model
|
||||
ASE_Load( filename, qfalse, qfalse );
|
||||
|
||||
// each ase surface will become a new bsp surface
|
||||
numSurfaces = ASE_GetNumSurfaces();
|
||||
|
||||
c_triangleModels++;
|
||||
c_triangleSurfaces += numSurfaces;
|
||||
|
||||
// expand, translate, and rotate the vertexes
|
||||
// swap all the surfaces
|
||||
for ( i = 0 ; i < numSurfaces ; i++) {
|
||||
name = ASE_GetSurfaceName( i );
|
||||
|
||||
pset = ASE_GetSurfaceAnimation( i, &numFrames, -1, -1, -1 );
|
||||
if ( !name || !pset ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate a surface
|
||||
out = AllocDrawSurf();
|
||||
out->miscModel = qtrue;
|
||||
|
||||
out->shaderInfo = ShaderInfoForShader( pset->materialname );
|
||||
|
||||
out->numVerts = 3 * pset->numtriangles;
|
||||
out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) );
|
||||
|
||||
out->numIndexes = 3 * pset->numtriangles;
|
||||
out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) );
|
||||
|
||||
out->lightmapNum = -1;
|
||||
out->fogNum = -1;
|
||||
|
||||
// emit the indexes
|
||||
c_triangleIndexes += out->numIndexes;
|
||||
for ( j = 0 ; j < out->numIndexes ; j++ ) {
|
||||
out->indexes[j] = j;
|
||||
}
|
||||
|
||||
// emit the vertexes
|
||||
c_triangleVertexes += out->numVerts;
|
||||
for ( j = 0 ; j < out->numVerts ; j++ ) {
|
||||
int index;
|
||||
triangle_t *tri;
|
||||
|
||||
index = j % 3;
|
||||
tri = &pset->triangles[ j / 3 ];
|
||||
|
||||
outv = &out->verts[ j ];
|
||||
|
||||
outv->st[0] = tri->texcoords[index][0];
|
||||
outv->st[1] = tri->texcoords[index][1];
|
||||
|
||||
outv->lightmap[0] = 0;
|
||||
outv->lightmap[1] = 0;
|
||||
|
||||
// the colors will be set by the lighting pass
|
||||
outv->color[0] = 255;
|
||||
outv->color[1] = 255;
|
||||
outv->color[2] = 255;
|
||||
outv->color[3] = 255;
|
||||
|
||||
outv->xyz[0] = origin[0] + tri->verts[index][0];
|
||||
outv->xyz[1] = origin[1] + tri->verts[index][1];
|
||||
outv->xyz[2] = origin[2] + tri->verts[index][2];
|
||||
|
||||
// rotate the normal
|
||||
outv->normal[0] = tri->normals[index][0];
|
||||
outv->normal[1] = tri->normals[index][1];
|
||||
outv->normal[2] = tri->normals[index][2];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
AddTriangleModels
|
||||
=====================
|
||||
*/
|
||||
void AddTriangleModels( tree_t *tree ) {
|
||||
int entity_num;
|
||||
entity_t *entity;
|
||||
|
||||
qprintf("----- AddTriangleModels -----\n");
|
||||
|
||||
for ( entity_num=1 ; entity_num< num_entities ; entity_num++ ) {
|
||||
entity = &entities[entity_num];
|
||||
|
||||
// convert misc_models into raw geometry
|
||||
if ( !Q_stricmp( "misc_model", ValueForKey( entity, "classname" ) ) ) {
|
||||
const char *model;
|
||||
vec3_t origin;
|
||||
float angle;
|
||||
|
||||
// get the angle for rotation FIXME: support full matrix positioning
|
||||
angle = FloatForKey( entity, "angle" );
|
||||
|
||||
GetVectorForKey( entity, "origin", origin );
|
||||
|
||||
model = ValueForKey( entity, "model" );
|
||||
if ( !model[0] ) {
|
||||
_printf("WARNING: misc_model at %i %i %i without a model key\n", (int)origin[0],
|
||||
(int)origin[1], (int)origin[2] );
|
||||
continue;
|
||||
}
|
||||
if ( strstr( model, ".md3" ) || strstr( model, ".MD3" ) ) {
|
||||
InsertMD3Model( model, origin, angle, tree );
|
||||
continue;
|
||||
}
|
||||
if ( strstr( model, ".ase" ) || strstr( model, ".ASE" ) ) {
|
||||
InsertASEModel( model, origin, angle, tree );
|
||||
continue;
|
||||
}
|
||||
_printf( "Unknown misc_model type: %s\n", model );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
qprintf( "%5i triangle models\n", c_triangleModels );
|
||||
qprintf( "%5i triangle surfaces\n", c_triangleSurfaces );
|
||||
qprintf( "%5i triangle vertexes\n", c_triangleVertexes );
|
||||
qprintf( "%5i triangle indexes\n", c_triangleIndexes );
|
||||
}
|
||||
|
||||
|
|
52
q3map/nodraw.c
Normal file → Executable file
52
q3map/nodraw.c
Normal file → Executable file
|
@ -19,29 +19,29 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
vec3_t draw_mins, draw_maxs;
|
||||
qboolean drawflag;
|
||||
|
||||
void Draw_ClearWindow (void)
|
||||
{
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
#define GLSERV_PORT 25001
|
||||
|
||||
|
||||
void GLS_BeginScene (void)
|
||||
{
|
||||
}
|
||||
|
||||
void GLS_Winding (winding_t *w, int code)
|
||||
{
|
||||
}
|
||||
|
||||
void GLS_EndScene (void)
|
||||
{
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
|
|
530
q3map/patch.c
Normal file → Executable file
530
q3map/patch.c
Normal file → Executable file
|
@ -19,268 +19,268 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
void PrintCtrl( vec3_t ctrl[9] ) {
|
||||
int i, j;
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
_printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] );
|
||||
}
|
||||
_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DrawSurfaceForMesh
|
||||
================
|
||||
*/
|
||||
mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ) {
|
||||
mapDrawSurface_t *ds;
|
||||
int i, j;
|
||||
mesh_t *copy;
|
||||
|
||||
// to make valid normals for patches with degenerate edges,
|
||||
// we need to make a copy of the mesh and put the aproximating
|
||||
// points onto the curve
|
||||
copy = CopyMesh( m );
|
||||
PutMeshOnCurve( *copy );
|
||||
MakeMeshNormals( *copy );
|
||||
for ( j = 0 ; j < m->width ; j++ ) {
|
||||
for ( i = 0 ; i < m->height ; i++ ) {
|
||||
VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
|
||||
}
|
||||
}
|
||||
FreeMesh( copy );
|
||||
|
||||
ds = AllocDrawSurf();
|
||||
ds->mapBrush = NULL;
|
||||
ds->side = NULL;
|
||||
|
||||
ds->patch = qtrue;
|
||||
ds->patchWidth = m->width;
|
||||
ds->patchHeight = m->height;
|
||||
ds->numVerts = ds->patchWidth * ds->patchHeight;
|
||||
ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
|
||||
memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
|
||||
|
||||
ds->lightmapNum = -1;
|
||||
ds->fogNum = -1;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
ParsePatch
|
||||
|
||||
Creates a mapDrawSurface_t from the patch text
|
||||
=================
|
||||
*/
|
||||
void ParsePatch( void ) {
|
||||
vec_t info[5];
|
||||
int i, j;
|
||||
parseMesh_t *pm;
|
||||
char texture[MAX_QPATH];
|
||||
char shader[MAX_QPATH];
|
||||
mesh_t m;
|
||||
drawVert_t *verts;
|
||||
epair_t *ep;
|
||||
|
||||
MatchToken( "{" );
|
||||
|
||||
// get texture
|
||||
GetToken (qtrue);
|
||||
strcpy( texture, token );
|
||||
|
||||
// save the shader name for retexturing
|
||||
if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
|
||||
Error( "MAX_MAP_BRUSHSIDES" );
|
||||
}
|
||||
strcpy( mapIndexedShaders[numMapIndexedShaders], texture );
|
||||
numMapIndexedShaders++;
|
||||
|
||||
|
||||
Parse1DMatrix( 5, info );
|
||||
m.width = info[0];
|
||||
m.height = info[1];
|
||||
m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) );
|
||||
|
||||
if ( m.width < 0 || m.width > MAX_PATCH_SIZE
|
||||
|| m.height < 0 || m.height > MAX_PATCH_SIZE ) {
|
||||
Error("ParsePatch: bad size");
|
||||
}
|
||||
|
||||
MatchToken( "(" );
|
||||
for ( j = 0 ; j < m.width ; j++ ) {
|
||||
MatchToken( "(" );
|
||||
for ( i = 0 ; i < m.height ; i++ ) {
|
||||
Parse1DMatrix( 5, verts[i*m.width+j].xyz );
|
||||
}
|
||||
MatchToken( ")" );
|
||||
}
|
||||
MatchToken( ")" );
|
||||
|
||||
// if brush primitives format, we may have some epairs to ignore here
|
||||
GetToken(qtrue);
|
||||
if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
|
||||
{
|
||||
// NOTE: we leak that!
|
||||
ep = ParseEpair();
|
||||
}
|
||||
else
|
||||
UnGetToken();
|
||||
|
||||
MatchToken( "}" );
|
||||
MatchToken( "}" );
|
||||
|
||||
if ( noCurveBrushes ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find default flags and values
|
||||
pm = malloc( sizeof( *pm ) );
|
||||
memset( pm, 0, sizeof( *pm ) );
|
||||
|
||||
sprintf( shader, "textures/%s", texture );
|
||||
pm->shaderInfo = ShaderInfoForShader( shader );
|
||||
pm->mesh = m;
|
||||
|
||||
// link to the entity
|
||||
pm->next = mapent->patches;
|
||||
mapent->patches = pm;
|
||||
}
|
||||
|
||||
|
||||
void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) {
|
||||
int i;
|
||||
const byte *row;
|
||||
|
||||
if ( group[patchNum] ) {
|
||||
return;
|
||||
}
|
||||
group[patchNum] = 1;
|
||||
row = bordering + patchNum * patchCount;
|
||||
for ( i = 0 ; i < patchCount ; i++ ) {
|
||||
if ( row[i] ) {
|
||||
GrowGroup_r( i, patchCount, bordering, group );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
PatchMapDrawSurfs
|
||||
|
||||
Any patches that share an edge need to choose their
|
||||
level of detail as a unit, otherwise the edges would
|
||||
pull apart.
|
||||
=====================
|
||||
*/
|
||||
void PatchMapDrawSurfs( entity_t *e ) {
|
||||
parseMesh_t *pm;
|
||||
parseMesh_t *check, *scan;
|
||||
mapDrawSurface_t *ds;
|
||||
int patchCount, groupCount;
|
||||
int i, j, k, l, c1, c2;
|
||||
drawVert_t *v1, *v2;
|
||||
vec3_t bounds[2];
|
||||
byte *bordering;
|
||||
parseMesh_t *meshes[MAX_MAP_DRAW_SURFS];
|
||||
qboolean grouped[MAX_MAP_DRAW_SURFS];
|
||||
byte group[MAX_MAP_DRAW_SURFS];
|
||||
|
||||
qprintf( "----- PatchMapDrawSurfs -----\n" );
|
||||
|
||||
patchCount = 0;
|
||||
for ( pm = e->patches ; pm ; pm = pm->next ) {
|
||||
meshes[patchCount] = pm;
|
||||
patchCount++;
|
||||
}
|
||||
|
||||
if ( !patchCount ) {
|
||||
return;
|
||||
}
|
||||
bordering = malloc( patchCount * patchCount );
|
||||
memset( bordering, 0, patchCount * patchCount );
|
||||
|
||||
// build the bordering matrix
|
||||
for ( k = 0 ; k < patchCount ; k++ ) {
|
||||
bordering[k*patchCount+k] = 1;
|
||||
|
||||
for ( l = k+1 ; l < patchCount ; l++ ) {
|
||||
check = meshes[k];
|
||||
scan = meshes[l];
|
||||
c1 = scan->mesh.width * scan->mesh.height;
|
||||
v1 = scan->mesh.verts;
|
||||
|
||||
for ( i = 0 ; i < c1 ; i++, v1++ ) {
|
||||
c2 = check->mesh.width * check->mesh.height;
|
||||
v2 = check->mesh.verts;
|
||||
for ( j = 0 ; j < c2 ; j++, v2++ ) {
|
||||
if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
|
||||
&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
|
||||
&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j != c2 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i != c1 ) {
|
||||
// we have a connection
|
||||
bordering[k*patchCount+l] =
|
||||
bordering[l*patchCount+k] = 1;
|
||||
} else {
|
||||
// no connection
|
||||
bordering[k*patchCount+l] =
|
||||
bordering[l*patchCount+k] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// build groups
|
||||
memset( grouped, 0, sizeof(grouped) );
|
||||
groupCount = 0;
|
||||
for ( i = 0 ; i < patchCount ; i++ ) {
|
||||
if ( !grouped[i] ) {
|
||||
groupCount++;
|
||||
}
|
||||
|
||||
// recursively find all patches that belong in the same group
|
||||
memset( group, 0, patchCount );
|
||||
GrowGroup_r( i, patchCount, bordering, group );
|
||||
|
||||
// bound them
|
||||
ClearBounds( bounds[0], bounds[1] );
|
||||
for ( j = 0 ; j < patchCount ; j++ ) {
|
||||
if ( group[j] ) {
|
||||
grouped[j] = qtrue;
|
||||
scan = meshes[j];
|
||||
c1 = scan->mesh.width * scan->mesh.height;
|
||||
v1 = scan->mesh.verts;
|
||||
for ( k = 0 ; k < c1 ; k++, v1++ ) {
|
||||
AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create drawsurf
|
||||
scan = meshes[i];
|
||||
scan->grouped = qtrue;
|
||||
ds = DrawSurfaceForMesh( &scan->mesh );
|
||||
ds->shaderInfo = scan->shaderInfo;
|
||||
VectorCopy( bounds[0], ds->lightmapVecs[0] );
|
||||
VectorCopy( bounds[1], ds->lightmapVecs[1] );
|
||||
}
|
||||
|
||||
qprintf( "%5i patches\n", patchCount );
|
||||
qprintf( "%5i patch LOD groups\n", groupCount );
|
||||
}
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
void PrintCtrl( vec3_t ctrl[9] ) {
|
||||
int i, j;
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
_printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] );
|
||||
}
|
||||
_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DrawSurfaceForMesh
|
||||
================
|
||||
*/
|
||||
mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ) {
|
||||
mapDrawSurface_t *ds;
|
||||
int i, j;
|
||||
mesh_t *copy;
|
||||
|
||||
// to make valid normals for patches with degenerate edges,
|
||||
// we need to make a copy of the mesh and put the aproximating
|
||||
// points onto the curve
|
||||
copy = CopyMesh( m );
|
||||
PutMeshOnCurve( *copy );
|
||||
MakeMeshNormals( *copy );
|
||||
for ( j = 0 ; j < m->width ; j++ ) {
|
||||
for ( i = 0 ; i < m->height ; i++ ) {
|
||||
VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
|
||||
}
|
||||
}
|
||||
FreeMesh( copy );
|
||||
|
||||
ds = AllocDrawSurf();
|
||||
ds->mapBrush = NULL;
|
||||
ds->side = NULL;
|
||||
|
||||
ds->patch = qtrue;
|
||||
ds->patchWidth = m->width;
|
||||
ds->patchHeight = m->height;
|
||||
ds->numVerts = ds->patchWidth * ds->patchHeight;
|
||||
ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
|
||||
memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
|
||||
|
||||
ds->lightmapNum = -1;
|
||||
ds->fogNum = -1;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
ParsePatch
|
||||
|
||||
Creates a mapDrawSurface_t from the patch text
|
||||
=================
|
||||
*/
|
||||
void ParsePatch( void ) {
|
||||
vec_t info[5];
|
||||
int i, j;
|
||||
parseMesh_t *pm;
|
||||
char texture[MAX_QPATH];
|
||||
char shader[MAX_QPATH];
|
||||
mesh_t m;
|
||||
drawVert_t *verts;
|
||||
epair_t *ep;
|
||||
|
||||
MatchToken( "{" );
|
||||
|
||||
// get texture
|
||||
GetToken (qtrue);
|
||||
strcpy( texture, token );
|
||||
|
||||
// save the shader name for retexturing
|
||||
if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
|
||||
Error( "MAX_MAP_BRUSHSIDES" );
|
||||
}
|
||||
strcpy( mapIndexedShaders[numMapIndexedShaders], texture );
|
||||
numMapIndexedShaders++;
|
||||
|
||||
|
||||
Parse1DMatrix( 5, info );
|
||||
m.width = info[0];
|
||||
m.height = info[1];
|
||||
m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) );
|
||||
|
||||
if ( m.width < 0 || m.width > MAX_PATCH_SIZE
|
||||
|| m.height < 0 || m.height > MAX_PATCH_SIZE ) {
|
||||
Error("ParsePatch: bad size");
|
||||
}
|
||||
|
||||
MatchToken( "(" );
|
||||
for ( j = 0 ; j < m.width ; j++ ) {
|
||||
MatchToken( "(" );
|
||||
for ( i = 0 ; i < m.height ; i++ ) {
|
||||
Parse1DMatrix( 5, verts[i*m.width+j].xyz );
|
||||
}
|
||||
MatchToken( ")" );
|
||||
}
|
||||
MatchToken( ")" );
|
||||
|
||||
// if brush primitives format, we may have some epairs to ignore here
|
||||
GetToken(qtrue);
|
||||
if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
|
||||
{
|
||||
// NOTE: we leak that!
|
||||
ep = ParseEpair();
|
||||
}
|
||||
else
|
||||
UnGetToken();
|
||||
|
||||
MatchToken( "}" );
|
||||
MatchToken( "}" );
|
||||
|
||||
if ( noCurveBrushes ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find default flags and values
|
||||
pm = malloc( sizeof( *pm ) );
|
||||
memset( pm, 0, sizeof( *pm ) );
|
||||
|
||||
sprintf( shader, "textures/%s", texture );
|
||||
pm->shaderInfo = ShaderInfoForShader( shader );
|
||||
pm->mesh = m;
|
||||
|
||||
// link to the entity
|
||||
pm->next = mapent->patches;
|
||||
mapent->patches = pm;
|
||||
}
|
||||
|
||||
|
||||
void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) {
|
||||
int i;
|
||||
const byte *row;
|
||||
|
||||
if ( group[patchNum] ) {
|
||||
return;
|
||||
}
|
||||
group[patchNum] = 1;
|
||||
row = bordering + patchNum * patchCount;
|
||||
for ( i = 0 ; i < patchCount ; i++ ) {
|
||||
if ( row[i] ) {
|
||||
GrowGroup_r( i, patchCount, bordering, group );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
PatchMapDrawSurfs
|
||||
|
||||
Any patches that share an edge need to choose their
|
||||
level of detail as a unit, otherwise the edges would
|
||||
pull apart.
|
||||
=====================
|
||||
*/
|
||||
void PatchMapDrawSurfs( entity_t *e ) {
|
||||
parseMesh_t *pm;
|
||||
parseMesh_t *check, *scan;
|
||||
mapDrawSurface_t *ds;
|
||||
int patchCount, groupCount;
|
||||
int i, j, k, l, c1, c2;
|
||||
drawVert_t *v1, *v2;
|
||||
vec3_t bounds[2];
|
||||
byte *bordering;
|
||||
parseMesh_t *meshes[MAX_MAP_DRAW_SURFS];
|
||||
qboolean grouped[MAX_MAP_DRAW_SURFS];
|
||||
byte group[MAX_MAP_DRAW_SURFS];
|
||||
|
||||
qprintf( "----- PatchMapDrawSurfs -----\n" );
|
||||
|
||||
patchCount = 0;
|
||||
for ( pm = e->patches ; pm ; pm = pm->next ) {
|
||||
meshes[patchCount] = pm;
|
||||
patchCount++;
|
||||
}
|
||||
|
||||
if ( !patchCount ) {
|
||||
return;
|
||||
}
|
||||
bordering = malloc( patchCount * patchCount );
|
||||
memset( bordering, 0, patchCount * patchCount );
|
||||
|
||||
// build the bordering matrix
|
||||
for ( k = 0 ; k < patchCount ; k++ ) {
|
||||
bordering[k*patchCount+k] = 1;
|
||||
|
||||
for ( l = k+1 ; l < patchCount ; l++ ) {
|
||||
check = meshes[k];
|
||||
scan = meshes[l];
|
||||
c1 = scan->mesh.width * scan->mesh.height;
|
||||
v1 = scan->mesh.verts;
|
||||
|
||||
for ( i = 0 ; i < c1 ; i++, v1++ ) {
|
||||
c2 = check->mesh.width * check->mesh.height;
|
||||
v2 = check->mesh.verts;
|
||||
for ( j = 0 ; j < c2 ; j++, v2++ ) {
|
||||
if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
|
||||
&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
|
||||
&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j != c2 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i != c1 ) {
|
||||
// we have a connection
|
||||
bordering[k*patchCount+l] =
|
||||
bordering[l*patchCount+k] = 1;
|
||||
} else {
|
||||
// no connection
|
||||
bordering[k*patchCount+l] =
|
||||
bordering[l*patchCount+k] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// build groups
|
||||
memset( grouped, 0, sizeof(grouped) );
|
||||
groupCount = 0;
|
||||
for ( i = 0 ; i < patchCount ; i++ ) {
|
||||
if ( !grouped[i] ) {
|
||||
groupCount++;
|
||||
}
|
||||
|
||||
// recursively find all patches that belong in the same group
|
||||
memset( group, 0, patchCount );
|
||||
GrowGroup_r( i, patchCount, bordering, group );
|
||||
|
||||
// bound them
|
||||
ClearBounds( bounds[0], bounds[1] );
|
||||
for ( j = 0 ; j < patchCount ; j++ ) {
|
||||
if ( group[j] ) {
|
||||
grouped[j] = qtrue;
|
||||
scan = meshes[j];
|
||||
c1 = scan->mesh.width * scan->mesh.height;
|
||||
v1 = scan->mesh.verts;
|
||||
for ( k = 0 ; k < c1 ; k++, v1++ ) {
|
||||
AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create drawsurf
|
||||
scan = meshes[i];
|
||||
scan->grouped = qtrue;
|
||||
ds = DrawSurfaceForMesh( &scan->mesh );
|
||||
ds->shaderInfo = scan->shaderInfo;
|
||||
VectorCopy( bounds[0], ds->lightmapVecs[0] );
|
||||
VectorCopy( bounds[1], ds->lightmapVecs[1] );
|
||||
}
|
||||
|
||||
qprintf( "%5i patches\n", patchCount );
|
||||
qprintf( "%5i patch LOD groups\n", groupCount );
|
||||
}
|
||||
|
||||
|
|
1644
q3map/portals.c
Normal file → Executable file
1644
q3map/portals.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
502
q3map/prtfile.c
Normal file → Executable file
502
q3map/prtfile.c
Normal file → Executable file
|
@ -19,254 +19,254 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PORTAL FILE GENERATION
|
||||
|
||||
Save out name.prt for qvis to read
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
|
||||
FILE *pf;
|
||||
int num_visclusters; // clusters the player can be in
|
||||
int num_visportals;
|
||||
int num_solidfaces;
|
||||
|
||||
void WriteFloat (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) {
|
||||
WritePortalFile_r (node->children[0]);
|
||||
WritePortalFile_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->opaque) {
|
||||
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_Passable(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);
|
||||
if (p->hint)
|
||||
fprintf (pf, "1 ");
|
||||
else
|
||||
fprintf (pf, "0 ");
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
WriteFaceFile_r
|
||||
=================
|
||||
*/
|
||||
void WriteFaceFile_r (node_t *node)
|
||||
{
|
||||
int i, s;
|
||||
portal_t *p;
|
||||
winding_t *w;
|
||||
|
||||
// decision node
|
||||
if (node->planenum != PLANENUM_LEAF) {
|
||||
WriteFaceFile_r (node->children[0]);
|
||||
WriteFaceFile_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->opaque) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (p = node->portals ; p ; p=p->next[s])
|
||||
{
|
||||
w = p->winding;
|
||||
s = (p->nodes[1] == node);
|
||||
if (w)
|
||||
{
|
||||
if (Portal_Passable(p))
|
||||
continue;
|
||||
// write out to the file
|
||||
|
||||
if (p->nodes[0] == node)
|
||||
{
|
||||
fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
|
||||
for (i = w->numpoints-1; i >= 0; i--)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
NumberLeafs_r
|
||||
================
|
||||
*/
|
||||
void NumberLeafs_r (node_t *node)
|
||||
{
|
||||
portal_t *p;
|
||||
|
||||
if ( node->planenum != PLANENUM_LEAF ) {
|
||||
// decision node
|
||||
node->cluster = -99;
|
||||
NumberLeafs_r (node->children[0]);
|
||||
NumberLeafs_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
node->area = -1;
|
||||
|
||||
if ( node->opaque ) {
|
||||
// solid block, viewpoint never inside
|
||||
node->cluster = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
node->cluster = 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_Passable(p))
|
||||
num_visportals++;
|
||||
else
|
||||
num_solidfaces++;
|
||||
p = p->next[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Portal_Passable(p))
|
||||
num_solidfaces++;
|
||||
p = p->next[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
NumberClusters
|
||||
================
|
||||
*/
|
||||
void NumberClusters(tree_t *tree) {
|
||||
num_visclusters = 0;
|
||||
num_visportals = 0;
|
||||
num_solidfaces = 0;
|
||||
|
||||
qprintf ("--- NumberClusters ---\n");
|
||||
|
||||
// set the cluster field in every leaf and count the total number of portals
|
||||
NumberLeafs_r (tree->headnode);
|
||||
|
||||
qprintf ("%5i visclusters\n", num_visclusters);
|
||||
qprintf ("%5i visportals\n", num_visportals);
|
||||
qprintf ("%5i solidfaces\n", num_solidfaces);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
WritePortalFile
|
||||
================
|
||||
*/
|
||||
void WritePortalFile (tree_t *tree)
|
||||
{
|
||||
char filename[1024];
|
||||
|
||||
qprintf ("--- WritePortalFile ---\n");
|
||||
|
||||
// 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);
|
||||
fprintf (pf, "%i\n", num_solidfaces);
|
||||
|
||||
WritePortalFile_r(tree->headnode);
|
||||
WriteFaceFile_r(tree->headnode);
|
||||
|
||||
fclose (pf);
|
||||
}
|
||||
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PORTAL FILE GENERATION
|
||||
|
||||
Save out name.prt for qvis to read
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
|
||||
FILE *pf;
|
||||
int num_visclusters; // clusters the player can be in
|
||||
int num_visportals;
|
||||
int num_solidfaces;
|
||||
|
||||
void WriteFloat (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) {
|
||||
WritePortalFile_r (node->children[0]);
|
||||
WritePortalFile_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->opaque) {
|
||||
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_Passable(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);
|
||||
if (p->hint)
|
||||
fprintf (pf, "1 ");
|
||||
else
|
||||
fprintf (pf, "0 ");
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
WriteFaceFile_r
|
||||
=================
|
||||
*/
|
||||
void WriteFaceFile_r (node_t *node)
|
||||
{
|
||||
int i, s;
|
||||
portal_t *p;
|
||||
winding_t *w;
|
||||
|
||||
// decision node
|
||||
if (node->planenum != PLANENUM_LEAF) {
|
||||
WriteFaceFile_r (node->children[0]);
|
||||
WriteFaceFile_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->opaque) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (p = node->portals ; p ; p=p->next[s])
|
||||
{
|
||||
w = p->winding;
|
||||
s = (p->nodes[1] == node);
|
||||
if (w)
|
||||
{
|
||||
if (Portal_Passable(p))
|
||||
continue;
|
||||
// write out to the file
|
||||
|
||||
if (p->nodes[0] == node)
|
||||
{
|
||||
fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
|
||||
for (i=0 ; i<w->numpoints ; i++)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
|
||||
for (i = w->numpoints-1; i >= 0; i--)
|
||||
{
|
||||
fprintf (pf,"(");
|
||||
WriteFloat (pf, w->p[i][0]);
|
||||
WriteFloat (pf, w->p[i][1]);
|
||||
WriteFloat (pf, w->p[i][2]);
|
||||
fprintf (pf,") ");
|
||||
}
|
||||
fprintf (pf,"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
NumberLeafs_r
|
||||
================
|
||||
*/
|
||||
void NumberLeafs_r (node_t *node)
|
||||
{
|
||||
portal_t *p;
|
||||
|
||||
if ( node->planenum != PLANENUM_LEAF ) {
|
||||
// decision node
|
||||
node->cluster = -99;
|
||||
NumberLeafs_r (node->children[0]);
|
||||
NumberLeafs_r (node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
node->area = -1;
|
||||
|
||||
if ( node->opaque ) {
|
||||
// solid block, viewpoint never inside
|
||||
node->cluster = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
node->cluster = 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_Passable(p))
|
||||
num_visportals++;
|
||||
else
|
||||
num_solidfaces++;
|
||||
p = p->next[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Portal_Passable(p))
|
||||
num_solidfaces++;
|
||||
p = p->next[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
NumberClusters
|
||||
================
|
||||
*/
|
||||
void NumberClusters(tree_t *tree) {
|
||||
num_visclusters = 0;
|
||||
num_visportals = 0;
|
||||
num_solidfaces = 0;
|
||||
|
||||
qprintf ("--- NumberClusters ---\n");
|
||||
|
||||
// set the cluster field in every leaf and count the total number of portals
|
||||
NumberLeafs_r (tree->headnode);
|
||||
|
||||
qprintf ("%5i visclusters\n", num_visclusters);
|
||||
qprintf ("%5i visportals\n", num_visportals);
|
||||
qprintf ("%5i solidfaces\n", num_solidfaces);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
WritePortalFile
|
||||
================
|
||||
*/
|
||||
void WritePortalFile (tree_t *tree)
|
||||
{
|
||||
char filename[1024];
|
||||
|
||||
qprintf ("--- WritePortalFile ---\n");
|
||||
|
||||
// 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);
|
||||
fprintf (pf, "%i\n", num_solidfaces);
|
||||
|
||||
WritePortalFile_r(tree->headnode);
|
||||
WriteFaceFile_r(tree->headnode);
|
||||
|
||||
fclose (pf);
|
||||
}
|
||||
|
||||
|
|
112
q3map/q3map.sln
Normal file → Executable file
112
q3map/q3map.sln
Normal file → Executable file
|
@ -1,56 +1,56 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg6", "..\libs\jpeg6\jpeg6.vcproj", "{A862AD26-94DD-4618-A814-F6AACA0B2FE3}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "..\libs\pak\pak.vcproj", "{F2ACC9D7-D628-4624-864F-87FE58787625}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3map", "q3map.vcproj", "{F1162C55-66E7-4486-B1F3-071CFAA78332}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625} = {F2ACC9D7-D628-4624-864F-87FE58787625}
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3} = {A862AD26-94DD-4618-A814-F6AACA0B2FE3}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SourceCodeControl) = preSolution
|
||||
SccNumberOfProjects = 3
|
||||
SccProjectUniqueName0 = ..\\libs\\jpeg6\\jpeg6.vcproj
|
||||
SccProjectName0 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
|
||||
SccLocalPath0 = ..\\q3radiant
|
||||
SccProvider0 = MSSCCI:Perforce\u0020SCM
|
||||
SccProjectFilePathRelativizedFromConnection0 = ..\\libs\\jpeg6\\
|
||||
SccProjectUniqueName1 = ..\\libs\\pak\\pak.vcproj
|
||||
SccProjectName1 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
|
||||
SccLocalPath1 = ..\\q3radiant
|
||||
SccProvider1 = MSSCCI:Perforce\u0020SCM
|
||||
SccProjectFilePathRelativizedFromConnection1 = ..\\libs\\pak\\
|
||||
SccProjectUniqueName2 = q3map.vcproj
|
||||
SccProjectName2 = \u0022$/source/q3map\u0022,\u0020PADAAAAA
|
||||
SccLocalPath2 = .
|
||||
SccProvider2 = MSSCCI:Perforce\u0020SCM
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.ActiveCfg = Debug|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.Build.0 = Debug|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.ActiveCfg = Release|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.Build.0 = Release|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.ActiveCfg = Debug|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.Build.0 = Debug|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Release.ActiveCfg = Release|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Release.Build.0 = Release|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.ActiveCfg = Debug|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.Build.0 = Debug|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.ActiveCfg = Release|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg6", "..\libs\jpeg6\jpeg6.vcproj", "{A862AD26-94DD-4618-A814-F6AACA0B2FE3}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "..\libs\pak\pak.vcproj", "{F2ACC9D7-D628-4624-864F-87FE58787625}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3map", "q3map.vcproj", "{F1162C55-66E7-4486-B1F3-071CFAA78332}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625} = {F2ACC9D7-D628-4624-864F-87FE58787625}
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3} = {A862AD26-94DD-4618-A814-F6AACA0B2FE3}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SourceCodeControl) = preSolution
|
||||
SccNumberOfProjects = 3
|
||||
SccProjectUniqueName0 = ..\\libs\\jpeg6\\jpeg6.vcproj
|
||||
SccProjectName0 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
|
||||
SccLocalPath0 = ..\\q3radiant
|
||||
SccProvider0 = MSSCCI:Perforce\u0020SCM
|
||||
SccProjectFilePathRelativizedFromConnection0 = ..\\libs\\jpeg6\\
|
||||
SccProjectUniqueName1 = ..\\libs\\pak\\pak.vcproj
|
||||
SccProjectName1 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
|
||||
SccLocalPath1 = ..\\q3radiant
|
||||
SccProvider1 = MSSCCI:Perforce\u0020SCM
|
||||
SccProjectFilePathRelativizedFromConnection1 = ..\\libs\\pak\\
|
||||
SccProjectUniqueName2 = q3map.vcproj
|
||||
SccProjectName2 = \u0022$/source/q3map\u0022,\u0020PADAAAAA
|
||||
SccLocalPath2 = .
|
||||
SccProvider2 = MSSCCI:Perforce\u0020SCM
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.ActiveCfg = Debug|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.Build.0 = Debug|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.ActiveCfg = Release|Win32
|
||||
{A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.Build.0 = Release|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.ActiveCfg = Debug|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.Build.0 = Debug|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Release.ActiveCfg = Release|Win32
|
||||
{F2ACC9D7-D628-4624-864F-87FE58787625}.Release.Build.0 = Release|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.ActiveCfg = Debug|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.Build.0 = Debug|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.ActiveCfg = Release|Win32
|
||||
{F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
3212
q3map/q3map.vcproj
Normal file → Executable file
3212
q3map/q3map.vcproj
Normal file → Executable file
File diff suppressed because it is too large
Load diff
868
q3map/qbsp.h
Normal file → Executable file
868
q3map/qbsp.h
Normal file → Executable file
|
@ -19,437 +19,437 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "scriplib.h"
|
||||
#include "polylib.h"
|
||||
#include "imagelib.h"
|
||||
#include "threads.h"
|
||||
#include "bspfile.h"
|
||||
#include "shaders.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
#define MAX_PATCH_SIZE 32
|
||||
|
||||
#define CLIP_EPSILON 0.1
|
||||
#define PLANENUM_LEAF -1
|
||||
|
||||
#define HINT_PRIORITY 1000
|
||||
|
||||
typedef struct parseMesh_s {
|
||||
struct parseMesh_s *next;
|
||||
mesh_t mesh;
|
||||
shaderInfo_t *shaderInfo;
|
||||
|
||||
qboolean grouped; // used during shared edge grouping
|
||||
struct parseMesh_s *groupChain;
|
||||
} parseMesh_t;
|
||||
|
||||
typedef struct bspface_s {
|
||||
struct bspface_s *next;
|
||||
int planenum;
|
||||
int priority; // added to value calculation
|
||||
qboolean checked;
|
||||
qboolean hint;
|
||||
winding_t *w;
|
||||
} bspface_t;
|
||||
|
||||
typedef struct plane_s {
|
||||
vec3_t normal;
|
||||
vec_t dist;
|
||||
int type;
|
||||
struct plane_s *hash_chain;
|
||||
} plane_t;
|
||||
|
||||
typedef struct side_s {
|
||||
int planenum;
|
||||
|
||||
float texMat[2][3]; // brush primitive texture matrix
|
||||
// for old brush coordinates mode
|
||||
float vecs[2][4]; // texture coordinate mapping
|
||||
|
||||
winding_t *winding;
|
||||
winding_t *visibleHull; // convex hull of all visible fragments
|
||||
|
||||
struct shaderInfo_s *shaderInfo;
|
||||
|
||||
int contents; // from shaderInfo
|
||||
int surfaceFlags; // from shaderInfo
|
||||
int value; // from shaderInfo
|
||||
|
||||
qboolean visible; // choose visble planes first
|
||||
qboolean bevel; // don't ever use for bsp splitting, and don't bother
|
||||
// making windings for it
|
||||
qboolean backSide; // generated side for a q3map_backShader
|
||||
} side_t;
|
||||
|
||||
|
||||
#define MAX_BRUSH_SIDES 1024
|
||||
|
||||
typedef struct bspbrush_s {
|
||||
struct bspbrush_s *next;
|
||||
|
||||
int entitynum; // editor numbering
|
||||
int brushnum; // editor numbering
|
||||
|
||||
struct shaderInfo_s *contentShader;
|
||||
|
||||
int contents;
|
||||
qboolean detail;
|
||||
qboolean opaque;
|
||||
int outputNumber; // set when the brush is written to the file list
|
||||
|
||||
int portalareas[2];
|
||||
|
||||
struct bspbrush_s *original; // chopped up brushes will reference the originals
|
||||
|
||||
vec3_t mins, maxs;
|
||||
int numsides;
|
||||
side_t sides[6]; // variably sized
|
||||
} bspbrush_t;
|
||||
|
||||
|
||||
|
||||
typedef struct drawsurf_s {
|
||||
shaderInfo_t *shaderInfo;
|
||||
|
||||
bspbrush_t *mapBrush; // not valid for patches
|
||||
side_t *side; // not valid for patches
|
||||
|
||||
struct drawsurf_s *nextOnShader; // when sorting by shader for lightmaps
|
||||
|
||||
int fogNum; // set by FogDrawSurfs
|
||||
|
||||
int lightmapNum; // -1 = no lightmap
|
||||
int lightmapX, lightmapY;
|
||||
int lightmapWidth, lightmapHeight;
|
||||
|
||||
int numVerts;
|
||||
drawVert_t *verts;
|
||||
|
||||
int numIndexes;
|
||||
int *indexes;
|
||||
|
||||
// for faces only
|
||||
int planeNum;
|
||||
|
||||
vec3_t lightmapOrigin; // also used for flares
|
||||
vec3_t lightmapVecs[3]; // also used for flares
|
||||
|
||||
// for patches only
|
||||
qboolean patch;
|
||||
int patchWidth;
|
||||
int patchHeight;
|
||||
|
||||
// for misc_models only
|
||||
qboolean miscModel;
|
||||
|
||||
qboolean flareSurface;
|
||||
} mapDrawSurface_t;
|
||||
|
||||
typedef struct drawSurfRef_s {
|
||||
struct drawSurfRef_s *nextRef;
|
||||
int outputNumber;
|
||||
} drawSurfRef_t;
|
||||
|
||||
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
|
||||
side_t *side; // the side that created the node
|
||||
struct node_s *children[2];
|
||||
qboolean hint;
|
||||
int tinyportals;
|
||||
vec3_t referencepoint;
|
||||
|
||||
// leafs only
|
||||
qboolean opaque; // view can never be inside
|
||||
qboolean areaportal;
|
||||
int cluster; // for portalfile writing
|
||||
int area; // for areaportals
|
||||
bspbrush_t *brushlist; // fragments of all brushes in this leaf
|
||||
drawSurfRef_t *drawSurfReferences; // references to patches pushed down
|
||||
|
||||
int occupied; // 1 or greater can reach entity
|
||||
entity_t *occupant; // for leak file testing
|
||||
|
||||
struct portal_s *portals; // also on nodes during construction
|
||||
} node_t;
|
||||
|
||||
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
|
||||
qboolean hint;
|
||||
side_t *side; // NULL = non-visible
|
||||
} portal_t;
|
||||
|
||||
typedef struct {
|
||||
node_t *headnode;
|
||||
node_t outside_node;
|
||||
vec3_t mins, maxs;
|
||||
} tree_t;
|
||||
|
||||
extern int entity_num;
|
||||
|
||||
|
||||
extern qboolean noprune;
|
||||
extern qboolean nodetail;
|
||||
extern qboolean fulldetail;
|
||||
extern qboolean nowater;
|
||||
extern qboolean noCurveBrushes;
|
||||
extern qboolean fakemap;
|
||||
extern qboolean coplanar;
|
||||
extern qboolean nofog;
|
||||
extern qboolean testExpand;
|
||||
extern qboolean showseams;
|
||||
|
||||
extern vec_t microvolume;
|
||||
|
||||
extern char outbase[32];
|
||||
extern char source[1024];
|
||||
|
||||
extern int samplesize; //sample size in units
|
||||
extern int novertexlighting;
|
||||
extern int nogridlighting;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// brush.c
|
||||
|
||||
int CountBrushList (bspbrush_t *brushes);
|
||||
bspbrush_t *AllocBrush (int numsides);
|
||||
void FreeBrush (bspbrush_t *brushes);
|
||||
void FreeBrushList (bspbrush_t *brushes);
|
||||
bspbrush_t *CopyBrush (bspbrush_t *brush);
|
||||
void DrawBrushList (bspbrush_t *brush);
|
||||
void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);
|
||||
void PrintBrush (bspbrush_t *brush);
|
||||
qboolean BoundBrush (bspbrush_t *brush);
|
||||
qboolean CreateBrushWindings (bspbrush_t *brush);
|
||||
bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs);
|
||||
vec_t BrushVolume (bspbrush_t *brush);
|
||||
void WriteBspBrushMap (char *name, bspbrush_t *list);
|
||||
|
||||
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
|
||||
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// map.c
|
||||
|
||||
extern int entitySourceBrushes;
|
||||
|
||||
// mapplanes[ num^1 ] will always be the mirror or mapplanes[ num ]
|
||||
// nummapplanes will always be even
|
||||
extern plane_t mapplanes[MAX_MAP_PLANES];
|
||||
extern int nummapplanes;
|
||||
|
||||
extern vec3_t map_mins, map_maxs;
|
||||
|
||||
extern char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH];
|
||||
extern int numMapIndexedShaders;
|
||||
|
||||
extern entity_t *mapent;
|
||||
|
||||
#define MAX_BUILD_SIDES 300
|
||||
extern bspbrush_t *buildBrush;
|
||||
|
||||
|
||||
void LoadMapFile (char *filename);
|
||||
int FindFloatPlane (vec3_t normal, vec_t dist);
|
||||
int PlaneTypeForNormal (vec3_t normal);
|
||||
bspbrush_t *FinishBrush( void );
|
||||
mapDrawSurface_t *AllocDrawSurf( void );
|
||||
mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// draw.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);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// csg
|
||||
|
||||
bspbrush_t *MakeBspBrushList ( bspbrush_t *brushes, vec3_t clipmins, vec3_t clipmaxs);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// brushbsp
|
||||
|
||||
#define PSIDE_FRONT 1
|
||||
#define PSIDE_BACK 2
|
||||
#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK)
|
||||
#define PSIDE_FACING 4
|
||||
|
||||
int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane);
|
||||
qboolean WindingIsTiny (winding_t *w);
|
||||
|
||||
void SplitBrush (bspbrush_t *brush, int planenum,
|
||||
bspbrush_t **front, bspbrush_t **back);
|
||||
|
||||
tree_t *AllocTree (void);
|
||||
node_t *AllocNode (void);
|
||||
|
||||
tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// portals.c
|
||||
|
||||
void MakeHeadnodePortals (tree_t *tree);
|
||||
void MakeNodePortal (node_t *node);
|
||||
void SplitNodePortals (node_t *node);
|
||||
|
||||
qboolean Portal_Passable(portal_t *p);
|
||||
|
||||
qboolean FloodEntities (tree_t *tree);
|
||||
void FillOutside (node_t *headnode);
|
||||
void FloodAreas (tree_t *tree);
|
||||
bspface_t *VisibleFaces(entity_t *e, tree_t *tree);
|
||||
void FreePortal (portal_t *p);
|
||||
|
||||
void MakeTreePortals (tree_t *tree);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// glfile.c
|
||||
|
||||
void OutputWinding( winding_t *w, FILE *glview );
|
||||
void WriteGLView( tree_t *tree, char *source );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// leakfile.c
|
||||
|
||||
void LeakFile( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// prtfile.c
|
||||
|
||||
void NumberClusters( tree_t *tree );
|
||||
void WritePortalFile( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// writebsp.c
|
||||
|
||||
void SetModelNumbers (void);
|
||||
void SetLightStyles (void);
|
||||
|
||||
int EmitShader( const char *shader );
|
||||
|
||||
void BeginBSPFile (void);
|
||||
void EndBSPFile (void);
|
||||
|
||||
void BeginModel (void);
|
||||
void EndModel( node_t *headnode );
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// tree.c
|
||||
|
||||
void FreeTree (tree_t *tree);
|
||||
void FreeTree_r (node_t *node);
|
||||
void PrintTree_r (node_t *node, int depth);
|
||||
void FreeTreePortals_r (node_t *node);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// patch.c
|
||||
|
||||
extern int numMapPatches;
|
||||
|
||||
mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m );
|
||||
void ParsePatch( void );
|
||||
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
|
||||
void PatchMapDrawSurfs( entity_t *e );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// lightmap.c
|
||||
|
||||
void AllocateLightmaps( entity_t *e );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// tjunction.c
|
||||
|
||||
void FixTJunctions( entity_t *e );
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// fog.c
|
||||
|
||||
void FogDrawSurfs( void );
|
||||
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// facebsp.c
|
||||
|
||||
bspface_t *BspFaceForPortal( portal_t *p );
|
||||
bspface_t *MakeStructuralBspFaceList( bspbrush_t *list );
|
||||
bspface_t *MakeVisibleBspFaceList( bspbrush_t *list );
|
||||
tree_t *FaceBSP( bspface_t *list );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// misc_model.c
|
||||
|
||||
extern int c_triangleModels;
|
||||
extern int c_triangleSurfaces;
|
||||
extern int c_triangleVertexes;
|
||||
extern int c_triangleIndexes;
|
||||
|
||||
void AddTriangleModels( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// surface.c
|
||||
|
||||
extern mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS];
|
||||
extern int numMapDrawSurfs;
|
||||
|
||||
mapDrawSurface_t *AllocDrawSurf( void );
|
||||
void MergeSides( entity_t *e, tree_t *tree );
|
||||
void SubdivideDrawSurfs( entity_t *e, tree_t *tree );
|
||||
void MakeDrawSurfaces( bspbrush_t *b );
|
||||
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
|
||||
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// brush_primit.c
|
||||
|
||||
#define BPRIMIT_UNDEFINED 0
|
||||
#define BPRIMIT_OLDBRUSHES 1
|
||||
#define BPRIMIT_NEWBRUSHES 2
|
||||
extern int g_bBrushPrimit;
|
||||
|
||||
void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY);
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "scriplib.h"
|
||||
#include "polylib.h"
|
||||
#include "imagelib.h"
|
||||
#include "threads.h"
|
||||
#include "bspfile.h"
|
||||
#include "shaders.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
#define MAX_PATCH_SIZE 32
|
||||
|
||||
#define CLIP_EPSILON 0.1
|
||||
#define PLANENUM_LEAF -1
|
||||
|
||||
#define HINT_PRIORITY 1000
|
||||
|
||||
typedef struct parseMesh_s {
|
||||
struct parseMesh_s *next;
|
||||
mesh_t mesh;
|
||||
shaderInfo_t *shaderInfo;
|
||||
|
||||
qboolean grouped; // used during shared edge grouping
|
||||
struct parseMesh_s *groupChain;
|
||||
} parseMesh_t;
|
||||
|
||||
typedef struct bspface_s {
|
||||
struct bspface_s *next;
|
||||
int planenum;
|
||||
int priority; // added to value calculation
|
||||
qboolean checked;
|
||||
qboolean hint;
|
||||
winding_t *w;
|
||||
} bspface_t;
|
||||
|
||||
typedef struct plane_s {
|
||||
vec3_t normal;
|
||||
vec_t dist;
|
||||
int type;
|
||||
struct plane_s *hash_chain;
|
||||
} plane_t;
|
||||
|
||||
typedef struct side_s {
|
||||
int planenum;
|
||||
|
||||
float texMat[2][3]; // brush primitive texture matrix
|
||||
// for old brush coordinates mode
|
||||
float vecs[2][4]; // texture coordinate mapping
|
||||
|
||||
winding_t *winding;
|
||||
winding_t *visibleHull; // convex hull of all visible fragments
|
||||
|
||||
struct shaderInfo_s *shaderInfo;
|
||||
|
||||
int contents; // from shaderInfo
|
||||
int surfaceFlags; // from shaderInfo
|
||||
int value; // from shaderInfo
|
||||
|
||||
qboolean visible; // choose visble planes first
|
||||
qboolean bevel; // don't ever use for bsp splitting, and don't bother
|
||||
// making windings for it
|
||||
qboolean backSide; // generated side for a q3map_backShader
|
||||
} side_t;
|
||||
|
||||
|
||||
#define MAX_BRUSH_SIDES 1024
|
||||
|
||||
typedef struct bspbrush_s {
|
||||
struct bspbrush_s *next;
|
||||
|
||||
int entitynum; // editor numbering
|
||||
int brushnum; // editor numbering
|
||||
|
||||
struct shaderInfo_s *contentShader;
|
||||
|
||||
int contents;
|
||||
qboolean detail;
|
||||
qboolean opaque;
|
||||
int outputNumber; // set when the brush is written to the file list
|
||||
|
||||
int portalareas[2];
|
||||
|
||||
struct bspbrush_s *original; // chopped up brushes will reference the originals
|
||||
|
||||
vec3_t mins, maxs;
|
||||
int numsides;
|
||||
side_t sides[6]; // variably sized
|
||||
} bspbrush_t;
|
||||
|
||||
|
||||
|
||||
typedef struct drawsurf_s {
|
||||
shaderInfo_t *shaderInfo;
|
||||
|
||||
bspbrush_t *mapBrush; // not valid for patches
|
||||
side_t *side; // not valid for patches
|
||||
|
||||
struct drawsurf_s *nextOnShader; // when sorting by shader for lightmaps
|
||||
|
||||
int fogNum; // set by FogDrawSurfs
|
||||
|
||||
int lightmapNum; // -1 = no lightmap
|
||||
int lightmapX, lightmapY;
|
||||
int lightmapWidth, lightmapHeight;
|
||||
|
||||
int numVerts;
|
||||
drawVert_t *verts;
|
||||
|
||||
int numIndexes;
|
||||
int *indexes;
|
||||
|
||||
// for faces only
|
||||
int planeNum;
|
||||
|
||||
vec3_t lightmapOrigin; // also used for flares
|
||||
vec3_t lightmapVecs[3]; // also used for flares
|
||||
|
||||
// for patches only
|
||||
qboolean patch;
|
||||
int patchWidth;
|
||||
int patchHeight;
|
||||
|
||||
// for misc_models only
|
||||
qboolean miscModel;
|
||||
|
||||
qboolean flareSurface;
|
||||
} mapDrawSurface_t;
|
||||
|
||||
typedef struct drawSurfRef_s {
|
||||
struct drawSurfRef_s *nextRef;
|
||||
int outputNumber;
|
||||
} drawSurfRef_t;
|
||||
|
||||
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
|
||||
side_t *side; // the side that created the node
|
||||
struct node_s *children[2];
|
||||
qboolean hint;
|
||||
int tinyportals;
|
||||
vec3_t referencepoint;
|
||||
|
||||
// leafs only
|
||||
qboolean opaque; // view can never be inside
|
||||
qboolean areaportal;
|
||||
int cluster; // for portalfile writing
|
||||
int area; // for areaportals
|
||||
bspbrush_t *brushlist; // fragments of all brushes in this leaf
|
||||
drawSurfRef_t *drawSurfReferences; // references to patches pushed down
|
||||
|
||||
int occupied; // 1 or greater can reach entity
|
||||
entity_t *occupant; // for leak file testing
|
||||
|
||||
struct portal_s *portals; // also on nodes during construction
|
||||
} node_t;
|
||||
|
||||
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
|
||||
qboolean hint;
|
||||
side_t *side; // NULL = non-visible
|
||||
} portal_t;
|
||||
|
||||
typedef struct {
|
||||
node_t *headnode;
|
||||
node_t outside_node;
|
||||
vec3_t mins, maxs;
|
||||
} tree_t;
|
||||
|
||||
extern int entity_num;
|
||||
|
||||
|
||||
extern qboolean noprune;
|
||||
extern qboolean nodetail;
|
||||
extern qboolean fulldetail;
|
||||
extern qboolean nowater;
|
||||
extern qboolean noCurveBrushes;
|
||||
extern qboolean fakemap;
|
||||
extern qboolean coplanar;
|
||||
extern qboolean nofog;
|
||||
extern qboolean testExpand;
|
||||
extern qboolean showseams;
|
||||
|
||||
extern vec_t microvolume;
|
||||
|
||||
extern char outbase[32];
|
||||
extern char source[1024];
|
||||
|
||||
extern int samplesize; //sample size in units
|
||||
extern int novertexlighting;
|
||||
extern int nogridlighting;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// brush.c
|
||||
|
||||
int CountBrushList (bspbrush_t *brushes);
|
||||
bspbrush_t *AllocBrush (int numsides);
|
||||
void FreeBrush (bspbrush_t *brushes);
|
||||
void FreeBrushList (bspbrush_t *brushes);
|
||||
bspbrush_t *CopyBrush (bspbrush_t *brush);
|
||||
void DrawBrushList (bspbrush_t *brush);
|
||||
void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);
|
||||
void PrintBrush (bspbrush_t *brush);
|
||||
qboolean BoundBrush (bspbrush_t *brush);
|
||||
qboolean CreateBrushWindings (bspbrush_t *brush);
|
||||
bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs);
|
||||
vec_t BrushVolume (bspbrush_t *brush);
|
||||
void WriteBspBrushMap (char *name, bspbrush_t *list);
|
||||
|
||||
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
|
||||
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// map.c
|
||||
|
||||
extern int entitySourceBrushes;
|
||||
|
||||
// mapplanes[ num^1 ] will always be the mirror or mapplanes[ num ]
|
||||
// nummapplanes will always be even
|
||||
extern plane_t mapplanes[MAX_MAP_PLANES];
|
||||
extern int nummapplanes;
|
||||
|
||||
extern vec3_t map_mins, map_maxs;
|
||||
|
||||
extern char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH];
|
||||
extern int numMapIndexedShaders;
|
||||
|
||||
extern entity_t *mapent;
|
||||
|
||||
#define MAX_BUILD_SIDES 300
|
||||
extern bspbrush_t *buildBrush;
|
||||
|
||||
|
||||
void LoadMapFile (char *filename);
|
||||
int FindFloatPlane (vec3_t normal, vec_t dist);
|
||||
int PlaneTypeForNormal (vec3_t normal);
|
||||
bspbrush_t *FinishBrush( void );
|
||||
mapDrawSurface_t *AllocDrawSurf( void );
|
||||
mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// draw.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);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// csg
|
||||
|
||||
bspbrush_t *MakeBspBrushList ( bspbrush_t *brushes, vec3_t clipmins, vec3_t clipmaxs);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// brushbsp
|
||||
|
||||
#define PSIDE_FRONT 1
|
||||
#define PSIDE_BACK 2
|
||||
#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK)
|
||||
#define PSIDE_FACING 4
|
||||
|
||||
int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane);
|
||||
qboolean WindingIsTiny (winding_t *w);
|
||||
|
||||
void SplitBrush (bspbrush_t *brush, int planenum,
|
||||
bspbrush_t **front, bspbrush_t **back);
|
||||
|
||||
tree_t *AllocTree (void);
|
||||
node_t *AllocNode (void);
|
||||
|
||||
tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// portals.c
|
||||
|
||||
void MakeHeadnodePortals (tree_t *tree);
|
||||
void MakeNodePortal (node_t *node);
|
||||
void SplitNodePortals (node_t *node);
|
||||
|
||||
qboolean Portal_Passable(portal_t *p);
|
||||
|
||||
qboolean FloodEntities (tree_t *tree);
|
||||
void FillOutside (node_t *headnode);
|
||||
void FloodAreas (tree_t *tree);
|
||||
bspface_t *VisibleFaces(entity_t *e, tree_t *tree);
|
||||
void FreePortal (portal_t *p);
|
||||
|
||||
void MakeTreePortals (tree_t *tree);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// glfile.c
|
||||
|
||||
void OutputWinding( winding_t *w, FILE *glview );
|
||||
void WriteGLView( tree_t *tree, char *source );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// leakfile.c
|
||||
|
||||
void LeakFile( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// prtfile.c
|
||||
|
||||
void NumberClusters( tree_t *tree );
|
||||
void WritePortalFile( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// writebsp.c
|
||||
|
||||
void SetModelNumbers (void);
|
||||
void SetLightStyles (void);
|
||||
|
||||
int EmitShader( const char *shader );
|
||||
|
||||
void BeginBSPFile (void);
|
||||
void EndBSPFile (void);
|
||||
|
||||
void BeginModel (void);
|
||||
void EndModel( node_t *headnode );
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// tree.c
|
||||
|
||||
void FreeTree (tree_t *tree);
|
||||
void FreeTree_r (node_t *node);
|
||||
void PrintTree_r (node_t *node, int depth);
|
||||
void FreeTreePortals_r (node_t *node);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// patch.c
|
||||
|
||||
extern int numMapPatches;
|
||||
|
||||
mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m );
|
||||
void ParsePatch( void );
|
||||
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
|
||||
void PatchMapDrawSurfs( entity_t *e );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// lightmap.c
|
||||
|
||||
void AllocateLightmaps( entity_t *e );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// tjunction.c
|
||||
|
||||
void FixTJunctions( entity_t *e );
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// fog.c
|
||||
|
||||
void FogDrawSurfs( void );
|
||||
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// facebsp.c
|
||||
|
||||
bspface_t *BspFaceForPortal( portal_t *p );
|
||||
bspface_t *MakeStructuralBspFaceList( bspbrush_t *list );
|
||||
bspface_t *MakeVisibleBspFaceList( bspbrush_t *list );
|
||||
tree_t *FaceBSP( bspface_t *list );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// misc_model.c
|
||||
|
||||
extern int c_triangleModels;
|
||||
extern int c_triangleSurfaces;
|
||||
extern int c_triangleVertexes;
|
||||
extern int c_triangleIndexes;
|
||||
|
||||
void AddTriangleModels( tree_t *tree );
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// surface.c
|
||||
|
||||
extern mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS];
|
||||
extern int numMapDrawSurfs;
|
||||
|
||||
mapDrawSurface_t *AllocDrawSurf( void );
|
||||
void MergeSides( entity_t *e, tree_t *tree );
|
||||
void SubdivideDrawSurfs( entity_t *e, tree_t *tree );
|
||||
void MakeDrawSurfaces( bspbrush_t *b );
|
||||
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
|
||||
void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
|
||||
|
||||
//==============================================================================
|
||||
|
||||
// brush_primit.c
|
||||
|
||||
#define BPRIMIT_UNDEFINED 0
|
||||
#define BPRIMIT_OLDBRUSHES 1
|
||||
#define BPRIMIT_NEWBRUSHES 2
|
||||
extern int g_bBrushPrimit;
|
||||
|
||||
void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY);
|
||||
|
|
1174
q3map/shaders.c
Normal file → Executable file
1174
q3map/shaders.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
100
q3map/shaders.h
Normal file → Executable file
100
q3map/shaders.h
Normal file → Executable file
|
@ -19,53 +19,53 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct shaderInfo_s {
|
||||
char shader[MAX_QPATH];
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
int value;
|
||||
|
||||
char backShader[MAX_QPATH]; // for surfaces that generate different front and back passes
|
||||
char flareShader[MAX_QPATH]; // for light flares
|
||||
|
||||
float subdivisions; // from a "tesssize xxx"
|
||||
float backsplashFraction; // floating point value, usually 0.05
|
||||
float backsplashDistance; // default 16
|
||||
float lightSubdivide; // default 120
|
||||
int lightmapSampleSize; // lightmap sample size
|
||||
|
||||
qboolean hasPasses; // false if the shader doesn't define any rendering passes
|
||||
|
||||
qboolean globalTexture; // don't normalize texture repeats
|
||||
|
||||
qboolean twoSided; // cull none
|
||||
qboolean autosprite; // autosprite shaders will become point lights
|
||||
// instead of area lights
|
||||
qboolean lightFilter; // light rays that cross surfaces of this type
|
||||
// should test against the filter image
|
||||
qboolean forceTraceLight; // always use -light for this surface
|
||||
qboolean forceVLight; // always use -vlight for this surface
|
||||
qboolean patchShadows; // have patches casting shadows when using -light for this surface
|
||||
qboolean vertexShadows; // shadows will be casted at this surface even when vertex lit
|
||||
qboolean noVertexShadows; // no shadows will be casted at this surface in vertex lighting
|
||||
qboolean forceSunLight; // force sun light at this surface even tho we might not calculate shadows in vertex lighting
|
||||
qboolean notjunc; // don't use this surface for tjunction fixing
|
||||
float vertexScale; // vertex light scale
|
||||
|
||||
char editorimage[MAX_QPATH]; // use this image to generate texture coordinates
|
||||
char lightimage[MAX_QPATH]; // use this image to generate color / averageColor
|
||||
vec3_t color; // colorNormalized
|
||||
vec3_t averageColor;
|
||||
|
||||
int width, height;
|
||||
byte *pixels;
|
||||
|
||||
vec3_t sunLight;
|
||||
vec3_t sunDirection;
|
||||
} shaderInfo_t;
|
||||
|
||||
void LoadShaderInfo( void );
|
||||
shaderInfo_t *ShaderInfoForShader( const char *shader );
|
||||
|
||||
|
||||
|
||||
typedef struct shaderInfo_s {
|
||||
char shader[MAX_QPATH];
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
int value;
|
||||
|
||||
char backShader[MAX_QPATH]; // for surfaces that generate different front and back passes
|
||||
char flareShader[MAX_QPATH]; // for light flares
|
||||
|
||||
float subdivisions; // from a "tesssize xxx"
|
||||
float backsplashFraction; // floating point value, usually 0.05
|
||||
float backsplashDistance; // default 16
|
||||
float lightSubdivide; // default 120
|
||||
int lightmapSampleSize; // lightmap sample size
|
||||
|
||||
qboolean hasPasses; // false if the shader doesn't define any rendering passes
|
||||
|
||||
qboolean globalTexture; // don't normalize texture repeats
|
||||
|
||||
qboolean twoSided; // cull none
|
||||
qboolean autosprite; // autosprite shaders will become point lights
|
||||
// instead of area lights
|
||||
qboolean lightFilter; // light rays that cross surfaces of this type
|
||||
// should test against the filter image
|
||||
qboolean forceTraceLight; // always use -light for this surface
|
||||
qboolean forceVLight; // always use -vlight for this surface
|
||||
qboolean patchShadows; // have patches casting shadows when using -light for this surface
|
||||
qboolean vertexShadows; // shadows will be casted at this surface even when vertex lit
|
||||
qboolean noVertexShadows; // no shadows will be casted at this surface in vertex lighting
|
||||
qboolean forceSunLight; // force sun light at this surface even tho we might not calculate shadows in vertex lighting
|
||||
qboolean notjunc; // don't use this surface for tjunction fixing
|
||||
float vertexScale; // vertex light scale
|
||||
|
||||
char editorimage[MAX_QPATH]; // use this image to generate texture coordinates
|
||||
char lightimage[MAX_QPATH]; // use this image to generate color / averageColor
|
||||
vec3_t color; // colorNormalized
|
||||
vec3_t averageColor;
|
||||
|
||||
int width, height;
|
||||
byte *pixels;
|
||||
|
||||
vec3_t sunLight;
|
||||
vec3_t sunDirection;
|
||||
} shaderInfo_t;
|
||||
|
||||
void LoadShaderInfo( void );
|
||||
shaderInfo_t *ShaderInfoForShader( const char *shader );
|
||||
|
||||
|
|
11442
q3map/soundv.c
Normal file → Executable file
11442
q3map/soundv.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2274
q3map/surface.c
Normal file → Executable file
2274
q3map/surface.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2468
q3map/terrain.c
Normal file → Executable file
2468
q3map/terrain.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1060
q3map/tjunction.c
Normal file → Executable file
1060
q3map/tjunction.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
250
q3map/tree.c
Normal file → Executable file
250
q3map/tree.c
Normal file → Executable file
|
@ -19,128 +19,128 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
extern int c_nodes;
|
||||
|
||||
void RemovePortalFromNode (portal_t *portal, node_t *l);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTreePortals_r
|
||||
=============
|
||||
*/
|
||||
void FreeTreePortals_r (node_t *node)
|
||||
{
|
||||
portal_t *p, *nextp;
|
||||
int s;
|
||||
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTreePortals_r (node->children[0]);
|
||||
FreeTreePortals_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]);
|
||||
FreePortal (p);
|
||||
}
|
||||
node->portals = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree_r
|
||||
=============
|
||||
*/
|
||||
void FreeTree_r (node_t *node)
|
||||
{
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTree_r (node->children[0]);
|
||||
FreeTree_r (node->children[1]);
|
||||
}
|
||||
|
||||
// free bspbrushes
|
||||
FreeBrushList (node->brushlist);
|
||||
|
||||
// free the node
|
||||
if (node->volume)
|
||||
FreeBrush (node->volume);
|
||||
|
||||
if (numthreads == 1)
|
||||
c_nodes--;
|
||||
free (node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree
|
||||
=============
|
||||
*/
|
||||
void FreeTree (tree_t *tree)
|
||||
{
|
||||
FreeTreePortals_r (tree->headnode);
|
||||
FreeTree_r (tree->headnode);
|
||||
free (tree);
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
void PrintTree_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);
|
||||
PrintTree_r (node->children[0], depth+1);
|
||||
PrintTree_r (node->children[1], depth+1);
|
||||
}
|
||||
#include "qbsp.h"
|
||||
|
||||
|
||||
extern int c_nodes;
|
||||
|
||||
void RemovePortalFromNode (portal_t *portal, node_t *l);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTreePortals_r
|
||||
=============
|
||||
*/
|
||||
void FreeTreePortals_r (node_t *node)
|
||||
{
|
||||
portal_t *p, *nextp;
|
||||
int s;
|
||||
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTreePortals_r (node->children[0]);
|
||||
FreeTreePortals_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]);
|
||||
FreePortal (p);
|
||||
}
|
||||
node->portals = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree_r
|
||||
=============
|
||||
*/
|
||||
void FreeTree_r (node_t *node)
|
||||
{
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTree_r (node->children[0]);
|
||||
FreeTree_r (node->children[1]);
|
||||
}
|
||||
|
||||
// free bspbrushes
|
||||
FreeBrushList (node->brushlist);
|
||||
|
||||
// free the node
|
||||
if (node->volume)
|
||||
FreeBrush (node->volume);
|
||||
|
||||
if (numthreads == 1)
|
||||
c_nodes--;
|
||||
free (node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree
|
||||
=============
|
||||
*/
|
||||
void FreeTree (tree_t *tree)
|
||||
{
|
||||
FreeTreePortals_r (tree->headnode);
|
||||
FreeTree_r (tree->headnode);
|
||||
free (tree);
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
void PrintTree_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);
|
||||
PrintTree_r (node->children[0], depth+1);
|
||||
PrintTree_r (node->children[1], depth+1);
|
||||
}
|
||||
|
|
2352
q3map/vis.c
Normal file → Executable file
2352
q3map/vis.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
282
q3map/vis.h
Normal file → Executable file
282
q3map/vis.h
Normal file → Executable file
|
@ -19,144 +19,144 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// vis.h
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
|
||||
#define MAX_PORTALS 32768
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
|
||||
#define ON_EPSILON 0.1
|
||||
|
||||
//#define MREDEBUG
|
||||
|
||||
// seperator caching helps a bit
|
||||
#define SEPERATORCACHE
|
||||
|
||||
// can't have more seperators than the max number of points on a winding
|
||||
#define MAX_SEPERATORS 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
} plane_t;
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 64
|
||||
#define MAX_POINTS_ON_FIXED_WINDING 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numpoints;
|
||||
vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
winding_t *NewWinding (int points);
|
||||
void FreeWinding (winding_t *w);
|
||||
winding_t *CopyWinding (winding_t *w);
|
||||
|
||||
|
||||
typedef struct passage_s
|
||||
{
|
||||
struct passage_s *next;
|
||||
byte cansee[1]; //all portals that can be seen through this passage
|
||||
} passage_t;
|
||||
|
||||
typedef enum {stat_none, stat_working, stat_done} vstatus_t;
|
||||
typedef struct
|
||||
{
|
||||
int num;
|
||||
qboolean hint; // true if this portal was created from a hint splitter
|
||||
qboolean removed;
|
||||
plane_t plane; // normal pointing into neighbor
|
||||
int leaf; // neighbor
|
||||
|
||||
vec3_t origin; // for fast clip testing
|
||||
float radius;
|
||||
|
||||
winding_t *winding;
|
||||
vstatus_t status;
|
||||
byte *portalfront; // [portals], preliminary
|
||||
byte *portalflood; // [portals], intermediate
|
||||
byte *portalvis; // [portals], final
|
||||
|
||||
int nummightsee; // bit count on portalflood for sort
|
||||
passage_t *passages; // there are just as many passages as there
|
||||
// are portals in the leaf this portal leads to
|
||||
} vportal_t;
|
||||
|
||||
#define MAX_PORTALS_ON_LEAF 128
|
||||
typedef struct leaf_s
|
||||
{
|
||||
int numportals;
|
||||
int merged;
|
||||
vportal_t *portals[MAX_PORTALS_ON_LEAF];
|
||||
} leaf_t;
|
||||
|
||||
|
||||
typedef struct pstack_s
|
||||
{
|
||||
byte mightsee[MAX_PORTALS/8]; // bit string
|
||||
struct pstack_s *next;
|
||||
leaf_t *leaf;
|
||||
vportal_t *portal; // portal exiting
|
||||
winding_t *source;
|
||||
winding_t *pass;
|
||||
|
||||
winding_t windings[3]; // source, pass, temp in any order
|
||||
int freewindings[3];
|
||||
|
||||
plane_t portalplane;
|
||||
int depth;
|
||||
#ifdef SEPERATORCACHE
|
||||
plane_t seperators[2][MAX_SEPERATORS];
|
||||
int numseperators[2];
|
||||
#endif
|
||||
} pstack_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vportal_t *base;
|
||||
int c_chains;
|
||||
pstack_t pstack_head;
|
||||
} threaddata_t;
|
||||
|
||||
|
||||
|
||||
extern int numportals;
|
||||
extern int portalclusters;
|
||||
|
||||
extern vportal_t *portals;
|
||||
extern leaf_t *leafs;
|
||||
|
||||
extern int c_portaltest, c_portalpass, c_portalcheck;
|
||||
extern int c_portalskip, c_leafskip;
|
||||
extern int c_vistest, c_mighttest;
|
||||
extern int c_chains;
|
||||
|
||||
extern byte *vismap, *vismap_p, *vismap_end; // past visfile
|
||||
|
||||
extern int testlevel;
|
||||
|
||||
extern byte *uncompressed;
|
||||
|
||||
extern int leafbytes, leaflongs;
|
||||
extern int portalbytes, portallongs;
|
||||
|
||||
|
||||
void LeafFlow (int leafnum);
|
||||
|
||||
|
||||
void BasePortalVis(int portalnum);
|
||||
void BetterPortalVis(int portalnum);
|
||||
void PortalFlow(int portalnum);
|
||||
void PassagePortalFlow(int portalnum);
|
||||
void CreatePassages(int portalnum);
|
||||
void PassageFlow(int portalnum);
|
||||
|
||||
extern vportal_t *sorted_portals[MAX_MAP_PORTALS*2];
|
||||
|
||||
int CountBits (byte *bits, int numbits);
|
||||
// vis.h
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "bspfile.h"
|
||||
|
||||
#define MAX_PORTALS 32768
|
||||
|
||||
#define PORTALFILE "PRT1"
|
||||
|
||||
#define ON_EPSILON 0.1
|
||||
|
||||
//#define MREDEBUG
|
||||
|
||||
// seperator caching helps a bit
|
||||
#define SEPERATORCACHE
|
||||
|
||||
// can't have more seperators than the max number of points on a winding
|
||||
#define MAX_SEPERATORS 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
} plane_t;
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 64
|
||||
#define MAX_POINTS_ON_FIXED_WINDING 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numpoints;
|
||||
vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
winding_t *NewWinding (int points);
|
||||
void FreeWinding (winding_t *w);
|
||||
winding_t *CopyWinding (winding_t *w);
|
||||
|
||||
|
||||
typedef struct passage_s
|
||||
{
|
||||
struct passage_s *next;
|
||||
byte cansee[1]; //all portals that can be seen through this passage
|
||||
} passage_t;
|
||||
|
||||
typedef enum {stat_none, stat_working, stat_done} vstatus_t;
|
||||
typedef struct
|
||||
{
|
||||
int num;
|
||||
qboolean hint; // true if this portal was created from a hint splitter
|
||||
qboolean removed;
|
||||
plane_t plane; // normal pointing into neighbor
|
||||
int leaf; // neighbor
|
||||
|
||||
vec3_t origin; // for fast clip testing
|
||||
float radius;
|
||||
|
||||
winding_t *winding;
|
||||
vstatus_t status;
|
||||
byte *portalfront; // [portals], preliminary
|
||||
byte *portalflood; // [portals], intermediate
|
||||
byte *portalvis; // [portals], final
|
||||
|
||||
int nummightsee; // bit count on portalflood for sort
|
||||
passage_t *passages; // there are just as many passages as there
|
||||
// are portals in the leaf this portal leads to
|
||||
} vportal_t;
|
||||
|
||||
#define MAX_PORTALS_ON_LEAF 128
|
||||
typedef struct leaf_s
|
||||
{
|
||||
int numportals;
|
||||
int merged;
|
||||
vportal_t *portals[MAX_PORTALS_ON_LEAF];
|
||||
} leaf_t;
|
||||
|
||||
|
||||
typedef struct pstack_s
|
||||
{
|
||||
byte mightsee[MAX_PORTALS/8]; // bit string
|
||||
struct pstack_s *next;
|
||||
leaf_t *leaf;
|
||||
vportal_t *portal; // portal exiting
|
||||
winding_t *source;
|
||||
winding_t *pass;
|
||||
|
||||
winding_t windings[3]; // source, pass, temp in any order
|
||||
int freewindings[3];
|
||||
|
||||
plane_t portalplane;
|
||||
int depth;
|
||||
#ifdef SEPERATORCACHE
|
||||
plane_t seperators[2][MAX_SEPERATORS];
|
||||
int numseperators[2];
|
||||
#endif
|
||||
} pstack_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vportal_t *base;
|
||||
int c_chains;
|
||||
pstack_t pstack_head;
|
||||
} threaddata_t;
|
||||
|
||||
|
||||
|
||||
extern int numportals;
|
||||
extern int portalclusters;
|
||||
|
||||
extern vportal_t *portals;
|
||||
extern leaf_t *leafs;
|
||||
|
||||
extern int c_portaltest, c_portalpass, c_portalcheck;
|
||||
extern int c_portalskip, c_leafskip;
|
||||
extern int c_vistest, c_mighttest;
|
||||
extern int c_chains;
|
||||
|
||||
extern byte *vismap, *vismap_p, *vismap_end; // past visfile
|
||||
|
||||
extern int testlevel;
|
||||
|
||||
extern byte *uncompressed;
|
||||
|
||||
extern int leafbytes, leaflongs;
|
||||
extern int portalbytes, portallongs;
|
||||
|
||||
|
||||
void LeafFlow (int leafnum);
|
||||
|
||||
|
||||
void BasePortalVis(int portalnum);
|
||||
void BetterPortalVis(int portalnum);
|
||||
void PortalFlow(int portalnum);
|
||||
void PassagePortalFlow(int portalnum);
|
||||
void CreatePassages(int portalnum);
|
||||
void PassageFlow(int portalnum);
|
||||
|
||||
extern vportal_t *sorted_portals[MAX_MAP_PORTALS*2];
|
||||
|
||||
int CountBits (byte *bits, int numbits);
|
||||
|
|
3272
q3map/visflow.c
Normal file → Executable file
3272
q3map/visflow.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
794
q3map/writebsp.c
Normal file → Executable file
794
q3map/writebsp.c
Normal file → Executable file
|
@ -19,400 +19,400 @@ along with Foobar; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "qbsp.h"
|
||||
|
||||
/*
|
||||
============
|
||||
EmitShader
|
||||
============
|
||||
*/
|
||||
int EmitShader( const char *shader ) {
|
||||
int i;
|
||||
shaderInfo_t *si;
|
||||
|
||||
if ( !shader ) {
|
||||
shader = "noshader";
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < numShaders ; i++ ) {
|
||||
if ( !Q_stricmp( shader, dshaders[i].shader ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == MAX_MAP_SHADERS ) {
|
||||
Error( "MAX_MAP_SHADERS" );
|
||||
}
|
||||
numShaders++;
|
||||
strcpy( dshaders[i].shader, shader );
|
||||
|
||||
si = ShaderInfoForShader( shader );
|
||||
dshaders[i].surfaceFlags = si->surfaceFlags;
|
||||
dshaders[i].contentFlags = si->contents;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
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;
|
||||
|
||||
mp = mapplanes;
|
||||
for (i=0 ; i<nummapplanes ; i++, mp++)
|
||||
{
|
||||
dp = &dplanes[numplanes];
|
||||
VectorCopy ( mp->normal, dp->normal);
|
||||
dp->dist = mp->dist;
|
||||
numplanes++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
EmitLeaf
|
||||
==================
|
||||
*/
|
||||
void EmitLeaf (node_t *node)
|
||||
{
|
||||
dleaf_t *leaf_p;
|
||||
bspbrush_t *b;
|
||||
drawSurfRef_t *dsr;
|
||||
|
||||
// emit a leaf
|
||||
if (numleafs >= MAX_MAP_LEAFS)
|
||||
Error ("MAX_MAP_LEAFS");
|
||||
|
||||
leaf_p = &dleafs[numleafs];
|
||||
numleafs++;
|
||||
|
||||
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" );
|
||||
}
|
||||
dleafbrushes[numleafbrushes] = b->original->outputNumber;
|
||||
numleafbrushes++;
|
||||
}
|
||||
leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush;
|
||||
|
||||
//
|
||||
// write the surfaces visible in this leaf
|
||||
//
|
||||
if ( node->opaque ) {
|
||||
return; // no leaffaces in solids
|
||||
}
|
||||
|
||||
// add the drawSurfRef_t drawsurfs
|
||||
leaf_p->firstLeafSurface = numleafsurfaces;
|
||||
for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) {
|
||||
if ( numleafsurfaces >= MAX_MAP_LEAFFACES)
|
||||
Error ("MAX_MAP_LEAFFACES");
|
||||
dleafsurfaces[numleafsurfaces] = dsr->outputNumber;
|
||||
numleafsurfaces++;
|
||||
}
|
||||
|
||||
|
||||
leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
EmitDrawNode_r
|
||||
============
|
||||
*/
|
||||
int EmitDrawNode_r (node_t *node)
|
||||
{
|
||||
dnode_t *n;
|
||||
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);
|
||||
|
||||
if (node->planenum & 1)
|
||||
Error ("WriteDrawNodes_r: odd planenum");
|
||||
n->planeNum = node->planenum;
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
SetModelNumbers
|
||||
============
|
||||
*/
|
||||
void SetModelNumbers (void)
|
||||
{
|
||||
int i;
|
||||
int models;
|
||||
char value[10];
|
||||
|
||||
models = 1;
|
||||
for ( i=1 ; i<num_entities ; i++ ) {
|
||||
if ( entities[i].brushes || entities[i].patches ) {
|
||||
sprintf ( value, "*%i", models );
|
||||
models++;
|
||||
SetKeyValue (&entities[i], "model", value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
SetLightStyles
|
||||
============
|
||||
*/
|
||||
#define MAX_SWITCHED_LIGHTS 32
|
||||
void SetLightStyles (void)
|
||||
{
|
||||
int stylenum;
|
||||
const 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginBSPFile
|
||||
==================
|
||||
*/
|
||||
void BeginBSPFile( void ) {
|
||||
// these values may actually be initialized
|
||||
// if the file existed when loaded, so clear them explicitly
|
||||
nummodels = 0;
|
||||
numnodes = 0;
|
||||
numbrushsides = 0;
|
||||
numleafsurfaces = 0;
|
||||
numleafbrushes = 0;
|
||||
|
||||
// leave leaf 0 as an error, because leafs are referenced as
|
||||
// negative number nodes
|
||||
numleafs = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
EndBSPFile
|
||||
============
|
||||
*/
|
||||
void EndBSPFile( void ) {
|
||||
char path[1024];
|
||||
|
||||
EmitPlanes ();
|
||||
UnparseEntities ();
|
||||
|
||||
// write the map
|
||||
sprintf (path, "%s.bsp", source);
|
||||
_printf ("Writing %s\n", path);
|
||||
WriteBSPFile (path);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
============
|
||||
EmitBrushes
|
||||
============
|
||||
*/
|
||||
void EmitBrushes ( bspbrush_t *brushes ) {
|
||||
int j;
|
||||
dbrush_t *db;
|
||||
bspbrush_t *b;
|
||||
dbrushside_t *cp;
|
||||
|
||||
for ( b = brushes ; b ; b = b->next ) {
|
||||
if ( numbrushes == MAX_MAP_BRUSHES ) {
|
||||
Error( "MAX_MAP_BRUSHES" );
|
||||
}
|
||||
b->outputNumber = numbrushes;
|
||||
db = &dbrushes[numbrushes];
|
||||
numbrushes++;
|
||||
|
||||
db->shaderNum = EmitShader( b->contentShader->shader );
|
||||
db->firstSide = numbrushsides;
|
||||
|
||||
// don't emit any generated backSide sides
|
||||
db->numSides = 0;
|
||||
for ( j=0 ; j<b->numsides ; j++ ) {
|
||||
if ( b->sides[j].backSide ) {
|
||||
continue;
|
||||
}
|
||||
if ( numbrushsides == MAX_MAP_BRUSHSIDES ) {
|
||||
Error( "MAX_MAP_BRUSHSIDES ");
|
||||
}
|
||||
cp = &dbrushsides[numbrushsides];
|
||||
db->numSides++;
|
||||
numbrushsides++;
|
||||
cp->planeNum = b->sides[j].planenum;
|
||||
cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginModel
|
||||
==================
|
||||
*/
|
||||
void BeginModel( void ) {
|
||||
dmodel_t *mod;
|
||||
bspbrush_t *b;
|
||||
entity_t *e;
|
||||
vec3_t mins, maxs;
|
||||
parseMesh_t *p;
|
||||
int i;
|
||||
|
||||
if ( nummodels == MAX_MAP_MODELS ) {
|
||||
Error( "MAX_MAP_MODELS" );
|
||||
}
|
||||
mod = &dmodels[nummodels];
|
||||
|
||||
//
|
||||
// bound the brushes
|
||||
//
|
||||
e = &entities[entity_num];
|
||||
|
||||
ClearBounds (mins, maxs);
|
||||
for ( b = e->brushes ; b ; b = b->next ) {
|
||||
if ( !b->numsides ) {
|
||||
continue; // not a real brush (origin brush, etc)
|
||||
}
|
||||
AddPointToBounds (b->mins, mins, maxs);
|
||||
AddPointToBounds (b->maxs, mins, maxs);
|
||||
}
|
||||
|
||||
for ( p = e->patches ; p ; p = p->next ) {
|
||||
for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) {
|
||||
AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy (mins, mod->mins);
|
||||
VectorCopy (maxs, mod->maxs);
|
||||
|
||||
mod->firstSurface = numDrawSurfaces;
|
||||
mod->firstBrush = numbrushes;
|
||||
|
||||
EmitBrushes( e->brushes );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
EndModel
|
||||
==================
|
||||
*/
|
||||
void EndModel( node_t *headnode ) {
|
||||
dmodel_t *mod;
|
||||
|
||||
qprintf ("--- EndModel ---\n");
|
||||
|
||||
mod = &dmodels[nummodels];
|
||||
EmitDrawNode_r (headnode);
|
||||
mod->numSurfaces = numDrawSurfaces - mod->firstSurface;
|
||||
mod->numBrushes = numbrushes - mod->firstBrush;
|
||||
|
||||
nummodels++;
|
||||
}
|
||||
|
||||
#include "qbsp.h"
|
||||
|
||||
/*
|
||||
============
|
||||
EmitShader
|
||||
============
|
||||
*/
|
||||
int EmitShader( const char *shader ) {
|
||||
int i;
|
||||
shaderInfo_t *si;
|
||||
|
||||
if ( !shader ) {
|
||||
shader = "noshader";
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < numShaders ; i++ ) {
|
||||
if ( !Q_stricmp( shader, dshaders[i].shader ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == MAX_MAP_SHADERS ) {
|
||||
Error( "MAX_MAP_SHADERS" );
|
||||
}
|
||||
numShaders++;
|
||||
strcpy( dshaders[i].shader, shader );
|
||||
|
||||
si = ShaderInfoForShader( shader );
|
||||
dshaders[i].surfaceFlags = si->surfaceFlags;
|
||||
dshaders[i].contentFlags = si->contents;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
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;
|
||||
|
||||
mp = mapplanes;
|
||||
for (i=0 ; i<nummapplanes ; i++, mp++)
|
||||
{
|
||||
dp = &dplanes[numplanes];
|
||||
VectorCopy ( mp->normal, dp->normal);
|
||||
dp->dist = mp->dist;
|
||||
numplanes++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
EmitLeaf
|
||||
==================
|
||||
*/
|
||||
void EmitLeaf (node_t *node)
|
||||
{
|
||||
dleaf_t *leaf_p;
|
||||
bspbrush_t *b;
|
||||
drawSurfRef_t *dsr;
|
||||
|
||||
// emit a leaf
|
||||
if (numleafs >= MAX_MAP_LEAFS)
|
||||
Error ("MAX_MAP_LEAFS");
|
||||
|
||||
leaf_p = &dleafs[numleafs];
|
||||
numleafs++;
|
||||
|
||||
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" );
|
||||
}
|
||||
dleafbrushes[numleafbrushes] = b->original->outputNumber;
|
||||
numleafbrushes++;
|
||||
}
|
||||
leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush;
|
||||
|
||||
//
|
||||
// write the surfaces visible in this leaf
|
||||
//
|
||||
if ( node->opaque ) {
|
||||
return; // no leaffaces in solids
|
||||
}
|
||||
|
||||
// add the drawSurfRef_t drawsurfs
|
||||
leaf_p->firstLeafSurface = numleafsurfaces;
|
||||
for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) {
|
||||
if ( numleafsurfaces >= MAX_MAP_LEAFFACES)
|
||||
Error ("MAX_MAP_LEAFFACES");
|
||||
dleafsurfaces[numleafsurfaces] = dsr->outputNumber;
|
||||
numleafsurfaces++;
|
||||
}
|
||||
|
||||
|
||||
leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
EmitDrawNode_r
|
||||
============
|
||||
*/
|
||||
int EmitDrawNode_r (node_t *node)
|
||||
{
|
||||
dnode_t *n;
|
||||
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);
|
||||
|
||||
if (node->planenum & 1)
|
||||
Error ("WriteDrawNodes_r: odd planenum");
|
||||
n->planeNum = node->planenum;
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
SetModelNumbers
|
||||
============
|
||||
*/
|
||||
void SetModelNumbers (void)
|
||||
{
|
||||
int i;
|
||||
int models;
|
||||
char value[10];
|
||||
|
||||
models = 1;
|
||||
for ( i=1 ; i<num_entities ; i++ ) {
|
||||
if ( entities[i].brushes || entities[i].patches ) {
|
||||
sprintf ( value, "*%i", models );
|
||||
models++;
|
||||
SetKeyValue (&entities[i], "model", value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
SetLightStyles
|
||||
============
|
||||
*/
|
||||
#define MAX_SWITCHED_LIGHTS 32
|
||||
void SetLightStyles (void)
|
||||
{
|
||||
int stylenum;
|
||||
const 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginBSPFile
|
||||
==================
|
||||
*/
|
||||
void BeginBSPFile( void ) {
|
||||
// these values may actually be initialized
|
||||
// if the file existed when loaded, so clear them explicitly
|
||||
nummodels = 0;
|
||||
numnodes = 0;
|
||||
numbrushsides = 0;
|
||||
numleafsurfaces = 0;
|
||||
numleafbrushes = 0;
|
||||
|
||||
// leave leaf 0 as an error, because leafs are referenced as
|
||||
// negative number nodes
|
||||
numleafs = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
EndBSPFile
|
||||
============
|
||||
*/
|
||||
void EndBSPFile( void ) {
|
||||
char path[1024];
|
||||
|
||||
EmitPlanes ();
|
||||
UnparseEntities ();
|
||||
|
||||
// write the map
|
||||
sprintf (path, "%s.bsp", source);
|
||||
_printf ("Writing %s\n", path);
|
||||
WriteBSPFile (path);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*
|
||||
============
|
||||
EmitBrushes
|
||||
============
|
||||
*/
|
||||
void EmitBrushes ( bspbrush_t *brushes ) {
|
||||
int j;
|
||||
dbrush_t *db;
|
||||
bspbrush_t *b;
|
||||
dbrushside_t *cp;
|
||||
|
||||
for ( b = brushes ; b ; b = b->next ) {
|
||||
if ( numbrushes == MAX_MAP_BRUSHES ) {
|
||||
Error( "MAX_MAP_BRUSHES" );
|
||||
}
|
||||
b->outputNumber = numbrushes;
|
||||
db = &dbrushes[numbrushes];
|
||||
numbrushes++;
|
||||
|
||||
db->shaderNum = EmitShader( b->contentShader->shader );
|
||||
db->firstSide = numbrushsides;
|
||||
|
||||
// don't emit any generated backSide sides
|
||||
db->numSides = 0;
|
||||
for ( j=0 ; j<b->numsides ; j++ ) {
|
||||
if ( b->sides[j].backSide ) {
|
||||
continue;
|
||||
}
|
||||
if ( numbrushsides == MAX_MAP_BRUSHSIDES ) {
|
||||
Error( "MAX_MAP_BRUSHSIDES ");
|
||||
}
|
||||
cp = &dbrushsides[numbrushsides];
|
||||
db->numSides++;
|
||||
numbrushsides++;
|
||||
cp->planeNum = b->sides[j].planenum;
|
||||
cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
BeginModel
|
||||
==================
|
||||
*/
|
||||
void BeginModel( void ) {
|
||||
dmodel_t *mod;
|
||||
bspbrush_t *b;
|
||||
entity_t *e;
|
||||
vec3_t mins, maxs;
|
||||
parseMesh_t *p;
|
||||
int i;
|
||||
|
||||
if ( nummodels == MAX_MAP_MODELS ) {
|
||||
Error( "MAX_MAP_MODELS" );
|
||||
}
|
||||
mod = &dmodels[nummodels];
|
||||
|
||||
//
|
||||
// bound the brushes
|
||||
//
|
||||
e = &entities[entity_num];
|
||||
|
||||
ClearBounds (mins, maxs);
|
||||
for ( b = e->brushes ; b ; b = b->next ) {
|
||||
if ( !b->numsides ) {
|
||||
continue; // not a real brush (origin brush, etc)
|
||||
}
|
||||
AddPointToBounds (b->mins, mins, maxs);
|
||||
AddPointToBounds (b->maxs, mins, maxs);
|
||||
}
|
||||
|
||||
for ( p = e->patches ; p ; p = p->next ) {
|
||||
for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) {
|
||||
AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy (mins, mod->mins);
|
||||
VectorCopy (maxs, mod->maxs);
|
||||
|
||||
mod->firstSurface = numDrawSurfaces;
|
||||
mod->firstBrush = numbrushes;
|
||||
|
||||
EmitBrushes( e->brushes );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
EndModel
|
||||
==================
|
||||
*/
|
||||
void EndModel( node_t *headnode ) {
|
||||
dmodel_t *mod;
|
||||
|
||||
qprintf ("--- EndModel ---\n");
|
||||
|
||||
mod = &dmodels[nummodels];
|
||||
EmitDrawNode_r (headnode);
|
||||
mod->numSurfaces = numDrawSurfaces - mod->firstSurface;
|
||||
mod->numBrushes = numbrushes - mod->firstBrush;
|
||||
|
||||
nummodels++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue