Itsa me, quake3io!

This commit is contained in:
Zachary Slater 2005-08-26 04:48:05 +00:00
parent dbe4ddb103
commit 5b755058f5
1409 changed files with 798983 additions and 798983 deletions

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

File diff suppressed because it is too large Load diff

716
q3map/facebsp.c Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

422
q3map/gldraw.c Normal file → Executable file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

260
q3map/light.h Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

748
q3map/lightmaps.c Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

296
q3map/makefile Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

502
q3map/prtfile.c Normal file → Executable file
View 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
View 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

File diff suppressed because it is too large Load diff

868
q3map/qbsp.h Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

100
q3map/shaders.h Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

282
q3map/vis.h Normal file → Executable file
View 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

File diff suppressed because it is too large Load diff

794
q3map/writebsp.c Normal file → Executable file
View 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++;
}