The GtkRadiant sources as originally released under the GPL license.

This commit is contained in:
Travis Bradshaw
2012-01-31 15:20:35 -06:00
commit 0991a5ce8b
1590 changed files with 431941 additions and 0 deletions

View File

@@ -0,0 +1,789 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; 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 "scriplib.h"
#include "inout.h"
void GetLeafNums (void);
//=============================================================================
int nummodels;
dmodel_t dmodels[MAX_MAP_MODELS];
int visdatasize;
byte dvisdata[MAX_MAP_VISIBILITY];
dvis_t *dvis = (dvis_t *)dvisdata;
int lightdatasize;
byte dlightdata[MAX_MAP_LIGHTING];
int entdatasize;
char dentdata[MAX_MAP_ENTSTRING];
int numleafs;
dleaf_t dleafs[MAX_MAP_LEAFS];
int numplanes;
dplane_t dplanes[MAX_MAP_PLANES];
int numvertexes;
dvertex_t dvertexes[MAX_MAP_VERTS];
int numnodes;
dnode_t dnodes[MAX_MAP_NODES];
int numtexinfo;
texinfo_t texinfo[MAX_MAP_TEXINFO];
int numfaces;
dface_t dfaces[MAX_MAP_FACES];
int numedges;
dedge_t dedges[MAX_MAP_EDGES];
int numleaffaces;
unsigned short dleaffaces[MAX_MAP_LEAFFACES];
int numleafbrushes;
unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
int numsurfedges;
int dsurfedges[MAX_MAP_SURFEDGES];
int numbrushes;
dbrush_t dbrushes[MAX_MAP_BRUSHES];
int numbrushsides;
dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
int numareas;
darea_t dareas[MAX_MAP_AREAS];
int numareaportals;
dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
byte dpop[256];
/*
===============
CompressVis
===============
*/
int CompressVis (byte *vis, byte *dest)
{
int j;
int rep;
int visrow;
byte *dest_p;
dest_p = dest;
// visrow = (r_numvisleafs + 7)>>3;
visrow = (dvis->numclusters + 7)>>3;
for (j=0 ; j<visrow ; j++)
{
*dest_p++ = vis[j];
if (vis[j])
continue;
rep = 1;
for ( j++; j<visrow ; j++)
if (vis[j] || rep == 255)
break;
else
rep++;
*dest_p++ = rep;
j--;
}
return dest_p - dest;
}
/*
===================
DecompressVis
===================
*/
void DecompressVis (byte *in, byte *decompressed)
{
int c;
byte *out;
int row;
// row = (r_numvisleafs+7)>>3;
row = (dvis->numclusters+7)>>3;
out = decompressed;
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
if (!c)
Error ("DecompressVis: 0 repeat");
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
}
//=============================================================================
/*
=============
SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void SwapBSPFile (qboolean todisk)
{
int i, j;
dmodel_t *d;
// models
for (i=0 ; i<nummodels ; i++)
{
d = &dmodels[i];
d->firstface = LittleLong (d->firstface);
d->numfaces = LittleLong (d->numfaces);
d->headnode = LittleLong (d->headnode);
for (j=0 ; j<3 ; j++)
{
d->mins[j] = LittleFloat(d->mins[j]);
d->maxs[j] = LittleFloat(d->maxs[j]);
d->origin[j] = LittleFloat(d->origin[j]);
}
}
//
// vertexes
//
for (i=0 ; i<numvertexes ; i++)
{
for (j=0 ; j<3 ; j++)
dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
}
//
// planes
//
for (i=0 ; i<numplanes ; i++)
{
for (j=0 ; j<3 ; j++)
dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
dplanes[i].dist = LittleFloat (dplanes[i].dist);
dplanes[i].type = LittleLong (dplanes[i].type);
}
//
// texinfos
//
for (i=0 ; i<numtexinfo ; i++)
{
for (j=0 ; j<8 ; j++)
texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
texinfo[i].flags = LittleLong (texinfo[i].flags);
texinfo[i].value = LittleLong (texinfo[i].value);
texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
}
//
// faces
//
for (i=0 ; i<numfaces ; i++)
{
dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
dfaces[i].planenum = LittleShort (dfaces[i].planenum);
dfaces[i].side = LittleShort (dfaces[i].side);
dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
dfaces[i].numedges = LittleShort (dfaces[i].numedges);
}
//
// nodes
//
for (i=0 ; i<numnodes ; i++)
{
dnodes[i].planenum = LittleLong (dnodes[i].planenum);
for (j=0 ; j<3 ; j++)
{
dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
}
dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
dnodes[i].firstface = LittleShort (dnodes[i].firstface);
dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
}
//
// leafs
//
for (i=0 ; i<numleafs ; i++)
{
dleafs[i].contents = LittleLong (dleafs[i].contents);
dleafs[i].cluster = LittleShort (dleafs[i].cluster);
dleafs[i].area = LittleShort (dleafs[i].area);
for (j=0 ; j<3 ; j++)
{
dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
}
dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
}
//
// leaffaces
//
for (i=0 ; i<numleaffaces ; i++)
dleaffaces[i] = LittleShort (dleaffaces[i]);
//
// leafbrushes
//
for (i=0 ; i<numleafbrushes ; i++)
dleafbrushes[i] = LittleShort (dleafbrushes[i]);
//
// surfedges
//
for (i=0 ; i<numsurfedges ; i++)
dsurfedges[i] = LittleLong (dsurfedges[i]);
//
// edges
//
for (i=0 ; i<numedges ; i++)
{
dedges[i].v[0] = LittleShort (dedges[i].v[0]);
dedges[i].v[1] = LittleShort (dedges[i].v[1]);
}
//
// brushes
//
for (i=0 ; i<numbrushes ; i++)
{
dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
dbrushes[i].contents = LittleLong (dbrushes[i].contents);
}
//
// areas
//
for (i=0 ; i<numareas ; i++)
{
dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
}
//
// areasportals
//
for (i=0 ; i<numareaportals ; i++)
{
dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
}
//
// brushsides
//
for (i=0 ; i<numbrushsides ; i++)
{
dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
}
//
// visibility
//
if (todisk)
j = dvis->numclusters;
else
j = LittleLong(dvis->numclusters);
dvis->numclusters = LittleLong (dvis->numclusters);
for (i=0 ; i<j ; i++)
{
dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
}
}
dheader_t *header;
int CopyLump (int lump, void *dest, int size)
{
int length, ofs;
length = header->lumps[lump].filelen;
ofs = header->lumps[lump].fileofs;
if (length % size)
Error ("LoadBSPFile: odd lump size");
memcpy (dest, (byte *)header + ofs, length);
return length / size;
}
/*
=============
LoadBSPFile
=============
*/
void LoadBSPFile (char *filename)
{
int i;
//
// load the file header
//
LoadFile (filename, (void **)&header);
// swap the header
for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
if (header->ident != IDBSPHEADER)
Error ("%s is not a IBSP file", filename);
if (header->version != BSPVERSION)
Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
CopyLump (LUMP_POP, dpop, 1);
free (header); // everything has been copied out
//
// swap everything
//
SwapBSPFile (false);
}
/*
=============
LoadBSPFileTexinfo
Only loads the texinfo lump, so qdata can scan for textures
=============
*/
void LoadBSPFileTexinfo (char *filename)
{
int i;
FILE *f;
int length, ofs;
header = malloc(sizeof(dheader_t));
f = fopen (filename, "rb");
fread (header, sizeof(dheader_t), 1, f);
// swap the header
for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
if (header->ident != IDBSPHEADER)
Error ("%s is not a IBSP file", filename);
if (header->version != BSPVERSION)
Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
length = header->lumps[LUMP_TEXINFO].filelen;
ofs = header->lumps[LUMP_TEXINFO].fileofs;
fseek (f, ofs, SEEK_SET);
fread (texinfo, length, 1, f);
fclose (f);
numtexinfo = length / sizeof(texinfo_t);
free (header); // everything has been copied out
SwapBSPFile (false);
}
//============================================================================
FILE *wadfile;
dheader_t outheader;
void AddLump (int lumpnum, void *data, int len)
{
lump_t *lump;
lump = &header->lumps[lumpnum];
lump->fileofs = LittleLong( ftell(wadfile) );
lump->filelen = LittleLong(len);
SafeWrite (wadfile, data, (len+3)&~3);
}
/*
=============
WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void WriteBSPFile (char *filename)
{
header = &outheader;
memset (header, 0, sizeof(dheader_t));
SwapBSPFile (true);
header->ident = LittleLong (IDBSPHEADER);
header->version = LittleLong (BSPVERSION);
wadfile = SafeOpenWrite (filename);
SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later
AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
AddLump (LUMP_ENTITIES, dentdata, entdatasize);
AddLump (LUMP_POP, dpop, sizeof(dpop));
fseek (wadfile, 0, SEEK_SET);
SafeWrite (wadfile, header, sizeof(dheader_t));
fclose (wadfile);
}
//============================================================================
/*
=============
PrintBSPFileSizes
Dumps info about current file
=============
*/
void PrintBSPFileSizes (void)
{
if (!num_entities)
ParseEntities ();
printf ("%5i models %7i\n"
,nummodels, (int)(nummodels*sizeof(dmodel_t)));
printf ("%5i brushes %7i\n"
,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
printf ("%5i brushsides %7i\n"
,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
printf ("%5i planes %7i\n"
,numplanes, (int)(numplanes*sizeof(dplane_t)));
printf ("%5i texinfo %7i\n"
,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
printf ("%5i entdata %7i\n", num_entities, entdatasize);
printf ("\n");
printf ("%5i vertexes %7i\n"
,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
printf ("%5i nodes %7i\n"
,numnodes, (int)(numnodes*sizeof(dnode_t)));
printf ("%5i faces %7i\n"
,numfaces, (int)(numfaces*sizeof(dface_t)));
printf ("%5i leafs %7i\n"
,numleafs, (int)(numleafs*sizeof(dleaf_t)));
printf ("%5i leaffaces %7i\n"
,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
printf ("%5i leafbrushes %7i\n"
,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
printf ("%5i surfedges %7i\n"
,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
printf ("%5i edges %7i\n"
,numedges, (int)(numedges*sizeof(dedge_t)));
printf (" lightdata %7i\n", lightdatasize);
printf (" visdata %7i\n", visdatasize);
}
//============================================
int num_entities;
entity_t entities[MAX_MAP_ENTITIES];
void StripTrailing (char *e)
{
char *s;
s = e + strlen(e)-1;
while (s >= e && *s <= 32)
{
*s = 0;
s--;
}
}
/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair (void)
{
epair_t *e;
e = malloc (sizeof(epair_t));
memset (e, 0, sizeof(epair_t));
if (strlen(token) >= MAX_KEY-1)
Error ("ParseEpar: token too long");
e->key = copystring(token);
GetToken (false);
if (strlen(token) >= MAX_VALUE-1)
Error ("ParseEpar: token too long");
e->value = copystring(token);
// strip trailing spaces
StripTrailing (e->key);
StripTrailing (e->value);
return e;
}
/*
================
ParseEntity
================
*/
qboolean ParseEntity (void)
{
epair_t *e;
entity_t *mapent;
if (!GetToken (true))
return false;
if (strcmp (token, "{") )
Error ("ParseEntity: { not found");
if (num_entities == MAX_MAP_ENTITIES)
Error ("num_entities == MAX_MAP_ENTITIES");
mapent = &entities[num_entities];
num_entities++;
do
{
if (!GetToken (true))
Error ("ParseEntity: EOF without closing brace");
if (!strcmp (token, "}") )
break;
e = ParseEpair ();
e->next = mapent->epairs;
mapent->epairs = e;
} while (1);
return true;
}
/*
================
ParseEntities
Parses the dentdata string into entities
================
*/
void ParseEntities (void)
{
num_entities = 0;
ParseFromMemory (dentdata, entdatasize);
while (ParseEntity ())
{
}
}
/*
================
UnparseEntities
Generates the dentdata string from all the entities
================
*/
void UnparseEntities (void)
{
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
char key[1024], value[1024];
buf = dentdata;
end = buf;
*end = 0;
for (i=0 ; i<num_entities ; i++)
{
ep = entities[i].epairs;
if (!ep)
continue; // ent got removed
strcat (end,"{\n");
end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next)
{
strcpy (key, ep->key);
StripTrailing (key);
strcpy (value, ep->value);
StripTrailing (value);
sprintf (line, "\"%s\" \"%s\"\n", key, value);
strcat (end, line);
end += strlen(line);
}
strcat (end,"}\n");
end += 2;
if (end > buf + MAX_MAP_ENTSTRING)
Error ("Entity text too long");
}
entdatasize = end - buf + 1;
}
void PrintEntity (entity_t *ent)
{
epair_t *ep;
printf ("------- entity %p -------\n", ent);
for (ep=ent->epairs ; ep ; ep=ep->next)
{
printf ("%s = %s\n", ep->key, ep->value);
}
}
void SetKeyValue (entity_t *ent, char *key, char *value)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
{
free (ep->value);
ep->value = copystring(value);
return;
}
ep = malloc (sizeof(*ep));
ep->next = ent->epairs;
ent->epairs = ep;
ep->key = copystring(key);
ep->value = copystring(value);
}
char *ValueForKey (entity_t *ent, char *key)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
return ep->value;
return "";
}
vec_t FloatForKey (entity_t *ent, char *key)
{
char *k;
k = ValueForKey (ent, key);
return atof(k);
}
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
{
char *k;
double v1, v2, v3;
k = ValueForKey (ent, key);
// scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
vec[0] = v1;
vec[1] = v2;
vec[2] = v3;
}

View File

@@ -0,0 +1,128 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qfiles.h"
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int visdatasize;
extern byte dvisdata[MAX_MAP_VISIBILITY];
extern dvis_t *dvis;
extern int lightdatasize;
extern byte dlightdata[MAX_MAP_LIGHTING];
extern int entdatasize;
extern char dentdata[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t dleafs[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t dvertexes[MAX_MAP_VERTS];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern int numtexinfo;
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
extern int numfaces;
extern dface_t dfaces[MAX_MAP_FACES];
extern int numedges;
extern dedge_t dedges[MAX_MAP_EDGES];
extern int numleaffaces;
extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
extern int numleafbrushes;
extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
extern int numsurfedges;
extern int dsurfedges[MAX_MAP_SURFEDGES];
extern int numareas;
extern darea_t dareas[MAX_MAP_AREAS];
extern int numareaportals;
extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
extern int numbrushes;
extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
extern int numbrushsides;
extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
extern byte dpop[256];
void DecompressVis (byte *in, byte *decompressed);
int CompressVis (byte *vis, byte *dest);
void LoadBSPFile (char *filename);
void LoadBSPFileTexinfo (char *filename); // just for qdata
void WriteBSPFile (char *filename);
void PrintBSPFileSizes (void);
//===============
typedef struct epair_s
{
struct epair_s *next;
char *key;
char *value;
} epair_t;
typedef struct
{
vec3_t origin;
int firstbrush;
int numbrushes;
epair_t *epairs;
// only valid for func_areaportals
int areaportalnum;
int portalareas[2];
} entity_t;
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void ParseEntities (void);
void UnparseEntities (void);
void SetKeyValue (entity_t *ent, char *key, char *value);
char *ValueForKey (entity_t *ent, char *key);
// will return "" if not present
vec_t FloatForKey (entity_t *ent, char *key);
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
epair_t *ParseEpair (void);
void PrintEntity (entity_t *ent);

1221
tools/quake2/common/cmdlib.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// cmdlib.h
#ifndef __CMDLIB__
#define __CMDLIB__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#ifdef WIN32
#ifdef NDEBUG // Don't show in a Release build
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4244) // conversion from double to float
#pragma warning(disable : 4018) // signed/unsigned mismatch
#endif
#endif
#ifdef WIN32
#pragma intrinsic( memset, memcpy )
#endif
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
typedef enum {false, true} qboolean;
typedef unsigned char byte;
#endif
#define MAX_OS_PATH 1024
#define MEM_BLOCKSIZE 4096
/*
extern qboolean verbose;
#define SYS_VRB 0 // verbose support (on/off)
#define SYS_STD 1 // standard print level
#define SYS_WRN 2 // warnings
#define SYS_ERR 3 // error
*/
// the dec offsetof macro doesnt work very well...
#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
#define SAFE_MALLOC
#ifdef SAFE_MALLOC
void *safe_malloc( size_t size );
void *safe_malloc_info( size_t size, char* info );
#else
#define safe_malloc(a) malloc(a)
#endif /* SAFE_MALLOC */
// set these before calling CheckParm
extern int myargc;
extern char **myargv;
char *strlower (char *in);
int Q_strncasecmp( const char *s1, const char *s2, int n );
int Q_strcasecmp( const char *s1, const char *s2 );
int Q_stricmp( const char *s1, const char *s2 );
void Q_getwd( char *out );
int Q_filelength (FILE *f);
int FileTime( const char *path );
void Q_mkdir( const char *path );
extern char qdir[1024];
extern char gamedir[1024];
extern char writedir[1024];
extern char *moddirparam;
void SetQdirFromPath( const char *path);
char *ExpandArg( const char *path ); // from cmd line
char *ExpandPath( const char *path ); // from scripts
char *ExpandGamePath (const char *path);
char *ExpandPathAndArchive( const char *path );
void ExpandWildcards( int *argc, char ***argv );
double I_FloatTime( void );
int CheckParm( const char *check );
FILE *SafeOpenWrite( const char *filename );
FILE *SafeOpenRead( const char *filename );
void SafeRead (FILE *f, void *buffer, int count);
void SafeWrite (FILE *f, const void *buffer, int count);
int LoadFile( const char *filename, void **bufferptr );
int LoadFileBlock( const char *filename, void **bufferptr );
int TryLoadFile( const char *filename, void **bufferptr );
void SaveFile( const char *filename, const void *buffer, int count );
qboolean FileExists( const char *filename );
void DefaultExtension( char *path, const char *extension );
void DefaultPath( char *path, const char *basepath );
void StripFilename( char *path );
void StripExtension( char *path );
void ExtractFilePath( const char *path, char *dest );
void ExtractFileBase( const char *path, char *dest );
void ExtractFileExtension( const char *path, char *dest );
int ParseNum (const char *str);
//void Sys_Printf (const char *text, ...);
//void Sys_FPrintf (int flag, const char *text, ...);
//void Error( const char *error, ... );
short BigShort (short l);
short LittleShort (short l);
int BigLong (int l);
int LittleLong (int l);
float BigFloat (float l);
float LittleFloat (float l);
char *COM_Parse (char *data);
extern char com_token[1024];
extern qboolean com_eof;
char *copystring(const char *s);
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
void CreatePath( const char *path );
void QCopyFile( const char *from, const char *to );
extern qboolean archive;
extern char archivedir[1024];
// sleep for the given amount of milliseconds
void Sys_Sleep(int n);
// for compression routines
typedef struct
{
byte *data;
int count;
} cblock_t;
extern char game[64];
#endif

367
tools/quake2/common/inout.c Normal file
View File

@@ -0,0 +1,367 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//-----------------------------------------------------------------------------
//
//
// DESCRIPTION:
// deal with in/out tasks, for either stdin/stdout or network/XML stream
//
#include "cmdlib.h"
#include "mathlib.h"
#include "polylib.h"
#include "inout.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
#include <direct.h>
#include <windows.h>
#endif
// network broadcasting
#include "l_net/l_net.h"
#include "libxml/tree.h"
#ifdef WIN32
HWND hwndOut = NULL;
qboolean lookedForServer = false;
UINT wm_BroadcastCommand = -1;
#endif
socket_t *brdcst_socket;
netmessage_t msg;
qboolean verbose = false;
// our main document
// is streamed through the network to Radiant
// possibly written to disk at the end of the run
//++timo FIXME: need to be global, required when creating nodes?
xmlDocPtr doc;
xmlNodePtr tree;
// some useful stuff
xmlNodePtr xml_NodeForVec( vec3_t v )
{
xmlNodePtr ret;
char buf[1024];
sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
ret = xmlNewNode (NULL, "point");
xmlNodeSetContent (ret, buf);
return ret;
}
// send a node down the stream, add it to the document
void xml_SendNode (xmlNodePtr node)
{
xmlBufferPtr xml_buf;
char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
// this index loops through the node buffer
int pos = 0;
int size;
xmlAddChild( doc->children, node );
if (brdcst_socket)
{
xml_buf = xmlBufferCreate();
xmlNodeDump( xml_buf, doc, node, 0, 0 );
// the XML node might be too big to fit in a single network message
// l_net library defines an upper limit of MAX_NETMESSAGE
// there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
// if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
while (pos < xml_buf->use)
{
// what size are we gonna send now?
(xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
//++timo just a debug thing
if (size == MAX_NETMESSAGE - 10)
Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
memcpy( xmlbuf, xml_buf->content+pos, size);
xmlbuf[size] = '\0';
NMSG_Clear( &msg );
NMSG_WriteString (&msg, xmlbuf );
Net_Send(brdcst_socket, &msg );
// now that the thing is sent prepare to loop again
pos += size;
}
#if 0
// NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
// we will need to split into chunks
// (we could also go lower level, in the end it's using send and receiv which are not size limited)
//++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
// there's some tweaking to do in l_net for that .. so let's give us a margin for now
//++timo we need to handle the case of a buffer too big to fit in a single message
// try without checks for now
if (xml_buf->use > MAX_NETMESSAGE-10 )
{
// if we send that we are probably gonna break the stream at the other end..
// and Error will call right there
//Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
Sys_FPrintf (SYS_NOXML, xml_buf->content);
}
size = xml_buf->use;
memcpy( xmlbuf, xml_buf->content, size );
xmlbuf[size] = '\0';
NMSG_Clear( &msg );
NMSG_WriteString (&msg, xmlbuf );
Net_Send(brdcst_socket, &msg );
#endif
xmlBufferFree( xml_buf );
}
}
void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
{
xmlNodePtr node, select;
char buf[1024];
char level[2];
// now build a proper "select" XML node
sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
node = xmlNewNode (NULL, "select");
xmlNodeSetContent (node, buf);
level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN) ;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'select' information
sprintf (buf, "%i %i", entitynum, brushnum);
select = xmlNewNode (NULL, "brush");
xmlNodeSetContent (select, buf);
xmlAddChild (node, select);
xml_SendNode (node);
sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
if (bError)
Error(buf);
else
Sys_FPrintf (SYS_NOXML, "%s\n", buf);
}
void xml_Point (char *msg, vec3_t pt)
{
xmlNodePtr node, point;
char buf[1024];
char level[2];
node = xmlNewNode (NULL, "pointmsg");
xmlNodeSetContent (node, msg);
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'point' node
sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
point = xmlNewNode (NULL, "point");
xmlNodeSetContent (point, buf);
xmlAddChild (node, point);
xml_SendNode (node);
sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
Error (buf);
}
#define WINDING_BUFSIZE 2048
void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
{
xmlNodePtr node, winding;
char buf[WINDING_BUFSIZE];
char smlbuf[128];
char level[2];
int i;
node = xmlNewNode (NULL, "windingmsg");
xmlNodeSetContent (node, msg);
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'winding' node
sprintf( buf, "%i ", numpoints);
for(i = 0; i < numpoints; i++)
{
sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
// don't overflow
if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
break;
strcat( buf, smlbuf);
}
winding = xmlNewNode (NULL, "winding");
xmlNodeSetContent (winding, buf);
xmlAddChild (node, winding);
xml_SendNode (node);
if(die)
Error (msg);
else
{
Sys_Printf(msg);
Sys_Printf("\n");
}
}
// in include
#include "stream_version.h"
void Broadcast_Setup( const char *dest )
{
address_t address;
char sMsg[1024];
Net_Setup();
Net_StringToAddress((char *)dest, &address);
brdcst_socket = Net_Connect(&address, 0);
if (brdcst_socket)
{
// send in a header
sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
NMSG_Clear( &msg );
NMSG_WriteString(&msg, sMsg );
Net_Send(brdcst_socket, &msg );
}
}
void Broadcast_Shutdown()
{
if (brdcst_socket)
{
Sys_Printf("Disconnecting\n");
Net_Disconnect(brdcst_socket);
brdcst_socket = NULL;
}
}
// all output ends up through here
void FPrintf (int flag, char *buf)
{
xmlNodePtr node;
static qboolean bGotXML = false;
char level[2];
printf(buf);
// the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
if (flag == SYS_NOXML)
return;
// ouput an XML file of the run
// use the DOM interface to build a tree
/*
<message level='flag'>
message string
.. various nodes to describe corresponding geometry ..
</message>
*/
if (!bGotXML)
{
// initialize
doc = xmlNewDoc("1.0");
doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
bGotXML = true;
}
node = xmlNewNode (NULL, "message");
xmlNodeSetContent (node, buf);
level[0] = (int)'0' + flag;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level );
xml_SendNode (node);
}
#ifdef DBG_XML
void DumpXML()
{
xmlSaveFile( "XMLDump.xml", doc );
}
#endif
void Sys_FPrintf (int flag, const char *format, ...)
{
char out_buffer[4096];
va_list argptr;
if ((flag == SYS_VRB) && (verbose == false))
return;
va_start (argptr, format);
vsprintf (out_buffer, format, argptr);
va_end (argptr);
FPrintf (flag, out_buffer);
}
void Sys_Printf (const char *format, ...)
{
char out_buffer[4096];
va_list argptr;
va_start (argptr, format);
vsprintf (out_buffer, format, argptr);
va_end (argptr);
FPrintf (SYS_STD, out_buffer);
}
/*
=================
Error
For abnormal program terminations
=================
*/
void Error( const char *error, ...)
{
char out_buffer[4096];
char tmp[4096];
va_list argptr;
va_start (argptr,error);
vsprintf (tmp, error, argptr);
va_end (argptr);
sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
FPrintf( SYS_ERR, out_buffer );
#ifdef DBG_XML
DumpXML();
#endif
//++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
// a clean solution is to send a sync request node in the stream and wait for an answer before exiting
Sys_Sleep( 1000 );
Broadcast_Shutdown();
exit (1);
}

View File

@@ -0,0 +1,63 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __INOUT__
#define __INOUT__
// inout is the only stuff relying on xml, include the headers there
#include "libxml/tree.h"
#include "mathlib.h"
// some useful xml routines
xmlNodePtr xml_NodeForVec( vec3_t v );
void xml_SendNode (xmlNodePtr node);
// print a message in q3map output and send the corresponding select information down the xml stream
// bError: do we end with an error on this one or do we go ahead?
void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
// end q3map with an error message and send a point information in the xml stream
// note: we might want to add a boolean to use this as a warning or an error thing..
void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
void xml_Point (char *msg, vec3_t pt);
extern qboolean bNetworkBroadcast;
void Broadcast_Setup( const char *dest );
void Broadcast_Shutdown();
#define SYS_VRB 0 // verbose support (on/off)
#define SYS_STD 1 // standard print level
#define SYS_WRN 2 // warnings
#define SYS_ERR 3 // error
#define SYS_NOXML 4 // don't send that down the XML stream
extern qboolean verbose;
void Sys_Printf (const char *text, ...);
void Sys_FPrintf (int flag, const char *text, ...);
void Error( const char *error, ...);
#ifdef _DEBUG
#define DBG_XML 1
#endif
#ifdef DBG_XML
void DumpXML();
#endif
#endif

View File

@@ -0,0 +1,300 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// l3dslib.c: library for loading triangles from an Alias triangle file
//
#include <stdio.h>
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "trilib.h"
#include "l3dslib.h"
#define MAIN3DS 0x4D4D
#define EDIT3DS 0x3D3D // this is the start of the editor config
#define EDIT_OBJECT 0x4000
#define OBJ_TRIMESH 0x4100
#define TRI_VERTEXL 0x4110
#define TRI_FACEL1 0x4120
#define MAXVERTS 2000
typedef struct {
int v[4];
} tri;
float fverts[MAXVERTS][3];
tri tris[MAXTRIANGLES];
int bytesread, level, numtris, totaltris;
int vertsfound, trisfound;
triangle_t *ptri;
// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
// start out with a vertex pool and vertex indices for triangles, we have to convert
// to raw, explicit triangles
void StoreAliasTriangles (void)
{
int i, j, k;
if ((totaltris + numtris) > MAXTRIANGLES)
Error ("Error: Too many triangles");
for (i=0; i<numtris ; i++)
{
for (j=0 ; j<3 ; j++)
{
for (k=0 ; k<3 ; k++)
{
ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
}
}
}
totaltris += numtris;
numtris = 0;
vertsfound = 0;
trisfound = 0;
}
int ParseVertexL (FILE *input)
{
int i, j, startbytesread, numverts;
unsigned short tshort;
if (vertsfound)
Error ("Error: Multiple vertex chunks");
vertsfound = 1;
startbytesread = bytesread;
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
numverts = (int)tshort;
if (numverts > MAXVERTS)
Error ("Error: Too many vertices");
for (i=0 ; i<numverts ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (feof(input))
Error ("Error: unexpected end of file");
fread(&fverts[i][j], sizeof(float), 1, input);
bytesread += sizeof(float);
}
}
if (vertsfound && trisfound)
StoreAliasTriangles ();
return bytesread - startbytesread;
}
int ParseFaceL1 (FILE *input)
{
int i, j, startbytesread;
unsigned short tshort;
if (trisfound)
Error ("Error: Multiple face chunks");
trisfound = 1;
startbytesread = bytesread;
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
numtris = (int)tshort;
if (numtris > MAXTRIANGLES)
Error ("Error: Too many triangles");
for (i=0 ; i<numtris ; i++)
{
for (j=0 ; j<4 ; j++)
{
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
tris[i].v[j] = (int)tshort;
}
}
if (vertsfound && trisfound)
StoreAliasTriangles ();
return bytesread - startbytesread;
}
int ParseChunk (FILE *input)
{
#define BLOCK_SIZE 4096
char temp[BLOCK_SIZE];
unsigned short type;
int i, length, w, t, retval;
level++;
retval = 0;
// chunk type
if (feof(input))
Error ("Error: unexpected end of file");
fread(&type, sizeof(type), 1, input);
bytesread += sizeof(type);
// chunk length
if (feof(input))
Error ("Error: unexpected end of file");
fread (&length, sizeof(length), 1, input);
bytesread += sizeof(length);
w = length - 6;
// process chunk if we care about it, otherwise skip it
switch (type)
{
case TRI_VERTEXL:
w -= ParseVertexL (input);
goto ParseSubchunk;
case TRI_FACEL1:
w -= ParseFaceL1 (input);
goto ParseSubchunk;
case EDIT_OBJECT:
// read the name
i = 0;
do
{
if (feof(input))
Error ("Error: unexpected end of file");
fread (&temp[i], 1, 1, input);
i++;
w--;
bytesread++;
} while (temp[i-1]);
case MAIN3DS:
case OBJ_TRIMESH:
case EDIT3DS:
// parse through subchunks
ParseSubchunk:
while (w > 0)
{
w -= ParseChunk (input);
}
retval = length;
goto Done;
default:
// skip other chunks
while (w > 0)
{
t = w;
if (t > BLOCK_SIZE)
t = BLOCK_SIZE;
if (feof(input))
Error ("Error: unexpected end of file");
fread (&temp, t, 1, input);
bytesread += t;
w -= t;
}
retval = length;
goto Done;
}
Done:
level--;
return retval;
}
void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
{
FILE *input;
short int tshort;
bytesread = 0;
level = 0;
numtris = 0;
totaltris = 0;
vertsfound = 0;
trisfound = 0;
if ((input = fopen(filename, "rb")) == 0) {
fprintf(stderr,"reader: could not open file '%s'\n", filename);
exit(0);
}
fread(&tshort, sizeof(tshort), 1, input);
// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
// no MAIN3DS
if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
fprintf(stderr,"File is not a 3DS file.\n");
exit(0);
}
// back to top of file so we can parse the first chunk descriptor
fseek(input, 0, SEEK_SET);
ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
*pptri = ptri;
// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
ParseChunk (input);
if (vertsfound || trisfound)
Error ("Incomplete triangle set");
*numtriangles = totaltris;
fclose (input);
}

View File

@@ -0,0 +1,25 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// l3dslib.h: header file for loading triangles from a 3DS triangle file
//
void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles);

View File

@@ -0,0 +1,837 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// lbmlib.c
#include "cmdlib.h"
#include "inout.h"
#include "lbmlib.h"
/*
============================================================================
LBM STUFF
============================================================================
*/
typedef unsigned char UBYTE;
//conflicts with windows typedef short WORD;
typedef unsigned short UWORD;
typedef long LONG;
typedef enum
{
ms_none,
ms_mask,
ms_transcolor,
ms_lasso
} mask_t;
typedef enum
{
cm_none,
cm_rle1
} compress_t;
typedef struct
{
UWORD w,h;
short x,y;
UBYTE nPlanes;
UBYTE masking;
UBYTE compression;
UBYTE pad1;
UWORD transparentColor;
UBYTE xAspect,yAspect;
short pageWidth,pageHeight;
} bmhd_t;
extern bmhd_t bmhd; // will be in native byte order
#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
bmhd_t bmhd;
int Align (int l)
{
if (l&1)
return l+1;
return l;
}
/*
================
LBMRLEdecompress
Source must be evenly aligned!
================
*/
byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
{
int count;
byte b,rept;
count = 0;
do
{
rept = *source++;
if (rept > 0x80)
{
rept = (rept^0xff)+2;
b = *source++;
memset(unpacked,b,rept);
unpacked += rept;
}
else if (rept < 0x80)
{
rept++;
memcpy(unpacked,source,rept);
unpacked += rept;
source += rept;
}
else
rept = 0; // rept of 0x80 is NOP
count += rept;
} while (count<bpwidth);
if (count>bpwidth)
Error ("Decompression exceeded width!\n");
return source;
}
/*
=================
LoadLBM
=================
*/
void LoadLBM (char *filename, byte **picture, byte **palette)
{
byte *LBMbuffer, *picbuffer, *cmapbuffer;
int y;
byte *LBM_P, *LBMEND_P;
byte *pic_p;
byte *body_p;
int formtype,formlength;
int chunktype,chunklength;
// qiet compiler warnings
picbuffer = NULL;
cmapbuffer = NULL;
//
// load the LBM
//
LoadFile (filename, (void **)&LBMbuffer);
//
// parse the LBM header
//
LBM_P = LBMbuffer;
if ( *(int *)LBMbuffer != LittleLong(FORMID) )
Error ("No FORM ID at start of file!\n");
LBM_P += 4;
formlength = BigLong( *(int *)LBM_P );
LBM_P += 4;
LBMEND_P = LBM_P + Align(formlength);
formtype = LittleLong(*(int *)LBM_P);
if (formtype != ILBMID && formtype != PBMID)
Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
LBM_P += 4;
//
// parse chunks
//
while (LBM_P < LBMEND_P)
{
chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
LBM_P += 4;
chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
LBM_P += 4;
switch ( chunktype )
{
case BMHDID:
memcpy (&bmhd,LBM_P,sizeof(bmhd));
bmhd.w = BigShort(bmhd.w);
bmhd.h = BigShort(bmhd.h);
bmhd.x = BigShort(bmhd.x);
bmhd.y = BigShort(bmhd.y);
bmhd.pageWidth = BigShort(bmhd.pageWidth);
bmhd.pageHeight = BigShort(bmhd.pageHeight);
break;
case CMAPID:
cmapbuffer = malloc (768);
memset (cmapbuffer, 0, 768);
memcpy (cmapbuffer, LBM_P, chunklength);
break;
case BODYID:
body_p = LBM_P;
pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
if (formtype == PBMID)
{
//
// unpack PBM
//
for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
{
if (bmhd.compression == cm_rle1)
body_p = LBMRLEDecompress ((byte *)body_p
, pic_p , bmhd.w);
else if (bmhd.compression == cm_none)
{
memcpy (pic_p,body_p,bmhd.w);
body_p += Align(bmhd.w);
}
}
}
else
{
//
// unpack ILBM
//
Error ("%s is an interlaced LBM, not packed", filename);
}
break;
}
LBM_P += Align(chunklength);
}
free (LBMbuffer);
*picture = picbuffer;
if (palette)
*palette = cmapbuffer;
}
/*
============================================================================
WRITE LBM
============================================================================
*/
/*
==============
WriteLBMfile
==============
*/
void WriteLBMfile (char *filename, byte *data,
int width, int height, byte *palette)
{
byte *lbm, *lbmptr;
int *formlength, *bmhdlength, *cmaplength, *bodylength;
int length;
bmhd_t basebmhd;
lbm = lbmptr = malloc (width*height+1000);
//
// start FORM
//
*lbmptr++ = 'F';
*lbmptr++ = 'O';
*lbmptr++ = 'R';
*lbmptr++ = 'M';
formlength = (int*)lbmptr;
lbmptr+=4; // leave space for length
*lbmptr++ = 'P';
*lbmptr++ = 'B';
*lbmptr++ = 'M';
*lbmptr++ = ' ';
//
// write BMHD
//
*lbmptr++ = 'B';
*lbmptr++ = 'M';
*lbmptr++ = 'H';
*lbmptr++ = 'D';
bmhdlength = (int *)lbmptr;
lbmptr+=4; // leave space for length
memset (&basebmhd,0,sizeof(basebmhd));
basebmhd.w = BigShort((short)width);
basebmhd.h = BigShort((short)height);
basebmhd.nPlanes = BigShort(8);
basebmhd.xAspect = BigShort(5);
basebmhd.yAspect = BigShort(6);
basebmhd.pageWidth = BigShort((short)width);
basebmhd.pageHeight = BigShort((short)height);
memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
lbmptr += sizeof(basebmhd);
length = lbmptr-(byte *)bmhdlength-4;
*bmhdlength = BigLong(length);
if (length&1)
*lbmptr++ = 0; // pad chunk to even offset
//
// write CMAP
//
*lbmptr++ = 'C';
*lbmptr++ = 'M';
*lbmptr++ = 'A';
*lbmptr++ = 'P';
cmaplength = (int *)lbmptr;
lbmptr+=4; // leave space for length
memcpy (lbmptr,palette,768);
lbmptr += 768;
length = lbmptr-(byte *)cmaplength-4;
*cmaplength = BigLong(length);
if (length&1)
*lbmptr++ = 0; // pad chunk to even offset
//
// write BODY
//
*lbmptr++ = 'B';
*lbmptr++ = 'O';
*lbmptr++ = 'D';
*lbmptr++ = 'Y';
bodylength = (int *)lbmptr;
lbmptr+=4; // leave space for length
memcpy (lbmptr,data,width*height);
lbmptr += width*height;
length = lbmptr-(byte *)bodylength-4;
*bodylength = BigLong(length);
if (length&1)
*lbmptr++ = 0; // pad chunk to even offset
//
// done
//
length = lbmptr-(byte *)formlength-4;
*formlength = BigLong(length);
if (length&1)
*lbmptr++ = 0; // pad chunk to even offset
//
// write output file
//
SaveFile (filename, lbm, lbmptr-lbm);
free (lbm);
}
/*
============================================================================
LOAD PCX
============================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
==============
LoadPCX
==============
*/
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
{
byte *raw;
pcx_t *pcx;
int x, y;
int len;
int dataByte, runLength;
byte *out, *pix;
//
// load the file
//
len = LoadFile (filename, (void **)&raw);
//
// parse the PCX file
//
pcx = (pcx_t *)raw;
raw = &pcx->data;
pcx->xmin = LittleShort(pcx->xmin);
pcx->ymin = LittleShort(pcx->ymin);
pcx->xmax = LittleShort(pcx->xmax);
pcx->ymax = LittleShort(pcx->ymax);
pcx->hres = LittleShort(pcx->hres);
pcx->vres = LittleShort(pcx->vres);
pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
pcx->palette_type = LittleShort(pcx->palette_type);
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8
|| pcx->xmax >= 640
|| pcx->ymax >= 480)
Error ("Bad pcx file %s", filename);
if (palette)
{
*palette = malloc(768);
memcpy (*palette, (byte *)pcx + len - 768, 768);
}
if (width)
*width = pcx->xmax+1;
if (height)
*height = pcx->ymax+1;
if (!pic)
return;
out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
if (!out)
Error ("Skin_Cache: couldn't allocate");
*pic = out;
pix = out;
for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
{
for (x=0 ; x<=pcx->xmax ; )
{
dataByte = *raw++;
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
dataByte = *raw++;
}
else
runLength = 1;
while(runLength-- > 0)
pix[x++] = dataByte;
}
}
if ( raw - (byte *)pcx > len)
Error ("PCX file %s was malformed", filename);
free (pcx);
}
/*
==============
WritePCXfile
==============
*/
void WritePCXfile (char *filename, byte *data,
int width, int height, byte *palette)
{
int i, j, length;
pcx_t *pcx;
byte *pack;
pcx = malloc (width*height*2+1000);
memset (pcx, 0, sizeof(*pcx));
pcx->manufacturer = 0x0a; // PCX id
pcx->version = 5; // 256 color
pcx->encoding = 1; // uncompressed
pcx->bits_per_pixel = 8; // 256 color
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = LittleShort((short)(width-1));
pcx->ymax = LittleShort((short)(height-1));
pcx->hres = LittleShort((short)width);
pcx->vres = LittleShort((short)height);
pcx->color_planes = 1; // chunky image
pcx->bytes_per_line = LittleShort((short)width);
pcx->palette_type = LittleShort(2); // not a grey scale
// pack the image
pack = &pcx->data;
for (i=0 ; i<height ; i++)
{
for (j=0 ; j<width ; j++)
{
if ( (*data & 0xc0) != 0xc0)
*pack++ = *data++;
else
{
*pack++ = 0xc1;
*pack++ = *data++;
}
}
}
// write the palette
*pack++ = 0x0c; // palette ID byte
for (i=0 ; i<768 ; i++)
*pack++ = *palette++;
// write output file
length = pack - (byte *)pcx;
SaveFile (filename, pcx, length);
free (pcx);
}
/*
============================================================================
LOAD IMAGE
============================================================================
*/
/*
==============
Load256Image
Will load either an lbm or pcx, depending on extension.
Any of the return pointers can be NULL if you don't want them.
==============
*/
void Load256Image (char *name, byte **pixels, byte **palette,
int *width, int *height)
{
char ext[128];
ExtractFileExtension (name, ext);
if (!Q_strncasecmp (ext, "lbm", strlen(ext) ))
{
LoadLBM (name, pixels, palette);
if (width)
*width = bmhd.w;
if (height)
*height = bmhd.h;
}
else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
{
LoadPCX (name, pixels, palette, width, height);
}
else
Error ("%s doesn't have a known image extension", name);
}
/*
==============
Save256Image
Will save either an lbm or pcx, depending on extension.
==============
*/
void Save256Image (char *name, byte *pixels, byte *palette,
int width, int height)
{
char ext[128];
ExtractFileExtension (name, ext);
if (!Q_strncasecmp (ext, "lbm",strlen(ext)))
{
WriteLBMfile (name, pixels, width, height, palette);
}
else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
{
WritePCXfile (name, pixels, width, height, palette);
}
else
Error ("%s doesn't have a known image extension", name);
}
/*
============================================================================
TARGA IMAGE
============================================================================
*/
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
int fgetLittleShort (FILE *f)
{
byte b1, b2;
b1 = fgetc(f);
b2 = fgetc(f);
return (short)(b1 + b2*256);
}
int fgetLittleLong (FILE *f)
{
byte b1, b2, b3, b4;
b1 = fgetc(f);
b2 = fgetc(f);
b3 = fgetc(f);
b4 = fgetc(f);
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}
/*
=============
LoadTGA
=============
*/
void LoadTGA (char *name, byte **pixels, int *width, int *height)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
FILE *fin;
byte *targa_rgba;
TargaHeader targa_header;
fin = fopen (name, "rb");
if (!fin)
Error ("Couldn't read %s", name);
targa_header.id_length = fgetc(fin);
targa_header.colormap_type = fgetc(fin);
targa_header.image_type = fgetc(fin);
targa_header.colormap_index = fgetLittleShort(fin);
targa_header.colormap_length = fgetLittleShort(fin);
targa_header.colormap_size = fgetc(fin);
targa_header.x_origin = fgetLittleShort(fin);
targa_header.y_origin = fgetLittleShort(fin);
targa_header.width = fgetLittleShort(fin);
targa_header.height = fgetLittleShort(fin);
targa_header.pixel_size = fgetc(fin);
targa_header.attributes = fgetc(fin);
if (targa_header.image_type!=2
&& targa_header.image_type!=10)
Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
if (targa_header.colormap_type !=0
|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
if (width)
*width = columns;
if (height)
*height = rows;
targa_rgba = malloc(numPixels*4);
*pixels = targa_rgba;
if (targa_header.id_length != 0)
fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
if (targa_header.image_type==2) { // Uncompressed, RGB images
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++) {
unsigned char red,green,blue,alphabyte;
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader=getc(fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
break;
}
for(j=0;j<packetSize;j++) {
*pixbuf++=red;
*pixbuf++=green;
*pixbuf++=blue;
*pixbuf++=alphabyte;
column++;
if (column==columns) { // run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
else { // non run-length packet
for(j=0;j<packetSize;j++) {
switch (targa_header.pixel_size) {
case 24:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = getc(fin);
green = getc(fin);
red = getc(fin);
alphabyte = getc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
column++;
if (column==columns) { // pixel packet run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
}
breakOut:;
}
}
// vertically flipped
if ( (targa_header.attributes & (1<<5)) ) {
int flip;
for (row = 0; row < .5f * rows; row++)
{
for (column = 0; column < columns; column++)
{
flip = *( (int*)targa_rgba + row * columns + column);
*( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
*( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
}
}
}
fclose(fin);
}

View File

@@ -0,0 +1,38 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// piclib.h
void LoadLBM (char *filename, byte **picture, byte **palette);
void WriteLBMfile (char *filename, byte *data, int width, int height
, byte *palette);
void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
void WritePCXfile (char *filename, byte *data, int width, int height
, byte *palette);
// loads / saves either lbm or pcx, depending on extension
void Load256Image (char *name, byte **pixels, byte **palette,
int *width, int *height);
void Save256Image (char *name, byte *pixels, byte *palette,
int width, int height);
void LoadTGA (char *filename, byte **pixels, int *width, int *height);

View File

@@ -0,0 +1,172 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// mathlib.c -- math primitives
#include "cmdlib.h"
#include "mathlib.h"
vec3_t vec3_origin = {0,0,0};
double VectorLength(vec3_t v)
{
int i;
double length;
length = 0;
for (i=0 ; i< 3 ; i++)
length += v[i]*v[i];
length = sqrt (length); // FIXME
return length;
}
qboolean VectorCompare (vec3_t v1, vec3_t v2)
{
int i;
for (i=0 ; i<3 ; i++)
if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
return false;
return true;
}
vec_t Q_rint (vec_t in)
{
return floor (in + 0.5);
}
void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
{
vc[0] = va[0] + scale*vb[0];
vc[1] = va[1] + scale*vb[1];
vc[2] = va[2] + scale*vb[2];
}
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
{
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
vec_t _DotProduct (vec3_t v1, vec3_t v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]-vb[0];
out[1] = va[1]-vb[1];
out[2] = va[2]-vb[2];
}
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]+vb[0];
out[1] = va[1]+vb[1];
out[2] = va[2]+vb[2];
}
void _VectorCopy (vec3_t in, vec3_t out)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
{
out[0] = v[0] * scale;
out[1] = v[1] * scale;
out[2] = v[2] * scale;
}
vec_t VectorNormalize (vec3_t in, vec3_t out)
{
vec_t length, ilength;
length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
if (length == 0)
{
VectorClear (out);
return 0;
}
ilength = 1.0/length;
out[0] = in[0]*ilength;
out[1] = in[1]*ilength;
out[2] = in[2]*ilength;
return length;
}
vec_t ColorNormalize (vec3_t in, vec3_t out)
{
float max, scale;
max = in[0];
if (in[1] > max)
max = in[1];
if (in[2] > max)
max = in[2];
if (max == 0)
return 0;
scale = 1.0 / max;
VectorScale (in, scale, out);
return max;
}
void VectorInverse (vec3_t v)
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void ClearBounds (vec3_t mins, vec3_t maxs)
{
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
}
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
{
int i;
vec_t val;
for (i=0 ; i<3 ; i++)
{
val = v[i];
if (val < mins[i])
mins[i] = val;
if (val > maxs[i])
maxs[i] = val;
}
}

View File

@@ -0,0 +1,75 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __MATHLIB__
#define __MATHLIB__
// mathlib.h
#include <math.h>
#ifdef DOUBLEVEC_T
typedef double vec_t;
#else
typedef float vec_t;
#endif
typedef vec_t vec3_t[3];
#define SIDE_FRONT 0
#define SIDE_ON 2
#define SIDE_BACK 1
#define SIDE_CROSS -2
#define Q_PI 3.14159265358979323846
extern vec3_t vec3_origin;
#define EQUAL_EPSILON 0.001
qboolean VectorCompare (vec3_t v1, vec3_t v2);
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
vec_t Q_rint (vec_t in);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
void _VectorCopy (vec3_t in, vec3_t out);
void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
double VectorLength(vec3_t v);
void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
vec_t VectorNormalize (vec3_t in, vec3_t out);
vec_t ColorNormalize (vec3_t in, vec3_t out);
void VectorInverse (vec3_t v);
void ClearBounds (vec3_t mins, vec3_t maxs);
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
#endif

297
tools/quake2/common/md4.c Normal file
View File

@@ -0,0 +1,297 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* GLOBAL.H - RSAREF types and constants */
#include <string.h>
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* MD4.H - header file for MD4C.C */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
All rights reserved.
License to copy and use this software is granted provided that it is identified as the RSA Data Security, Inc. MD4 Message-Digest Algorithm in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided as is without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* MD4 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD4_CTX;
void MD4Init (MD4_CTX *);
void MD4Update (MD4_CTX *, unsigned char *, unsigned int);
void MD4Final (unsigned char [16], MD4_CTX *);
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
License to copy and use this software is granted provided that it is identified as the
RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as
derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
as is without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* Constants for MD4Transform routine. */
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
static void MD4Transform (UINT4 [4], unsigned char [64]);
static void Encode (unsigned char *, UINT4 *, unsigned int);
static void Decode (UINT4 *, unsigned char *, unsigned int);
static void MD4_memcpy (POINTER, POINTER, unsigned int);
static void MD4_memset (POINTER, int, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = \
ROTATE_LEFT ((a), (s)); }
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
void MD4Init (MD4_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.*/
if (inputLen >= partLen)
{
memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD4Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD4Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
}
/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
void MD4Final (unsigned char digest[16], MD4_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD4Update (context, PADDING, padLen);
/* Append length (before padding) */
MD4Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.*/
memset ((POINTER)context, 0, sizeof (*context));
}
/* MD4 basic transformation. Transforms state based on block. */
static void MD4Transform (UINT4 state[4], unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11); /* 1 */
FF (d, a, b, c, x[ 1], S12); /* 2 */
FF (c, d, a, b, x[ 2], S13); /* 3 */
FF (b, c, d, a, x[ 3], S14); /* 4 */
FF (a, b, c, d, x[ 4], S11); /* 5 */
FF (d, a, b, c, x[ 5], S12); /* 6 */
FF (c, d, a, b, x[ 6], S13); /* 7 */
FF (b, c, d, a, x[ 7], S14); /* 8 */
FF (a, b, c, d, x[ 8], S11); /* 9 */
FF (d, a, b, c, x[ 9], S12); /* 10 */
FF (c, d, a, b, x[10], S13); /* 11 */
FF (b, c, d, a, x[11], S14); /* 12 */
FF (a, b, c, d, x[12], S11); /* 13 */
FF (d, a, b, c, x[13], S12); /* 14 */
FF (c, d, a, b, x[14], S13); /* 15 */
FF (b, c, d, a, x[15], S14); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 0], S21); /* 17 */
GG (d, a, b, c, x[ 4], S22); /* 18 */
GG (c, d, a, b, x[ 8], S23); /* 19 */
GG (b, c, d, a, x[12], S24); /* 20 */
GG (a, b, c, d, x[ 1], S21); /* 21 */
GG (d, a, b, c, x[ 5], S22); /* 22 */
GG (c, d, a, b, x[ 9], S23); /* 23 */
GG (b, c, d, a, x[13], S24); /* 24 */
GG (a, b, c, d, x[ 2], S21); /* 25 */
GG (d, a, b, c, x[ 6], S22); /* 26 */
GG (c, d, a, b, x[10], S23); /* 27 */
GG (b, c, d, a, x[14], S24); /* 28 */
GG (a, b, c, d, x[ 3], S21); /* 29 */
GG (d, a, b, c, x[ 7], S22); /* 30 */
GG (c, d, a, b, x[11], S23); /* 31 */
GG (b, c, d, a, x[15], S24); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 0], S31); /* 33 */
HH (d, a, b, c, x[ 8], S32); /* 34 */
HH (c, d, a, b, x[ 4], S33); /* 35 */
HH (b, c, d, a, x[12], S34); /* 36 */
HH (a, b, c, d, x[ 2], S31); /* 37 */
HH (d, a, b, c, x[10], S32); /* 38 */
HH (c, d, a, b, x[ 6], S33); /* 39 */
HH (b, c, d, a, x[14], S34); /* 40 */
HH (a, b, c, d, x[ 1], S31); /* 41 */
HH (d, a, b, c, x[ 9], S32); /* 42 */
HH (c, d, a, b, x[ 5], S33); /* 43 */
HH (b, c, d, a, x[13], S34); /* 44 */
HH (a, b, c, d, x[ 3], S31); /* 45 */
HH (d, a, b, c, x[11], S32); /* 46 */
HH (c, d, a, b, x[ 7], S33); /* 47 */
HH (b, c, d, a, x[15], S34); /* 48 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.*/
memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
//===================================================================
unsigned Com_BlockChecksum (void *buffer, int length)
{
int digest[4];
unsigned val;
MD4_CTX ctx;
MD4Init (&ctx);
MD4Update (&ctx, (unsigned char *)buffer, length);
MD4Final ( (unsigned char *)digest, &ctx);
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
return val;
}

View File

@@ -0,0 +1,404 @@
/* -------------------------------------------------------------------------------
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Nurail: Swiped from Q3Map2
*/
/* marker */
#define PATH_INIT_C
#if defined( __linux__ ) || defined( __APPLE__ )
#define Q_UNIX
#endif
#ifdef Q_UNIX
#include <unistd.h>
#include <pwd.h>
#include <limits.h>
#endif
/* dependencies */
#include "cmdlib.h"
#include "inout.h"
/* path support */
#define MAX_BASE_PATHS 10
#define MAX_GAME_PATHS 10
char *homePath;
char installPath[ MAX_OS_PATH ];
int numBasePaths;
char *basePaths[ MAX_BASE_PATHS ];
int numGamePaths;
char *gamePaths[ MAX_GAME_PATHS ];
/*
some of this code is based off the original q3map port from loki
and finds various paths. moved here from bsp.c for clarity.
*/
/*
PathLokiGetHomeDir()
gets the user's home dir (for ~/.q3a)
*/
char *LokiGetHomeDir( void )
{
#ifndef Q_UNIX
return NULL;
#else
char *home;
uid_t id;
struct passwd *pwd;
/* get the home environment variable */
home = getenv( "HOME" );
if( home == NULL )
{
/* do some more digging */
id = getuid();
setpwent();
while( (pwd = getpwent()) != NULL )
{
if( pwd->pw_uid == id )
{
home = pwd->pw_dir;
break;
}
}
endpwent();
}
/* return it */
return home;
#endif
}
/*
PathLokiInitPaths()
initializes some paths on linux/os x
*/
void LokiInitPaths( char *argv0 )
{
#ifndef Q_UNIX
/* this is kinda crap, but hey */
strcpy( installPath, "../" );
#else
char temp[ MAX_OS_PATH ];
char *home;
char *path;
char *last;
qboolean found;
/* get home dir */
home = LokiGetHomeDir();
if( home == NULL )
home = ".";
/* do some path divining */
strcpy( temp, argv0 );
if( strrchr( temp, '/' ) )
argv0 = strrchr( argv0, '/' ) + 1;
else
{
/* get path environment variable */
path = getenv( "PATH" );
/* minor setup */
last[ 0 ] = path[ 0 ];
last[ 1 ] = '\0';
found = false;
/* go through each : segment of path */
while( last[ 0 ] != '\0' && found == false )
{
/* null out temp */
temp[ 0 ] = '\0';
/* find next chunk */
last = strchr( path, ':' );
if( last == NULL )
last = path + strlen( path );
/* found home dir candidate */
if( *path == '~' )
{
strcpy( temp, home );
path++;
}
/* concatenate */
if( last > (path + 1) )
{
strncat( temp, path, (last - path) );
strcat( temp, "/" );
}
strcat( temp, "./" );
strcat( temp, argv0 );
/* verify the path */
if( access( temp, X_OK ) == 0 )
found++;
path = last + 1;
}
}
/* flake */
if( realpath( temp, installPath ) )
{
/* q3map is in "tools/" */
*(strrchr( installPath, '/' )) = '\0';
*(strrchr( installPath, '/' ) + 1) = '\0';
}
/* set home path */
homePath = home;
#endif
}
/*
CleanPath() - ydnar
cleans a dos path \ -> /
*/
void CleanPath( char *path )
{
while( *path )
{
if( *path == '\\' )
*path = '/';
path++;
}
}
/*
AddBasePath() - ydnar
adds a base path to the list
*/
void AddBasePath( char *path )
{
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
return;
/* add it to the list */
basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
strcpy( basePaths[ numBasePaths ], path );
CleanPath( basePaths[ numBasePaths ] );
numBasePaths++;
}
/*
AddHomeBasePath() - ydnar
adds a base path to the beginning of the list, prefixed by ~/
*/
void AddHomeBasePath( char *path )
{
#ifdef Q_UNIX
int i;
char temp[ MAX_OS_PATH ];
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' )
return;
/* make a hole */
for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
basePaths[ i + 1 ] = basePaths[ i ];
/* concatenate home dir and path */
sprintf( temp, "%s/%s", homePath, path );
/* add it to the list */
basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
strcpy( basePaths[ 0 ], temp );
CleanPath( basePaths[ 0 ] );
numBasePaths++;
#endif
}
/*
AddGamePath() - ydnar
adds a game path to the list
*/
void AddGamePath( char *path )
{
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
return;
/* add it to the list */
gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
strcpy( gamePaths[ numGamePaths ], path );
CleanPath( gamePaths[ numGamePaths ] );
numGamePaths++;
}
/*
InitPaths() - ydnar
cleaned up some of the path initialization code from bsp.c
will remove any arguments it uses
*/
void InitPaths( int *argc, char **argv )
{
int i, j, k, len, len2;
char temp[ MAX_OS_PATH ];
char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
strcpy(gamePath, "baseq2");
strcpy(game_magic, "quake");
strcpy(homeBasePath, ".quake2");
/* note it */
Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
/* get the install path for backup */
LokiInitPaths( argv[ 0 ] );
/* set game to default (q3a) */
numBasePaths = 0;
numGamePaths = 0;
/* parse through the arguments and extract those relevant to paths */
for( i = 0; i < *argc; i++ )
{
/* check for null */
if( argv[ i ] == NULL )
continue;
/* -fs_basepath */
if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
{
if( ++i >= *argc )
Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
argv[ i - 1 ] = NULL;
AddBasePath( argv[ i ] );
argv[ i ] = NULL;
}
}
/* remove processed arguments */
for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
{
for( j; j < *argc && argv[ j ] == NULL; j++ );
argv[ i ] = argv[ j ];
if( argv[ i ] != NULL )
k++;
}
*argc = k;
/* add standard game path */
AddGamePath( gamePath );
/* if there is no base path set, figure it out */
if( numBasePaths == 0 )
{
/* this is another crappy replacement for SetQdirFromPath() */
len2 = strlen( game_magic );
for( i = 0; i < *argc && numBasePaths == 0; i++ )
{
/* extract the arg */
strcpy( temp, argv[ i ] );
CleanPath( temp );
len = strlen( temp );
Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
/* this is slow, but only done once */
for( j = 0; j < (len - len2); j++ )
{
/* check for the game's magic word */
if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
{
/* now find the next slash and nuke everything after it */
while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
temp[ j ] = '\0';
/* add this as a base path */
AddBasePath( temp );
break;
}
}
}
/* add install path */
if( numBasePaths == 0 )
AddBasePath( installPath );
/* check again */
if( numBasePaths == 0 )
Error( "Failed to find a valid base path." );
}
/* this only affects unix */
AddHomeBasePath( homeBasePath );
/* initialize vfs paths */
if( numBasePaths > MAX_BASE_PATHS )
numBasePaths = MAX_BASE_PATHS;
if( numGamePaths > MAX_GAME_PATHS )
numGamePaths = MAX_GAME_PATHS;
/* walk the list of game paths */
//for( j = 0; j < numGamePaths; j++ )
//{
/* walk the list of base paths */
// for( i = 0; i < numBasePaths; i++ )
// {
/* create a full path and initialize it */
// sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
// vfsInitDirectory( temp );
// }
//}
/* done */
Sys_Printf( "\n" );
}

View File

@@ -0,0 +1,642 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "polylib.h"
extern int numthreads;
// counters are only bumped when running single threaded,
// because they are an awefull coherence problem
int c_active_windings;
int c_peak_windings;
int c_winding_allocs;
int c_winding_points;
#define BOGUS_RANGE 8192
void pw(winding_t *w)
{
int i;
for (i=0 ; i<w->numpoints ; i++)
printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
}
/*
=============
AllocWinding
=============
*/
winding_t *AllocWinding (int points)
{
winding_t *w;
int s;
if (numthreads == 1)
{
c_winding_allocs++;
c_winding_points += points;
c_active_windings++;
if (c_active_windings > c_peak_windings)
c_peak_windings = c_active_windings;
}
s = sizeof(vec_t)*3*points + sizeof(int);
w = malloc (s);
memset (w, 0, s);
return w;
}
void FreeWinding (winding_t *w)
{
if (*(unsigned *)w == 0xdeaddead)
Error ("FreeWinding: freed a freed winding");
*(unsigned *)w = 0xdeaddead;
if (numthreads == 1)
c_active_windings--;
free (w);
}
/*
============
RemoveColinearPoints
============
*/
int c_removed;
void RemoveColinearPoints (winding_t *w)
{
int i, j, k;
vec3_t v1, v2;
int nump;
vec3_t p[MAX_POINTS_ON_WINDING];
nump = 0;
for (i=0 ; i<w->numpoints ; i++)
{
j = (i+1)%w->numpoints;
k = (i+w->numpoints-1)%w->numpoints;
VectorSubtract (w->p[j], w->p[i], v1);
VectorSubtract (w->p[i], w->p[k], v2);
VectorNormalize(v1,v1);
VectorNormalize(v2,v2);
if (DotProduct(v1, v2) < 0.999)
{
VectorCopy (w->p[i], p[nump]);
nump++;
}
}
if (nump == w->numpoints)
return;
if (numthreads == 1)
c_removed += w->numpoints - nump;
w->numpoints = nump;
memcpy (w->p, p, nump*sizeof(p[0]));
}
/*
============
WindingPlane
============
*/
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
{
vec3_t v1, v2;
VectorSubtract (w->p[1], w->p[0], v1);
VectorSubtract (w->p[2], w->p[0], v2);
CrossProduct (v2, v1, normal);
VectorNormalize (normal, normal);
*dist = DotProduct (w->p[0], normal);
}
/*
=============
WindingArea
=============
*/
vec_t WindingArea (winding_t *w)
{
int i;
vec3_t d1, d2, cross;
vec_t total;
total = 0;
for (i=2 ; i<w->numpoints ; i++)
{
VectorSubtract (w->p[i-1], w->p[0], d1);
VectorSubtract (w->p[i], w->p[0], d2);
CrossProduct (d1, d2, cross);
total += 0.5 * VectorLength ( cross );
}
return total;
}
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
{
vec_t v;
int i,j;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for (i=0 ; i<w->numpoints ; i++)
{
for (j=0 ; j<3 ; j++)
{
v = w->p[i][j];
if (v < mins[j])
mins[j] = v;
if (v > maxs[j])
maxs[j] = v;
}
}
}
/*
=============
WindingCenter
=============
*/
void WindingCenter (winding_t *w, vec3_t center)
{
int i;
float scale;
VectorCopy (vec3_origin, center);
for (i=0 ; i<w->numpoints ; i++)
VectorAdd (w->p[i], center, center);
scale = 1.0/w->numpoints;
VectorScale (center, scale, center);
}
/*
=================
BaseWindingForPlane
=================
*/
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
{
int i, x;
vec_t max, v;
vec3_t org, vright, vup;
winding_t *w;
// find the major axis
max = -BOGUS_RANGE;
x = -1;
for (i=0 ; i<3; i++)
{
v = fabs(normal[i]);
if (v > max)
{
x = i;
max = v;
}
}
if (x==-1)
Error ("BaseWindingForPlane: no axis found");
VectorCopy (vec3_origin, vup);
switch (x)
{
case 0:
case 1:
vup[2] = 1;
break;
case 2:
vup[0] = 1;
break;
}
v = DotProduct (vup, normal);
VectorMA (vup, -v, normal, vup);
VectorNormalize (vup, vup);
VectorScale (normal, dist, org);
CrossProduct (vup, normal, vright);
VectorScale (vup, 8192, vup);
VectorScale (vright, 8192, vright);
// project a really big axis aligned box onto the plane
w = AllocWinding (4);
VectorSubtract (org, vright, w->p[0]);
VectorAdd (w->p[0], vup, w->p[0]);
VectorAdd (org, vright, w->p[1]);
VectorAdd (w->p[1], vup, w->p[1]);
VectorAdd (org, vright, w->p[2]);
VectorSubtract (w->p[2], vup, w->p[2]);
VectorSubtract (org, vright, w->p[3]);
VectorSubtract (w->p[3], vup, w->p[3]);
w->numpoints = 4;
return w;
}
/*
==================
CopyWinding
==================
*/
winding_t *CopyWinding (winding_t *w)
{
int size;
winding_t *c;
c = AllocWinding (w->numpoints);
size = (int)((winding_t *)0)->p[w->numpoints];
memcpy (c, w, size);
return c;
}
/*
==================
ReverseWinding
==================
*/
winding_t *ReverseWinding (winding_t *w)
{
int i;
winding_t *c;
c = AllocWinding (w->numpoints);
for (i=0 ; i<w->numpoints ; i++)
{
VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
}
c->numpoints = w->numpoints;
return c;
}
/*
=============
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back)
{
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
static vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f, *b;
int maxpts;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*front = *back = NULL;
if (!counts[0])
{
*back = CopyWinding (in);
return;
}
if (!counts[1])
{
*front = CopyWinding (in);
return;
}
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
*front = f = AllocWinding (maxpts);
*back = b = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i] == SIDE_BACK)
{
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (mid, b->p[b->numpoints]);
b->numpoints++;
}
if (f->numpoints > maxpts || b->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
}
/*
=============
ChopWindingInPlace
=============
*/
void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
{
winding_t *in;
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
static vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f;
int maxpts;
in = *inout;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
if (!counts[0])
{
FreeWinding (in);
*inout = NULL;
return;
}
if (!counts[1])
return; // inout stays the same
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
f = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
}
if (f->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
FreeWinding (in);
*inout = f;
}
/*
=================
ChopWinding
Returns the fragment of in that is on the front side
of the cliping plane. The original is freed.
=================
*/
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
{
winding_t *f, *b;
ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
FreeWinding (in);
if (b)
FreeWinding (b);
return f;
}
/*
=================
CheckWinding
=================
*/
void CheckWinding (winding_t *w)
{
int i, j;
vec_t *p1, *p2;
vec_t d, edgedist;
vec3_t dir, edgenormal, facenormal;
vec_t area;
vec_t facedist;
if (w->numpoints < 3)
Error ("CheckWinding: %i points",w->numpoints);
area = WindingArea(w);
if (area < 1)
Error ("CheckWinding: %f area", area);
WindingPlane (w, facenormal, &facedist);
for (i=0 ; i<w->numpoints ; i++)
{
p1 = w->p[i];
for (j=0 ; j<3 ; j++)
if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
j = i+1 == w->numpoints ? 0 : i+1;
// check the point is on the face plane
d = DotProduct (p1, facenormal) - facedist;
if (d < -ON_EPSILON || d > ON_EPSILON)
Error ("CheckWinding: point off plane");
// check the edge isnt degenerate
p2 = w->p[j];
VectorSubtract (p2, p1, dir);
if (VectorLength (dir) < ON_EPSILON)
Error ("CheckWinding: degenerate edge");
CrossProduct (facenormal, dir, edgenormal);
VectorNormalize (edgenormal, edgenormal);
edgedist = DotProduct (p1, edgenormal);
edgedist += ON_EPSILON;
// all other points must be on front side
for (j=0 ; j<w->numpoints ; j++)
{
if (j == i)
continue;
d = DotProduct (w->p[j], edgenormal);
if (d > edgedist)
Error ("CheckWinding: non-convex");
}
}
}
/*
============
WindingOnPlaneSide
============
*/
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
{
qboolean front, back;
int i;
vec_t d;
front = false;
back = false;
for (i=0 ; i<w->numpoints ; i++)
{
d = DotProduct (w->p[i], normal) - dist;
if (d < -ON_EPSILON)
{
if (front)
return SIDE_CROSS;
back = true;
continue;
}
if (d > ON_EPSILON)
{
if (back)
return SIDE_CROSS;
front = true;
continue;
}
}
if (back)
return SIDE_BACK;
if (front)
return SIDE_FRONT;
return SIDE_ON;
}

View File

@@ -0,0 +1,54 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedef struct
{
int numpoints;
vec3_t p[4]; // variable sized
} winding_t;
#define MAX_POINTS_ON_WINDING 64
// you can define on_epsilon in the makefile as tighter
#ifndef ON_EPSILON
#define ON_EPSILON 0.1
#endif
winding_t *AllocWinding (int points);
vec_t WindingArea (winding_t *w);
void WindingCenter (winding_t *w, vec3_t center);
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back);
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
winding_t *CopyWinding (winding_t *w);
winding_t *ReverseWinding (winding_t *w);
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
void CheckWinding (winding_t *w);
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
void RemoveColinearPoints (winding_t *w);
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
void FreeWinding (winding_t *w);
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
// frees the original if clipped
void pw(winding_t *w);

View File

@@ -0,0 +1,34 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _THREADS_H
#define _THREADS_H
extern int numthreads;
void ThreadSetDefault (void);
int GetThreadWork (void);
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
void ThreadLock (void);
void ThreadUnlock (void);
#endif // _THREADS_H

View File

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

View File

@@ -0,0 +1,296 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// scriplib.c
#include "cmdlib.h"
#include "inout.h"
#include "scriplib.h"
/*
=============================================================================
PARSING STUFF
=============================================================================
*/
typedef struct
{
char filename[1024];
char *buffer,*script_p,*end_p;
int line;
} script_t;
#define MAX_INCLUDES 8
script_t scriptstack[MAX_INCLUDES];
script_t *script;
int scriptline;
char token[MAXTOKEN];
qboolean endofscript;
qboolean tokenready; // only true if UnGetToken was just called
/*
==============
AddScriptToStack
==============
*/
void AddScriptToStack (char *filename)
{
int size;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, ExpandPath (filename) );
size = LoadFile (script->filename, (void **)&script->buffer);
printf ("entering %s\n", script->filename);
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
}
/*
==============
LoadScriptFile
==============
*/
void LoadScriptFile (char *filename)
{
script = scriptstack;
AddScriptToStack (filename);
endofscript = false;
tokenready = false;
}
/*
==============
ParseFromMemory
==============
*/
void ParseFromMemory (char *buffer, int size)
{
script = scriptstack;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, "memory buffer" );
script->buffer = buffer;
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
endofscript = false;
tokenready = false;
}
/*
==============
UnGetToken
Signals that the current token was not used, and should be reported
for the next GetToken. Note that
GetToken (true);
UnGetToken ();
GetToken (false);
could cross a line boundary.
==============
*/
void UnGetToken (void)
{
tokenready = true;
}
qboolean EndOfScript (qboolean crossline)
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
if (!strcmp (script->filename, "memory buffer"))
{
endofscript = true;
return false;
}
free (script->buffer);
if (script == scriptstack+1)
{
endofscript = true;
return false;
}
script--;
scriptline = script->line;
printf ("returning to %s\n", script->filename);
return GetToken (crossline);
}
/*
==============
GetToken
==============
*/
qboolean GetToken (qboolean crossline)
{
char *token_p;
if (tokenready) // is a token allready waiting?
{
tokenready = false;
return true;
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
//
// skip space
//
skipspace:
while (*script->script_p <= 32)
{
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
if (*script->script_p++ == '\n')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
scriptline = script->line++;
}
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
// ; # // comments
if (*script->script_p == ';' || *script->script_p == '#'
|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
while (*script->script_p++ != '\n')
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
goto skipspace;
}
// /* */ comments
if (script->script_p[0] == '/' && script->script_p[1] == '*')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
script->script_p+=2;
while (script->script_p[0] != '*' && script->script_p[1] != '/')
{
script->script_p++;
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
}
script->script_p += 2;
goto skipspace;
}
//
// copy token
//
token_p = token;
if (*script->script_p == '"')
{
// quoted token
script->script_p++;
while (*script->script_p != '"')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
script->script_p++;
}
else // regular token
while ( *script->script_p > 32 && *script->script_p != ';')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
*token_p = 0;
if (!strcmp (token, "$include"))
{
GetToken (false);
AddScriptToStack (token);
return GetToken (crossline);
}
return true;
}
/*
==============
TokenAvailable
Returns true if there is another token on the line
==============
*/
qboolean TokenAvailable (void)
{
char *search_p;
search_p = script->script_p;
if (search_p >= script->end_p)
return false;
while ( *search_p <= 32)
{
if (*search_p == '\n')
return false;
search_p++;
if (search_p == script->end_p)
return false;
}
if (*search_p == ';')
return false;
return true;
}

View File

@@ -0,0 +1,43 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// scriplib.h
#ifndef __CMDLIB__
#include "cmdlib.h"
#endif
#define MAXTOKEN 1024
extern char token[MAXTOKEN];
extern char *scriptbuffer,*script_p,*scriptend_p;
extern int grabbed;
extern int scriptline;
extern qboolean endofscript;
void LoadScriptFile (char *filename);
void ParseFromMemory (char *buffer, int size);
qboolean GetToken (qboolean crossline);
void UnGetToken (void);
qboolean TokenAvailable (void);

View File

@@ -0,0 +1,622 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIN32
// The below define is necessary to use
// pthreads extensions like pthread_mutexattr_settype
#define _GNU_SOURCE
#include <pthread.h>
#endif
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include "q2_threads.h"
#define MAX_THREADS 64
int dispatch;
int workcount;
int oldf;
qboolean pacifier;
qboolean threaded;
/*
=============
GetThreadWork
=============
*/
int GetThreadWork (void)
{
int r;
int f;
ThreadLock ();
if (dispatch == workcount)
{
ThreadUnlock ();
return -1;
}
f = 10*dispatch / workcount;
if (f != oldf)
{
oldf = f;
if (pacifier)
{
Sys_Printf ("%i...", f);
fflush( stdout ); /* ydnar */
}
}
r = dispatch;
dispatch++;
ThreadUnlock ();
return r;
}
void (*workfunction) (int);
void ThreadWorkerFunction (int threadnum)
{
int work;
while (1)
{
work = GetThreadWork ();
if (work == -1)
break;
//Sys_FPrintf( SYS_VRB,"thread %i, work %i\n", threadnum, work);
workfunction(work);
}
}
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
{
if (numthreads == -1)
ThreadSetDefault ();
workfunction = func;
RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
}
/*
===================================================================
WIN32
===================================================================
*/
#ifdef WIN32
#define USED
#include <windows.h>
// Setting default Threads to 1
int numthreads = 1;
CRITICAL_SECTION crit;
static int enter;
void ThreadSetDefault (void)
{
SYSTEM_INFO info;
if (numthreads == -1) // not set manually
{
GetSystemInfo (&info);
numthreads = info.dwNumberOfProcessors;
if (numthreads < 1 || numthreads > 32)
numthreads = 1;
}
Sys_Printf ("%i threads\n", numthreads);
}
void ThreadLock (void)
{
if (!threaded)
return;
EnterCriticalSection (&crit);
if (enter)
Error ("Recursive ThreadLock\n");
enter = 1;
}
void ThreadUnlock (void)
{
if (!threaded)
return;
if (!enter)
Error ("ThreadUnlock without lock\n");
enter = 0;
LeaveCriticalSection (&crit);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int threadid[MAX_THREADS];
HANDLE threadhandle[MAX_THREADS];
int i;
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
//
// run threads in parallel
//
InitializeCriticalSection (&crit);
if (numthreads == 1)
{ // use same thread
func (0);
}
else
{
for (i=0 ; i<numthreads ; i++)
{
threadhandle[i] = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
//0, // DWORD cbStack,
/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
(4096 * 1024),
(LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
(LPVOID)i, // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&threadid[i]);
}
for (i=0 ; i<numthreads ; i++)
WaitForSingleObject (threadhandle[i], INFINITE);
}
DeleteCriticalSection (&crit);
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
===================================================================
OSF1
===================================================================
*/
#ifdef __osf__
#define USED
int numthreads = 4;
void ThreadSetDefault (void)
{
if (numthreads == -1) // not set manually
{
numthreads = 4;
}
}
#include <pthread.h>
pthread_mutex_t *my_mutex;
void ThreadLock (void)
{
if (my_mutex)
pthread_mutex_lock (my_mutex);
}
void ThreadUnlock (void)
{
if (my_mutex)
pthread_mutex_unlock (my_mutex);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
pthread_t work_threads[MAX_THREADS];
pthread_addr_t status;
pthread_attr_t attrib;
pthread_mutexattr_t mattrib;
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
if (pacifier)
setbuf (stdout, NULL);
if (!my_mutex)
{
my_mutex = safe_malloc (sizeof(*my_mutex));
if (pthread_mutexattr_create (&mattrib) == -1)
Error ("pthread_mutex_attr_create failed");
if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
Error ("pthread_mutexattr_setkind_np failed");
if (pthread_mutex_init (my_mutex, mattrib) == -1)
Error ("pthread_mutex_init failed");
}
if (pthread_attr_create (&attrib) == -1)
Error ("pthread_attr_create failed");
if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
Error ("pthread_attr_setstacksize failed");
for (i=0 ; i<numthreads ; i++)
{
if (pthread_create(&work_threads[i], attrib
, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
Error ("pthread_create failed");
}
for (i=0 ; i<numthreads ; i++)
{
if (pthread_join (work_threads[i], &status) == -1)
Error ("pthread_join failed");
}
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
===================================================================
IRIX
===================================================================
*/
#ifdef _MIPS_ISA
#define USED
#include <task.h>
#include <abi_mutex.h>
#include <sys/types.h>
#include <sys/prctl.h>
int numthreads = -1;
abilock_t lck;
void ThreadSetDefault (void)
{
if (numthreads == -1)
numthreads = prctl(PR_MAXPPROCS);
Sys_Printf ("%i threads\n", numthreads);
usconfig (CONF_INITUSERS, numthreads);
}
void ThreadLock (void)
{
spin_lock (&lck);
}
void ThreadUnlock (void)
{
release_lock (&lck);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
int pid[MAX_THREADS];
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
if (pacifier)
setbuf (stdout, NULL);
init_lock (&lck);
for (i=0 ; i<numthreads-1 ; i++)
{
pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
, NULL, 0x200000); // 2 meg stacks
if (pid[i] == -1)
{
perror ("sproc");
Error ("sproc failed");
}
}
func(i);
for (i=0 ; i<numthreads-1 ; i++)
wait (NULL);
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
=======================================================================
Linux pthreads
=======================================================================
*/
#if defined( __linux__ ) || defined( __APPLE__ )
#define USED
// Setting default Threads to 1
int numthreads = 1;
void ThreadSetDefault (void)
{
if (numthreads == -1) // not set manually
{
/* default to one thread, only multi-thread when specifically told to */
numthreads = 1;
}
if(numthreads > 1)
Sys_Printf("threads: %d\n", numthreads);
}
#include <pthread.h>
typedef struct pt_mutex_s
{
pthread_t *owner;
pthread_mutex_t a_mutex;
pthread_cond_t cond;
unsigned int lock;
} pt_mutex_t;
pt_mutex_t global_lock;
void ThreadLock(void)
{
pt_mutex_t *pt_mutex = &global_lock;
if(!threaded)
return;
pthread_mutex_lock(&pt_mutex->a_mutex);
if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner))
pt_mutex->lock++;
else
{
if((!pt_mutex->owner) && (pt_mutex->lock == 0))
{
pt_mutex->owner = (pthread_t *)pthread_self();
pt_mutex->lock = 1;
}
else
{
while(1)
{
pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
if((!pt_mutex->owner) && (pt_mutex->lock == 0))
{
pt_mutex->owner = (pthread_t *)pthread_self();
pt_mutex->lock = 1;
break;
}
}
}
}
pthread_mutex_unlock(&pt_mutex->a_mutex);
}
void ThreadUnlock(void)
{
pt_mutex_t *pt_mutex = &global_lock;
if(!threaded)
return;
pthread_mutex_lock(&pt_mutex->a_mutex);
pt_mutex->lock--;
if(pt_mutex->lock == 0)
{
pt_mutex->owner = NULL;
pthread_cond_signal(&pt_mutex->cond);
}
pthread_mutex_unlock(&pt_mutex->a_mutex);
}
void recursive_mutex_init(pthread_mutexattr_t attribs)
{
pt_mutex_t *pt_mutex = &global_lock;
pt_mutex->owner = NULL;
if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
Error("pthread_mutex_init failed\n");
if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
Error("pthread_cond_init failed\n");
pt_mutex->lock = 0;
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
pthread_mutexattr_t mattrib;
pthread_t work_threads[MAX_THREADS];
int start, end;
int i=0, status=0;
start = I_FloatTime ();
pacifier = showpacifier;
dispatch = 0;
oldf = -1;
workcount = workcnt;
if(numthreads == 1)
func(0);
else
{
threaded = true;
if(pacifier)
setbuf(stdout, NULL);
if(pthread_mutexattr_init(&mattrib) != 0)
Error("pthread_mutexattr_init failed");
#if __GLIBC_MINOR__ == 1
if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
#else
if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
#endif
Error ("pthread_mutexattr_settype failed");
recursive_mutex_init(mattrib);
for (i=0 ; i<numthreads ; i++)
{
/* Default pthread attributes: joinable & non-realtime scheduling */
if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
Error("pthread_create failed");
}
for (i=0 ; i<numthreads ; i++)
{
if(pthread_join(work_threads[i], (void **)&status) != 0)
Error("pthread_join failed");
}
pthread_mutexattr_destroy(&mattrib);
threaded = false;
}
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif // ifdef __linux__
/*
=======================================================================
SINGLE THREAD
=======================================================================
*/
#ifndef USED
int numthreads = 1;
void ThreadSetDefault (void)
{
numthreads = 1;
}
void ThreadLock (void)
{
}
void ThreadUnlock (void)
{
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
int start, end;
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
start = I_FloatTime ();
func(0);
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif

View File

@@ -0,0 +1,186 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// trilib.c: library for loading triangles from an Alias triangle file
//
#include <stdio.h>
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "trilib.h"
// on disk representation of a face
#define FLOAT_START 99999.0
#define FLOAT_END -FLOAT_START
#define MAGIC 123322
//#define NOISY 1
typedef struct {
float v[3];
} vector;
typedef struct
{
vector n; /* normal */
vector p; /* point */
vector c; /* color */
float u; /* u */
float v; /* v */
} aliaspoint_t;
typedef struct {
aliaspoint_t pt[3];
} tf_triangle;
void ByteSwapTri (tf_triangle *tri)
{
int i;
for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
{
((int *)tri)[i] = BigLong (((int *)tri)[i]);
}
}
void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
{
FILE *input;
float start;
char name[256], tex[256];
int i, count, magic;
tf_triangle tri;
triangle_t *ptri;
int iLevel;
int exitpattern;
float t;
t = -FLOAT_START;
*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
if ((input = fopen(filename, "rb")) == 0)
Error ("reader: could not open file '%s'", filename);
iLevel = 0;
fread(&magic, sizeof(int), 1, input);
if (BigLong(magic) != MAGIC)
Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
*pptri = ptri;
while (feof(input) == 0) {
if (fread(&start, sizeof(float), 1, input) < 1)
break;
*(int *)&start = BigLong(*(int *)&start);
if (*(int *)&start != exitpattern)
{
if (start == FLOAT_START) {
/* Start of an object or group of objects. */
i = -1;
do {
/* There are probably better ways to read a string from */
/* a file, but this does allow you to do error checking */
/* (which I'm not doing) on a per character basis. */
++i;
fread( &(name[i]), sizeof( char ), 1, input);
} while( name[i] != '\0' );
// indent();
// fprintf(stdout,"OBJECT START: %s\n",name);
fread( &count, sizeof(int), 1, input);
count = BigLong(count);
++iLevel;
if (count != 0) {
// indent();
// fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
i = -1;
do {
++i;
fread( &(tex[i]), sizeof( char ), 1, input);
} while( tex[i] != '\0' );
// indent();
// fprintf(stdout," Object texture name: '%s'\n",tex);
}
/* Else (count == 0) this is the start of a group, and */
/* no texture name is present. */
}
else if (start == FLOAT_END) {
/* End of an object or group. Yes, the name should be */
/* obvious from context, but it is in here just to be */
/* safe and to provide a little extra information for */
/* those who do not wish to write a recursive reader. */
/* Mia culpa. */
--iLevel;
i = -1;
do {
++i;
fread( &(name[i]), sizeof( char ), 1, input);
} while( name[i] != '\0' );
// indent();
// fprintf(stdout,"OBJECT END: %s\n",name);
continue;
}
}
//
// read the triangles
//
for (i = 0; i < count; ++i) {
int j;
fread( &tri, sizeof(tf_triangle), 1, input );
ByteSwapTri (&tri);
for (j=0 ; j<3 ; j++)
{
int k;
for (k=0 ; k<3 ; k++)
{
ptri->verts[j][k] = tri.pt[j].p.v[k];
}
}
ptri++;
if ((ptri - *pptri) >= MAXTRIANGLES)
Error ("Error: too many triangles; increase MAXTRIANGLES\n");
}
}
*numtriangles = ptri - *pptri;
fclose (input);
}

View File

@@ -0,0 +1,31 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// trilib.h: header file for loading triangles from an Alias triangle file
//
#define MAXTRIANGLES 2048
typedef struct {
vec3_t verts[3];
} triangle_t;
void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles);

File diff suppressed because it is too large Load Diff

634
tools/quake2/q2map/csg.c Normal file
View File

@@ -0,0 +1,634 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qbsp.h"
/*
tag all brushes with original contents
brushes may contain multiple contents
there will be no brush overlap after csg phase
each side has a count of the other sides it splits
the best split will be the one that minimizes the total split counts
of all remaining sides
precalc side on plane table
evaluate split side
{
cost = 0
for all sides
for all sides
get
if side splits side and splitside is on same child
cost++;
}
*/
void SplitBrush2 (bspbrush_t *brush, int planenum,
bspbrush_t **front, bspbrush_t **back)
{
SplitBrush (brush, planenum, front, back);
#if 0
if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1)
(*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo; // not -1
if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
(*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo; // not -1
#endif
}
/*
===============
SubtractBrush
Returns a list of brushes that remain after B is subtracted from A.
May by empty if A is contained inside B.
The originals are undisturbed.
===============
*/
bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b)
{ // a - b = out (list)
int i;
bspbrush_t *front, *back;
bspbrush_t *out, *in;
in = a;
out = NULL;
for (i=0 ; i<b->numsides && in ; i++)
{
SplitBrush2 (in, b->sides[i].planenum, &front, &back);
if (in != a)
FreeBrush (in);
if (front)
{ // add to list
front->next = out;
out = front;
}
in = back;
}
if (in)
FreeBrush (in);
else
{ // didn't really intersect
FreeBrushList (out);
return a;
}
return out;
}
/*
===============
IntersectBrush
Returns a single brush made up by the intersection of the
two provided brushes, or NULL if they are disjoint.
The originals are undisturbed.
===============
*/
bspbrush_t *IntersectBrush (bspbrush_t *a, bspbrush_t *b)
{
int i;
bspbrush_t *front, *back;
bspbrush_t *in;
in = a;
for (i=0 ; i<b->numsides && in ; i++)
{
SplitBrush2 (in, b->sides[i].planenum, &front, &back);
if (in != a)
FreeBrush (in);
if (front)
FreeBrush (front);
in = back;
}
if (in == a)
return NULL;
in->next = NULL;
return in;
}
/*
===============
BrushesDisjoint
Returns true if the two brushes definately do not intersect.
There will be false negatives for some non-axial combinations.
===============
*/
qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b)
{
int i, j;
// check bounding boxes
for (i=0 ; i<3 ; i++)
if (a->mins[i] >= b->maxs[i]
|| a->maxs[i] <= b->mins[i])
return true; // bounding boxes don't overlap
// check for opposing planes
for (i=0 ; i<a->numsides ; i++)
{
for (j=0 ; j<b->numsides ; j++)
{
if (a->sides[i].planenum ==
(b->sides[j].planenum^1) )
return true; // opposite planes, so not touching
}
}
return false; // might intersect
}
/*
===============
IntersectionContents
Returns a content word for the intersection of two brushes.
Some combinations will generate a combination (water + clip),
but most will be the stronger of the two contents.
===============
*/
int IntersectionContents (int c1, int c2)
{
int out;
out = c1 | c2;
if (out & CONTENTS_SOLID)
out = CONTENTS_SOLID;
return out;
}
int minplanenums[3];
int maxplanenums[3];
/*
===============
ClipBrushToBox
Any planes shared with the box edge will be set to no texinfo
===============
*/
bspbrush_t *ClipBrushToBox (bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
{
int i, j;
bspbrush_t *front, *back;
int p;
for (j=0 ; j<2 ; j++)
{
if (brush->maxs[j] > clipmaxs[j])
{
SplitBrush (brush, maxplanenums[j], &front, &back);
if (front)
FreeBrush (front);
brush = back;
if (!brush)
return NULL;
}
if (brush->mins[j] < clipmins[j])
{
SplitBrush (brush, minplanenums[j], &front, &back);
if (back)
FreeBrush (back);
brush = front;
if (!brush)
return NULL;
}
}
// remove any colinear faces
for (i=0 ; i<brush->numsides ; i++)
{
p = brush->sides[i].planenum & ~1;
if (p == maxplanenums[0] || p == maxplanenums[1]
|| p == minplanenums[0] || p == minplanenums[1])
{
brush->sides[i].texinfo = TEXINFO_NODE;
brush->sides[i].visible = false;
}
}
return brush;
}
/*
===============
MakeBspBrushList
===============
*/
bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
vec3_t clipmins, vec3_t clipmaxs)
{
mapbrush_t *mb;
bspbrush_t *brushlist, *newbrush;
int i, j;
int c_faces;
int c_brushes;
int numsides;
int vis;
vec3_t normal;
float dist;
for (i=0 ; i<2 ; i++)
{
VectorClear (normal);
normal[i] = 1;
dist = clipmaxs[i];
maxplanenums[i] = FindFloatPlane (normal, dist);
dist = clipmins[i];
minplanenums[i] = FindFloatPlane (normal, dist);
}
brushlist = NULL;
c_faces = 0;
c_brushes = 0;
for (i=startbrush ; i<endbrush ; i++)
{
mb = &mapbrushes[i];
numsides = mb->numsides;
if (!numsides)
continue;
// make sure the brush has at least one face showing
vis = 0;
for (j=0 ; j<numsides ; j++)
if (mb->original_sides[j].visible && mb->original_sides[j].winding)
vis++;
#if 0
if (!vis)
continue; // no faces at all
#endif
// if the brush is outside the clip area, skip it
for (j=0 ; j<3 ; j++)
if (mb->mins[j] >= clipmaxs[j]
|| mb->maxs[j] <= clipmins[j])
break;
if (j != 3)
continue;
//
// make a copy of the brush
//
newbrush = AllocBrush (mb->numsides);
newbrush->original = mb;
newbrush->numsides = mb->numsides;
memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t));
for (j=0 ; j<numsides ; j++)
{
if (newbrush->sides[j].winding)
newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding);
if (newbrush->sides[j].surf & SURF_HINT)
newbrush->sides[j].visible = true; // hints are always visible
}
VectorCopy (mb->mins, newbrush->mins);
VectorCopy (mb->maxs, newbrush->maxs);
//
// carve off anything outside the clip box
//
newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs);
if (!newbrush)
continue;
c_faces += vis;
c_brushes++;
newbrush->next = brushlist;
brushlist = newbrush;
}
return brushlist;
}
/*
===============
AddBspBrushListToTail
===============
*/
bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
{
bspbrush_t *walk, *next;
for (walk=list ; walk ; walk=next)
{ // add to end of list
next = walk->next;
walk->next = NULL;
tail->next = walk;
tail = walk;
}
return tail;
}
/*
===========
CullList
Builds a new list that doesn't hold the given brush
===========
*/
bspbrush_t *CullList (bspbrush_t *list, bspbrush_t *skip1)
{
bspbrush_t *newlist;
bspbrush_t *next;
newlist = NULL;
for ( ; list ; list = next)
{
next = list->next;
if (list == skip1)
{
FreeBrush (list);
continue;
}
list->next = newlist;
newlist = list;
}
return newlist;
}
/*
==================
WriteBrushMap
==================
*/
void WriteBrushMap (char *name, bspbrush_t *list)
{
FILE *f;
side_t *s;
int i;
winding_t *w;
Sys_Printf ("writing %s\n", name);
f = fopen (name, "wb");
if (!f)
Error ("Can't write %s\b", name);
fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
for ( ; list ; list=list->next )
{
fprintf (f, "{\n");
for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
{
w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);
fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
FreeWinding (w);
}
fprintf (f, "}\n");
}
fprintf (f, "}\n");
fclose (f);
}
/*
==================
BrushGE
Returns true if b1 is allowed to bite b2
==================
*/
qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
{
// detail brushes never bite structural brushes
if ( (b1->original->contents & CONTENTS_DETAIL)
&& !(b2->original->contents & CONTENTS_DETAIL) )
return false;
if (b1->original->contents & CONTENTS_SOLID)
return true;
return false;
}
/*
=================
ChopBrushes
Carves any intersecting solid brushes into the minimum number
of non-intersecting brushes.
=================
*/
bspbrush_t *ChopBrushes (bspbrush_t *head)
{
bspbrush_t *b1, *b2, *next;
bspbrush_t *tail;
bspbrush_t *keep;
bspbrush_t *sub, *sub2;
int c1, c2;
Sys_FPrintf( SYS_VRB, "---- ChopBrushes ----\n");
Sys_FPrintf( SYS_VRB, "original brushes: %i\n", CountBrushList (head));
#if 0
if (startbrush == 0)
WriteBrushList ("before.gl", head, false);
#endif
keep = NULL;
newlist:
// find tail
if (!head)
return NULL;
for (tail=head ; tail->next ; tail=tail->next)
;
for (b1=head ; b1 ; b1=next)
{
next = b1->next;
for (b2=b1->next ; b2 ; b2 = b2->next)
{
if (BrushesDisjoint (b1, b2))
continue;
sub = NULL;
sub2 = NULL;
c1 = 999999;
c2 = 999999;
if ( BrushGE (b2, b1) )
{
sub = SubtractBrush (b1, b2);
if (sub == b1)
continue; // didn't really intersect
if (!sub)
{ // b1 is swallowed by b2
head = CullList (b1, b1);
goto newlist;
}
c1 = CountBrushList (sub);
}
if ( BrushGE (b1, b2) )
{
sub2 = SubtractBrush (b2, b1);
if (sub2 == b2)
continue; // didn't really intersect
if (!sub2)
{ // b2 is swallowed by b1
FreeBrushList (sub);
head = CullList (b1, b2);
goto newlist;
}
c2 = CountBrushList (sub2);
}
if (!sub && !sub2)
continue; // neither one can bite
// only accept if it didn't fragment
// (commening this out allows full fragmentation)
if (c1 > 1 && c2 > 1)
{
if (sub2)
FreeBrushList (sub2);
if (sub)
FreeBrushList (sub);
continue;
}
if (c1 < c2)
{
if (sub2)
FreeBrushList (sub2);
tail = AddBrushListToTail (sub, tail);
head = CullList (b1, b1);
goto newlist;
}
else
{
if (sub)
FreeBrushList (sub);
tail = AddBrushListToTail (sub2, tail);
head = CullList (b1, b2);
goto newlist;
}
}
if (!b2)
{ // b1 is no longer intersecting anything, so keep it
b1->next = keep;
keep = b1;
}
}
Sys_FPrintf( SYS_VRB, "output brushes: %i\n", CountBrushList (keep));
#if 0
{
WriteBrushList ("after.gl", keep, false);
WriteBrushMap ("after.map", keep);
}
#endif
return keep;
}
/*
=================
InitialBrushList
=================
*/
bspbrush_t *InitialBrushList (bspbrush_t *list)
{
bspbrush_t *b;
bspbrush_t *out, *newb;
int i;
// only return brushes that have visible faces
out = NULL;
for (b=list ; b ; b=b->next)
{
#if 0
for (i=0 ; i<b->numsides ; i++)
if (b->sides[i].visible)
break;
if (i == b->numsides)
continue;
#endif
newb = CopyBrush (b);
newb->next = out;
out = newb;
// clear visible, so it must be set by MarkVisibleFaces_r
// to be used in the optimized list
for (i=0 ; i<b->numsides ; i++)
{
newb->sides[i].original = &b->sides[i];
// newb->sides[i].visible = true;
b->sides[i].visible = false;
}
}
return out;
}
/*
=================
OptimizedBrushList
=================
*/
bspbrush_t *OptimizedBrushList (bspbrush_t *list)
{
bspbrush_t *b;
bspbrush_t *out, *newb;
int i;
// only return brushes that have visible faces
out = NULL;
for (b=list ; b ; b=b->next)
{
for (i=0 ; i<b->numsides ; i++)
if (b->sides[i].visible)
break;
if (i == b->numsides)
continue;
newb = CopyBrush (b);
newb->next = out;
out = newb;
}
// WriteBrushList ("vis.gl", out, true);
return out;
}

1076
tools/quake2/q2map/faces.c Normal file

File diff suppressed because it is too large Load Diff

787
tools/quake2/q2map/flow.c Normal file
View File

@@ -0,0 +1,787 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qvis.h"
/*
each portal will have a list of all possible to see from first portal
if (!thread->portalmightsee[portalnum])
portal mightsee
for p2 = all other portals in leaf
get sperating planes
for all portals that might be seen by p2
mark as unseen if not present in seperating plane
flood fill a new mightsee
save as passagemightsee
void CalcMightSee (leaf_t *leaf,
*/
int CountBits (byte *bits, int numbits)
{
int i;
int c;
c = 0;
for (i=0 ; i<numbits ; i++)
if (bits[i>>3] & (1<<(i&7)) )
c++;
return c;
}
int c_fullskip;
int c_portalskip, c_leafskip;
int c_vistest, c_mighttest;
int c_chop, c_nochop;
int active;
void CheckStack (leaf_t *leaf, threaddata_t *thread)
{
pstack_t *p, *p2;
for (p=thread->pstack_head.next ; p ; p=p->next)
{
// printf ("=");
if (p->leaf == leaf)
Error ("CheckStack: leaf recursion");
for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
if (p2->leaf == p->leaf)
Error ("CheckStack: late leaf recursion");
}
// printf ("\n");
}
winding_t *AllocStackWinding (pstack_t *stack)
{
int i;
for (i=0 ; i<3 ; i++)
{
if (stack->freewindings[i])
{
stack->freewindings[i] = 0;
return &stack->windings[i];
}
}
Error ("AllocStackWinding: failed");
return NULL;
}
void FreeStackWinding (winding_t *w, pstack_t *stack)
{
int i;
i = w - stack->windings;
if (i<0 || i>2)
return; // not from local
if (stack->freewindings[i])
Error ("FreeStackWinding: allready free");
stack->freewindings[i] = 1;
}
/*
==============
Vis_ChopWinding
==============
*/
winding_t *Vis_ChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
{
vec_t dists[128];
int sides[128];
int counts[3];
vec_t dot;
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *neww;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->points[i], split->normal);
dot -= split->dist;
dists[i] = dot;
if (dot > ON_EPSILON)
sides[i] = SIDE_FRONT;
else if (dot < -ON_EPSILON)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
if (!counts[1])
return in; // completely on front side
if (!counts[0])
{
FreeStackWinding (in, stack);
return NULL;
}
sides[i] = sides[0];
dists[i] = dists[0];
neww = AllocStackWinding (stack);
neww->numpoints = 0;
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->points[i];
if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
{
FreeStackWinding (neww, stack);
return in; // can't chop -- fall back to original
}
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
{
FreeStackWinding (neww, stack);
return in; // can't chop -- fall back to original
}
// generate a split point
p2 = in->points[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (split->normal[j] == 1)
mid[j] = split->dist;
else if (split->normal[j] == -1)
mid[j] = -split->dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, neww->points[neww->numpoints]);
neww->numpoints++;
}
// free the original winding
FreeStackWinding (in, stack);
return neww;
}
/*
==============
ClipToSeperators
Source, pass, and target are an ordering of portals.
Generates seperating planes canidates by taking two points from source and one
point from pass, and clips target by them.
If target is totally clipped away, that portal can not be seen through.
Normal clip keeps target on the same side as pass, which is correct if the
order goes source, pass, target. If the order goes pass, source, target then
flipclip should be set.
==============
*/
winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
{
int i, j, k, l;
plane_t plane;
vec3_t v1, v2;
float d;
vec_t length;
int counts[3];
qboolean fliptest;
// check all combinations
for (i=0 ; i<source->numpoints ; i++)
{
l = (i+1)%source->numpoints;
VectorSubtract (source->points[l] , source->points[i], v1);
// fing a vertex of pass that makes a plane that puts all of the
// vertexes of pass on the front side and all of the vertexes of
// source on the back side
for (j=0 ; j<pass->numpoints ; j++)
{
VectorSubtract (pass->points[j], source->points[i], v2);
plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
// if points don't make a valid plane, skip it
length = plane.normal[0] * plane.normal[0]
+ plane.normal[1] * plane.normal[1]
+ plane.normal[2] * plane.normal[2];
if (length < ON_EPSILON)
continue;
length = 1/sqrt(length);
plane.normal[0] *= length;
plane.normal[1] *= length;
plane.normal[2] *= length;
plane.dist = DotProduct (pass->points[j], plane.normal);
//
// find out which side of the generated seperating plane has the
// source portal
//
#if 1
fliptest = false;
for (k=0 ; k<source->numpoints ; k++)
{
if (k == i || k == l)
continue;
d = DotProduct (source->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
{ // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
break;
}
else if (d > ON_EPSILON)
{ // source is on the positive side, so we want all
// pass and target on the negative side
fliptest = true;
break;
}
}
if (k == source->numpoints)
continue; // planar with source portal
#else
fliptest = flipclip;
#endif
//
// flip the normal if the source portal is backwards
//
if (fliptest)
{
VectorSubtract (vec3_origin, plane.normal, plane.normal);
plane.dist = -plane.dist;
}
#if 1
//
// if all of the pass portal points are now on the positive side,
// this is the seperating plane
//
counts[0] = counts[1] = counts[2] = 0;
for (k=0 ; k<pass->numpoints ; k++)
{
if (k==j)
continue;
d = DotProduct (pass->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
break;
else if (d > ON_EPSILON)
counts[0]++;
else
counts[2]++;
}
if (k != pass->numpoints)
continue; // points on negative side, not a seperating plane
if (!counts[0])
continue; // planar with seperating plane
#else
k = (j+1)%pass->numpoints;
d = DotProduct (pass->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
continue;
k = (j+pass->numpoints-1)%pass->numpoints;
d = DotProduct (pass->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
continue;
#endif
//
// flip the normal if we want the back side
//
if (flipclip)
{
VectorSubtract (vec3_origin, plane.normal, plane.normal);
plane.dist = -plane.dist;
}
//
// clip target by the seperating plane
//
target = Vis_ChopWinding (target, stack, &plane);
if (!target)
return NULL; // target is not visible
}
}
return target;
}
/*
==================
RecursiveLeafFlow
Flood fill through the leafs
If src_portal is NULL, this is the originating leaf
==================
*/
void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
{
pstack_t stack;
portal_t *p;
plane_t backplane;
leaf_t *leaf;
int i, j;
long *test, *might, *vis, more;
int pnum;
thread->c_chains++;
leaf = &leafs[leafnum];
// CheckStack (leaf, thread);
prevstack->next = &stack;
stack.next = NULL;
stack.leaf = leaf;
stack.portal = NULL;
might = (long *)stack.mightsee;
vis = (long *)thread->base->portalvis;
// check all portals for flowing into other leafs
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
{
continue; // can't possibly see it
}
// if the portal can't see anything we haven't allready seen, skip it
if (p->status == stat_done)
{
test = (long *)p->portalvis;
}
else
{
test = (long *)p->portalflood;
}
more = 0;
for (j=0 ; j<portallongs ; j++)
{
might[j] = ((long *)prevstack->mightsee)[j] & test[j];
more |= (might[j] & ~vis[j]);
}
if (!more &&
(thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
{ // can't see anything new
continue;
}
// get plane of portal, point normal into the neighbor leaf
stack.portalplane = p->plane;
VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
backplane.dist = -p->plane.dist;
// c_portalcheck++;
stack.portal = p;
stack.next = NULL;
stack.freewindings[0] = 1;
stack.freewindings[1] = 1;
stack.freewindings[2] = 1;
#if 1
{
float d;
d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
d -= thread->pstack_head.portalplane.dist;
if (d < -p->radius)
{
continue;
}
else if (d > p->radius)
{
stack.pass = p->winding;
}
else
{
stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
if (!stack.pass)
continue;
}
}
#else
stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
if (!stack.pass)
continue;
#endif
#if 1
{
float d;
d = DotProduct (thread->base->origin, p->plane.normal);
d -= p->plane.dist;
if (d > p->radius)
{
continue;
}
else if (d < -p->radius)
{
stack.source = prevstack->source;
}
else
{
stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
if (!stack.source)
continue;
}
}
#else
stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
if (!stack.source)
continue;
#endif
if (!prevstack->pass)
{ // the second leaf can only be blocked if coplanar
// mark the portal as visible
thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
RecursiveLeafFlow (p->leaf, thread, &stack);
continue;
}
stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack);
if (!stack.pass)
continue;
stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack);
if (!stack.pass)
continue;
// mark the portal as visible
thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
// flow through it for real
RecursiveLeafFlow (p->leaf, thread, &stack);
}
}
/*
===============
PortalFlow
generates the portalvis bit vector
===============
*/
void PortalFlow (int portalnum)
{
threaddata_t data;
int i;
portal_t *p;
int c_might, c_can;
p = sorted_portals[portalnum];
p->status = stat_working;
c_might = CountBits (p->portalflood, numportals*2);
memset (&data, 0, sizeof(data));
data.base = p;
data.pstack_head.portal = p;
data.pstack_head.source = p->winding;
data.pstack_head.portalplane = p->plane;
for (i=0 ; i<portallongs ; i++)
((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
p->status = stat_done;
c_can = CountBits (p->portalvis, numportals*2);
Sys_FPrintf ( SYS_VRB, "portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
(int)(p - portals), c_might, c_can, data.c_chains);
}
/*
===============================================================================
This is a rough first-order aproximation that is used to trivially reject some
of the final calculations.
Calculates portalfront and portalflood bit vectors
thinking about:
typedef struct passage_s
{
struct passage_s *next;
struct portal_s *to;
stryct sep_s *seperators;
byte *mightsee;
} passage_t;
typedef struct portal_s
{
struct passage_s *passages;
int leaf; // leaf portal faces into
} portal_s;
leaf = portal->leaf
clear
for all portals
calc portal visibility
clear bit vector
for all passages
passage visibility
for a portal to be visible to a passage, it must be on the front of
all seperating planes, and both portals must be behind the mew portal
===============================================================================
*/
int c_flood, c_vis;
/*
==================
SimpleFlood
==================
*/
void SimpleFlood (portal_t *srcportal, int leafnum)
{
int i;
leaf_t *leaf;
portal_t *p;
int pnum;
leaf = &leafs[leafnum];
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
continue;
if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
continue;
srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
SimpleFlood (srcportal, p->leaf);
}
}
/*
==============
BasePortalVis
==============
*/
void BasePortalVis (int portalnum)
{
int j, k;
portal_t *tp, *p;
float d;
winding_t *w;
p = portals+portalnum;
p->portalfront = malloc (portalbytes);
memset (p->portalfront, 0, portalbytes);
p->portalflood = malloc (portalbytes);
memset (p->portalflood, 0, portalbytes);
p->portalvis = malloc (portalbytes);
memset (p->portalvis, 0, portalbytes);
for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
{
if (j == portalnum)
continue;
w = tp->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], p->plane.normal)
- p->plane.dist;
if (d > ON_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
w = p->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], tp->plane.normal)
- tp->plane.dist;
if (d < -ON_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
p->portalfront[j>>3] |= (1<<(j&7));
}
SimpleFlood (p, p->leaf);
p->nummightsee = CountBits (p->portalflood, numportals*2);
// printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
c_flood += p->nummightsee;
}
/*
===============================================================================
This is a second order aproximation
Calculates portalvis bit vector
WAAAAAAY too slow.
===============================================================================
*/
/*
==================
RecursiveLeafBitFlow
==================
*/
void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
{
portal_t *p;
leaf_t *leaf;
int i, j;
long more;
int pnum;
byte newmight[MAX_PORTALS/8];
leaf = &leafs[leafnum];
// check all portals for flowing into other leafs
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
pnum = p - portals;
// if some previous portal can't see it, skip
if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
continue;
// if this portal can see some portals we mightsee, recurse
more = 0;
for (j=0 ; j<portallongs ; j++)
{
((long *)newmight)[j] = ((long *)mightsee)[j]
& ((long *)p->portalflood)[j];
more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
}
if (!more)
continue; // can't see anything new
cansee[pnum>>3] |= (1<<(pnum&7));
RecursiveLeafBitFlow (p->leaf, newmight, cansee);
}
}
/*
==============
BetterPortalVis
==============
*/
void BetterPortalVis (int portalnum)
{
portal_t *p;
p = portals+portalnum;
RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
// build leaf vis information
p->nummightsee = CountBits (p->portalvis, numportals*2);
c_vis += p->nummightsee;
}

231
tools/quake2/q2map/gldraw.c Normal file
View File

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

148
tools/quake2/q2map/glfile.c Normal file
View File

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

View File

@@ -0,0 +1,180 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; 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;
Sys_Printf ("--- 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]);
Sys_Printf ("%5i point linefile\n", count+1);
fclose (linefile);
}
*/
/*
=============
LeakFile
Finds the shortest possible chain of portals
that leads from the outside leaf to a specifically
occupied leaf
TTimo: builds a polyline xml node
=============
*/
xmlNodePtr LeakFile (tree_t *tree)
{
vec3_t mid;
FILE *linefile;
char filename[1024];
node_t *node;
int count;
xmlNodePtr xml_node, point;
if (!tree->outside_node.occupied)
return NULL;
Sys_FPrintf (SYS_VRB,"--- 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);
xml_node = xmlNewNode (NULL, "polyline");
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]);
point = xml_NodeForVec(mid);
xmlAddChild(xml_node, point);
count++;
}
// add the occupant center
GetVectorForKey (node->occupant, "origin", mid);
fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
point = xml_NodeForVec(mid);
xmlAddChild(xml_node, point);
Sys_FPrintf( SYS_VRB, "%9d point linefile\n", count+1);
fclose (linefile);
return xml_node;
}

File diff suppressed because it is too large Load Diff

721
tools/quake2/q2map/main.c Normal file
View File

@@ -0,0 +1,721 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* marker */
#define MAIN_C
/* dependencies */
#include "q2map.h"
#define qtrue true
#define qfalse false
char *mapname;
char game[64];
extern qboolean verbose;
/// BSP
extern qboolean drawflag;
extern qboolean noprune;
extern qboolean glview;
extern qboolean nodetail;
extern qboolean fulldetail;
extern qboolean onlyents;
extern qboolean nomerge;
extern qboolean nowater;
extern qboolean nofill;
extern qboolean nocsg;
extern qboolean noweld;
extern qboolean noshare;
extern qboolean nosubdiv;
extern qboolean notjunc;
extern qboolean noopt;
extern qboolean leaktest;
extern qboolean verboseentities;
extern char outbase[32];
extern int block_xl, block_xh, block_yl, block_yh;
extern vec_t microvolume;
extern float subdivide_size;
// VIS
extern char inbase[32];
extern qboolean fastvis;
extern qboolean nosort;
extern int testlevel;
// RAD
extern qboolean dumppatches;
extern int numbounce;
extern qboolean extrasamples;
extern float subdiv;
extern float lightscale;
extern float direct_scale;
extern float entity_scale;
extern qboolean nopvs;
extern float ambient;
extern float maxlight;
void InitPaths( int *argc, char **argv );
/*
Random()
returns a pseudorandom number between 0 and 1
*/
/*
vec_t Random( void )
{
return (vec_t) rand() / RAND_MAX;
}
*/
/*
ExitQ2Map()
cleanup routine
*/
/*
static void ExitQ2Map( void )
{
BSPFilesCleanup();
if( mapDrawSurfs != NULL )
free( mapDrawSurfs );
}
*/
/*
BSPInfo()
emits statistics about the bsp file
*/
int BSPInfo()
{
char source[ 1024 ], ext[ 64 ];
int size;
FILE *f;
Sys_Printf ("\n----- INFO ----\n\n");
/* dummy check */
if( mapname == NULL )
{
Sys_Printf( "No files to dump info for.\n");
return -1;
}
/* enable info mode */
//infoMode = qtrue;
/* mangle filename and get size */
strcpy( source, mapname );
ExtractFileExtension( source, ext );
if( !Q_stricmp( ext, "map" ) )
StripExtension( source );
DefaultExtension( source, ".bsp" );
f = fopen( source, "rb" );
if( f )
{
size = Q_filelength (f);
fclose( f );
}
else
size = 0;
/* load the bsp file and print lump sizes */
Sys_Printf( "Map: %s\n\n", source );
Sys_Printf( "-----------------------------------------------------\n" );
LoadBSPFile( source );
PrintBSPFileSizes();
Sys_Printf( "-----------------------------------------------------\n" );
/* print sizes */
Sys_Printf( "Total: %d B = %.3f kB = %.3f MB\n", size, size / 1024.0, size / (1024.0 * 1024.0) );
Sys_Printf( "-----------------------------------------------------\n" );
/* return count */
return 0;
}
/*
ScaleBSPMain()
amaze and confuse your enemies with wierd scaled maps!
*/
/*
int ScaleBSPMain( int argc, char **argv )
{
int i;
float f, scale;
vec3_t vec;
char str[ 1024 ];
// arg checking
if( argc < 2 )
{
Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
return 0;
}
// get scale
scale = atof( argv[ argc - 2 ] );
if( scale == 0.0f )
{
Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
Sys_Printf( "Non-zero scale value required.\n" );
return 0;
}
// do some path mangling
strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
StripExtension( source );
DefaultExtension( source, ".bsp" );
// load the bsp
Sys_Printf( "Loading %s\n", source );
LoadBSPFile( source );
ParseEntities();
// note it
Sys_Printf( "--- ScaleBSP ---\n" );
Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
// scale entity keys
for( i = 0; i < numBSPEntities && i < numEntities; i++ )
{
// scale origin
GetVectorForKey( &entities[ i ], "origin", vec );
if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
{
VectorScale( vec, scale, vec );
sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
SetKeyValue( &entities[ i ], "origin", str );
}
// scale door lip
f = FloatForKey( &entities[ i ], "lip" );
if( f )
{
f *= scale;
sprintf( str, "%f", f );
SetKeyValue( &entities[ i ], "lip", str );
}
}
// scale models
for( i = 0; i < numBSPModels; i++ )
{
VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
}
// scale nodes
for( i = 0; i < numBSPNodes; i++ )
{
VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
}
// scale leafs
for( i = 0; i < numBSPLeafs; i++ )
{
VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
}
// scale drawverts
for( i = 0; i < numBSPDrawVerts; i++ )
VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
// scale planes
for( i = 0; i < numBSPPlanes; i++ )
bspPlanes[ i ].dist *= scale;
// scale gridsize
GetVectorForKey( &entities[ 0 ], "gridsize", vec );
if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
VectorCopy( gridSize, vec );
VectorScale( vec, scale, vec );
sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
SetKeyValue( &entities[ 0 ], "gridsize", str );
// write the bsp
UnparseEntities();
StripExtension( source );
DefaultExtension( source, "_s.bsp" );
Sys_Printf( "Writing %s\n", source );
WriteBSPFile( source );
// return to sender
return 0;
}
*/
/*
ConvertBSPMain()
main argument processing function for bsp conversion
*/
/*
int ConvertBSPMain( int argc, char **argv )
{
int i;
int (*convertFunc)( char * );
// set default
convertFunc = ConvertBSPToASE;
// arg checking
if( argc < 1 )
{
Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
return 0;
}
// process arguments
for( i = 1; i < (argc - 1); i++ )
{
// -format map|ase|...
if( !strcmp( argv[ i ], "-format" ) )
{
i++;
if( !Q_stricmp( argv[ i ], "ase" ) )
convertFunc = ConvertBSPToASE;
else if( !Q_stricmp( argv[ i ], "map" ) )
convertFunc = ConvertBSPToMap;
else
Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
}
}
// clean up map name
strcpy( source, ExpandArg( argv[ i ] ) );
StripExtension( source );
DefaultExtension( source, ".bsp" );
LoadShaderInfo();
Sys_Printf( "Loading %s\n", source );
// ydnar: load surface file
//% LoadSurfaceExtraFile( source );
LoadBSPFile( source );
// parse bsp entities
ParseEntities();
// convert
return convertFunc( source );
}
*/
int Check_BSP_Options( int argc, char **argv )
{
int i;
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i],"-glview"))
{
glview = true;
}
else if (!strcmp(argv[i], "-draw"))
{
Sys_Printf ("drawflag = true\n");
drawflag = true;
}
else if (!strcmp(argv[i], "-noweld"))
{
Sys_Printf ("noweld = true\n");
noweld = true;
}
else if (!strcmp(argv[i], "-nocsg"))
{
Sys_Printf ("nocsg = true\n");
nocsg = true;
}
else if (!strcmp(argv[i], "-noshare"))
{
Sys_Printf ("noshare = true\n");
noshare = true;
}
else if (!strcmp(argv[i], "-notjunc"))
{
Sys_Printf ("notjunc = true\n");
notjunc = true;
}
else if (!strcmp(argv[i], "-nowater"))
{
Sys_Printf ("nowater = true\n");
nowater = true;
}
else if (!strcmp(argv[i], "-noopt"))
{
Sys_Printf ("noopt = true\n");
noopt = true;
}
else if (!strcmp(argv[i], "-noprune"))
{
Sys_Printf ("noprune = true\n");
noprune = true;
}
else if (!strcmp(argv[i], "-nofill"))
{
Sys_Printf ("nofill = true\n");
nofill = true;
}
else if (!strcmp(argv[i], "-nomerge"))
{
Sys_Printf ("nomerge = true\n");
nomerge = true;
}
else if (!strcmp(argv[i], "-nosubdiv"))
{
Sys_Printf ("nosubdiv = true\n");
nosubdiv = true;
}
else if (!strcmp(argv[i], "-nodetail"))
{
Sys_Printf ("nodetail = true\n");
nodetail = true;
}
else if (!strcmp(argv[i], "-fulldetail"))
{
Sys_Printf ("fulldetail = true\n");
fulldetail = true;
}
else if (!strcmp(argv[i], "-onlyents"))
{
Sys_Printf ("onlyents = true\n");
onlyents = true;
}
else if (!strcmp(argv[i], "-micro"))
{
microvolume = atof(argv[i+1]);
Sys_Printf ("microvolume = %f\n", microvolume);
i++;
}
else if (!strcmp(argv[i], "-leaktest"))
{
Sys_Printf ("leaktest = true\n");
leaktest = true;
}
else if (!strcmp(argv[i], "-verboseentities"))
{
Sys_Printf ("verboseentities = true\n");
verboseentities = true;
}
else if (!strcmp(argv[i], "-chop"))
{
subdivide_size = atof(argv[i+1]);
Sys_Printf ("subdivide_size = %f\n", subdivide_size);
i++;
}
else if (!strcmp(argv[i], "-block"))
{
block_xl = block_xh = atoi(argv[i+1]);
block_yl = block_yh = atoi(argv[i+2]);
Sys_Printf ("block: %i,%i\n", block_xl, block_yl);
i+=2;
}
else if (!strcmp(argv[i], "-blocks"))
{
block_xl = atoi(argv[i+1]);
block_yl = atoi(argv[i+2]);
block_xh = atoi(argv[i+3]);
block_yh = atoi(argv[i+4]);
Sys_Printf ("blocks: %i,%i to %i,%i\n",
block_xl, block_yl, block_xh, block_yh);
i+=4;
}
else if (!strcmp (argv[i],"-tmpout"))
{
strcpy (outbase, "/tmp");
}
else
break;
}
return 0;
}
int Check_VIS_Options( int argc, char **argv )
{
int i;
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i], "-fast"))
{
Sys_Printf ("fastvis = true\n");
fastvis = true;
}
else if (!strcmp(argv[i], "-level"))
{
testlevel = atoi(argv[i+1]);
Sys_Printf ("testlevel = %i\n", testlevel);
i++;
}
else if (!strcmp (argv[i],"-nosort"))
{
Sys_Printf ("nosort = true\n");
nosort = true;
}
else if (!strcmp (argv[i],"-tmpin"))
strcpy (inbase, "/tmp");
else if (!strcmp (argv[i],"-tmpout"))
strcpy (outbase, "/tmp");
else
break;
}
return 0;
}
int Check_RAD_Options( int argc, char **argv )
{
int i;
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i],"-dump"))
dumppatches = true;
else if (!strcmp(argv[i],"-bounce"))
{
numbounce = atoi (argv[i+1]);
i++;
}
else if (!strcmp(argv[i],"-extra"))
{
extrasamples = true;
Sys_Printf ("extrasamples = true\n");
}
else if (!strcmp(argv[i],"-chop"))
{
subdiv = atoi (argv[i+1]);
i++;
}
else if (!strcmp(argv[i],"-scale"))
{
lightscale = atof (argv[i+1]);
i++;
}
else if (!strcmp(argv[i],"-direct"))
{
direct_scale *= atof(argv[i+1]);
Sys_Printf ("direct light scaling at %f\n", direct_scale);
i++;
}
else if (!strcmp(argv[i],"-entity"))
{
entity_scale *= atof(argv[i+1]);
Sys_Printf ("entity light scaling at %f\n", entity_scale);
i++;
}
else if (!strcmp(argv[i],"-glview"))
{
glview = true;
Sys_Printf ("glview = true\n");
}
else if (!strcmp(argv[i],"-nopvs"))
{
nopvs = true;
Sys_Printf ("nopvs = true\n");
}
else if (!strcmp(argv[i],"-ambient"))
{
ambient = atof (argv[i+1]) * 128;
i++;
}
else if (!strcmp(argv[i],"-maxlight"))
{
maxlight = atof (argv[i+1]) * 128;
i++;
}
else if (!strcmp (argv[i],"-tmpin"))
strcpy (inbase, "/tmp");
else if (!strcmp (argv[i],"-tmpout"))
strcpy (outbase, "/tmp");
else
break;
}
return 0;
}
/*
main()
*/
int main( int argc, char **argv )
{
int i;
int r=0;
int total_time;
double start, end;
int alt_argc;
char** alt_argv;
qboolean do_info=qfalse;
qboolean do_bsp=qfalse;
qboolean do_vis=qfalse;
qboolean do_rad=qfalse;
/* we want consistent 'randomness' */
srand( 0 );
/* start timer */
start = I_FloatTime();
Sys_Printf( "\nQ2Map - Ver. 1.0\n" );
/* set exit call */
//atexit( ExitQ3Map );
game[0] = 0;
if ( argc < 2 )
{
Sys_Printf(" %s: -game [quake2,heretic2] -fs_basepath basepath -info -bsp -vis -rad mapname\n",argv[0]);
return -1;
}
/* read general options first */
for( i = 1; i < argc; i++ )
{
/* -connect */
if( !strcmp( argv[ i ], "-connect" ) )
{
i++;
Broadcast_Setup( argv[ i ] );
}
/* verbose */
else if( !strcmp( argv[ i ], "-v" ) )
{
verbose = qtrue;
}
/* threads */
else if( !strcmp( argv[ i ], "-threads" ) )
{
i++;
numthreads = atoi( argv[ i ] );
}
else if( !strcmp( argv[ i ], "-game" ) )
{
i++;
strncpy (game, argv[ i ] , 64);
strlower(game);
}
}
/* set number of threads */
ThreadSetDefault();
/* ydnar: new path initialization */
InitPaths( &argc, argv );
/* read compiling options */
for( i = 1; i < argc; i++ )
{
/* info */
if( !strcmp( argv[ i ], "-info" ) )
{
do_info=qtrue;
}
/* bsp */
if( !strcmp( argv[ i ], "-bsp" ) )
{
do_bsp=qtrue;
alt_argc=argc - i;
alt_argv= (char **) ( argv + i );
Check_BSP_Options( alt_argc, alt_argv );
}
/* vis */
if( !strcmp( argv[ i ], "-vis" ) )
{
do_vis=qtrue;
alt_argc=argc - i;
alt_argv= (char **) ( argv + i );
Check_VIS_Options( alt_argc, alt_argv );
}
/* rad */
if( !strcmp( argv[ i ], "-rad" ) )
{
do_rad=qtrue;
alt_argc=argc - i;
alt_argv= (char **) ( argv + i );
Check_RAD_Options( alt_argc, alt_argv );
}
}
if (game[0] == 0)
strncpy( game, "quake2", 7);
Sys_Printf("Game: %s\n", game);
if ( !do_info && !do_bsp && !do_vis && !do_rad)
Sys_Printf("ERROR: -bsp, -vis, -light, nor -info specified.\nWhat to you want me to do?\n\n");
else
{
mapname=argv[argc-1];
if (do_bsp)
BSP_Main();
if (do_vis)
VIS_Main();
if (do_rad)
RAD_Main();
if (do_info)
BSPInfo();
}
/* emit time */
end = I_FloatTime();
total_time = (int) (end-start);
Sys_Printf("\nTotal Time: ");
if ( total_time > 59 )
Sys_Printf("%d Minutes ", total_time/60 );
Sys_Printf( "%d Seconds\n", total_time%60 );
/* shut down connection */
Broadcast_Shutdown();
/* return any error code */
return r;
}

1017
tools/quake2/q2map/map.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; 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)
{
}

View File

@@ -0,0 +1,603 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qrad.h"
vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
/*
===================================================================
TEXTURE LIGHT VALUES
===================================================================
*/
/*
======================
CalcTextureReflectivity_Quake2
======================
*/
void CalcTextureReflectivity_Quake2 (void)
{
int i;
int j, k, texels;
int color[3];
int texel;
byte *palette;
char path[1024];
float r, scale;
miptex_t *mt;
sprintf (path, "%spics/colormap.pcx", gamedir);
// get the game palette
Load256Image (path, NULL, &palette, NULL, NULL);
// allways set index 0 even if no textures
texture_reflectivity[0][0] = 0.5;
texture_reflectivity[0][1] = 0.5;
texture_reflectivity[0][2] = 0.5;
for (i=0 ; i<numtexinfo ; i++)
{
// see if an earlier texinfo allready got the value
for (j=0 ; j<i ; j++)
{
if (!strcmp (texinfo[i].texture, texinfo[j].texture))
{
VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
break;
}
}
if (j != i)
continue;
// load the wal file
sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);
if (TryLoadFile (path, (void **)&mt) == -1)
{
Sys_Printf ("Couldn't load %s\n", path);
texture_reflectivity[i][0] = 0.5;
texture_reflectivity[i][1] = 0.5;
texture_reflectivity[i][2] = 0.5;
continue;
}
texels = LittleLong(mt->width)*LittleLong(mt->height);
color[0] = color[1] = color[2] = 0;
for (j=0 ; j<texels ; j++)
{
texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
for (k=0 ; k<3 ; k++)
color[k] += palette[texel*3+k];
}
for (j=0 ; j<3 ; j++)
{
r = color[j]/texels/255.0;
texture_reflectivity[i][j] = r;
}
// scale the reflectivity up, because the textures are
// so dim
scale = ColorNormalize (texture_reflectivity[i],
texture_reflectivity[i]);
if (scale < 0.5)
{
scale *= 2;
VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);
}
#if 0
texture_reflectivity[i][0] = 0.5;
texture_reflectivity[i][1] = 0.5;
texture_reflectivity[i][2] = 0.5;
#endif
}
}
/*
======================
CalcTextureReflectivity_Heretic2
======================
*/
void CalcTextureReflectivity_Heretic2 (void)
{
int i;
int j, texels;
int color[3];
int texel;
char path[1024];
float r;
miptex_m8_t *mt;
miptex_m32_t *mt32;
byte *pos;
// allways set index 0 even if no textures
texture_reflectivity[0][0] = 0.5;
texture_reflectivity[0][1] = 0.5;
texture_reflectivity[0][2] = 0.5;
for (i=0 ; i<numtexinfo ; i++)
{
// see if an earlier texinfo allready got the value
for (j=0 ; j<i ; j++)
{
if (!strcmp (texinfo[i].texture, texinfo[j].texture))
{
VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
break;
}
}
if (j != i)
continue;
// load the wal file
sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);
if (TryLoadFile (path, (void **)&mt32) == -1)
{
sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);
if (TryLoadFile (path, (void **)&mt) == -1)
{
Sys_Printf ("Couldn't load %s\n", path);
texture_reflectivity[i][0] = 0.5;
texture_reflectivity[i][1] = 0.5;
texture_reflectivity[i][2] = 0.5;
continue;
}
texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);
color[0] = color[1] = color[2] = 0;
for (j=0 ; j<texels ; j++)
{
texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
color[0] += mt->palette[texel].r;
color[1] += mt->palette[texel].g;
color[2] += mt->palette[texel].b;
}
free(mt);
}
else
{
texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);
color[0] = color[1] = color[2] = 0;
for (j=0 ; j<texels ; j++)
{
pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);
color[0] += *pos++; // r
color[1] += *pos++; // g
color[2] += *pos++; // b
}
free(mt32);
}
for (j=0 ; j<3 ; j++)
{
r = color[j]/((float) texels*255.0);
texture_reflectivity[i][j] = r;
}
}
}
/*
=======================================================================
MAKE FACES
=======================================================================
*/
/*
=============
WindingFromFace
=============
*/
winding_t *WindingFromFace (dface_t *f)
{
int i;
int se;
dvertex_t *dv;
int v;
winding_t *w;
w = AllocWinding (f->numedges);
w->numpoints = f->numedges;
for (i=0 ; i<f->numedges ; i++)
{
se = dsurfedges[f->firstedge + i];
if (se < 0)
v = dedges[-se].v[1];
else
v = dedges[se].v[0];
dv = &dvertexes[v];
VectorCopy (dv->point, w->p[i]);
}
RemoveColinearPoints (w);
return w;
}
/*
=============
BaseLightForFace
=============
*/
void BaseLightForFace (dface_t *f, vec3_t color)
{
texinfo_t *tx;
//
// check for light emited by texture
//
tx = &texinfo[f->texinfo];
if (!(tx->flags & SURF_LIGHT) || tx->value == 0)
{
VectorClear (color);
return;
}
VectorScale (texture_reflectivity[f->texinfo], tx->value, color);
}
qboolean IsSky (dface_t *f)
{
texinfo_t *tx;
tx = &texinfo[f->texinfo];
if (tx->flags & SURF_SKY)
return true;
return false;
}
/*
=============
MakePatchForFace
=============
*/
float totalarea;
void MakePatchForFace (int fn, winding_t *w)
{
dface_t *f;
float area;
patch_t *patch;
dplane_t *pl;
int i;
vec3_t color;
dleaf_t *leaf;
f = &dfaces[fn];
area = WindingArea (w);
totalarea += area;
patch = &patches[num_patches];
if (num_patches == MAX_PATCHES)
Error ("num_patches == MAX_PATCHES");
patch->next = face_patches[fn];
face_patches[fn] = patch;
patch->winding = w;
if (f->side)
patch->plane = &backplanes[f->planenum];
else
patch->plane = &dplanes[f->planenum];
if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )
{ // origin offset faces must create new planes
if (numplanes + fakeplanes >= MAX_MAP_PLANES)
Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");
pl = &dplanes[numplanes + fakeplanes];
fakeplanes++;
*pl = *(patch->plane);
pl->dist += DotProduct (face_offset[fn], pl->normal);
patch->plane = pl;
}
WindingCenter (w, patch->origin);
VectorAdd (patch->origin, patch->plane->normal, patch->origin);
leaf = Rad_PointInLeaf(patch->origin);
patch->cluster = leaf->cluster;
if (patch->cluster == -1)
Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
patch->area = area;
if (patch->area <= 1)
patch->area = 1;
patch->sky = IsSky (f);
VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);
// non-bmodel patches can emit light
if (fn < dmodels[0].numfaces)
{
BaseLightForFace (f, patch->baselight);
ColorNormalize (patch->reflectivity, color);
for (i=0 ; i<3 ; i++)
patch->baselight[i] *= color[i];
VectorCopy (patch->baselight, patch->totallight);
}
num_patches++;
}
entity_t *EntityForModel (int modnum)
{
int i;
char *s;
char name[16];
sprintf (name, "*%i", modnum);
// search the entities for one using modnum
for (i=0 ; i<num_entities ; i++)
{
s = ValueForKey (&entities[i], "model");
if (!strcmp (s, name))
return &entities[i];
}
return &entities[0];
}
/*
=============
MakePatches
=============
*/
void MakePatches (void)
{
int i, j, k;
dface_t *f;
int fn;
winding_t *w;
dmodel_t *mod;
vec3_t origin;
entity_t *ent;
Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);
for (i=0 ; i<nummodels ; i++)
{
mod = &dmodels[i];
ent = EntityForModel (i);
// bmodels with origin brushes need to be offset into their
// in-use position
GetVectorForKey (ent, "origin", origin);
//VectorCopy (vec3_origin, origin);
for (j=0 ; j<mod->numfaces ; j++)
{
fn = mod->firstface + j;
face_entity[fn] = ent;
VectorCopy (origin, face_offset[fn]);
f = &dfaces[fn];
w = WindingFromFace (f);
for (k=0 ; k<w->numpoints ; k++)
{
VectorAdd (w->p[k], origin, w->p[k]);
}
MakePatchForFace (fn, w);
}
}
Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));
}
/*
=======================================================================
SUBDIVIDE
=======================================================================
*/
void FinishSplit (patch_t *patch, patch_t *newp)
{
dleaf_t *leaf;
VectorCopy (patch->baselight, newp->baselight);
VectorCopy (patch->totallight, newp->totallight);
VectorCopy (patch->reflectivity, newp->reflectivity);
newp->plane = patch->plane;
newp->sky = patch->sky;
patch->area = WindingArea (patch->winding);
newp->area = WindingArea (newp->winding);
if (patch->area <= 1)
patch->area = 1;
if (newp->area <= 1)
newp->area = 1;
WindingCenter (patch->winding, patch->origin);
VectorAdd (patch->origin, patch->plane->normal, patch->origin);
leaf = Rad_PointInLeaf(patch->origin);
patch->cluster = leaf->cluster;
if (patch->cluster == -1)
Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
WindingCenter (newp->winding, newp->origin);
VectorAdd (newp->origin, newp->plane->normal, newp->origin);
leaf = Rad_PointInLeaf(newp->origin);
newp->cluster = leaf->cluster;
if (newp->cluster == -1)
Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
}
/*
=============
SubdividePatch
Chops the patch only if its local bounds exceed the max size
=============
*/
void SubdividePatch (patch_t *patch)
{
winding_t *w, *o1, *o2;
vec3_t mins, maxs, total;
vec3_t split;
vec_t dist;
int i, j;
vec_t v;
patch_t *newp;
w = patch->winding;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for (i=0 ; i<w->numpoints ; i++)
{
for (j=0 ; j<3 ; j++)
{
v = w->p[i][j];
if (v < mins[j])
mins[j] = v;
if (v > maxs[j])
maxs[j] = v;
}
}
VectorSubtract (maxs, mins, total);
for (i=0 ; i<3 ; i++)
if (total[i] > (subdiv+1) )
break;
if (i == 3)
{
// no splitting needed
return;
}
//
// split the winding
//
VectorCopy (vec3_origin, split);
split[i] = 1;
dist = (mins[i] + maxs[i])*0.5;
ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
//
// create a new patch
//
if (num_patches == MAX_PATCHES)
Error ("MAX_PATCHES");
newp = &patches[num_patches];
num_patches++;
newp->next = patch->next;
patch->next = newp;
patch->winding = o1;
newp->winding = o2;
FinishSplit (patch, newp);
SubdividePatch (patch);
SubdividePatch (newp);
}
/*
=============
DicePatch
Chops the patch by a global grid
=============
*/
void DicePatch (patch_t *patch)
{
winding_t *w, *o1, *o2;
vec3_t mins, maxs;
vec3_t split;
vec_t dist;
int i;
patch_t *newp;
w = patch->winding;
WindingBounds (w, mins, maxs);
for (i=0 ; i<3 ; i++)
if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))
break;
if (i == 3)
{
// no splitting needed
return;
}
//
// split the winding
//
VectorCopy (vec3_origin, split);
split[i] = 1;
dist = subdiv*(1+floor((mins[i]+1)/subdiv));
ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
//
// create a new patch
//
if (num_patches == MAX_PATCHES)
Error ("MAX_PATCHES");
newp = &patches[num_patches];
num_patches++;
newp->next = patch->next;
patch->next = newp;
patch->winding = o1;
newp->winding = o2;
FinishSplit (patch, newp);
DicePatch (patch);
DicePatch (newp);
}
/*
=============
SubdividePatches
=============
*/
void SubdividePatches (void)
{
int i, num;
if (subdiv < 1)
return;
num = num_patches; // because the list will grow
for (i=0 ; i<num ; i++)
{
// SubdividePatch (&patches[i]);
DicePatch (&patches[i]);
}
Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);
}
//=====================================================================

1110
tools/quake2/q2map/portals.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,290 @@
# Microsoft Developer Studio Project File - Name="q2map" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=q2map - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "q2map.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "q2map.mak" CFG="q2map - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "q2map - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "q2map - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "q2map - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
F90=df.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX- /Zi /O2 /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 wsock32.lib l_net.lib mathlib.lib /nologo /stack:0x400000 /subsystem:console /map /machine:I386 /libpath:"..\..\..\libs\mathlib\Release" /libpath:"..\..\..\libs\l_net\Release" /libpath:"..\..\..\..\libxml2\win32\libxml2\release_so"
!ELSEIF "$(CFG)" == "q2map - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
F90=df.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\include" /I "..\..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\..\gtk2-win32\lib\glib-2.0\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 wsock32.lib l_net.lib mathlib.lib /nologo /stack:0x400000 /subsystem:console /profile /map /debug /machine:I386 /nodefaultlib:"libcd" /libpath:"..\..\..\libs\mathlib\Debug" /libpath:"..\..\..\libs\l_net\Debug" /libpath:"..\..\..\..\libxml2\win32\libxml2\debug_so"
!ENDIF
# Begin Target
# Name "q2map - Win32 Release"
# Name "q2map - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\brushbsp.c
# End Source File
# Begin Source File
SOURCE=..\common\bspfile.c
# End Source File
# Begin Source File
SOURCE=..\common\cmdlib.c
# End Source File
# Begin Source File
SOURCE=.\csg.c
# End Source File
# Begin Source File
SOURCE=.\faces.c
# End Source File
# Begin Source File
SOURCE=.\flow.c
# End Source File
# Begin Source File
SOURCE=.\glfile.c
# End Source File
# Begin Source File
SOURCE=..\common\inout.c
# End Source File
# Begin Source File
SOURCE=..\common\l3dslib.c
# End Source File
# Begin Source File
SOURCE=..\common\lbmlib.c
# End Source File
# Begin Source File
SOURCE=.\leakfile.c
# End Source File
# Begin Source File
SOURCE=.\lightmap.c
# End Source File
# Begin Source File
SOURCE=.\main.c
# End Source File
# Begin Source File
SOURCE=.\map.c
# End Source File
# Begin Source File
SOURCE=..\common\mathlib.c
# End Source File
# Begin Source File
SOURCE=..\common\md4.c
# End Source File
# Begin Source File
SOURCE=.\nodraw.c
# End Source File
# Begin Source File
SOURCE=.\patches.c
# End Source File
# Begin Source File
SOURCE=..\common\path_init.c
# End Source File
# Begin Source File
SOURCE=..\common\polylib.c
# End Source File
# Begin Source File
SOURCE=.\portals.c
# End Source File
# Begin Source File
SOURCE=.\prtfile.c
# End Source File
# Begin Source File
SOURCE=.\qbsp.c
# End Source File
# Begin Source File
SOURCE=.\qrad.c
# End Source File
# Begin Source File
SOURCE=.\qvis.c
# End Source File
# Begin Source File
SOURCE=..\common\scriplib.c
# End Source File
# Begin Source File
SOURCE=.\textures.c
# End Source File
# Begin Source File
SOURCE=..\common\threads.c
# End Source File
# Begin Source File
SOURCE=.\trace.c
# End Source File
# Begin Source File
SOURCE=.\tree.c
# End Source File
# Begin Source File
SOURCE=..\common\trilib.c
# End Source File
# Begin Source File
SOURCE=.\writebsp.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\common\bspfile.h
# End Source File
# Begin Source File
SOURCE=..\common\cmdlib.h
# End Source File
# Begin Source File
SOURCE=..\common\inout.h
# End Source File
# Begin Source File
SOURCE=..\common\l3dslib.h
# End Source File
# Begin Source File
SOURCE=..\common\lbmlib.h
# End Source File
# Begin Source File
SOURCE=..\common\mathlib.h
# End Source File
# Begin Source File
SOURCE=..\common\polylib.h
# End Source File
# Begin Source File
SOURCE=..\common\q2_threads.h
# End Source File
# Begin Source File
SOURCE=.\q2map.h
# End Source File
# Begin Source File
SOURCE=.\qbsp.h
# End Source File
# Begin Source File
SOURCE=..\common\qfiles.h
# End Source File
# Begin Source File
SOURCE=.\qrad.h
# End Source File
# Begin Source File
SOURCE=.\qvis.h
# End Source File
# Begin Source File
SOURCE=..\common\scriplib.h
# End Source File
# Begin Source File
SOURCE=..\common\trilib.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,50 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// q2map.h
/* platform-specific */
#if defined( __linux__ ) || defined( __APPLE__ )
#define Q_UNIX
#endif
#ifdef Q_UNIX
#include <unistd.h>
#include <pwd.h>
#include <limits.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include <stdlib.h>
#include "cmdlib.h"
#include "mathlib.h"
#include "scriplib.h"
#include "polylib.h"
#include "q2_threads.h"
#include "bspfile.h"
#include "inout.h"
int BSP_Main ();
int VIS_Main ();
int RAD_Main ();

View File

@@ -0,0 +1,330 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="q2map"
ProjectGUID="{FB80DE6C-51C8-4D56-876D-C7878A4EB10B}"
RootNamespace="q2map">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\include;..\common;..\..\..\libs;&quot;..\..\..\..\libxml2-2.6\include&quot;"
PreprocessorDefinitions="_DEBUG,WIN32,_CONSOLE"
ExceptionHandling="FALSE"
BasicRuntimeChecks="0"
RuntimeLibrary="3"
BufferSecurityCheck="FALSE"
PrecompiledHeaderFile=".\Debug/q2map.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
BrowseInformation="0"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="wsock32.lib libxml2.lib"
OutputFile=".\Debug/q2map.exe"
LinkIncremental="2"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="&quot;..\..\..\..\libxml2-2.6\win32\lib&quot;"
IgnoreDefaultLibraryNames="libcd"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\Debug/q2map.pdb"
GenerateMapFile="TRUE"
MapFileName=".\Debug/q2map.map"
SubSystem="1"
StackReserveSize="4194304"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/q2map.tlb"/>
<Tool
Name="VCPostBuildEventTool"
Description="Copy to dir..."
CommandLine="copy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)install&quot;"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="3"
GlobalOptimizations="TRUE"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="TRUE"
FavorSizeOrSpeed="1"
OptimizeForProcessor="2"
OptimizeForWindowsApplication="TRUE"
AdditionalIncludeDirectories="..\..\..\include;..\common;..\..\..\libs;&quot;..\..\..\..\libxml2-2.6\include&quot;"
PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE"
StringPooling="TRUE"
ExceptionHandling="FALSE"
BasicRuntimeChecks="0"
RuntimeLibrary="2"
BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE"
PrecompiledHeaderFile=".\Release/q2map.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
BrowseInformation="0"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="3"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="wsock32.lib libxml2.lib"
OutputFile=".\Release/q2map.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="&quot;..\..\..\..\libxml2-2.6\win32\lib&quot;"
ProgramDatabaseFile=".\Release/q2map.pdb"
GenerateMapFile="TRUE"
MapFileName=".\Release/q2map.map"
SubSystem="1"
StackReserveSize="4194304"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/q2map.tlb"/>
<Tool
Name="VCPostBuildEventTool"
Description="Copy to dir..."
CommandLine="copy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)install&quot;"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="src"
Filter="">
<File
RelativePath=".\brushbsp.c">
</File>
<File
RelativePath="..\common\bspfile.c">
</File>
<File
RelativePath="..\common\bspfile.h">
</File>
<File
RelativePath="..\common\cmdlib.c">
</File>
<File
RelativePath="..\common\cmdlib.h">
</File>
<File
RelativePath=".\csg.c">
</File>
<File
RelativePath=".\faces.c">
</File>
<File
RelativePath=".\flow.c">
</File>
<File
RelativePath=".\glfile.c">
</File>
<File
RelativePath="..\common\inout.c">
</File>
<File
RelativePath="..\common\inout.h">
</File>
<File
RelativePath="..\common\l3dslib.c">
</File>
<File
RelativePath="..\common\l3dslib.h">
</File>
<File
RelativePath="..\common\lbmlib.c">
</File>
<File
RelativePath="..\common\lbmlib.h">
</File>
<File
RelativePath=".\leakfile.c">
</File>
<File
RelativePath=".\lightmap.c">
</File>
<File
RelativePath=".\main.c">
</File>
<File
RelativePath=".\map.c">
</File>
<File
RelativePath="..\common\mathlib.c">
</File>
<File
RelativePath="..\common\mathlib.h">
</File>
<File
RelativePath="..\common\md4.c">
</File>
<File
RelativePath=".\nodraw.c">
</File>
<File
RelativePath=".\patches.c">
</File>
<File
RelativePath="..\common\path_init.c">
</File>
<File
RelativePath="..\common\polylib.c">
</File>
<File
RelativePath="..\common\polylib.h">
</File>
<File
RelativePath=".\portals.c">
</File>
<File
RelativePath=".\prtfile.c">
</File>
<File
RelativePath="..\common\q2_threads.h">
</File>
<File
RelativePath=".\q2map.h">
</File>
<File
RelativePath=".\qbsp.c">
</File>
<File
RelativePath=".\qbsp.h">
</File>
<File
RelativePath="..\common\qfiles.h">
</File>
<File
RelativePath=".\qrad.c">
</File>
<File
RelativePath=".\qrad.h">
</File>
<File
RelativePath=".\qvis.c">
</File>
<File
RelativePath=".\qvis.h">
</File>
<File
RelativePath="..\common\scriplib.c">
</File>
<File
RelativePath="..\common\scriplib.h">
</File>
<File
RelativePath=".\textures.c">
</File>
<File
RelativePath="..\common\threads.c">
</File>
<File
RelativePath=".\trace.c">
</File>
<File
RelativePath=".\tree.c">
</File>
<File
RelativePath="..\common\trilib.c">
</File>
<File
RelativePath="..\common\trilib.h">
</File>
<File
RelativePath=".\writebsp.c">
</File>
</Filter>
<File
RelativePath="..\..\..\touch.py">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="python &quot;$(SolutionDir)touch.py&quot; &quot;$(TargetPath)&quot;
"
AdditionalDependencies="&quot;$(SolutionDir)install\$(TargetFileName)&quot;"
Outputs="&quot;$(TargetPath)&quot;"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="python &quot;$(SolutionDir)touch.py&quot; &quot;$(TargetPath)&quot;
"
AdditionalDependencies="&quot;$(SolutionDir)install\$(TargetFileName)&quot;"
Outputs="&quot;$(TargetPath)&quot;"/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

426
tools/quake2/q2map/qbsp.c Normal file
View File

@@ -0,0 +1,426 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// csg4.c
#include "qbsp.h"
extern float subdivide_size;
char source[1024];
char name[1024];
vec_t microvolume = 1.0;
qboolean noprune;
qboolean glview;
qboolean nodetail;
qboolean fulldetail;
qboolean onlyents;
qboolean nomerge;
qboolean nowater;
qboolean nofill;
qboolean nocsg;
qboolean noweld;
qboolean noshare;
qboolean nosubdiv;
qboolean notjunc;
qboolean noopt;
qboolean leaktest;
qboolean verboseentities;
char outbase[32];
int block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
int entity_num;
node_t *block_nodes[10][10];
/*
============
BlockTree
============
*/
node_t *BlockTree (int xl, int yl, int xh, int yh)
{
node_t *node;
vec3_t normal;
float dist;
int mid;
if (xl == xh && yl == yh)
{
node = block_nodes[xl+5][yl+5];
if (!node)
{ // return an empty leaf
node = AllocNode ();
node->planenum = PLANENUM_LEAF;
node->contents = 0; //CONTENTS_SOLID;
return node;
}
return node;
}
// create a seperator along the largest axis
node = AllocNode ();
if (xh - xl > yh - yl)
{ // split x axis
mid = xl + (xh-xl)/2 + 1;
normal[0] = 1;
normal[1] = 0;
normal[2] = 0;
dist = mid*1024;
node->planenum = FindFloatPlane (normal, dist);
node->children[0] = BlockTree ( mid, yl, xh, yh);
node->children[1] = BlockTree ( xl, yl, mid-1, yh);
}
else
{
mid = yl + (yh-yl)/2 + 1;
normal[0] = 0;
normal[1] = 1;
normal[2] = 0;
dist = mid*1024;
node->planenum = FindFloatPlane (normal, dist);
node->children[0] = BlockTree ( xl, mid, xh, yh);
node->children[1] = BlockTree ( xl, yl, xh, mid-1);
}
return node;
}
/*
============
ProcessBlock_Thread
============
*/
int brush_start, brush_end;
void ProcessBlock_Thread (int blocknum)
{
int xblock, yblock;
vec3_t mins, maxs;
bspbrush_t *brushes;
tree_t *tree;
node_t *node;
yblock = block_yl + blocknum / (block_xh-block_xl+1);
xblock = block_xl + blocknum % (block_xh-block_xl+1);
Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);
mins[0] = xblock*1024;
mins[1] = yblock*1024;
mins[2] = -4096;
maxs[0] = (xblock+1)*1024;
maxs[1] = (yblock+1)*1024;
maxs[2] = 4096;
// the makelist and chopbrushes could be cached between the passes...
brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
if (!brushes)
{
node = AllocNode ();
node->planenum = PLANENUM_LEAF;
node->contents = CONTENTS_SOLID;
block_nodes[xblock+5][yblock+5] = node;
return;
}
if (!nocsg)
brushes = ChopBrushes (brushes);
tree = BrushBSP (brushes, mins, maxs);
block_nodes[xblock+5][yblock+5] = tree->headnode;
}
/*
============
ProcessWorldModel
============
*/
void ProcessWorldModel (void)
{
entity_t *e;
tree_t *tree;
qboolean leaked;
qboolean optimize;
xmlNodePtr polyline, leaknode;
char level[ 2 ];
e = &entities[entity_num];
brush_start = e->firstbrush;
brush_end = brush_start + e->numbrushes;
leaked = false;
//
// perform per-block operations
//
if (block_xh * 1024 > map_maxs[0])
block_xh = floor(map_maxs[0]/1024.0);
if ( (block_xl+1) * 1024 < map_mins[0])
block_xl = floor(map_mins[0]/1024.0);
if (block_yh * 1024 > map_maxs[1])
block_yh = floor(map_maxs[1]/1024.0);
if ( (block_yl+1) * 1024 < map_mins[1])
block_yl = floor(map_mins[1]/1024.0);
if (block_xl <-4)
block_xl = -4;
if (block_yl <-4)
block_yl = -4;
if (block_xh > 3)
block_xh = 3;
if (block_yh > 3)
block_yh = 3;
for (optimize = false ; optimize <= true ; optimize++)
{
Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
!verbose, ProcessBlock_Thread);
//
// build the division tree
// oversizing the blocks guarantees that all the boundaries
// will also get nodes.
//
Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
tree = AllocTree ();
tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
tree->mins[0] = (block_xl)*1024;
tree->mins[1] = (block_yl)*1024;
tree->mins[2] = map_mins[2] - 8;
tree->maxs[0] = (block_xh+1)*1024;
tree->maxs[1] = (block_yh+1)*1024;
tree->maxs[2] = map_maxs[2] + 8;
//
// perform the global operations
//
MakeTreePortals (tree);
if (FloodEntities (tree))
FillOutside (tree->headnode);
else
{
Sys_FPrintf( SYS_NOXML, "**********************\n" );
Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
Sys_FPrintf( SYS_NOXML, "**********************\n" );
polyline = LeakFile( tree );
leaknode = xmlNewNode( NULL, "message" );
xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
xmlAddChild( leaknode, polyline );
level[0] = (int) '0' + SYS_ERR;
level[1] = 0;
xmlSetProp( leaknode, "level", (char*) &level );
xml_SendNode( leaknode );
if( leaktest )
{
Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
exit( 0 );
}
leaked = true;
/*
Sys_Printf ("**** leaked ****\n");
leaked = true;
LeakFile (tree);
if (leaktest)
{
Sys_Printf ("--- MAP LEAKED ---\n");
exit (0);
} */
}
MarkVisibleSides (tree, brush_start, brush_end);
if (noopt || leaked)
break;
if (!optimize)
{
FreeTree (tree);
}
}
FloodAreas (tree);
if (glview)
WriteGLView (tree, source);
MakeFaces (tree->headnode);
FixTjuncs (tree->headnode);
if (!noprune)
PruneNodes (tree->headnode);
WriteBSP (tree->headnode);
if (!leaked)
WritePortalFile (tree);
FreeTree (tree);
}
/*
============
ProcessSubModel
============
*/
void ProcessSubModel (void)
{
entity_t *e;
int start, end;
tree_t *tree;
bspbrush_t *list;
vec3_t mins, maxs;
e = &entities[entity_num];
start = e->firstbrush;
end = start + e->numbrushes;
mins[0] = mins[1] = mins[2] = -4096;
maxs[0] = maxs[1] = maxs[2] = 4096;
list = MakeBspBrushList (start, end, mins, maxs);
if (!nocsg)
list = ChopBrushes (list);
tree = BrushBSP (list, mins, maxs);
MakeTreePortals (tree);
MarkVisibleSides (tree, start, end);
MakeFaces (tree->headnode);
FixTjuncs (tree->headnode);
WriteBSP (tree->headnode);
FreeTree (tree);
}
/*
============
ProcessModels
============
*/
void ProcessModels (void)
{
BeginBSPFile ();
for (entity_num=0 ; entity_num< num_entities ; entity_num++)
{
if (!entities[entity_num].numbrushes)
continue;
Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);
BeginModel ();
if (entity_num == 0)
ProcessWorldModel ();
else
ProcessSubModel ();
EndModel ();
//if (!verboseentities)
// verbose = false; // don't bother printing submodels
}
EndBSPFile ();
}
/*
============
main
============
*/
int BSP_Main ()
{
double start, end;
char path[1024];
int total_bsp_time;
Sys_Printf ("\n----- BSP ----\n\n");
start = I_FloatTime ();
ThreadSetDefault ();
SetQdirFromPath (mapname);
strcpy (source, ExpandArg (mapname));
StripExtension (source);
// delete portal and line files
sprintf (path, "%s.prt", source);
remove (path);
sprintf (path, "%s.lin", source);
remove (path);
strcpy (name, ExpandArg (mapname));
DefaultExtension (name, ".map"); // might be .reg
//
// if onlyents, just grab the entites and resave
//
if (onlyents)
{
char out[1024];
sprintf (out, "%s.bsp", source);
LoadBSPFile (out);
num_entities = 0;
LoadMapFile (name);
SetModelNumbers ();
SetLightStyles ();
UnparseEntities ();
WriteBSPFile (out);
}
else
{
//
// start from scratch
//
LoadMapFile (name);
SetModelNumbers ();
SetLightStyles ();
ProcessModels ();
}
end = I_FloatTime ();
total_bsp_time = (int) (end-start);
Sys_Printf("\nBSP Time: ");
if ( total_bsp_time > 59 )
Sys_Printf("%d Minutes ", total_bsp_time/60 );
Sys_Printf( "%d Seconds\n", total_bsp_time%60 );
return 0;
}

390
tools/quake2/q2map/qbsp.h Normal file
View File

@@ -0,0 +1,390 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Files:
brushbsp.c
csg.c
faces.c
gldraw.c
glfile.c
leakfile.c
map.c
nodraw.c
portals.c
prtfile.c
qbsp3.c
textures.c
tree.c
writebsp.c
*/
#include "cmdlib.h"
#include "mathlib.h"
#include "scriplib.h"
#include "polylib.h"
#include "q2_threads.h"
#include "bspfile.h"
#include "inout.h"
#ifdef WIN32
#ifdef NDEBUG // Don't show in a Release build
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4244) // conversion from double to float
#pragma warning(disable : 4018) // signed/unsigned mismatch
#endif
#endif
#define MAX_BRUSH_SIDES 128
#define CLIP_EPSILON 0.1
#define BOGUS_RANGE 8192
#define TEXINFO_NODE -1 // side is allready on a node
typedef struct plane_s
{
vec3_t normal;
vec_t dist;
int type;
struct plane_s *hash_chain;
} plane_t;
typedef struct
{
vec_t shift[2];
vec_t rotate;
vec_t scale[2];
char name[32];
int flags;
int value;
} brush_texture_t;
typedef struct side_s
{
int planenum;
int texinfo;
winding_t *winding;
struct side_s *original; // bspbrush_t sides will reference the mapbrush_t sides
int contents; // from miptex
int surf; // from miptex
qboolean visible; // choose visble planes first
qboolean tested; // this plane allready checked as a split
qboolean bevel; // don't ever use for bsp splitting
} side_t;
typedef struct brush_s
{
int entitynum;
int brushnum;
int contents;
vec3_t mins, maxs;
int numsides;
side_t *original_sides;
} mapbrush_t;
#define PLANENUM_LEAF -1
#define MAXEDGES 20
typedef struct face_s
{
struct face_s *next; // on node
// the chain of faces off of a node can be merged or split,
// but each face_t along the way will remain in the chain
// until the entire tree is freed
struct face_s *merged; // if set, this face isn't valid anymore
struct face_s *split[2]; // if set, this face isn't valid anymore
struct portal_s *portal;
int texinfo;
int planenum;
int contents; // faces in different contents can't merge
int outputnumber;
winding_t *w;
int numpoints;
qboolean badstartvert; // tjunctions cannot be fixed without a midpoint vertex
int vertexnums[MAXEDGES];
} face_t;
typedef struct bspbrush_s
{
struct bspbrush_s *next;
vec3_t mins, maxs;
int side, testside; // side of node during construction
mapbrush_t *original;
int numsides;
side_t sides[6]; // variably sized
} bspbrush_t;
#define MAX_NODE_BRUSHES 8
typedef struct node_s
{
// both leafs and nodes
int planenum; // -1 = leaf node
struct node_s *parent;
vec3_t mins, maxs; // valid after portalization
bspbrush_t *volume; // one for each leaf/node
// nodes only
qboolean detail_seperator; // a detail brush caused the split
side_t *side; // the side that created the node
struct node_s *children[2];
face_t *faces;
// leafs only
bspbrush_t *brushlist; // fragments of all brushes in this leaf
int contents; // OR of all brush contents
int occupied; // 1 or greater can reach entity
entity_t *occupant; // for leak file testing
int cluster; // for portalfile writing
int area; // for areaportals
struct portal_s *portals; // also on nodes during construction
} 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
side_t *side; // NULL = non-visible
face_t *face[2]; // output face in bsp file
} portal_t;
typedef struct
{
node_t *headnode;
node_t outside_node;
vec3_t mins, maxs;
} tree_t;
extern int entity_num;
extern plane_t mapplanes[MAX_MAP_PLANES];
extern int nummapplanes;
extern int nummapbrushes;
extern mapbrush_t mapbrushes[MAX_MAP_BRUSHES];
extern vec3_t map_mins, map_maxs;
#define MAX_MAP_SIDES (MAX_MAP_BRUSHES*6)
extern int nummapbrushsides;
extern side_t brushsides[MAX_MAP_SIDES];
extern qboolean noprune;
extern qboolean nodetail;
extern qboolean fulldetail;
extern qboolean nomerge;
extern qboolean nosubdiv;
extern qboolean nowater;
extern qboolean noweld;
extern qboolean noshare;
extern qboolean notjunc;
extern vec_t microvolume;
extern char outbase[32];
extern char source[1024];
void LoadMapFile (char *filename);
int FindFloatPlane (vec3_t normal, vec_t dist);
//=============================================================================
// textures.c
typedef struct
{
char name[64];
int flags;
int value;
int contents;
char animname[64];
} textureref_t;
#define MAX_MAP_TEXTURES 1024
extern textureref_t textureref[MAX_MAP_TEXTURES];
int FindMiptex (char *name);
int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin);
//=============================================================================
void FindGCD (int *v);
mapbrush_t *Brush_LoadEntity (entity_t *ent);
int PlaneTypeForNormal (vec3_t normal);
qboolean MakeBrushPlanes (mapbrush_t *b);
int FindIntPlane (int *inormal, int *iorigin);
void CreateBrush (int brushnum);
//=============================================================================
// 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 (int startbrush, int endbrush,
vec3_t clipmins, vec3_t clipmaxs);
bspbrush_t *ChopBrushes (bspbrush_t *head);
bspbrush_t *InitialBrushList (bspbrush_t *list);
bspbrush_t *OptimizedBrushList (bspbrush_t *list);
void WriteBrushMap (char *name, bspbrush_t *list);
//=============================================================================
// brushbsp
void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);
bspbrush_t *CopyBrush (bspbrush_t *brush);
void SplitBrush (bspbrush_t *brush, int planenum,
bspbrush_t **front, bspbrush_t **back);
tree_t *AllocTree (void);
node_t *AllocNode (void);
bspbrush_t *AllocBrush (int numsides);
int CountBrushList (bspbrush_t *brushes);
void FreeBrush (bspbrush_t *brushes);
vec_t BrushVolume (bspbrush_t *brush);
void BoundBrush (bspbrush_t *brush);
void FreeBrushList (bspbrush_t *brushes);
tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
//=============================================================================
// portals.c
int VisibleContents (int contents);
void MakeHeadnodePortals (tree_t *tree);
void MakeNodePortal (node_t *node);
void SplitNodePortals (node_t *node);
qboolean Portal_VisFlood (portal_t *p);
qboolean FloodEntities (tree_t *tree);
void FillOutside (node_t *headnode);
void FloodAreas (tree_t *tree);
void MarkVisibleSides (tree_t *tree, int start, int end);
void FreePortal (portal_t *p);
void EmitAreaPortals (node_t *headnode);
void MakeTreePortals (tree_t *tree);
//=============================================================================
// glfile.c
void OutputWinding (winding_t *w, FILE *glview);
void WriteGLView (tree_t *tree, char *source);
//=============================================================================
// leakfile.c
//void LeakFile (tree_t *tree);
xmlNodePtr LeakFile (tree_t *tree);
//=============================================================================
// prtfile.c
void WritePortalFile (tree_t *tree);
//=============================================================================
// writebsp.c
void SetModelNumbers (void);
void SetLightStyles (void);
void BeginBSPFile (void);
void WriteBSP (node_t *headnode);
void EndBSPFile (void);
void BeginModel (void);
void EndModel (void);
//=============================================================================
// faces.c
void MakeFaces (node_t *headnode);
void FixTjuncs (node_t *headnode);
int GetEdge2 (int v1, int v2, face_t *f);
face_t *AllocFace (void);
void FreeFace (face_t *f);
void MergeNodeFaces (node_t *node);
//=============================================================================
// 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);
void PruneNodes_r (node_t *node);
void PruneNodes (node_t *node);
//=============================================================================
// externs
extern char *mapname;
extern char game[64];

647
tools/quake2/q2map/qrad.c Normal file
View File

@@ -0,0 +1,647 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// qrad.c
#include "qrad.h"
/*
NOTES
-----
every surface must be divided into at least two patches each axis
*/
patch_t *face_patches[MAX_MAP_FACES];
entity_t *face_entity[MAX_MAP_FACES];
patch_t patches[MAX_PATCHES];
unsigned num_patches;
vec3_t radiosity[MAX_PATCHES]; // light leaving a patch
vec3_t illumination[MAX_PATCHES]; // light arriving at a patch
vec3_t face_offset[MAX_MAP_FACES]; // for rotating bmodels
dplane_t backplanes[MAX_MAP_PLANES];
char inbase[32], outbase[32];
int fakeplanes; // created planes for origin offset
int numbounce = 8;
qboolean extrasamples;
float subdiv = 64;
qboolean dumppatches;
void BuildLightmaps (void);
int TestLine (vec3_t start, vec3_t stop);
int junk;
float ambient = 0;
float maxlight = 196;
float lightscale = 1.0;
qboolean glview;
qboolean nopvs;
char source[1024];
float direct_scale = 0.4;
float entity_scale = 1.0;
/*
===================================================================
MISC
===================================================================
*/
/*
=============
MakeBackplanes
=============
*/
void MakeBackplanes (void)
{
int i;
for (i=0 ; i<numplanes ; i++)
{
backplanes[i].dist = -dplanes[i].dist;
VectorSubtract (vec3_origin, dplanes[i].normal, backplanes[i].normal);
}
}
int leafparents[MAX_MAP_LEAFS];
int nodeparents[MAX_MAP_NODES];
/*
=============
MakeParents
=============
*/
void MakeParents (int nodenum, int parent)
{
int i, j;
dnode_t *node;
nodeparents[nodenum] = parent;
node = &dnodes[nodenum];
for (i=0 ; i<2 ; i++)
{
j = node->children[i];
if (j < 0)
leafparents[-j - 1] = nodenum;
else
MakeParents (j, nodenum);
}
}
/*
===================================================================
TRANSFER SCALES
===================================================================
*/
int PointInLeafnum (vec3_t point)
{
int nodenum;
vec_t dist;
dnode_t *node;
dplane_t *plane;
nodenum = 0;
while (nodenum >= 0)
{
node = &dnodes[nodenum];
plane = &dplanes[node->planenum];
dist = DotProduct (point, plane->normal) - plane->dist;
if (dist > 0)
nodenum = node->children[0];
else
nodenum = node->children[1];
}
return -nodenum - 1;
}
dleaf_t *Rad_PointInLeaf (vec3_t point)
{
int num;
num = PointInLeafnum (point);
return &dleafs[num];
}
qboolean PvsForOrigin (vec3_t org, byte *pvs)
{
dleaf_t *leaf;
if (!visdatasize)
{
memset (pvs, 255, (numleafs+7)/8 );
return true;
}
leaf = Rad_PointInLeaf (org);
if (leaf->cluster == -1)
return false; // in solid leaf
DecompressVis (dvisdata + dvis->bitofs[leaf->cluster][DVIS_PVS], pvs);
return true;
}
/*
=============
MakeTransfers
=============
*/
int total_transfer;
void MakeTransfers (int i)
{
int j;
vec3_t delta;
vec_t dist, scale;
float trans;
int itrans;
patch_t *patch, *patch2;
float total;
dplane_t plane;
vec3_t origin;
float transfers[MAX_PATCHES], *all_transfers;
int s;
int itotal;
byte pvs[(MAX_MAP_LEAFS+7)/8];
int cluster;
patch = patches + i;
total = 0;
VectorCopy (patch->origin, origin);
plane = *patch->plane;
if (!PvsForOrigin (patch->origin, pvs))
return;
// find out which patch2s will collect light
// from patch
all_transfers = transfers;
patch->numtransfers = 0;
for (j=0, patch2 = patches ; j<num_patches ; j++, patch2++)
{
transfers[j] = 0;
if (j == i)
continue;
// check pvs bit
if (!nopvs)
{
cluster = patch2->cluster;
if (cluster == -1)
continue;
if ( ! ( pvs[cluster>>3] & (1<<(cluster&7)) ) )
continue; // not in pvs
}
// calculate vector
VectorSubtract (patch2->origin, origin, delta);
dist = VectorNormalize (delta, delta);
if (!dist)
continue; // should never happen
// reletive angles
scale = DotProduct (delta, plane.normal);
scale *= -DotProduct (delta, patch2->plane->normal);
if (scale <= 0)
continue;
// check exact tramsfer
if (TestLine_r (0, patch->origin, patch2->origin) )
continue;
trans = scale * patch2->area / (dist*dist);
if (trans < 0)
trans = 0; // rounding errors...
transfers[j] = trans;
if (trans > 0)
{
total += trans;
patch->numtransfers++;
}
}
// copy the transfers out and normalize
// total should be somewhere near PI if everything went right
// because partial occlusion isn't accounted for, and nearby
// patches have underestimated form factors, it will usually
// be higher than PI
if (patch->numtransfers)
{
transfer_t *t;
if (patch->numtransfers < 0 || patch->numtransfers > MAX_PATCHES)
Error ("Weird numtransfers");
s = patch->numtransfers * sizeof(transfer_t);
patch->transfers = malloc (s);
if (!patch->transfers)
Error ("Memory allocation failure");
//
// normalize all transfers so all of the light
// is transfered to the surroundings
//
t = patch->transfers;
itotal = 0;
for (j=0 ; j<num_patches ; j++)
{
if (transfers[j] <= 0)
continue;
itrans = transfers[j]*0x10000 / total;
itotal += itrans;
t->transfer = itrans;
t->patch = j;
t++;
}
}
// don't bother locking around this. not that important.
total_transfer += patch->numtransfers;
}
/*
=============
FreeTransfers
=============
*/
void FreeTransfers (void)
{
int i;
for (i=0 ; i<num_patches ; i++)
{
free (patches[i].transfers);
patches[i].transfers = NULL;
}
}
//===================================================================
/*
=============
WriteWorld
=============
*/
void WriteWorld (char *name)
{
int i, j;
FILE *out;
patch_t *patch;
winding_t *w;
out = fopen (name, "w");
if (!out)
Error ("Couldn't open %s", name);
for (j=0, patch=patches ; j<num_patches ; j++, patch++)
{
w = patch->winding;
fprintf (out, "%i\n", w->numpoints);
for (i=0 ; i<w->numpoints ; i++)
{
fprintf (out, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
w->p[i][0],
w->p[i][1],
w->p[i][2],
patch->totallight[0],
patch->totallight[1],
patch->totallight[2]);
}
fprintf (out, "\n");
}
fclose (out);
}
/*
=============
WriteGlView
=============
*/
void WriteGlView (void)
{
char name[1024];
FILE *f;
int i, j;
patch_t *p;
winding_t *w;
strcpy (name, source);
StripExtension (name);
strcat (name, ".glr");
f = fopen (name, "w");
if (!f)
Error ("Couldn't open %s", f);
for (j=0 ; j<num_patches ; j++)
{
p = &patches[j];
w = p->winding;
fprintf (f, "%i\n", w->numpoints);
for (i=0 ; i<w->numpoints ; i++)
{
fprintf (f, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
w->p[i][0],
w->p[i][1],
w->p[i][2],
p->totallight[0]/128,
p->totallight[1]/128,
p->totallight[2]/128);
}
fprintf (f, "\n");
}
fclose (f);
}
//==============================================================
/*
=============
CollectLight
=============
*/
float CollectLight (void)
{
int i, j;
patch_t *patch;
vec_t total;
total = 0;
for (i=0, patch=patches ; i<num_patches ; i++, patch++)
{
// skys never collect light, it is just dropped
if (patch->sky)
{
VectorClear (radiosity[i]);
VectorClear (illumination[i]);
continue;
}
for (j=0 ; j<3 ; j++)
{
patch->totallight[j] += illumination[i][j] / patch->area;
radiosity[i][j] = illumination[i][j] * patch->reflectivity[j];
}
total += radiosity[i][0] + radiosity[i][1] + radiosity[i][2];
VectorClear (illumination[i]);
}
return total;
}
/*
=============
ShootLight
Send light out to other patches
Run multi-threaded
=============
*/
void ShootLight (int patchnum)
{
int k, l;
transfer_t *trans;
int num;
patch_t *patch;
vec3_t send;
// this is the amount of light we are distributing
// prescale it so that multiplying by the 16 bit
// transfer values gives a proper output value
for (k=0 ; k<3 ; k++)
send[k] = radiosity[patchnum][k] / 0x10000;
patch = &patches[patchnum];
trans = patch->transfers;
num = patch->numtransfers;
for (k=0 ; k<num ; k++, trans++)
{
for (l=0 ; l<3 ; l++)
illumination[trans->patch][l] += send[l]*trans->transfer;
}
}
/*
=============
BounceLight
=============
*/
void BounceLight (void)
{
int i, j;
float added;
char name[64];
patch_t *p;
for (i=0 ; i<num_patches ; i++)
{
p = &patches[i];
for (j=0 ; j<3 ; j++)
{
// p->totallight[j] = p->samplelight[j];
radiosity[i][j] = p->samplelight[j] * p->reflectivity[j] * p->area;
}
}
for (i=0 ; i<numbounce ; i++)
{
RunThreadsOnIndividual (num_patches, false, ShootLight);
added = CollectLight ();
Sys_FPrintf( SYS_VRB, "bounce:%i added:%f\n", i, added);
if ( dumppatches && (i==0 || i == numbounce-1) )
{
sprintf (name, "bounce%i.txt", i);
WriteWorld (name);
}
}
}
//==============================================================
void CheckPatches (void)
{
int i;
patch_t *patch;
for (i=0 ; i<num_patches ; i++)
{
patch = &patches[i];
if (patch->totallight[0] < 0 || patch->totallight[1] < 0 || patch->totallight[2] < 0)
Error ("negative patch totallight\n");
}
}
/*
=============
RadWorld
=============
*/
void RadWorld (void)
{
if (numnodes == 0 || numfaces == 0)
Error ("Empty map");
MakeBackplanes ();
MakeParents (0, -1);
MakeTnodes (&dmodels[0]);
// turn each face into a single patch
MakePatches ();
// subdivide patches to a maximum dimension
SubdividePatches ();
// create directlights out of patches and lights
CreateDirectLights ();
// build initial facelights
RunThreadsOnIndividual (numfaces, true, BuildFacelights);
if (numbounce > 0)
{
// build transfer lists
RunThreadsOnIndividual (num_patches, true, MakeTransfers);
Sys_FPrintf( SYS_VRB, "transfer lists: %5.1f megs\n"
, (float)total_transfer * sizeof(transfer_t) / (1024*1024));
// spread light around
BounceLight ();
FreeTransfers ();
CheckPatches ();
}
if (glview)
WriteGlView ();
// blend bounced light into direct light and save
PairEdges ();
LinkPlaneFaces ();
lightdatasize = 0;
RunThreadsOnIndividual (numfaces, true, FinalLightFace);
}
/*
========
main
light modelfile
========
*/
int RAD_Main ()
{
double start, end;
char name[1024];
int total_rad_time;
Sys_Printf ("\n----- RAD ----\n\n");
if (maxlight > 255)
maxlight = 255;
start = I_FloatTime ();
if ( !strcmp( game, "heretic2" ) )
CalcTextureReflectivity = &CalcTextureReflectivity_Heretic2;
else
CalcTextureReflectivity = &CalcTextureReflectivity_Quake2;
SetQdirFromPath (mapname);
strcpy (source, ExpandArg(mapname));
StripExtension (source);
DefaultExtension (source, ".bsp");
// ReadLightFile ();
sprintf (name, "%s%s", inbase, source);
Sys_Printf ("reading %s\n", name);
LoadBSPFile (name);
ParseEntities ();
(*CalcTextureReflectivity) ();
if (!visdatasize)
{
Sys_Printf ("No vis information, direct lighting only.\n");
numbounce = 0;
ambient = 0.1;
}
RadWorld ();
sprintf (name, "%s%s", outbase, source);
Sys_Printf ("writing %s\n", name);
WriteBSPFile (name);
end = I_FloatTime ();
total_rad_time = (int) (end-start);
Sys_Printf("\nRAD Time: ");
if ( total_rad_time > 59 )
Sys_Printf("%d Minutes ", total_rad_time/60 );
Sys_Printf( "%d Seconds\n", total_rad_time%60 );
return 0;
}

184
tools/quake2/q2map/qrad.h Normal file
View File

@@ -0,0 +1,184 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Files:
lightmap.c
patches.c
qrad.c
trace.c
*/
#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"
#include "polylib.h"
#include "q2_threads.h"
#include "lbmlib.h"
#include "inout.h"
#ifdef WIN32
#include <windows.h>
#endif
#ifdef WIN32
#ifdef NDEBUG // Don't show in a Release build
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4244) // conversion from double to float
#pragma warning(disable : 4018) // signed/unsigned mismatch
#endif
#endif
typedef enum
{
emit_surface,
emit_point,
emit_spotlight
} emittype_t;
typedef struct directlight_s
{
struct directlight_s *next;
emittype_t type;
float intensity;
int style;
vec3_t origin;
vec3_t color;
vec3_t normal; // for surfaces and spotlights
float stopdot; // for spotlights
} directlight_t;
// the sum of all tranfer->transfer values for a given patch
// should equal exactly 0x10000, showing that all radiance
// reaches other patches
typedef struct
{
unsigned short patch;
unsigned short transfer;
} transfer_t;
#define MAX_PATCHES 65000 // larger will cause 32 bit overflows
typedef struct patch_s
{
winding_t *winding;
struct patch_s *next; // next in face
int numtransfers;
transfer_t *transfers;
int cluster; // for pvs checking
vec3_t origin;
dplane_t *plane;
qboolean sky;
vec3_t totallight; // accumulated by radiosity
// does NOT include light
// accounted for by direct lighting
float area;
// illuminance * reflectivity = radiosity
vec3_t reflectivity;
vec3_t baselight; // emissivity only
// each style 0 lightmap sample in the patch will be
// added up to get the average illuminance of the entire patch
vec3_t samplelight;
int samples; // for averaging direct light
} patch_t;
extern patch_t *face_patches[MAX_MAP_FACES];
extern entity_t *face_entity[MAX_MAP_FACES];
extern vec3_t face_offset[MAX_MAP_FACES]; // for rotating bmodels
extern patch_t patches[MAX_PATCHES];
extern unsigned num_patches;
extern int leafparents[MAX_MAP_LEAFS];
extern int nodeparents[MAX_MAP_NODES];
extern float lightscale;
void MakeShadowSplits (void);
//==============================================
void BuildVisMatrix (void);
qboolean CheckVisBit (unsigned p1, unsigned p2);
//==============================================
extern float ambient, maxlight;
void LinkPlaneFaces (void);
extern qboolean extrasamples;
extern int numbounce;
extern directlight_t *directlights[MAX_MAP_LEAFS];
extern byte nodehit[MAX_MAP_NODES];
void BuildLightmaps (void);
void BuildFacelights (int facenum);
void FinalLightFace (int facenum);
qboolean PvsForOrigin (vec3_t org, byte *pvs);
int TestLine_r (int node, vec3_t start, vec3_t stop);
void CreateDirectLights (void);
dleaf_t *Rad_PointInLeaf (vec3_t point);
extern dplane_t backplanes[MAX_MAP_PLANES];
extern int fakeplanes; // created planes for origin offset
extern float subdiv;
extern float direct_scale;
extern float entity_scale;
int PointInLeafnum (vec3_t point);
void MakeTnodes (dmodel_t *bm);
void MakePatches (void);
void SubdividePatches (void);
void PairEdges (void);
void (*CalcTextureReflectivity) (void);
void CalcTextureReflectivity_Quake2(void);
void CalcTextureReflectivity_Heretic2(void);
//=============================================================================
// externs
extern char *mapname;
extern char game[64];

581
tools/quake2/q2map/qvis.c Normal file
View File

@@ -0,0 +1,581 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// qvis.c
#include "qvis.h"
#include "q2_threads.h"
#include "stdlib.h"
int numportals;
int portalclusters;
char inbase[32];
char outbase[32];
portal_t *portals;
leaf_t *leafs;
int c_portaltest, c_portalpass, c_portalcheck;
byte *uncompressedvis;
byte *vismap, *vismap_p, *vismap_end; // past visfile
int originalvismapsize;
int leafbytes; // (portalclusters+63)>>3
int leaflongs;
int portalbytes, portallongs;
qboolean fastvis;
qboolean nosort;
int testlevel = 2;
int totalvis;
portal_t *sorted_portals[MAX_MAP_PORTALS*2];
//=============================================================================
void PlaneFromWinding (winding_t *w, plane_t *plane)
{
vec3_t v1, v2;
// calc plane
VectorSubtract (w->points[2], w->points[1], v1);
VectorSubtract (w->points[0], w->points[1], v2);
CrossProduct (v2, v1, plane->normal);
VectorNormalize (plane->normal, plane->normal);
plane->dist = DotProduct (w->points[0], plane->normal);
}
/*
==================
NewWinding
==================
*/
winding_t *NewWinding (int points)
{
winding_t *w;
int size;
if (points > MAX_POINTS_ON_WINDING)
Error ("NewWinding: %i points", points);
size = (int)((winding_t *)0)->points[points];
w = malloc (size);
memset (w, 0, size);
return w;
}
/*
void pw(winding_t *w)
{
int i;
for (i=0 ; i<w->numpoints ; i++)
Sys_Printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
}
*/
void prl(leaf_t *l)
{
int i;
portal_t *p;
plane_t pl;
for (i=0 ; i<l->numportals ; i++)
{
p = l->portals[i];
pl = p->plane;
Sys_Printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
}
}
//=============================================================================
/*
=============
SortPortals
Sorts the portals from the least complex, so the later ones can reuse
the earlier information.
=============
*/
int PComp (const void *a, const void *b)
{
if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
return 0;
if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
return -1;
return 1;
}
void SortPortals (void)
{
int i;
for (i=0 ; i<numportals*2 ; i++)
sorted_portals[i] = &portals[i];
if (nosort)
return;
qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
}
/*
==============
LeafVectorFromPortalVector
==============
*/
int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
{
int i;
portal_t *p;
int c_leafs;
memset (leafbits, 0, leafbytes);
for (i=0 ; i<numportals*2 ; i++)
{
if (portalbits[i>>3] & (1<<(i&7)) )
{
p = portals+i;
leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
}
}
c_leafs = CountBits (leafbits, portalclusters);
return c_leafs;
}
/*
===============
ClusterMerge
Merges the portal visibility for a leaf
===============
*/
void ClusterMerge (int leafnum)
{
leaf_t *leaf;
byte portalvector[MAX_PORTALS/8];
byte uncompressed[MAX_MAP_LEAFS/8];
byte compressed[MAX_MAP_LEAFS/8];
int i, j;
int numvis;
byte *dest;
portal_t *p;
int pnum;
// OR together all the portalvis bits
memset (portalvector, 0, portalbytes);
leaf = &leafs[leafnum];
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
if (p->status != stat_done)
Error ("portal not done");
for (j=0 ; j<portallongs ; j++)
((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
pnum = p - portals;
portalvector[pnum>>3] |= 1<<(pnum&7);
}
// convert portal bits to leaf bits
numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
Sys_Printf ("WARNING: Leaf portals saw into leaf\n");
uncompressed[leafnum>>3] |= (1<<(leafnum&7));
numvis++; // count the leaf itself
// save uncompressed for PHS calculation
memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
//
// compress the bit string
//
Sys_FPrintf( SYS_VRB, "cluster %4i : %4i visible\n", leafnum, numvis);
totalvis += numvis;
i = CompressVis (uncompressed, compressed);
dest = vismap_p;
vismap_p += i;
if (vismap_p > vismap_end)
Error ("Vismap expansion overflow");
dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
memcpy (dest, compressed, i);
}
/*
==================
CalcPortalVis
==================
*/
void CalcPortalVis (void)
{
int i;
// fastvis just uses mightsee for a very loose bound
if (fastvis)
{
for (i=0 ; i<numportals*2 ; i++)
{
portals[i].portalvis = portals[i].portalflood;
portals[i].status = stat_done;
}
return;
}
RunThreadsOnIndividual (numportals*2, true, PortalFlow);
}
/*
==================
CalcVis
==================
*/
void CalcVis (void)
{
int i;
RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
// RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
SortPortals ();
CalcPortalVis ();
//
// assemble the leaf vis lists by oring and compressing the portal lists
//
for (i=0 ; i<portalclusters ; i++)
ClusterMerge (i);
Sys_Printf ("Average clusters visible: %i\n", totalvis / portalclusters);
}
void SetPortalSphere (portal_t *p)
{
int i;
vec3_t total, dist;
winding_t *w;
float r, bestr;
w = p->winding;
VectorCopy (vec3_origin, total);
for (i=0 ; i<w->numpoints ; i++)
{
VectorAdd (total, w->points[i], total);
}
for (i=0 ; i<3 ; i++)
total[i] /= w->numpoints;
bestr = 0;
for (i=0 ; i<w->numpoints ; i++)
{
VectorSubtract (w->points[i], total, dist);
r = VectorLength (dist);
if (r > bestr)
bestr = r;
}
VectorCopy (total, p->origin);
p->radius = bestr;
}
/*
============
LoadPortals
============
*/
void LoadPortals (char *name)
{
int i, j;
portal_t *p;
leaf_t *l;
char magic[80];
FILE *f;
int numpoints;
winding_t *w;
int leafnums[2];
plane_t plane;
if (!strcmp(name,"-"))
f = stdin;
else
{
f = fopen(name, "r");
if (!f)
Error ("LoadPortals: couldn't read %s\n",name);
}
if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
Error ("LoadPortals: failed to read header");
if (strcmp(magic,PORTALFILE))
Error ("LoadPortals: not a portal file");
Sys_Printf ("%4i portalclusters\n", portalclusters);
Sys_Printf ("%4i numportals\n", numportals);
// these counts should take advantage of 64 bit systems automatically
leafbytes = ((portalclusters+63)&~63)>>3;
leaflongs = leafbytes/sizeof(long);
portalbytes = ((numportals*2+63)&~63)>>3;
portallongs = portalbytes/sizeof(long);
// each file portal is split into two memory portals
portals = malloc(2*numportals*sizeof(portal_t));
memset (portals, 0, 2*numportals*sizeof(portal_t));
leafs = malloc(portalclusters*sizeof(leaf_t));
memset (leafs, 0, portalclusters*sizeof(leaf_t));
originalvismapsize = portalclusters*leafbytes;
uncompressedvis = malloc(originalvismapsize);
vismap = vismap_p = dvisdata;
dvis->numclusters = portalclusters;
vismap_p = (byte *)&dvis->bitofs[portalclusters];
vismap_end = vismap + MAX_MAP_VISIBILITY;
for (i=0, p=portals ; i<numportals ; i++)
{
if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
!= 3)
Error ("LoadPortals: reading portal %i", i);
if (numpoints > MAX_POINTS_ON_WINDING)
Error ("LoadPortals: portal %i has too many points", i);
if ( (unsigned)leafnums[0] > portalclusters
|| (unsigned)leafnums[1] > portalclusters)
Error ("LoadPortals: reading portal %i", i);
w = p->winding = NewWinding (numpoints);
w->original = true;
w->numpoints = numpoints;
for (j=0 ; j<numpoints ; j++)
{
double v[3];
int k;
// scanf into double, then assign to vec_t
// so we don't care what size vec_t is
if (fscanf (f, "(%lf %lf %lf ) "
, &v[0], &v[1], &v[2]) != 3)
Error ("LoadPortals: reading portal %i", i);
for (k=0 ; k<3 ; k++)
w->points[j][k] = v[k];
}
fscanf (f, "\n");
// calc plane
PlaneFromWinding (w, &plane);
// create forward portal
l = &leafs[leafnums[0]];
if (l->numportals == MAX_PORTALS_ON_LEAF)
Error ("Leaf with too many portals");
l->portals[l->numportals] = p;
l->numportals++;
p->winding = w;
VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
p->plane.dist = -plane.dist;
p->leaf = leafnums[1];
SetPortalSphere (p);
p++;
// create backwards portal
l = &leafs[leafnums[1]];
if (l->numportals == MAX_PORTALS_ON_LEAF)
Error ("Leaf with too many portals");
l->portals[l->numportals] = p;
l->numportals++;
p->winding = NewWinding(w->numpoints);
p->winding->numpoints = w->numpoints;
for (j=0 ; j<w->numpoints ; j++)
{
VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
}
p->plane = plane;
p->leaf = leafnums[0];
SetPortalSphere (p);
p++;
}
fclose (f);
}
/*
================
CalcPHS
Calculate the PHS (Potentially Hearable Set)
by ORing together all the PVS visible from a leaf
================
*/
void CalcPHS (void)
{
int i, j, k, l, index;
int bitbyte;
long *dest, *src;
byte *scan;
int count;
byte uncompressed[MAX_MAP_LEAFS/8];
byte compressed[MAX_MAP_LEAFS/8];
Sys_Printf ("Building PHS...\n");
count = 0;
for (i=0 ; i<portalclusters ; i++)
{
scan = uncompressedvis + i*leafbytes;
memcpy (uncompressed, scan, leafbytes);
for (j=0 ; j<leafbytes ; j++)
{
bitbyte = scan[j];
if (!bitbyte)
continue;
for (k=0 ; k<8 ; k++)
{
if (! (bitbyte & (1<<k)) )
continue;
// OR this pvs row into the phs
index = ((j<<3)+k);
if (index >= portalclusters)
Error ("Bad bit in PVS"); // pad bits should be 0
src = (long *)(uncompressedvis + index*leafbytes);
dest = (long *)uncompressed;
for (l=0 ; l<leaflongs ; l++)
((long *)uncompressed)[l] |= src[l];
}
}
for (j=0 ; j<portalclusters ; j++)
if (uncompressed[j>>3] & (1<<(j&7)) )
count++;
//
// compress the bit string
//
j = CompressVis (uncompressed, compressed);
dest = (long *)vismap_p;
vismap_p += j;
if (vismap_p > vismap_end)
Error ("Vismap expansion overflow");
dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
memcpy (dest, compressed, j);
}
Sys_Printf ("Average clusters hearable: %i\n", count/portalclusters);
}
/*
===========
main
===========
*/
int VIS_Main ()
{
char portalfile[1024];
char source[1024];
char name[1024];
double start, end;
int total_vis_time;
Sys_Printf ("\n----- VIS ----\n\n");
//if (i != argc - 1)
// Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
start = I_FloatTime ();
ThreadSetDefault ();
SetQdirFromPath (mapname);
strcpy (source, ExpandArg(mapname));
StripExtension (source);
DefaultExtension (source, ".bsp");
sprintf (name, "%s%s", inbase, source);
Sys_Printf ("reading %s\n", name);
LoadBSPFile (name);
if (numnodes == 0 || numfaces == 0)
Error ("Empty map");
sprintf (portalfile, "%s%s", inbase, ExpandArg(mapname));
StripExtension (portalfile);
strcat (portalfile, ".prt");
Sys_Printf ("reading %s\n", portalfile);
LoadPortals (portalfile);
CalcVis ();
CalcPHS ();
visdatasize = vismap_p - dvisdata;
Sys_Printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize*2);
sprintf (name, "%s%s", outbase, source);
Sys_Printf ("writing %s\n", name);
WriteBSPFile (name);
end = I_FloatTime ();
total_vis_time = (int) (end-start);
Sys_Printf("\nVIS Time: ");
if ( total_vis_time > 59 )
Sys_Printf("%d Minutes ", total_vis_time/60 );
Sys_Printf( "%d Seconds\n", total_vis_time%60 );
return 0;
}

169
tools/quake2/q2map/qvis.h Normal file
View File

@@ -0,0 +1,169 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Files:
flow.c
qvis3.c
*/
#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"
#include "inout.h"
#ifdef WIN32
#ifdef NDEBUG // Don't show in a Release build
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4244) // conversion from double to float
#pragma warning(disable : 4018) // signed/unsigned mismatch
#endif
#endif
#define MAX_PORTALS 32768
#define PORTALFILE "PRT1"
#define ON_EPSILON 0.1
typedef struct
{
vec3_t normal;
float dist;
} plane_t;
#define MAX_POINTS_ON_WINDING 64
#define MAX_POINTS_ON_FIXED_WINDING 12
typedef struct
{
qboolean original; // don't free, it's part of the portal
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 enum {stat_none, stat_working, stat_done} vstatus_t;
typedef struct
{
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
} portal_t;
typedef struct seperating_plane_s
{
struct seperating_plane_s *next;
plane_t plane; // from portal is on positive side
} sep_t;
typedef struct passage_s
{
struct passage_s *next;
int from, to; // leaf numbers
sep_t *planes;
} passage_t;
#define MAX_PORTALS_ON_LEAF 128
typedef struct leaf_s
{
int numportals;
passage_t *passages;
portal_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;
portal_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;
} pstack_t;
typedef struct
{
portal_t *base;
int c_chains;
pstack_t pstack_head;
} threaddata_t;
extern int numportals;
extern int portalclusters;
extern portal_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);
extern portal_t *sorted_portals[MAX_MAP_PORTALS*2];
int CountBits (byte *bits, int numbits);
//=============================================================================
// externs
extern char *mapname;

View File

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

298
tools/quake2/q2map/trace.c Normal file
View File

@@ -0,0 +1,298 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// trace.c
/*
#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"
*/
#include "qrad.h"
#define ON_EPSILON 0.1
typedef struct tnode_s
{
int type;
vec3_t normal;
float dist;
int children[2];
int pad;
} tnode_t;
tnode_t *tnodes, *tnode_p;
/*
==============
MakeTnode
Converts the disk node structure into the efficient tracing structure
==============
*/
void MakeTnode (int nodenum)
{
tnode_t *t;
dplane_t *plane;
int i;
dnode_t *node;
t = tnode_p++;
node = dnodes + nodenum;
plane = dplanes + node->planenum;
t->type = plane->type;
VectorCopy (plane->normal, t->normal);
t->dist = plane->dist;
for (i=0 ; i<2 ; i++)
{
if (node->children[i] < 0)
t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
else
{
t->children[i] = tnode_p - tnodes;
MakeTnode (node->children[i]);
}
}
}
/*
=============
MakeTnodes
Loads the node structure out of a .bsp file to be used for light occlusion
=============
*/
void MakeTnodes (dmodel_t *bm)
{
// 32 byte align the structs
tnodes = malloc( (numnodes+1) * sizeof(tnode_t));
tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
tnode_p = tnodes;
MakeTnode (0);
}
//==========================================================
int TestLine_r (int node, vec3_t start, vec3_t stop)
{
tnode_t *tnode;
float front, back;
vec3_t mid;
float frac;
int side;
int r;
if (node & (1<<31))
return node & ~(1<<31); // leaf node
tnode = &tnodes[node];
switch (tnode->type)
{
case PLANE_X:
front = start[0] - tnode->dist;
back = stop[0] - tnode->dist;
break;
case PLANE_Y:
front = start[1] - tnode->dist;
back = stop[1] - tnode->dist;
break;
case PLANE_Z:
front = start[2] - tnode->dist;
back = stop[2] - tnode->dist;
break;
default:
front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
break;
}
if (front >= -ON_EPSILON && back >= -ON_EPSILON)
return TestLine_r (tnode->children[0], start, stop);
if (front < ON_EPSILON && back < ON_EPSILON)
return TestLine_r (tnode->children[1], start, stop);
side = front < 0;
frac = front / (front-back);
mid[0] = start[0] + (stop[0] - start[0])*frac;
mid[1] = start[1] + (stop[1] - start[1])*frac;
mid[2] = start[2] + (stop[2] - start[2])*frac;
r = TestLine_r (tnode->children[side], start, mid);
if (r)
return r;
return TestLine_r (tnode->children[!side], mid, stop);
}
int TestLine (vec3_t start, vec3_t stop)
{
return TestLine_r (0, start, stop);
}
/*
==============================================================================
LINE TRACING
The major lighting operation is a point to point visibility test, performed
by recursive subdivision of the line by the BSP tree.
==============================================================================
*/
typedef struct
{
vec3_t backpt;
int side;
int node;
} tracestack_t;
/*
==============
TestLine
==============
*/
qboolean _TestLine (vec3_t start, vec3_t stop)
{
int node;
float front, back;
tracestack_t *tstack_p;
int side;
float frontx,fronty, frontz, backx, backy, backz;
tracestack_t tracestack[64];
tnode_t *tnode;
frontx = start[0];
fronty = start[1];
frontz = start[2];
backx = stop[0];
backy = stop[1];
backz = stop[2];
tstack_p = tracestack;
node = 0;
while (1)
{
if (node == CONTENTS_SOLID)
{
#if 0
float d1, d2, d3;
d1 = backx - frontx;
d2 = backy - fronty;
d3 = backz - frontz;
if (d1*d1 + d2*d2 + d3*d3 > 1)
#endif
return false; // DONE!
}
while (node < 0)
{
// pop up the stack for a back side
tstack_p--;
if (tstack_p < tracestack)
return true;
node = tstack_p->node;
// set the hit point for this plane
frontx = backx;
fronty = backy;
frontz = backz;
// go down the back side
backx = tstack_p->backpt[0];
backy = tstack_p->backpt[1];
backz = tstack_p->backpt[2];
node = tnodes[tstack_p->node].children[!tstack_p->side];
}
tnode = &tnodes[node];
switch (tnode->type)
{
case PLANE_X:
front = frontx - tnode->dist;
back = backx - tnode->dist;
break;
case PLANE_Y:
front = fronty - tnode->dist;
back = backy - tnode->dist;
break;
case PLANE_Z:
front = frontz - tnode->dist;
back = backz - tnode->dist;
break;
default:
front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
break;
}
if (front > -ON_EPSILON && back > -ON_EPSILON)
// if (front > 0 && back > 0)
{
node = tnode->children[0];
continue;
}
if (front < ON_EPSILON && back < ON_EPSILON)
// if (front <= 0 && back <= 0)
{
node = tnode->children[1];
continue;
}
side = front < 0;
front = front / (front-back);
tstack_p->node = node;
tstack_p->side = side;
tstack_p->backpt[0] = backx;
tstack_p->backpt[1] = backy;
tstack_p->backpt[2] = backz;
tstack_p++;
backx = frontx + front*(backx-frontx);
backy = fronty + front*(backy-fronty);
backz = frontz + front*(backz-frontz);
node = tnode->children[side];
}
}

218
tools/quake2/q2map/tree.c Normal file
View File

@@ -0,0 +1,218 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; 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)
{
face_t *f, *nextf;
// free children
if (node->planenum != PLANENUM_LEAF)
{
FreeTree_r (node->children[0]);
FreeTree_r (node->children[1]);
}
// free bspbrushes
FreeBrushList (node->brushlist);
// free faces
for (f=node->faces ; f ; f=nextf)
{
nextf = f->next;
FreeFace (f);
}
// 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++)
Sys_Printf (" ");
if (node->planenum == PLANENUM_LEAF)
{
if (!node->brushlist)
Sys_Printf ("NULL\n");
else
{
for (bb=node->brushlist ; bb ; bb=bb->next)
Sys_Printf ("%i ", bb->original->brushnum);
Sys_Printf ("\n");
}
return;
}
plane = &mapplanes[node->planenum];
Sys_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);
}
/*
=========================================================
NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED
=========================================================
*/
int c_pruned;
/*
============
PruneNodes_r
============
*/
void PruneNodes_r (node_t *node)
{
bspbrush_t *b, *next;
if (node->planenum == PLANENUM_LEAF)
return;
PruneNodes_r (node->children[0]);
PruneNodes_r (node->children[1]);
if ( (node->children[0]->contents & CONTENTS_SOLID)
&& (node->children[1]->contents & CONTENTS_SOLID) )
{
if (node->faces)
Error ("node->faces seperating CONTENTS_SOLID");
if (node->children[0]->faces || node->children[1]->faces)
Error ("!node->faces with children");
// FIXME: free stuff
node->planenum = PLANENUM_LEAF;
node->contents = CONTENTS_SOLID;
node->detail_seperator = false;
if (node->brushlist)
Error ("PruneNodes: node->brushlist");
// combine brush lists
node->brushlist = node->children[1]->brushlist;
for (b=node->children[0]->brushlist ; b ; b=next)
{
next = b->next;
b->next = node->brushlist;
node->brushlist = b;
}
c_pruned++;
}
}
void PruneNodes (node_t *node)
{
Sys_FPrintf( SYS_VRB, "--- PruneNodes ---\n");
c_pruned = 0;
PruneNodes_r (node);
Sys_FPrintf( SYS_VRB, "%5i pruned nodes\n", c_pruned);
}
//===========================================================

View File

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

162
tools/quake2/qdata/anorms.h Normal file
View File

@@ -0,0 +1,162 @@
{ -0.525731f, 0.000000f, 0.850651f },
{ -0.442863f, 0.238856f, 0.864188f },
{ -0.295242f, 0.000000f, 0.955423f },
{ -0.309017f, 0.500000f, 0.809017f },
{ -0.162460f, 0.262866f, 0.951056f },
{ 0.000000f, 0.000000f, 1.000000f },
{ 0.000000f, 0.850651f, 0.525731f },
{ -0.147621f, 0.716567f, 0.681718f },
{ 0.147621f, 0.716567f, 0.681718f },
{ 0.000000f, 0.525731f, 0.850651f },
{ 0.309017f, 0.500000f, 0.809017f },
{ 0.525731f, 0.000000f, 0.850651f },
{ 0.295242f, 0.000000f, 0.955423f },
{ 0.442863f, 0.238856f, 0.864188f },
{ 0.162460f, 0.262866f, 0.951056f },
{ -0.681718f, 0.147621f, 0.716567f },
{ -0.809017f, 0.309017f, 0.500000f },
{ -0.587785f, 0.425325f, 0.688191f },
{ -0.850651f, 0.525731f, 0.000000f },
{ -0.864188f, 0.442863f, 0.238856f },
{ -0.716567f, 0.681718f, 0.147621f },
{ -0.688191f, 0.587785f, 0.425325f },
{ -0.500000f, 0.809017f, 0.309017f },
{ -0.238856f, 0.864188f, 0.442863f },
{ -0.425325f, 0.688191f, 0.587785f },
{ -0.716567f, 0.681718f, -0.147621f },
{ -0.500000f, 0.809017f, -0.309017f },
{ -0.525731f, 0.850651f, 0.000000f },
{ 0.000000f, 0.850651f, -0.525731f },
{ -0.238856f, 0.864188f, -0.442863f },
{ 0.000000f, 0.955423f, -0.295242f },
{ -0.262866f, 0.951056f, -0.162460f },
{ 0.000000f, 1.000000f, 0.000000f },
{ 0.000000f, 0.955423f, 0.295242f },
{ -0.262866f, 0.951056f, 0.162460f },
{ 0.238856f, 0.864188f, 0.442863f },
{ 0.262866f, 0.951056f, 0.162460f },
{ 0.500000f, 0.809017f, 0.309017f },
{ 0.238856f, 0.864188f, -0.442863f },
{ 0.262866f, 0.951056f, -0.162460f },
{ 0.500000f, 0.809017f, -0.309017f },
{ 0.850651f, 0.525731f, 0.000000f },
{ 0.716567f, 0.681718f, 0.147621f },
{ 0.716567f, 0.681718f, -0.147621f },
{ 0.525731f, 0.850651f, 0.000000f },
{ 0.425325f, 0.688191f, 0.587785f },
{ 0.864188f, 0.442863f, 0.238856f },
{ 0.688191f, 0.587785f, 0.425325f },
{ 0.809017f, 0.309017f, 0.500000f },
{ 0.681718f, 0.147621f, 0.716567f },
{ 0.587785f, 0.425325f, 0.688191f },
{ 0.955423f, 0.295242f, 0.000000f },
{ 1.000000f, 0.000000f, 0.000000f },
{ 0.951056f, 0.162460f, 0.262866f },
{ 0.850651f, -0.525731f, 0.000000f },
{ 0.955423f, -0.295242f, 0.000000f },
{ 0.864188f, -0.442863f, 0.238856f },
{ 0.951056f, -0.162460f, 0.262866f },
{ 0.809017f, -0.309017f, 0.500000f },
{ 0.681718f, -0.147621f, 0.716567f },
{ 0.850651f, 0.000000f, 0.525731f },
{ 0.864188f, 0.442863f, -0.238856f },
{ 0.809017f, 0.309017f, -0.500000f },
{ 0.951056f, 0.162460f, -0.262866f },
{ 0.525731f, 0.000000f, -0.850651f },
{ 0.681718f, 0.147621f, -0.716567f },
{ 0.681718f, -0.147621f, -0.716567f },
{ 0.850651f, 0.000000f, -0.525731f },
{ 0.809017f, -0.309017f, -0.500000f },
{ 0.864188f, -0.442863f, -0.238856f },
{ 0.951056f, -0.162460f, -0.262866f },
{ 0.147621f, 0.716567f, -0.681718f },
{ 0.309017f, 0.500000f, -0.809017f },
{ 0.425325f, 0.688191f, -0.587785f },
{ 0.442863f, 0.238856f, -0.864188f },
{ 0.587785f, 0.425325f, -0.688191f },
{ 0.688191f, 0.587785f, -0.425325f },
{ -0.147621f, 0.716567f, -0.681718f },
{ -0.309017f, 0.500000f, -0.809017f },
{ 0.000000f, 0.525731f, -0.850651f },
{ -0.525731f, 0.000000f, -0.850651f },
{ -0.442863f, 0.238856f, -0.864188f },
{ -0.295242f, 0.000000f, -0.955423f },
{ -0.162460f, 0.262866f, -0.951056f },
{ 0.000000f, 0.000000f, -1.000000f },
{ 0.295242f, 0.000000f, -0.955423f },
{ 0.162460f, 0.262866f, -0.951056f },
{ -0.442863f, -0.238856f, -0.864188f },
{ -0.309017f, -0.500000f, -0.809017f },
{ -0.162460f, -0.262866f, -0.951056f },
{ 0.000000f, -0.850651f, -0.525731f },
{ -0.147621f, -0.716567f, -0.681718f },
{ 0.147621f, -0.716567f, -0.681718f },
{ 0.000000f, -0.525731f, -0.850651f },
{ 0.309017f, -0.500000f, -0.809017f },
{ 0.442863f, -0.238856f, -0.864188f },
{ 0.162460f, -0.262866f, -0.951056f },
{ 0.238856f, -0.864188f, -0.442863f },
{ 0.500000f, -0.809017f, -0.309017f },
{ 0.425325f, -0.688191f, -0.587785f },
{ 0.716567f, -0.681718f, -0.147621f },
{ 0.688191f, -0.587785f, -0.425325f },
{ 0.587785f, -0.425325f, -0.688191f },
{ 0.000000f, -0.955423f, -0.295242f },
{ 0.000000f, -1.000000f, 0.000000f },
{ 0.262866f, -0.951056f, -0.162460f },
{ 0.000000f, -0.850651f, 0.525731f },
{ 0.000000f, -0.955423f, 0.295242f },
{ 0.238856f, -0.864188f, 0.442863f },
{ 0.262866f, -0.951056f, 0.162460f },
{ 0.500000f, -0.809017f, 0.309017f },
{ 0.716567f, -0.681718f, 0.147621f },
{ 0.525731f, -0.850651f, 0.000000f },
{ -0.238856f, -0.864188f, -0.442863f },
{ -0.500000f, -0.809017f, -0.309017f },
{ -0.262866f, -0.951056f, -0.162460f },
{ -0.850651f, -0.525731f, 0.000000f },
{ -0.716567f, -0.681718f, -0.147621f },
{ -0.716567f, -0.681718f, 0.147621f },
{ -0.525731f, -0.850651f, 0.000000f },
{ -0.500000f, -0.809017f, 0.309017f },
{ -0.238856f, -0.864188f, 0.442863f },
{ -0.262866f, -0.951056f, 0.162460f },
{ -0.864188f, -0.442863f, 0.238856f },
{ -0.809017f, -0.309017f, 0.500000f },
{ -0.688191f, -0.587785f, 0.425325f },
{ -0.681718f, -0.147621f, 0.716567f },
{ -0.442863f, -0.238856f, 0.864188f },
{ -0.587785f, -0.425325f, 0.688191f },
{ -0.309017f, -0.500000f, 0.809017f },
{ -0.147621f, -0.716567f, 0.681718f },
{ -0.425325f, -0.688191f, 0.587785f },
{ -0.162460f, -0.262866f, 0.951056f },
{ 0.442863f, -0.238856f, 0.864188f },
{ 0.162460f, -0.262866f, 0.951056f },
{ 0.309017f, -0.500000f, 0.809017f },
{ 0.147621f, -0.716567f, 0.681718f },
{ 0.000000f, -0.525731f, 0.850651f },
{ 0.425325f, -0.688191f, 0.587785f },
{ 0.587785f, -0.425325f, 0.688191f },
{ 0.688191f, -0.587785f, 0.425325f },
{ -0.955423f, 0.295242f, 0.000000f },
{ -0.951056f, 0.162460f, 0.262866f },
{ -1.000000f, 0.000000f, 0.000000f },
{ -0.850651f, 0.000000f, 0.525731f },
{ -0.955423f, -0.295242f, 0.000000f },
{ -0.951056f, -0.162460f, 0.262866f },
{ -0.864188f, 0.442863f, -0.238856f },
{ -0.951056f, 0.162460f, -0.262866f },
{ -0.809017f, 0.309017f, -0.500000f },
{ -0.864188f, -0.442863f, -0.238856f },
{ -0.951056f, -0.162460f, -0.262866f },
{ -0.809017f, -0.309017f, -0.500000f },
{ -0.681718f, 0.147621f, -0.716567f },
{ -0.681718f, -0.147621f, -0.716567f },
{ -0.850651f, 0.000000f, -0.525731f },
{ -0.688191f, 0.587785f, -0.425325f },
{ -0.587785f, 0.425325f, -0.688191f },
{ -0.425325f, 0.688191f, -0.587785f },
{ -0.425325f, -0.688191f, -0.587785f },
{ -0.587785f, -0.425325f, -0.688191f },
{ -0.688191f, -0.587785f, -0.425325f },

763
tools/quake2/qdata/images.c Normal file
View File

@@ -0,0 +1,763 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
#include "inout.h"
char mip_prefix[1024]; // directory to dump the textures in
qboolean colormap_issued;
byte colormap_palette[768];
/*
==============
RemapZero
Replaces all 0 bytes in an image with the closest palette entry.
This is because NT won't let us change index 0, so any palette
animation leaves those pixels untouched.
==============
*/
void RemapZero (byte *pixels, byte *palette, int width, int height)
{
int i, c;
int alt_zero;
int value, best;
alt_zero = 0;
best = 9999999;
for (i=1 ; i<255 ; i++)
{
value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
if (value < best)
{
best = value;
alt_zero = i;
}
}
c = width*height;
for (i=0 ; i<c ; i++)
if (pixels[i] == 0)
pixels[i] = alt_zero;
}
/*
==============
Cmd_Grab
$grab filename x y width height
==============
*/
void Cmd_Grab (void)
{
int xl,yl,w,h,y;
byte *cropped;
char savename[1024];
char dest[1024];
GetToken (false);
if (token[0] == '/' || token[0] == '\\')
sprintf (savename, "%s%s.pcx", gamedir, token+1);
else
sprintf (savename, "%spics/%s.pcx", gamedir, token);
if (g_release)
{
if (token[0] == '/' || token[0] == '\\')
sprintf (dest, "%s.pcx", token+1);
else
sprintf (dest, "pics/%s.pcx", token);
ReleaseFile (dest);
return;
}
GetToken (false);
xl = atoi (token);
GetToken (false);
yl = atoi (token);
GetToken (false);
w = atoi (token);
GetToken (false);
h = atoi (token);
if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
// crop it to the proper size
cropped = malloc (w*h);
for (y=0 ; y<h ; y++)
{
memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
}
// save off the new image
printf ("saving %s\n", savename);
CreatePath (savename);
WritePCXfile (savename, cropped, w, h, lbmpalette);
free (cropped);
}
/*
==============
Cmd_Raw
$grab filename x y width height
==============
*/
void Cmd_Raw (void)
{
int xl,yl,w,h,y;
byte *cropped;
char savename[1024];
char dest[1024];
GetToken (false);
sprintf (savename, "%s%s.lmp", gamedir, token);
if (g_release)
{
sprintf (dest, "%s.lmp", token);
ReleaseFile (dest);
return;
}
GetToken (false);
xl = atoi (token);
GetToken (false);
yl = atoi (token);
GetToken (false);
w = atoi (token);
GetToken (false);
h = atoi (token);
if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
// crop it to the proper size
cropped = malloc (w*h);
for (y=0 ; y<h ; y++)
{
memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
}
// save off the new image
printf ("saving %s\n", savename);
CreatePath (savename);
SaveFile (savename, cropped, w*h);
free (cropped);
}
/*
=============================================================================
COLORMAP GRABBING
=============================================================================
*/
/*
===============
BestColor
===============
*/
byte BestColor (int r, int g, int b, int start, int stop)
{
int i;
int dr, dg, db;
int bestdistortion, distortion;
int bestcolor;
byte *pal;
//
// let any color go to 0 as a last resort
//
bestdistortion = 256*256*4;
bestcolor = 0;
pal = colormap_palette + start*3;
for (i=start ; i<= stop ; i++)
{
dr = r - (int)pal[0];
dg = g - (int)pal[1];
db = b - (int)pal[2];
pal += 3;
distortion = dr*dr + dg*dg + db*db;
if (distortion < bestdistortion)
{
if (!distortion)
return i; // perfect match
bestdistortion = distortion;
bestcolor = i;
}
}
return bestcolor;
}
/*
==============
Cmd_Colormap
$colormap filename
the brightes colormap is first in the table (FIXME: reverse this now?)
64 rows of 256 : lightmaps
256 rows of 256 : translucency table
==============
*/
void Cmd_Colormap (void)
{
int levels, brights;
int l, c;
float frac, red, green, blue;
float range;
byte *cropped, *lump_p;
char savename[1024];
char dest[1024];
colormap_issued = true;
if (!g_release)
memcpy (colormap_palette, lbmpalette, 768);
if (!TokenAvailable ())
{ // just setting colormap_issued
return;
}
GetToken (false);
sprintf (savename, "%spics/%s.pcx", gamedir, token);
if (g_release)
{
sprintf (dest, "pics/%s.pcx", token);
ReleaseFile (dest);
return;
}
range = 2;
levels = 64;
brights = 1; // ignore 255 (transparent)
cropped = malloc((levels+256)*256);
lump_p = cropped;
// shaded levels
for (l=0;l<levels;l++)
{
frac = range - range*(float)l/(levels-1);
for (c=0 ; c<256-brights ; c++)
{
red = lbmpalette[c*3];
green = lbmpalette[c*3+1];
blue = lbmpalette[c*3+2];
red = (int)(red*frac+0.5);
green = (int)(green*frac+0.5);
blue = (int)(blue*frac+0.5);
//
// note: 254 instead of 255 because 255 is the transparent color, and we
// don't want anything remapping to that
// don't use color 0, because NT can't remap that (or 255)
//
*lump_p++ = BestColor(red,green,blue, 1, 254);
}
// fullbrights allways stay the same
for ( ; c<256 ; c++)
*lump_p++ = c;
}
// 66% transparancy table
for (l=0;l<255;l++)
{
for (c=0 ; c<255 ; c++)
{
red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
*lump_p++ = BestColor(red,green,blue, 1, 254);
}
*lump_p++ = 255;
}
for (c=0 ; c<256 ; c++)
*lump_p++ = 255;
// save off the new image
printf ("saving %s\n", savename);
CreatePath (savename);
WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
free (cropped);
}
/*
=============================================================================
MIPTEX GRABBING
=============================================================================
*/
byte pixdata[256];
int d_red, d_green, d_blue;
byte palmap[32][32][32];
qboolean palmap_built;
/*
=============
FindColor
=============
*/
int FindColor (int r, int g, int b)
{
int bestcolor;
if (r > 255)
r = 255;
if (r < 0)
r = 0;
if (g > 255)
g = 255;
if (g < 0)
g = 0;
if (b > 255)
b = 255;
if (b < 0)
b = 0;
#ifndef TABLECOLORS
bestcolor = BestColor (r, g, b, 0, 254);
#else
bestcolor = palmap[r>>3][g>>3][b>>3];
#endif
return bestcolor;
}
void BuildPalmap (void)
{
#ifdef TABLECOLORS
int r, g, b;
int bestcolor;
if (palmap_built)
return;
palmap_built = true;
for (r=4 ; r<256 ; r+=8)
{
for (g=4 ; g<256 ; g+=8)
{
for (b=4 ; b<256 ; b+=8)
{
bestcolor = BestColor (r, g, b, 1, 254);
palmap[r>>3][g>>3][b>>3] = bestcolor;
}
}
}
#endif
if (!colormap_issued)
Error ("You must issue a $colormap command first");
}
/*
=============
AveragePixels
=============
*/
byte AveragePixels (int count)
{
int r,g,b;
int i;
int vis;
int pix;
int bestcolor;
byte *pal;
int fullbright;
vis = 0;
r = g = b = 0;
fullbright = 0;
for (i=0 ; i<count ; i++)
{
pix = pixdata[i];
r += lbmpalette[pix*3];
g += lbmpalette[pix*3+1];
b += lbmpalette[pix*3+2];
vis++;
}
r /= vis;
g /= vis;
b /= vis;
// error diffusion
r += d_red;
g += d_green;
b += d_blue;
//
// find the best color
//
bestcolor = FindColor (r, g, b);
// error diffusion
pal = colormap_palette + bestcolor*3;
d_red = r - (int)pal[0];
d_green = g - (int)pal[1];
d_blue = b - (int)pal[2];
return bestcolor;
}
typedef enum
{
pt_contents,
pt_flags,
pt_animvalue,
pt_flagvalue
} parmtype_t;
typedef struct
{
char *name;
int flags;
parmtype_t type;
} mipparm_t;
mipparm_t mipparms[] =
{
// utility content attributes
{"water", CONTENTS_WATER, pt_contents},
{"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
{"lava", CONTENTS_LAVA, pt_contents}, // very damaging
{"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
{"mist", CONTENTS_MIST, pt_contents}, // non-solid window
{"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
{"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
{"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
// utility surface attributes
{"hint", SURF_HINT, pt_flags},
{"skip", SURF_SKIP, pt_flags},
{"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
// texture chaining
{"anim", 0, pt_animvalue}, // value is the next animation
// server attributes
{"slick", SURF_SLICK, pt_flags},
// drawing attributes
{"sky", SURF_SKY, pt_flags},
{"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
{"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
{"trans66", SURF_TRANS66, pt_flags},
{"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
{"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
{NULL, 0, pt_contents}
};
/*
==============
Cmd_Mip
$mip filename x y width height <OPTIONS>
must be multiples of sixteen
SURF_WINDOW
==============
*/
void Cmd_Mip (void)
{
int x,y,xl,yl,xh,yh,w,h;
byte *screen_p, *source;
int linedelta;
miptex_t *qtex;
int miplevel, mipstep;
int xx, yy, pix;
int count;
int flags, value, contents;
mipparm_t *mp;
char lumpname[64];
byte *lump_p;
char filename[1024];
char animname[64];
GetToken (false);
strcpy (lumpname, token);
GetToken (false);
xl = atoi (token);
GetToken (false);
yl = atoi (token);
GetToken (false);
w = atoi (token);
GetToken (false);
h = atoi (token);
if ( (w & 15) || (h & 15) )
Error ("line %i: miptex sizes must be multiples of 16", scriptline);
flags = 0;
contents = 0;
value = 0;
animname[0] = 0;
// get optional flags and values
while (TokenAvailable ())
{
GetToken (false);
for (mp=mipparms ; mp->name ; mp++)
{
if (!strcmp(mp->name, token))
{
switch (mp->type)
{
case pt_animvalue:
GetToken (false); // specify the next animation frame
strcpy (animname, token);
break;
case pt_flags:
flags |= mp->flags;
break;
case pt_contents:
contents |= mp->flags;
break;
case pt_flagvalue:
flags |= mp->flags;
GetToken (false); // specify the light value
value = atoi(token);
break;
}
break;
}
}
if (!mp->name)
Error ("line %i: unknown parm %s", scriptline, token);
}
sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
if (g_release)
return; // textures are only released by $maps
xh = xl+w;
yh = yl+h;
qtex = malloc (sizeof(miptex_t) + w*h*2);
memset (qtex, 0, sizeof(miptex_t));
qtex->width = LittleLong(w);
qtex->height = LittleLong(h);
qtex->flags = LittleLong(flags);
qtex->contents = LittleLong(contents);
qtex->value = LittleLong(value);
sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
if (animname[0])
sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
lump_p = (byte *)(&qtex->value+1);
screen_p = byteimage + yl*byteimagewidth + xl;
linedelta = byteimagewidth - w;
source = lump_p;
qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
for (y=yl ; y<yh ; y++)
{
for (x=xl ; x<xh ; x++)
{
pix = *screen_p++;
if (pix == 255)
pix = 1; // should never happen
*lump_p++ = pix;
}
screen_p += linedelta;
}
//
// subsample for greater mip levels
//
d_red = d_green = d_blue = 0; // no distortion yet
for (miplevel = 1 ; miplevel<4 ; miplevel++)
{
qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
mipstep = 1<<miplevel;
for (y=0 ; y<h ; y+=mipstep)
{
for (x = 0 ; x<w ; x+= mipstep)
{
count = 0;
for (yy=0 ; yy<mipstep ; yy++)
for (xx=0 ; xx<mipstep ; xx++)
{
pixdata[count] = source[ (y+yy)*w + x + xx ];
count++;
}
*lump_p++ = AveragePixels (count);
}
}
}
//
// dword align the size
//
while ((int)lump_p&3)
*lump_p++ = 0;
//
// write it out
//
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
free (qtex);
}
/*
===============
Cmd_Mippal
===============
*/
void Cmd_Mippal (void)
{
colormap_issued = true;
if (g_release)
return;
memcpy (colormap_palette, lbmpalette, 768);
BuildPalmap();
}
/*
===============
Cmd_Mipdir
===============
*/
void Cmd_Mipdir (void)
{
char filename[1024];
GetToken (false);
strcpy (mip_prefix, token);
// create the directory if needed
sprintf (filename, "%stextures", gamedir, mip_prefix);
Q_mkdir (filename);
sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
Q_mkdir (filename);
}
/*
=============================================================================
ENVIRONMENT MAP GRABBING
Creates six pcx files from tga files without any palette edge seams
also copies the tga files for GL rendering.
=============================================================================
*/
// 3dstudio environment map suffixes
char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
/*
=================
Cmd_Environment
=================
*/
void Cmd_Environment (void)
{
char name[1024];
int i, x, y;
byte image[256*256];
byte *tga;
GetToken (false);
if (g_release)
{
for (i=0 ; i<6 ; i++)
{
sprintf (name, "env/%s%s.pcx", token, suf[i]);
ReleaseFile (name);
sprintf (name, "env/%s%s.tga", token, suf[i]);
ReleaseFile (name);
}
return;
}
// get the palette
BuildPalmap ();
sprintf (name, "%senv/", gamedir);
CreatePath (name);
// convert the images
for (i=0 ; i<6 ; i++)
{
sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
printf ("loading %s...\n", name);
LoadTGA (name, &tga, NULL, NULL);
for (y=0 ; y<256 ; y++)
{
for (x=0 ; x<256 ; x++)
{
image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
}
}
free (tga);
sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
if (FileTime (name) != -1)
printf ("%s already exists, not overwriting.\n", name);
else
WritePCXfile (name, image, 256, 256, colormap_palette);
}
}

View File

@@ -0,0 +1,81 @@
CFLAGS = -c
LDFLAGS =
ODIR = baddir
EXEBASE = qdata
EXE = $(ODIR)/qdata
all: $(EXE)
_next:
make "CFLAGS = -c -g -I../common" "ODIR = next"
_irix:
make "CFLAGS = -c -Ofast=ip32_10k -I../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix"
_irixdebug:
make "CFLAGS = -c -O2 -g -I../common -Xcpluscomm" "LDFLAGS = -g" "ODIR = irix"
_irixinst:
make "CFLAGS = -c -Ofast=ip32_10k -I../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix"
cp irix/$(EXEBASE) /limbo/quake/bin_irix
_irixclean:
rm -f irix/*.o irix/$(EXEBASE)
_osf:
make "CFLAGS = -c -O4 -I../common -threads" "LDFLAGS = -threads" "ODIR = osf"
clean:
rm -f next/*.o next/$(EXEBASE)
rm -f osf/*.o osf/$(EXEBASE)
rm -f irix/*.o irix/$(EXEBASE)
install:
cp next/$(EXEBASE) /limbo/quake2/bin_next
cp osf/$(EXEBASE) /limbo/quake2/bin_osf
cp irix/$(EXEBASE) /limbo/quake2/bin_irix
FILES = $(ODIR)/qdata.o $(ODIR)/models.o $(ODIR)/sprites.o $(ODIR)/images.o $(ODIR)/cmdlib.o $(ODIR)/scriplib.o $(ODIR)/lbmlib.o $(ODIR)/mathlib.o $(ODIR)/l3dslib.o $(ODIR)/trilib.o $(ODIR)/threads.o $(ODIR)/tables.o
$(EXE) : $(FILES)
cc -o $(EXE) $(LDFLAGS) $(FILES) -lm
$(ODIR)/qdata.o : qdata.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/models.o : models.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/sprites.o : sprites.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/images.o : images.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/tables.o : tables.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)/scriplib.o : ../common/scriplib.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/lbmlib.o : ../common/lbmlib.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)/trilib.o : ../common/trilib.c
cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i
cc $(CFLAGS) -o $@ /tmp/temp.i
$(ODIR)/l3dslib.o : ../common/l3dslib.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

1152
tools/quake2/qdata/models.c Normal file

File diff suppressed because it is too large Load Diff

553
tools/quake2/qdata/qdata.c Normal file
View File

@@ -0,0 +1,553 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
#include "inout.h"
qboolean g_compress_pak;
qboolean g_release; // don't grab, copy output data to new tree
qboolean g_pak; // if true, copy to pak instead of release
char g_releasedir[1024]; // c:\quake2\baseq2, etc
qboolean g_archive; // don't grab, copy source data to new tree
qboolean do3ds;
char g_only[256]; // if set, only grab this cd
qboolean g_skipmodel; // set true when a cd is not g_only
char *ext_3ds = "3ds";
char *ext_tri= "tri";
char *trifileext;
char game[64] = "quake2";
void InitPaths( int *argc, char **argv );
/*
=======================================================
PAK FILES
=======================================================
*/
unsigned Com_BlockChecksum (void *buffer, int length);
typedef struct
{
char name[56];
int filepos, filelen;
} packfile_t;
typedef struct
{
char id[4];
int dirofs;
int dirlen;
} packheader_t;
packfile_t pfiles[16384];
FILE *pakfile;
packfile_t *pf;
packheader_t pakheader;
/*
==============
BeginPak
==============
*/
void BeginPak (char *outname)
{
if (!g_pak)
return;
pakfile = SafeOpenWrite (outname);
// leave space for header
SafeWrite (pakfile, &pakheader, sizeof(pakheader));
pf = pfiles;
}
/*
==============
ReleaseFile
Filename should be gamedir reletive.
Either copies the file to the release dir, or adds it to
the pak file.
==============
*/
void ReleaseFile (char *filename)
{
int len;
byte *buf;
char source[1024];
char dest[1024];
if (!g_release)
return;
sprintf (source, "%s%s", gamedir, filename);
if (!g_pak)
{ // copy it
sprintf (dest, "%s/%s", g_releasedir, filename);
printf ("copying to %s\n", dest);
QCopyFile (source, dest);
return;
}
// pak it
printf ("paking %s\n", filename);
if (strlen(filename) >= sizeof(pf->name))
Error ("Filename too long for pak: %s", filename);
len = LoadFile (source, (void **)&buf);
if (g_compress_pak && len < 4096*1024 )
{
cblock_t in, out;
cblock_t Huffman (cblock_t in);
in.count = len;
in.data = buf;
out = Huffman (in);
if (out.count < in.count)
{
printf (" compressed from %i to %i\n", in.count, out.count);
free (in.data);
buf = out.data;
len = out.count;
}
else
free (out.data);
}
strcpy (pf->name, filename);
pf->filepos = LittleLong(ftell(pakfile));
pf->filelen = LittleLong(len);
pf++;
SafeWrite (pakfile, buf, len);
free (buf);
}
/*
==============
FinishPak
==============
*/
void FinishPak (void)
{
int dirlen;
int d;
int i;
unsigned checksum;
if (!g_pak)
return;
pakheader.id[0] = 'P';
pakheader.id[1] = 'A';
pakheader.id[2] = 'C';
pakheader.id[3] = 'K';
dirlen = (byte *)pf - (byte *)pfiles;
pakheader.dirofs = LittleLong(ftell(pakfile));
pakheader.dirlen = LittleLong(dirlen);
checksum = Com_BlockChecksum ( (void *)pfiles, dirlen );
SafeWrite (pakfile, pfiles, dirlen);
i = ftell (pakfile);
fseek (pakfile, 0, SEEK_SET);
SafeWrite (pakfile, &pakheader, sizeof(pakheader));
fclose (pakfile);
d = pf - pfiles;
printf ("%i files packed in %i bytes\n",d, i);
printf ("checksum: 0x%x\n", checksum);
}
/*
===============
Cmd_File
This is only used to cause a file to be copied during a release
build (default.cfg, maps, etc)
===============
*/
void Cmd_File (void)
{
GetToken (false);
ReleaseFile (token);
}
/*
===============
PackDirectory_r
===============
*/
#ifdef _WIN32
#include "io.h"
void PackDirectory_r (char *dir)
{
struct _finddata_t fileinfo;
int handle;
char dirstring[1024];
char filename[1024];
sprintf (dirstring, "%s%s/*.*", gamedir, dir);
handle = _findfirst (dirstring, &fileinfo);
if (handle == -1)
return;
do
{
sprintf (filename, "%s/%s", dir, fileinfo.name);
if (fileinfo.attrib & _A_SUBDIR)
{ // directory
if (fileinfo.name[0] != '.') // don't pak . and ..
PackDirectory_r (filename);
continue;
}
// copy or pack the file
ReleaseFile (filename);
} while (_findnext( handle, &fileinfo ) != -1);
_findclose (handle);
}
#else
#include <sys/types.h>
#include <sys/dir.h>
void PackDirectory_r (char *dir)
{
#ifdef NeXT
struct direct **namelist, *ent;
#else
struct dirent **namelist, *ent;
#endif
int count;
struct stat st;
int i;
int len;
char fullname[1024];
char dirstring[1024];
char *name;
sprintf (dirstring, "%s%s", gamedir, dir);
count = scandir(dirstring, &namelist, NULL, NULL);
for (i=0 ; i<count ; i++)
{
ent = namelist[i];
name = ent->d_name;
if (name[0] == '.')
continue;
sprintf (fullname, "%s/%s", dir, name);
sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
if (stat (dirstring, &st) == -1)
Error ("fstating %s", pf->name);
if (st.st_mode & S_IFDIR)
{ // directory
PackDirectory_r (fullname);
continue;
}
// copy or pack the file
ReleaseFile (fullname);
}
}
#endif
/*
===============
Cmd_Dir
This is only used to cause a directory to be copied during a
release build (sounds, etc)
===============
*/
void Cmd_Dir (void)
{
GetToken (false);
PackDirectory_r (token);
}
//========================================================================
#define MAX_RTEX 16384
int numrtex;
char rtex[MAX_RTEX][64];
void ReleaseTexture (char *name)
{
int i;
char path[1024];
for (i=0 ; i<numrtex ; i++)
if (!Q_strncasecmp(name, rtex[i], strlen(name)))
return;
if (numrtex == MAX_RTEX)
Error ("numrtex == MAX_RTEX");
strcpy (rtex[i], name);
numrtex++;
sprintf (path, "textures/%s.wal", name);
ReleaseFile (path);
}
/*
===============
Cmd_Maps
Only relevent for release and pak files.
Releases the .bsp files for the maps, and scans all of the files to
build a list of all textures used, which are then released.
===============
*/
void Cmd_Maps (void)
{
char map[1024];
int i;
while (TokenAvailable ())
{
GetToken (false);
sprintf (map, "maps/%s.bsp", token);
ReleaseFile (map);
if (!g_release)
continue;
// get all the texture references
sprintf (map, "%smaps/%s.bsp", gamedir, token);
LoadBSPFileTexinfo (map);
for (i=0 ; i<numtexinfo ; i++)
ReleaseTexture (texinfo[i].texture);
}
}
//==============================================================
/*
===============
ParseScript
===============
*/
void ParseScript (void)
{
while (1)
{
do
{ // look for a line starting with a $ command
GetToken (true);
if (endofscript)
return;
if (token[0] == '$')
break;
while (TokenAvailable())
GetToken (false);
} while (1);
//
// model commands
//
if (!strcmp (token, "$modelname"))
Cmd_Modelname ();
else if (!strcmp (token, "$base"))
Cmd_Base ();
else if (!strcmp (token, "$cd"))
Cmd_Cd ();
else if (!strcmp (token, "$origin"))
Cmd_Origin ();
else if (!strcmp (token, "$scale"))
Cmd_ScaleUp ();
else if (!strcmp (token, "$frame"))
Cmd_Frame ();
else if (!strcmp (token, "$skin"))
Cmd_Skin ();
else if (!strcmp (token, "$skinsize"))
Cmd_Skinsize ();
//
// sprite commands
//
else if (!strcmp (token, "$spritename"))
Cmd_SpriteName ();
else if (!strcmp (token, "$load"))
Cmd_Load ();
else if (!strcmp (token, "$spriteframe"))
Cmd_SpriteFrame ();
//
// image commands
//
else if (!strcmp (token, "$grab"))
Cmd_Grab ();
else if (!strcmp (token, "$raw"))
Cmd_Raw ();
else if (!strcmp (token, "$colormap"))
Cmd_Colormap ();
else if (!strcmp (token, "$mippal"))
Cmd_Mippal ();
else if (!strcmp (token, "$mipdir"))
Cmd_Mipdir ();
else if (!strcmp (token, "$mip"))
Cmd_Mip ();
else if (!strcmp (token, "$environment"))
Cmd_Environment ();
//
// video
//
else if (!strcmp (token, "$video"))
Cmd_Video ();
//
// misc
//
else if (!strcmp (token, "$file"))
Cmd_File ();
else if (!strcmp (token, "$dir"))
Cmd_Dir ();
else if (!strcmp (token, "$maps"))
Cmd_Maps ();
else if (!strcmp (token, "$alphalight"))
Cmd_Alphalight ();
else if (!strcmp (token, "$inverse16table" ))
Cmd_Inverse16Table();
else
Error ("bad command %s\n", token);
}
}
//=======================================================
/*
==============
main
==============
*/
int main (int argc, char **argv)
{
static int i; // VC4.2 compiler bug if auto...
char path[1024];
ExpandWildcards (&argc, &argv);
InitPaths( &argc, argv );
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i], "-archive"))
{
// -archive f:/quake2/release/dump_11_30
archive = true;
strcpy (archivedir, argv[i+1]);
printf ("Archiving source to: %s\n", archivedir);
i++;
}
else if (!strcmp(argv[i], "-release"))
{
g_release = true;
strcpy (g_releasedir, argv[i+1]);
printf ("Copy output to: %s\n", g_releasedir);
i++;
}
else if (!strcmp(argv[i], "-compress"))
{
g_compress_pak = true;
printf ("Compressing pakfile\n");
}
else if (!strcmp(argv[i], "-pak"))
{
g_release = true;
g_pak = true;
printf ("Building pakfile: %s\n", argv[i+1]);
BeginPak (argv[i+1]);
i++;
}
else if (!strcmp(argv[i], "-only"))
{
strcpy (g_only, argv[i+1]);
printf ("Only grabbing %s\n", g_only);
i++;
}
else if (!strcmp(argv[i], "-3ds"))
{
do3ds = true;
printf ("loading .3ds files\n");
}
else if (argv[i][0] == '-')
Error ("Unknown option \"%s\"", argv[i]);
else
break;
}
if (i >= argc)
Error ("usage: %s [-archive <directory>] [-release <directory>] [-only <model>] [-3ds] file.qgr", argv[ 0 ] );
if (do3ds)
trifileext = ext_3ds;
else
trifileext = ext_tri;
for ( ; i<argc ; i++)
{
printf ("--------------- %s ---------------\n", argv[i]);
// load the script
strcpy (path, argv[i]);
DefaultExtension (path, ".qdt");
SetQdirFromPath (path);
LoadScriptFile (ExpandArg(path));
//
// parse it
//
ParseScript ();
// write out the last model
FinishModel ();
FinishSprite ();
}
if (g_pak)
FinishPak ();
return 0;
}

View File

@@ -0,0 +1,93 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/stat.h>
#include "cmdlib.h"
#include "scriplib.h"
#include "mathlib.h"
#include "trilib.h"
#include "lbmlib.h"
#include "q2_threads.h"
#include "l3dslib.h"
#include "bspfile.h"
#ifdef WIN32
#ifdef NDEBUG // Don't show in a Release build
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4244) // conversion from double to float
#pragma warning(disable : 4018) // signed/unsigned mismatch
#endif
#endif
void Cmd_Modelname (void);
void Cmd_Base (void);
void Cmd_Cd (void);
void Cmd_Origin (void);
void Cmd_ScaleUp (void);
void Cmd_Frame (void);
void Cmd_Modelname (void);
void Cmd_Skin (void);
void Cmd_Skinsize (void);
void FinishModel (void);
void Cmd_Inverse16Table( void );
void Cmd_SpriteName (void);
void Cmd_Load (void);
void Cmd_SpriteFrame (void);
void FinishSprite (void);
void Cmd_Grab (void);
void Cmd_Raw (void);
void Cmd_Mip (void);
void Cmd_Environment (void);
void Cmd_Colormap (void);
void Cmd_File (void);
void Cmd_Dir (void);
void Cmd_StartWad (void);
void Cmd_EndWad (void);
void Cmd_Mippal (void);
void Cmd_Mipdir (void);
void Cmd_Alphalight (void);
void Cmd_Video (void);
void RemapZero (byte *pixels, byte *palette, int width, int height);
void ReleaseFile (char *filename);
extern byte *byteimage, *lbmpalette;
extern int byteimagewidth, byteimageheight;
extern qboolean g_release; // don't grab, copy output data to new tree
extern char g_releasedir[1024]; // c:\quake2\baseq2, etc
extern qboolean g_archive; // don't grab, copy source data to new tree
extern qboolean do3ds;
extern char g_only[256]; // if set, only grab this cd
extern qboolean g_skipmodel; // set true when a cd is not g_only
extern char *trifileext;

View File

@@ -0,0 +1,218 @@
# Microsoft Developer Studio Project File - Name="qdata3" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=qdata3 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "qdata3.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "qdata3.mak" CFG="qdata3 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "qdata3 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "qdata3 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "qdata3 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
F90=df.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX- /Zi /O2 /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 wsock32.lib l_net.lib mathlib.lib /nologo /subsystem:console /map /machine:I386 /libpath:"..\..\..\libs\mathlib\Release" /libpath:"..\..\..\libs\l_net\Release" /libpath:"..\..\..\..\libxml2\win32\libxml2\release_so"
!ELSEIF "$(CFG)" == "qdata3 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
F90=df.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX- /ZI /Od /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 wsock32.lib l_net.lib mathlib.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /libpath:"..\..\..\libs\mathlib\Debug" /libpath:"..\..\..\libs\l_net\Debug" /libpath:"..\..\..\..\libxml2\win32\libxml2\debug_so"
!ENDIF
# Begin Target
# Name "qdata3 - Win32 Release"
# Name "qdata3 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\common\bspfile.c
# End Source File
# Begin Source File
SOURCE=..\common\cmdlib.c
# End Source File
# Begin Source File
SOURCE=.\images.c
# End Source File
# Begin Source File
SOURCE=..\common\inout.c
# End Source File
# Begin Source File
SOURCE=..\common\l3dslib.c
# End Source File
# Begin Source File
SOURCE=..\common\lbmlib.c
# End Source File
# Begin Source File
SOURCE=..\common\mathlib.c
# End Source File
# Begin Source File
SOURCE=..\common\md4.c
# End Source File
# Begin Source File
SOURCE=.\models.c
# End Source File
# Begin Source File
SOURCE=..\common\path_init.c
# End Source File
# Begin Source File
SOURCE=.\qdata.c
# End Source File
# Begin Source File
SOURCE=..\common\scriplib.c
# End Source File
# Begin Source File
SOURCE=.\sprites.c
# End Source File
# Begin Source File
SOURCE=.\tables.c
# End Source File
# Begin Source File
SOURCE=..\common\threads.c
# End Source File
# Begin Source File
SOURCE=..\common\trilib.c
# End Source File
# Begin Source File
SOURCE=.\video.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\anorms.h
# End Source File
# Begin Source File
SOURCE=..\common\bspfile.h
# End Source File
# Begin Source File
SOURCE=..\common\cmdlib.h
# End Source File
# Begin Source File
SOURCE=..\common\inout.h
# End Source File
# Begin Source File
SOURCE=..\common\l3dslib.h
# End Source File
# Begin Source File
SOURCE=..\common\lbmlib.h
# End Source File
# Begin Source File
SOURCE=..\common\mathlib.h
# End Source File
# Begin Source File
SOURCE=.\qdata.h
# End Source File
# Begin Source File
SOURCE=..\common\qfiles.h
# End Source File
# Begin Source File
SOURCE=..\common\scriplib.h
# End Source File
# Begin Source File
SOURCE=..\common\threads.h
# End Source File
# Begin Source File
SOURCE=..\common\trilib.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="qdata3"
>
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\common,..\..\..\..\libxml2\include,..\..\..\libs,..\..\..\include"
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\Debug/qdata3.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="wsock32.lib libxml2.lib"
OutputFile=".\Debug/qdata3.exe"
LinkIncremental="2"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="..\..\..\libs\mathlib\Debug;..\..\..\libs\l_net\Debug;&quot;..\..\..\..\libxml2\win32\binaries-debug&quot;"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\Debug/qdata3.pdb"
GenerateMapFile="TRUE"
MapFileName=".\Debug/qdata3.map"
SubSystem="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/qdata3.tlb"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\common,..\..\..\..\libxml2\include,..\..\..\libs,..\..\..\include"
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
StringPooling="TRUE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="TRUE"
PrecompiledHeaderFile=".\Release/qdata3.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="3"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="wsock32.lib libxml2.lib"
OutputFile=".\Release/qdata3.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="..\..\..\libs\mathlib\Release;..\..\..\libs\l_net\Release;&quot;..\..\..\..\libxml2\win32\binaries-release&quot;"
ProgramDatabaseFile=".\Release/qdata3.pdb"
GenerateMapFile="TRUE"
MapFileName=".\Release/qdata3.map"
SubSystem="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/qdata3.tlb"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
</Configurations>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath="..\common\bspfile.c">
</File>
<File
RelativePath="..\common\cmdlib.c">
</File>
<File
RelativePath=".\images.c">
</File>
<File
RelativePath="..\common\inout.c">
</File>
<File
RelativePath="..\common\l3dslib.c">
</File>
<File
RelativePath="..\common\lbmlib.c">
</File>
<File
RelativePath="..\common\mathlib.c">
</File>
<File
RelativePath="..\common\md4.c">
</File>
<File
RelativePath=".\models.c">
</File>
<File
RelativePath="..\common\path_init.c">
</File>
<File
RelativePath=".\qdata.c">
</File>
<File
RelativePath="..\common\scriplib.c">
</File>
<File
RelativePath=".\sprites.c">
</File>
<File
RelativePath=".\tables.c">
</File>
<File
RelativePath="..\common\threads.c">
</File>
<File
RelativePath="..\common\trilib.c">
</File>
<File
RelativePath=".\video.c">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
<File
RelativePath=".\anorms.h">
</File>
<File
RelativePath="..\common\bspfile.h">
</File>
<File
RelativePath="..\common\cmdlib.h">
</File>
<File
RelativePath="..\common\inout.h">
</File>
<File
RelativePath="..\common\l3dslib.h">
</File>
<File
RelativePath="..\common\lbmlib.h">
</File>
<File
RelativePath="..\common\mathlib.h">
</File>
<File
RelativePath=".\qdata.h">
</File>
<File
RelativePath="..\common\qfiles.h">
</File>
<File
RelativePath="..\common\scriplib.h">
</File>
<File
RelativePath="..\common\threads.h">
</File>
<File
RelativePath="..\common\trilib.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,228 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
#include "inout.h"
#define MAX_SPRFRAMES MAX_MD2SKINS
dsprite_t sprite;
dsprframe_t frames[MAX_SPRFRAMES];
byte *byteimage, *lbmpalette;
int byteimagewidth, byteimageheight;
char spritename[1024];
void FinishSprite (void);
void Cmd_Spritename (void);
/*
==============
FinishSprite
==============
*/
void FinishSprite (void)
{
FILE *spriteouthandle;
int i, curframe;
dsprite_t spritetemp;
char savename[1024];
if (sprite.numframes == 0)
return;
if (!strlen(spritename))
Error ("Didn't name sprite file");
sprintf (savename, "%s%s.sp2", gamedir, spritename);
if (g_release)
{
char name[1024];
sprintf (name, "%s.sp2", spritename);
ReleaseFile (name);
spritename[0] = 0; // clear for a new sprite
sprite.numframes = 0;
return;
}
printf ("saving in %s\n", savename);
CreatePath (savename);
spriteouthandle = SafeOpenWrite (savename);
//
// write out the sprite header
//
spritetemp.ident = LittleLong (IDSPRITEHEADER);
spritetemp.version = LittleLong (SPRITE_VERSION);
spritetemp.numframes = LittleLong (sprite.numframes);
SafeWrite (spriteouthandle, &spritetemp, 12);
//
// write out the frames
//
curframe = 0;
for (i=0 ; i<sprite.numframes ; i++)
{
frames[i].width = LittleLong(frames[i].width);
frames[i].height = LittleLong(frames[i].height);
frames[i].origin_x = LittleLong(frames[i].origin_x);
frames[i].origin_y = LittleLong(frames[i].origin_y);
}
SafeWrite (spriteouthandle, frames, sizeof(frames[0])*sprite.numframes);
fclose (spriteouthandle);
spritename[0] = 0; // clear for a new sprite
sprite.numframes = 0;
}
/*
===============
Cmd_Load
===============
*/
void Cmd_Load (void)
{
char *name;
GetToken (false);
if (g_release)
return;
name = ExpandPathAndArchive(token);
// load the image
printf ("loading %s\n", name);
Load256Image (name, &byteimage, &lbmpalette,
&byteimagewidth, &byteimageheight);
RemapZero (byteimage, lbmpalette,
byteimagewidth, byteimageheight);
}
/*
===============
Cmd_SpriteFrame
===============
*/
void Cmd_SpriteFrame (void)
{
int y,xl,yl,xh,yh,w,h;
dsprframe_t *pframe;
int ox, oy;
byte *cropped;
char savename[1024];
GetToken (false);
xl = atoi (token);
GetToken (false);
yl = atoi (token);
GetToken (false);
w = atoi (token);
GetToken (false);
h = atoi (token);
// origin offset is optional
if (TokenAvailable ())
{
GetToken (false);
ox = atoi (token);
GetToken (false);
oy = atoi (token);
}
else
{
ox = w/2;
oy = h/2;
}
if ((xl & 0x07) || (yl & 0x07) || (w & 0x07) || (h & 0x07))
Error ("Sprite dimensions not multiples of 8\n");
if ((w > 256) || (h > 256))
Error ("Sprite has a dimension longer than 256");
xh = xl+w;
yh = yl+h;
if (sprite.numframes >= MAX_SPRFRAMES)
Error ("Too many frames; increase MAX_SPRFRAMES\n");
pframe = &frames[sprite.numframes];
pframe->width = w;
pframe->height = h;
pframe->origin_x = ox;
pframe->origin_y = oy;
sprintf (pframe->name, "%s_%i.pcx", spritename, sprite.numframes);
sprintf (savename, "%s%s_%i.pcx", gamedir, spritename, sprite.numframes);
sprite.numframes++;
if (g_release)
{
ReleaseFile (pframe->name);
return;
}
// crop it to the proper size
cropped = malloc (w*h);
for (y=0 ; y<h ; y++)
{
memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
}
// save off the new image
printf ("saving %s\n", savename);
CreatePath (savename);
WritePCXfile (savename, cropped, w, h, lbmpalette);
free (cropped);
}
/*
==============
Cmd_SpriteName
==============
*/
void Cmd_SpriteName (void)
{
if (sprite.numframes)
FinishSprite ();
GetToken (false);
strcpy (spritename, token);
memset (&sprite, 0, sizeof(sprite));
memset (&frames, 0, sizeof(frames));
}

171
tools/quake2/qdata/tables.c Normal file
View File

@@ -0,0 +1,171 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
/*
=============================================================================
ALPHALIGHT GENERATION
Find alphamap values that best match modulated lightmap values
This isn't used anymore, but I'm keeping it around...
=============================================================================
*/
unsigned short alphamap[32*32*32];
unsigned char inverse16to8table[65536];
/*
static int FindNearestColor( unsigned int color )
{
int i;
int closest_so_far = 0;
float closest_distance_so_far = 100000000;
float d;
float r[2], g[2], b[2];
// incoming color is assumed to be in 0xRRGGBB format
r[0] = ( color & 31 ) << 3;
g[0] = ( ( color >> 5 ) & 63 ) << 2;
b[0] = ( ( color >> 11 ) & 31 ) << 3;
for ( i = 0; i < 256; i++ )
{
r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
( g[1] - g[0] ) * ( g[1] - g[0] ) +
( b[1] - b[0] ) * ( b[1] - b[0] );
if ( d < closest_distance_so_far )
{
closest_distance_so_far = d;
closest_so_far = i;
}
}
return closest_so_far;
}
*/
extern byte BestColor( int, int, int, int, int );
void Inverse16_BuildTable( void )
{
int i;
/*
** create the 16-to-8 table
*/
for ( i = 0; i < 65536; i++ )
{
int r = i & 31;
int g = ( i >> 5 ) & 63;
int b = ( i >> 11 ) & 31;
r <<= 3;
g <<= 2;
b <<= 3;
inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
}
}
void Alphalight_Thread (int i)
{
int j;
float r, g, b;
float mr, mg, mb, ma;
float distortion, bestdistortion;
float v;
r = (i>>10) * (1.0/16);
g = ((i>>5)&31) * (1.0/16);
b = (i&31) * (1.0/16);
bestdistortion = 999999;
for (j=0 ; j<16*16*16*16 ; j++)
{
mr = (j>>12) * (1.0/16);
mg = ((j>>8)&15) * (1.0/16);
mb = ((j>>4)&15) * (1.0/16);
ma = (j&15) * (1.0/16);
v = r * 0.5 - (mr*ma + 0.5*(1.0-ma));
distortion = v*v;
v = g * 0.5 - (mg*ma + 0.5*(1.0-ma));
distortion += v*v;
v = b * 0.5 - (mb*ma + 0.5*(1.0-ma));
distortion += v*v;
distortion *= 1.0 + ma*4;
if (distortion < bestdistortion)
{
bestdistortion = distortion;
alphamap[i] = j;
}
}
}
void Cmd_Alphalight (void)
{
char savename[1024];
GetToken (false);
if (g_release)
{
ReleaseFile (token);
return;
}
sprintf (savename, "%s%s", gamedir, token);
printf ("Building alphalight table...\n");
RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread);
SaveFile (savename, (byte *)alphamap, sizeof(alphamap));
}
void Cmd_Inverse16Table( void )
{
char savename[1024];
if ( g_release )
{
sprintf (savename, "pics/16to8.dat");
ReleaseFile( savename );
return;
}
sprintf (savename, "%spics/16to8.dat", gamedir);
printf ("Building inverse 16-to-8 table...\n");
Inverse16_BuildTable();
SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
}

1259
tools/quake2/qdata/video.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
** adpcm.h - include file for adpcm coder.
**
** Version 1.0, 7-Jul-92.
**
** Modded 10/3/98
** John Scott
*/
typedef struct adpcm_state_s
{
short in_valprev; // Previous output value
short in_index; // Index into stepsize table
short out_valprev; // Previous output value
short out_index; // Index into stepsize table
int count; // Number of sample counts
} adpcm_state_t;
typedef struct adpcm_s
{
adpcm_state_t state;
char adpcm[0x10000];
} adpcm_t;
void adpcm_coder(short [], adpcm_t *);
void adpcm_decoder(adpcm_t *, short []);
// end

View File

@@ -0,0 +1,351 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <memory.h>
#include "animcomp.h"
void *SafeMalloc(size_t n, char *desc);
float *matrix;
float *delta;
float *best;
float *comp;
float *tcomp;
float *bestcomp;
float *frames;
float *base;
int MatWidth;
int MatHeight;
int CFrameSize;
int nFrames;
void AnimCompressInit(int nframes,int nVerts,int CompressedFrameSize)
{
nFrames=nframes;
MatWidth=nVerts*3;
MatHeight=CompressedFrameSize;
CFrameSize=CompressedFrameSize;
matrix=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
best=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
delta=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
comp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
tcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
bestcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
base=(float *)SafeMalloc(MatWidth*sizeof(float), "AnimCompressInit");
frames=(float *)SafeMalloc(MatWidth*nFrames*sizeof(float), "AnimCompressInit");
}
void AnimSetFrame(int frame,int index,float x,float y,float z)
{
frames[frame*MatWidth+index*3]=x;
frames[frame*MatWidth+index*3+1]=y;
frames[frame*MatWidth+index*3+2]=z;
}
typedef struct
{
int index;
float val;
} SORTP;
#define F_RANDOM (((float)rand())/(float)RAND_MAX)
extern void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize);
void AnimCompressDoit()
{
float compression;
float *rescale;
float *ans;
float maxdev;
float avedev;
float tmp;
int j,k,l,numave;
for (k=0;k<MatWidth;k++)
base[k]=0.0f;
for (j=0;j<nFrames;j++)
for (k=0;k<MatWidth;k++)
base[k]+=frames[j*MatWidth+k];
tmp=1.0f/(float)nFrames;
for (k=0;k<MatWidth;k++)
base[k]*=tmp;
for (j=0;j<nFrames;j++)
for (k=0;k<MatWidth;k++)
frames[j*MatWidth+k]-=base[k];
ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressDoit");
rescale=(float *)SafeMalloc(sizeof(float)*CFrameSize, "AnimCompressDoit");
DOsvd(frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight);
avedev=0.0;
for (l=0;l<CFrameSize;l++)
avedev+=rescale[l];
for (l=0;l<CFrameSize;l++)
printf("%3.1f ",100.0f*rescale[l]/avedev);
printf("\n");
for (j=0;j<nFrames;j++)
{
for (l=0;l<CFrameSize;l++)
{
bestcomp[j*CFrameSize+l]=0.0;
for (k=0;k<MatWidth;k++)
bestcomp[j*CFrameSize+l]+=best[l*MatWidth+k]*frames[j*MatWidth+k];
}
}
numave=0;
avedev=0.0;
maxdev=0.0;
for (j=0;j<nFrames;j++)
{
for (k=0;k<MatWidth;k++)
{
ans[k]=0.0;
for (l=0;l<CFrameSize;l++)
ans[k]+=best[l*MatWidth+k]*bestcomp[j*CFrameSize+l];
ans[k]-=frames[j*MatWidth+k];
tmp=(float)fabs(ans[k]);
if (tmp>maxdev)
maxdev=tmp;
avedev+=tmp;
numave++;
}
}
avedev/=(float)numave;
printf("%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev);
printf("%d bytes original size\n",MatWidth*nFrames);
printf("%d bytes of overhead\n",MatWidth*MatHeight);
printf("%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize*nFrames);
compression=(float)(MatWidth*MatHeight+CFrameSize*nFrames+MatWidth);
compression/=(float)(MatWidth*nFrames);
printf("Overall compression = %f %%\n",100.0f-100.0f*compression);
compression=(float)(CFrameSize);
compression/=(float)(MatWidth);
printf("frame size compression = %f %%\n",100.0f-100.0f*compression);
free(rescale);
free(ans);
}
void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax)
{
int k,l,nv,j;
float maxdev;
float avedev;
float tmp;
int numave;
float t,mx;
float *ans;
nv=MatWidth/3;
trans[0]=1E30f;
scale[0]=-1E30f;
trans[1]=1E30f;
scale[1]=-1E30f;
trans[2]=1E30f;
scale[2]=-1E30f;
for (k=0;k<MatWidth;k+=3)
{
if (base[k]>scale[0])
scale[0]=base[k];
if (base[k]<trans[0])
trans[0]=base[k];
if (base[k+1]>scale[1])
scale[1]=base[k+1];
if (base[k+1]<trans[1])
trans[1]=base[k+1];
if (base[k+2]>scale[2])
scale[2]=base[k+2];
if (base[k+2]<trans[2])
trans[2]=base[k+2];
}
scale[0]-=trans[0];
scale[1]-=trans[1];
scale[2]-=trans[2];
scale[0]/=255.0f;
scale[1]/=255.0f;
scale[2]/=255.0f;
for (k=0;k<MatWidth;k+=3)
{
t=(base[k]-trans[0])/scale[0];
if (t<0.0f)
t=0.0f;
if (t>255.0f)
t=255.0f;
cbase[k]=(unsigned char)t;
t=(base[k+1]-trans[1])/scale[1];
if (t<0.0f)
t=0.0f;
if (t>255.0f)
t=255.0f;
cbase[k+1]=(unsigned char)t;
t=(base[k+2]-trans[2])/scale[2];
if (t<0.0f)
t=0.0f;
if (t>255.0f)
t=255.0f;
cbase[k+2]=(unsigned char)t;
}
for (l=0;l<MatHeight;l++)
{
mx=0.0;
for (k=0;k<MatWidth;k++)
{
if (fabs(best[l*MatWidth+k])>mx)
mx=(float)fabs(best[l*MatWidth+k]);
}
if (mx>1E-8)
{
mx/=127.0f;
coffset[l]=1E30f;
cscale[l]=-1E30f;
for (j=0;j<nFrames;j++)
{
bestcomp[j*MatHeight+l]*=mx;
if (bestcomp[j*MatHeight+l]>cscale[l])
cscale[l]=bestcomp[j*MatHeight+l];
if (bestcomp[j*MatHeight+l]<coffset[l])
coffset[l]=bestcomp[j*MatHeight+l];
}
cscale[l]-=coffset[l];
if (cscale[l]>1E-10)
{
for (j=0;j<nFrames;j++)
{
tmp=254.0f*(bestcomp[j*MatHeight+l]-coffset[l])/cscale[l]-127.0f;
if (tmp>127.0f)
tmp=127.0f;
if (tmp<-127.0f)
tmp=-127.0f;
ccomp[j*MatHeight+l]=(char)floor(tmp+0.5);
}
coffset[l]+=cscale[l]*127.0f/254.0f;
cscale[l]/=254.0f;
}
else
{
cscale[l]=1.0f;
coffset[l]=0.0f;
for (j=0;j<nFrames;j++)
ccomp[j*MatHeight+l]=0;
}
mx=1.0f/mx;
for (k=0;k<MatWidth;k++)
{
tmp=best[l*MatWidth+k]*mx;
if (tmp>127.0f)
tmp=127.0f;
if (tmp<-127.0f)
tmp=-127.0f;
mat[k*MatHeight+l]=(char)floor(tmp+0.5);
}
}
else
{
cscale[l]=1.0f;
coffset[l]=0.0f;
for (j=0;j<nFrames;j++)
ccomp[j*MatHeight+l]=0;
for (k=0;k<MatWidth;k++)
mat[k*MatHeight+l]=0;
}
}
bmin[0]=1E30f;
bmin[1]=1E30f;
bmin[2]=1E30f;
bmax[0]=-1E30f;
bmax[1]=-1E30f;
bmax[2]=-1E30f;
numave=0;
avedev=0.0;
maxdev=0.0;
ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressToBytes");
for (j=0;j<nFrames;j++)
{
for (k=0;k<MatWidth;k++)
{
ans[k]=0.0;
for (l=0;l<CFrameSize;l++)
ans[k]+=(float)(mat[l+k*MatHeight])*((float)(ccomp[j*CFrameSize+l])*cscale[l]+coffset[l]);
ans[k]+=(float)(cbase[k])*scale[k%3]+trans[k%3];
tmp=(float)fabs(ans[k]-frames[j*MatWidth+k]-base[k]);
if (tmp>maxdev)
maxdev=tmp;
avedev+=tmp;
numave++;
if (bmin[k%3]>ans[k])
bmin[k%3]=ans[k];
if (bmax[k%3]<ans[k])
bmax[k%3]=ans[k];
}
}
avedev/=(float)numave;
printf("%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev);
free(ans);
}
void AnimCompressGetMatrix(float *mat)
{
int k,l;
for (k=0;k<MatWidth;k++)
for (l=0;l<MatHeight;l++)
mat[k*MatHeight+l]=best[l*MatWidth+k];
}
void AnimCompressGetFrames(float *mat)
{
memcpy(mat,bestcomp,CFrameSize*nFrames*sizeof(float));
}
void AnimCompressGetBase(int i,float *x,float *y,float *z)
{
*x=base[i*3];
*y=base[i*3+1];
*z=base[i*3+2];
}
void AnimCompressEnd()
{
free(matrix);
free(best);
free(delta);
free(comp);
free(tcomp);
free(bestcomp);
free(base);
free(frames);
}

View File

@@ -0,0 +1,43 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined(ANIMCOMP_INC)
#define ANIMCOMP_INC
#ifdef __cplusplus
extern "C"
{
#endif
void AnimCompressInit(int nFrames,int nVerts,int CompressedFrameSize);
void AnimSetFrame(int frame,int index,float x,float y,float z);
void AnimCompressDoit();
void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax);
void AnimCompressGetMatrix(float *mat);
void AnimCompressGetFrames(float *mat);
void AnimCompressGetBase(int i,float *x,float *y,float *z);
void AnimCompressEnd();
void DOsvdPlane(float *pnts,int npnts,float *n,float *base);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,184 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},

View File

@@ -0,0 +1,372 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
byte *byteimage, *lbmpalette;
int byteimagewidth, byteimageheight;
qboolean TrueColorImage;
int longimagewidth, longimageheight;
char book_prefix[1024];
byte buffer[640 * 480];
unsigned long bufferl[640 * 480];
miptex_t *CreateBook8(byte *buffer, int w, int h, byte *palette, int *FinalSize)
{
miptex_t *mp;
int i, j;
byte *pos;
int size;
size = sizeof(*mp) + (w * h);
mp = (miptex_t *)SafeMalloc(size, "CreateBook8");
memset(mp, 0, size);
mp->version = MIP_VERSION;
for(i=j=0;i<256;i++,j+=3)
{
mp->palette[i].r = palette[j];
mp->palette[i].g = palette[j+1];
mp->palette[i].b = palette[j+2];
}
pos = (byte *)(mp + 1);
mp->width[0] = w;
mp->height[0] = h;
mp->offsets[0] = sizeof(*mp);
memcpy(pos, buffer, w * h);
*FinalSize = size;
return(mp);
}
miptex32_t *CreateBook32(long *buffer, int w, int h, int *FinalSize)
{
miptex32_t *mp;
byte *pos;
int size;
size = sizeof(*mp) + (w * h * 4);
mp = (miptex32_t *)SafeMalloc(size, "CreateBook32");
memset(mp, 0, size);
mp->version = MIP32_VERSION;
pos = (byte *)(mp + 1);
mp->width[0] = w;
mp->height[0] = h;
mp->offsets[0] = sizeof(*mp);
memcpy(pos, buffer, w * h * 4);
*FinalSize = size;
return(mp);
}
// Routines to chop a random sized image into gl texture friendly chunks
typedef struct rect_s
{
int x, y;
int w, h;
char name[4];
} rect_t;
int GetCoords(int x, int store[MAX_MD2SKINS])
{
int index, start, delta;
index = 0;
start = 0;
delta = 256;
store[index++] = start;
while(x)
{
if(x >= delta)
{
start += delta;
store[index++] = start;
x -= delta;
}
else
{
delta >>= 1;
}
}
return(index);
}
int ChopImage(int w, int h, rect_t coords[MAX_MD2SKINS])
{
int xs[MAX_MD2SKINS], ys[MAX_MD2SKINS];
int xcount, ycount, x, y, index;
index = 0;
xcount = GetCoords(w, xs) - 1;
ycount = GetCoords(h, ys) - 1;
for(y = 0; y < ycount; y++)
{
for(x = 0; x < xcount; x++, index++)
{
coords[index].x = xs[x];
coords[index].y = ys[y];
coords[index].w = xs[x + 1] - xs[x];
coords[index].h = ys[y + 1] - ys[y];
coords[index].name[0] = x + '0';
coords[index].name[1] = y + '0';
coords[index].name[2] = 0;
}
}
return(index);
}
/*
===============
Cmd_Pic
===============
*/
void Cmd_Book()
{
int xl,yl,xh,yh,w,h;
byte *dest, *source;
int flags, value, contents;
char lumpname[64];
char filename[1024];
unsigned long *destl, *sourcel;
int linedelta, x, y;
int size;
miptex_t *qtex;
miptex32_t *qtex32;
float scale_x, scale_y;
int numrects, i;
rect_t coords[MAX_MD2SKINS];
bookframe_t bframes[MAX_MD2SKINS];
bookframe_t *bf;
book_t book;
GetScriptToken (false);
strcpy (lumpname, token);
GetScriptToken (false);
xl = atoi (token);
GetScriptToken (false);
yl = atoi (token);
GetScriptToken (false);
w = atoi (token);
GetScriptToken (false);
h = atoi (token);
total_x += w;
total_y += h;
total_textures++;
if ( (w & 7) || (h & 7) )
Error ("line %i: miptex sizes must be multiples of 8", scriptline);
flags = 0;
contents = 0;
value = 0;
scale_x = scale_y = 0.5;
if (g_release)
return;
if(TrueColorImage)
{
xh = xl + w;
yh = yl + h;
if (xl >= longimagewidth || xh > longimagewidth ||
yl >= longimageheight || yh > longimageheight)
{
Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
}
sourcel = (unsigned long *) longimage + (yl * longimagewidth) + xl;
destl = (unsigned long *) longimage;
linedelta = (longimagewidth - w);
for(y = yl; y < yh; y++)
{
for(x = xl; x < xh; x++)
{
*destl++ = *sourcel++; // RGBA
}
sourcel += linedelta;
}
// Get rectangles to chop into
numrects = ChopImage(w, h, coords);
bf = bframes;
for(i = 0; i < numrects; i++, bf++)
{
// Copy section of image to buffer
sourcel = (unsigned long *) longimage + (coords[i].y * w) + coords[i].x;
destl = bufferl;
linedelta = w - coords[i].w;
for(y = 0; y < coords[i].h; y++)
{
for(x = 0; x < coords[i].w; x++)
{
*destl++ = *sourcel++;
}
sourcel += linedelta;
}
qtex32 = CreateBook32(bufferl, coords[i].w, coords[i].h, &size);
qtex32->flags = flags;
qtex32->contents = contents;
qtex32->value = value;
qtex32->scale_x = scale_x;
qtex32->scale_y = scale_y;
sprintf (filename, "%sbook/%s/%s_%s.m32", gamedir, book_prefix, lumpname, coords[i].name);
sprintf (qtex32->name, "%s/%s_%s.m32", book_prefix, lumpname, coords[i].name);
strcpy(bf->name, qtex32->name);
bf->x = coords[i].x;
bf->y = coords[i].y;
bf->w = coords[i].w;
bf->h = coords[i].h;
//
// write it out
//
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)qtex32, size);
free (qtex32);
}
}
else
{
xh = xl + w;
yh = yl + h;
if (xl >= byteimagewidth || xh > byteimagewidth ||
yl >= byteimageheight || yh > byteimageheight)
{
Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
}
// Copy image to top left
source = byteimage + yl*byteimagewidth + xl;
dest = byteimage;
linedelta = byteimagewidth - w;
for(y = yl; y < yh; y++)
{
for(x = xl; x < xh; x++)
{
*dest++ = *source++;
}
source += linedelta;
}
// Get rectangles to chop into
numrects = ChopImage(w, h, coords);
bf = bframes;
for(i = 0; i < numrects; i++, bf++)
{
// Copy section of image to buffer
source = byteimage + (coords[i].y * w) + coords[i].x;
dest = buffer;
linedelta = w - coords[i].w;
for(y = 0; y < coords[i].h; y++)
{
for(x = 0; x < coords[i].w; x++)
{
*dest++ = *source++;
}
source += linedelta;
}
qtex = CreateBook8(buffer, coords[i].w, coords[i].h, lbmpalette, &size);
qtex->flags = flags;
qtex->contents = contents;
qtex->value = value;
sprintf (filename, "%sbook/%s/%s_%s.m8", gamedir, book_prefix, lumpname, coords[i].name);
sprintf (qtex->name, "%s/%s_%s.m8", book_prefix, lumpname, coords[i].name);
strcpy(bf->name, qtex->name);
bf->x = coords[i].x;
bf->y = coords[i].y;
bf->w = coords[i].w;
bf->h = coords[i].h;
//
// write it out
//
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)qtex, size);
free (qtex);
}
}
// Set up descriptor
size = sizeof(bookframe_t) * numrects;
book.bheader.ident = IDBOOKHEADER;
book.bheader.version = BOOK_VERSION;
book.bheader.num_segments = numrects;
book.bheader.total_w = w;
book.bheader.total_h = h;
memcpy(book.bframes, bframes, size);
// Save out segment descriptor
sprintf (filename, "%sBook/%s/%s.bk", gamedir, book_prefix, lumpname);
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)&book, size + sizeof(bookheader_t));
}
/*
===============
Cmd_picdir
===============
*/
void Cmd_Bookdir (void)
{
char filename[1024];
GetScriptToken (false);
strcpy (book_prefix, token);
// create the directory if needed
sprintf (filename, "%sBook", gamedir);
Q_mkdir (filename);
sprintf (filename, "%sBook/%s", gamedir, book_prefix);
Q_mkdir (filename);
}
// end

View File

@@ -0,0 +1,793 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "bspfile.h"
#include "scriplib.h"
void GetLeafNums (void);
//=============================================================================
int nummodels;
dmodel_t dmodels[MAX_MAP_MODELS];
int visdatasize;
byte dvisdata[MAX_MAP_VISIBILITY];
dvis_t *dvis = (dvis_t *)dvisdata;
int lightdatasize;
byte dlightdata[MAX_MAP_LIGHTING];
int entdatasize;
char dentdata[MAX_MAP_ENTSTRING];
int numleafs;
dleaf_t dleafs[MAX_MAP_LEAFS];
int numplanes;
dplane_t dplanes[MAX_MAP_PLANES];
int numvertexes;
dvertex_t dvertexes[MAX_MAP_VERTS];
int numnodes;
dnode_t dnodes[MAX_MAP_NODES];
int numtexinfo;
texinfo_t texinfo[MAX_MAP_TEXINFO];
int numfaces;
dface_t dfaces[MAX_MAP_FACES];
int numedges;
dedge_t dedges[MAX_MAP_EDGES];
int numleaffaces;
unsigned short dleaffaces[MAX_MAP_LEAFFACES];
int numleafbrushes;
unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
int numsurfedges;
int dsurfedges[MAX_MAP_SURFEDGES];
int numbrushes;
dbrush_t dbrushes[MAX_MAP_BRUSHES];
int numbrushsides;
dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
int numareas;
darea_t dareas[MAX_MAP_AREAS];
int numareaportals;
dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
byte dpop[256];
/*
===============
CompressVis
===============
*/
int CompressVis (byte *vis, byte *dest)
{
int j;
int rep;
int visrow;
byte *dest_p;
dest_p = dest;
// visrow = (r_numvisleafs + 7)>>3;
visrow = (dvis->numclusters + 7)>>3;
for (j=0 ; j<visrow ; j++)
{
*dest_p++ = vis[j];
if (vis[j])
continue;
rep = 1;
for ( j++; j<visrow ; j++)
if (vis[j] || rep == 255)
break;
else
rep++;
*dest_p++ = rep;
j--;
}
return dest_p - dest;
}
/*
===================
DecompressVis
===================
*/
void DecompressVis (byte *in, byte *decompressed)
{
int c;
byte *out;
int row;
// row = (r_numvisleafs+7)>>3;
row = (dvis->numclusters+7)>>3;
out = decompressed;
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
if (!c)
Error ("DecompressVis: 0 repeat");
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
}
//=============================================================================
/*
=============
SwapBSPFile
Byte swaps all data in a bsp file.
=============
*/
void SwapBSPFile (qboolean todisk)
{
int i, j;
dmodel_t *d;
// models
for (i=0 ; i<nummodels ; i++)
{
d = &dmodels[i];
d->firstface = LittleLong (d->firstface);
d->numfaces = LittleLong (d->numfaces);
d->headnode = LittleLong (d->headnode);
for (j=0 ; j<3 ; j++)
{
d->mins[j] = LittleFloat(d->mins[j]);
d->maxs[j] = LittleFloat(d->maxs[j]);
d->origin[j] = LittleFloat(d->origin[j]);
}
}
//
// vertexes
//
for (i=0 ; i<numvertexes ; i++)
{
for (j=0 ; j<3 ; j++)
dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
}
//
// planes
//
for (i=0 ; i<numplanes ; i++)
{
for (j=0 ; j<3 ; j++)
dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
dplanes[i].dist = LittleFloat (dplanes[i].dist);
dplanes[i].type = LittleLong (dplanes[i].type);
}
//
// texinfos
//
for (i=0 ; i<numtexinfo ; i++)
{
for (j=0 ; j<8 ; j++)
texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
texinfo[i].flags = LittleLong (texinfo[i].flags);
texinfo[i].value = LittleLong (texinfo[i].value);
texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
}
//
// faces
//
for (i=0 ; i<numfaces ; i++)
{
dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
dfaces[i].planenum = LittleShort (dfaces[i].planenum);
dfaces[i].side = LittleShort (dfaces[i].side);
dfaces[i].lighting.c = LittleLong (dfaces[i].lighting.c);
dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
dfaces[i].numedges = LittleShort (dfaces[i].numedges);
}
//
// nodes
//
for (i=0 ; i<numnodes ; i++)
{
dnodes[i].planenum = LittleLong (dnodes[i].planenum);
for (j=0 ; j<3 ; j++)
{
dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
}
dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
dnodes[i].firstface = LittleShort (dnodes[i].firstface);
dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
}
//
// leafs
//
for (i=0 ; i<numleafs ; i++)
{
dleafs[i].contents = LittleLong (dleafs[i].contents);
dleafs[i].cluster = LittleShort (dleafs[i].cluster);
dleafs[i].area = LittleShort (dleafs[i].area);
for (j=0 ; j<3 ; j++)
{
dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
}
dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
}
//
// leaffaces
//
for (i=0 ; i<numleaffaces ; i++)
dleaffaces[i] = LittleShort (dleaffaces[i]);
//
// leafbrushes
//
for (i=0 ; i<numleafbrushes ; i++)
dleafbrushes[i] = LittleShort (dleafbrushes[i]);
//
// surfedges
//
for (i=0 ; i<numsurfedges ; i++)
dsurfedges[i] = LittleLong (dsurfedges[i]);
//
// edges
//
for (i=0 ; i<numedges ; i++)
{
dedges[i].v[0] = LittleShort (dedges[i].v[0]);
dedges[i].v[1] = LittleShort (dedges[i].v[1]);
}
//
// brushes
//
for (i=0 ; i<numbrushes ; i++)
{
dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
dbrushes[i].contents = LittleLong (dbrushes[i].contents);
}
//
// areas
//
for (i=0 ; i<numareas ; i++)
{
dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
}
//
// areasportals
//
for (i=0 ; i<numareaportals ; i++)
{
dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
}
//
// brushsides
//
for (i=0 ; i<numbrushsides ; i++)
{
dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
}
//
// visibility
//
if (todisk)
j = dvis->numclusters;
else
j = LittleLong(dvis->numclusters);
dvis->numclusters = LittleLong (dvis->numclusters);
for (i=0 ; i<j ; i++)
{
dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
}
}
dheader_t *header;
int CopyLump (int lump, void *dest, int size)
{
int length, ofs;
length = header->lumps[lump].filelen;
ofs = header->lumps[lump].fileofs;
if (length % size)
Error ("LoadBSPFile: odd lump size");
memcpy (dest, (byte *)header + ofs, length);
return length / size;
}
/*
=============
LoadBSPFile
=============
*/
void LoadBSPFile (char *filename)
{
int i;
//
// load the file header
//
LoadFile (filename, (void **)&header);
// swap the header
for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
if (header->ident != IDBSPHEADER)
Error ("%s is not a IBSP file", filename);
if (header->version != BSPVERSION)
Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
CopyLump (LUMP_POP, dpop, 1);
free (header); // everything has been copied out
//
// swap everything
//
SwapBSPFile (false);
}
/*
=============
LoadBSPFileTexinfo
Only loads the texinfo lump, so qdata can scan for textures
=============
*/
void LoadBSPFileTexinfo (char *filename)
{
int i;
FILE *f;
int length, ofs;
header = malloc(sizeof(dheader_t));
f = fopen (filename, "rb");
fread (header, sizeof(dheader_t), 1, f);
// swap the header
for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
if (header->ident != IDBSPHEADER)
Error ("%s is not a IBSP file", filename);
if (header->version != BSPVERSION)
Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
length = header->lumps[LUMP_TEXINFO].filelen;
ofs = header->lumps[LUMP_TEXINFO].fileofs;
fseek (f, ofs, SEEK_SET);
fread (texinfo, length, 1, f);
fclose (f);
numtexinfo = length / sizeof(texinfo_t);
free (header); // everything has been copied out
SwapBSPFile (false);
}
//============================================================================
FILE *wadfile;
dheader_t outheader;
void AddLump (int lumpnum, void *data, int len)
{
lump_t *lump;
lump = &header->lumps[lumpnum];
lump->fileofs = LittleLong( ftell(wadfile) );
lump->filelen = LittleLong(len);
SafeWrite (wadfile, data, (len+3)&~3);
}
/*
=============
WriteBSPFile
Swaps the bsp file in place, so it should not be referenced again
=============
*/
void WriteBSPFile (char *filename)
{
header = &outheader;
memset (header, 0, sizeof(dheader_t));
SwapBSPFile (true);
header->ident = LittleLong (IDBSPHEADER);
header->version = LittleLong (BSPVERSION);
wadfile = SafeOpenWrite (filename);
SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later
AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
AddLump (LUMP_ENTITIES, dentdata, entdatasize);
AddLump (LUMP_POP, dpop, sizeof(dpop));
fseek (wadfile, 0, SEEK_SET);
SafeWrite (wadfile, header, sizeof(dheader_t));
fclose (wadfile);
}
//============================================================================
/*
=============
PrintBSPFileSizes
Dumps info about current file
=============
*/
void PrintBSPFileSizes (void)
{
if (!num_entities)
ParseEntities ();
printf ("%5i models %7i\n"
,nummodels, (int)(nummodels*sizeof(dmodel_t)));
printf ("%5i brushes %7i\n"
,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
printf ("%5i brushsides %7i\n"
,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
printf ("%5i planes %7i\n"
,numplanes, (int)(numplanes*sizeof(dplane_t)));
printf ("%5i texinfo %7i\n"
,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
printf ("%5i entdata %7i\n", num_entities, entdatasize);
printf ("\n");
printf ("%5i vertexes %7i\n"
,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
printf ("%5i nodes %7i\n"
,numnodes, (int)(numnodes*sizeof(dnode_t)));
printf ("%5i faces %7i\n"
,numfaces, (int)(numfaces*sizeof(dface_t)));
printf ("%5i leafs %7i\n"
,numleafs, (int)(numleafs*sizeof(dleaf_t)));
printf ("%5i leaffaces %7i\n"
,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
printf ("%5i leafbrushes %7i\n"
,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
printf ("%5i surfedges %7i\n"
,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
printf ("%5i edges %7i\n"
,numedges, (int)(numedges*sizeof(dedge_t)));
printf (" lightdata %7i\n", lightdatasize);
printf (" visdata %7i\n", visdatasize);
}
//============================================
int num_entities;
entity_t entities[MAX_MAP_ENTITIES];
void StripTrailing (char *e)
{
char *s;
s = e + strlen(e)-1;
while (s >= e && *s <= 32)
{
*s = 0;
s--;
}
}
/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair (void)
{
epair_t *e;
e = malloc (sizeof(epair_t));
memset (e, 0, sizeof(epair_t));
if (strlen(token) >= MAX_KEY-1)
Error ("ParseEpar: token too long");
e->key = copystring(token);
GetScriptToken (false);
if (strlen(token) >= MAX_VALUE-1)
Error ("ParseEpar: token too long");
e->value = copystring(token);
// strip trailing spaces
StripTrailing (e->key);
StripTrailing (e->value);
return e;
}
/*
================
ParseEntity
================
*/
qboolean ParseEntity (void)
{
epair_t *e;
entity_t *mapent;
if (!GetScriptToken (true))
return false;
if (strcmp (token, "{") )
Error ("ParseEntity: { not found");
if (num_entities == MAX_MAP_ENTITIES)
Error ("num_entities == MAX_MAP_ENTITIES");
mapent = &entities[num_entities];
num_entities++;
do
{
if (!GetScriptToken (true))
Error ("ParseEntity: EOF without closing brace");
if (!strcmp (token, "}") )
break;
e = ParseEpair ();
e->next = mapent->epairs;
mapent->epairs = e;
} while (1);
return true;
}
/*
================
ParseEntities
Parses the dentdata string into entities
================
*/
void ParseEntities (void)
{
num_entities = 0;
ParseFromMemory (dentdata, entdatasize);
while (ParseEntity ())
{
}
}
/*
================
UnparseEntities
Generates the dentdata string from all the entities
================
*/
void UnparseEntities (void)
{
char *buf, *end;
epair_t *ep;
char line[2048];
int i;
char key[1024], value[1024];
buf = dentdata;
end = buf;
*end = 0;
for (i=0 ; i<num_entities ; i++)
{
ep = entities[i].epairs;
if (!ep)
continue; // ent got removed
strcat (end,"{\n");
end += 2;
for (ep = entities[i].epairs ; ep ; ep=ep->next)
{
strcpy (key, ep->key);
StripTrailing (key);
strcpy (value, ep->value);
StripTrailing (value);
sprintf (line, "\"%s\" \"%s\"\n", key, value);
strcat (end, line);
end += strlen(line);
}
strcat (end,"}\n");
end += 2;
if (end > buf + MAX_MAP_ENTSTRING)
Error ("Entity text too long");
}
entdatasize = end - buf + 1;
}
void PrintEntity (entity_t *ent)
{
epair_t *ep;
printf ("------- entity %p -------\n", ent);
for (ep=ent->epairs ; ep ; ep=ep->next)
{
printf ("%s = %s\n", ep->key, ep->value);
}
}
void SetKeyValue (entity_t *ent, char *key, char *value)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
{
free (ep->value);
ep->value = copystring(value);
return;
}
ep = malloc (sizeof(*ep));
if (!ep)
Error("SetKeyValue MALLOC failed! Could not allocate %s bytes.", sizeof(*ep));
ep->next = ent->epairs;
ent->epairs = ep;
ep->key = copystring(key);
ep->value = copystring(value);
}
char *ValueForKey (entity_t *ent, char *key)
{
epair_t *ep;
for (ep=ent->epairs ; ep ; ep=ep->next)
if (!strcmp (ep->key, key) )
return ep->value;
return "";
}
vec_t FloatForKey (entity_t *ent, char *key)
{
char *k;
k = ValueForKey (ent, key);
return atof(k);
}
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
{
char *k;
double v1, v2, v3;
k = ValueForKey (ent, key);
// scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
vec[0] = v1;
vec[1] = v2;
vec[2] = v3;
}

View File

@@ -0,0 +1,133 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QBSP3_H
#define _QBSP3_H
#include "qfiles.h"
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int visdatasize;
extern byte dvisdata[MAX_MAP_VISIBILITY];
extern dvis_t *dvis;
extern int lightdatasize;
extern byte dlightdata[MAX_MAP_LIGHTING];
extern int entdatasize;
extern char dentdata[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t dleafs[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t dvertexes[MAX_MAP_VERTS];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern int numtexinfo;
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
extern int numfaces;
extern dface_t dfaces[MAX_MAP_FACES];
extern int numedges;
extern dedge_t dedges[MAX_MAP_EDGES];
extern int numleaffaces;
extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
extern int numleafbrushes;
extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
extern int numsurfedges;
extern int dsurfedges[MAX_MAP_SURFEDGES];
extern int numareas;
extern darea_t dareas[MAX_MAP_AREAS];
extern int numareaportals;
extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
extern int numbrushes;
extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
extern int numbrushsides;
extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
extern byte dpop[256];
void DecompressVis (byte *in, byte *decompressed);
int CompressVis (byte *vis, byte *dest);
void LoadBSPFile (char *filename);
void LoadBSPFileTexinfo (char *filename); // just for qdata
void WriteBSPFile (char *filename);
void PrintBSPFileSizes (void);
//===============
typedef struct epair_s
{
struct epair_s *next;
char *key;
char *value;
} epair_t;
typedef struct
{
vec3_t origin;
int firstbrush;
int numbrushes;
epair_t *epairs;
// only valid for func_areaportals
int areaportalnum;
int portalareas[2];
} entity_t;
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void ParseEntities (void);
void UnparseEntities (void);
void SetKeyValue (entity_t *ent, char *key, char *value);
char *ValueForKey (entity_t *ent, char *key);
// will return "" if not present
vec_t FloatForKey (entity_t *ent, char *key);
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
epair_t *ParseEpair (void);
void PrintEntity (entity_t *ent);
#endif //_QBSP3_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// cmdlib.h
#ifndef __CMDLIB__
#define __CMDLIB__
#ifdef _WIN32
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#pragma warning(disable : 4018) // signed/unsigned mismatch
#pragma warning(disable : 4305) // truncate from double to float
#pragma check_stack(off)
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#ifdef _WIN32
#pragma intrinsic( memset, memcpy )
#endif
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
//typedef enum {false, true} qboolean;
//typedef unsigned char byte;
#include "q_typedef.h"
#endif
#define MAX_OS_PATH 1024
#define MEM_BLOCKSIZE 4096
/*
extern qboolean verbose;
#define SYS_VRB 0 // verbose support (on/off)
#define SYS_STD 1 // standard print level
#define SYS_WRN 2 // warnings
#define SYS_ERR 3 // error
*/
// the dec offsetof macro doesnt work very well...
#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
#define SAFE_MALLOC
#ifdef SAFE_MALLOC
void *safe_malloc( size_t size );
void *safe_malloc_info( size_t size, char* info );
#else
#define safe_malloc(a) malloc(a)
#endif /* SAFE_MALLOC */
// set these before calling CheckParm
extern int myargc;
extern char **myargv;
char *strlower (char *in);
int Q_strncasecmp( const char *s1, const char *s2, int n );
int Q_stricmp( const char *s1, const char *s2 );
int Q_strcasecmp( const char *s1, const char *s2 );
void Q_getwd( char *out );
int Q_filelength (FILE *f);
int FileTime( const char *path );
void Q_mkdir( const char *path );
extern char qdir[1024];
extern char gamedir[1024];
extern char writedir[1024];
extern char *moddirparam;
void SetQdirFromPath( const char *path);
char *ExpandArg( const char *path ); // from cmd line
char *ExpandPath( const char *path ); // from scripts
char *ExpandGamePath (const char *path);
char *ExpandPathAndArchive( const char *path );
void ExpandWildcards( int *argc, char ***argv );
double I_FloatTime( void );
int CheckParm( const char *check );
void *SafeMalloc(size_t n, char *desc);
FILE *SafeOpenWrite( const char *filename );
FILE *SafeOpenRead( const char *filename );
void SafeRead (FILE *f, void *buffer, int count);
void SafeWrite (FILE *f, const void *buffer, int count);
int LoadFile( const char *filename, void **bufferptr );
int LoadFileBlock( const char *filename, void **bufferptr );
int TryLoadFile( const char *filename, void **bufferptr );
void SaveFile( const char *filename, const void *buffer, int count );
qboolean FileExists( const char *filename );
void DefaultExtension( char *path, const char *extension );
void DefaultPath( char *path, const char *basepath );
void StripFilename( char *path );
void StripExtension( char *path );
void ExtractFilePath( const char *path, char *dest );
void ExtractFileBase( const char *path, char *dest );
void ExtractFileExtension( const char *path, char *dest );
int ParseNum (const char *str);
/*
void Sys_Printf (const char *text, ...);
void Sys_FPrintf (int flag, const char *text, ...);
void Error( const char *error, ... );
*/
short BigShort (short l);
short LittleShort (short l);
int BigLong (int l);
int LittleLong (int l);
float BigFloat (float l);
float LittleFloat (float l);
char *COM_Parse (char *data);
extern char com_token[1024];
extern qboolean com_eof;
char *copystring(const char *s);
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
void CreatePath( const char *path );
void QCopyFile( const char *from, const char *to );
extern qboolean archive;
extern char archivedir[1024];
extern qboolean g_dokeypress;
// sleep for the given amount of milliseconds
void Sys_Sleep(int n);
// for compression routines
typedef struct
{
byte *data;
int count;
} cblock_t;
#endif

View File

@@ -0,0 +1,35 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _THREADS_H
#define _THREADS_H
extern int numthreads;
void ThreadSetDefault (void);
int GetThreadWork (void);
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
void ThreadLock (void);
void ThreadUnlock (void);
#endif //_THREADS_H

View File

@@ -0,0 +1,367 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//-----------------------------------------------------------------------------
//
//
// DESCRIPTION:
// deal with in/out tasks, for either stdin/stdout or network/XML stream
//
#include "cmdlib.h"
#include "mathlib.h"
#include "polylib.h"
#include "inout.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
#include <direct.h>
#include <windows.h>
#endif
// network broadcasting
#include "l_net/l_net.h"
#include "libxml/tree.h"
#ifdef WIN32
HWND hwndOut = NULL;
qboolean lookedForServer = false;
UINT wm_BroadcastCommand = -1;
#endif
socket_t *brdcst_socket;
netmessage_t msg;
qboolean verbose = false;
// our main document
// is streamed through the network to Radiant
// possibly written to disk at the end of the run
//++timo FIXME: need to be global, required when creating nodes?
xmlDocPtr doc;
xmlNodePtr tree;
// some useful stuff
xmlNodePtr xml_NodeForVec( vec3_t v )
{
xmlNodePtr ret;
char buf[1024];
sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
ret = xmlNewNode (NULL, "point");
xmlNodeSetContent (ret, buf);
return ret;
}
// send a node down the stream, add it to the document
void xml_SendNode (xmlNodePtr node)
{
xmlBufferPtr xml_buf;
char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
// this index loops through the node buffer
int pos = 0;
int size;
xmlAddChild( doc->children, node );
if (brdcst_socket)
{
xml_buf = xmlBufferCreate();
xmlNodeDump( xml_buf, doc, node, 0, 0 );
// the XML node might be too big to fit in a single network message
// l_net library defines an upper limit of MAX_NETMESSAGE
// there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
// if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
while (pos < xml_buf->use)
{
// what size are we gonna send now?
(xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
//++timo just a debug thing
if (size == MAX_NETMESSAGE - 10)
Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
memcpy( xmlbuf, xml_buf->content+pos, size);
xmlbuf[size] = '\0';
NMSG_Clear( &msg );
NMSG_WriteString (&msg, xmlbuf );
Net_Send(brdcst_socket, &msg );
// now that the thing is sent prepare to loop again
pos += size;
}
#if 0
// NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
// we will need to split into chunks
// (we could also go lower level, in the end it's using send and receiv which are not size limited)
//++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
// there's some tweaking to do in l_net for that .. so let's give us a margin for now
//++timo we need to handle the case of a buffer too big to fit in a single message
// try without checks for now
if (xml_buf->use > MAX_NETMESSAGE-10 )
{
// if we send that we are probably gonna break the stream at the other end..
// and Error will call right there
//Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
Sys_FPrintf (SYS_NOXML, xml_buf->content);
}
size = xml_buf->use;
memcpy( xmlbuf, xml_buf->content, size );
xmlbuf[size] = '\0';
NMSG_Clear( &msg );
NMSG_WriteString (&msg, xmlbuf );
Net_Send(brdcst_socket, &msg );
#endif
xmlBufferFree( xml_buf );
}
}
void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
{
xmlNodePtr node, select;
char buf[1024];
char level[2];
// now build a proper "select" XML node
sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
node = xmlNewNode (NULL, "select");
xmlNodeSetContent (node, buf);
level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN) ;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'select' information
sprintf (buf, "%i %i", entitynum, brushnum);
select = xmlNewNode (NULL, "brush");
xmlNodeSetContent (select, buf);
xmlAddChild (node, select);
xml_SendNode (node);
sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
if (bError)
Error(buf);
else
Sys_FPrintf (SYS_NOXML, "%s\n", buf);
}
void xml_Point (char *msg, vec3_t pt)
{
xmlNodePtr node, point;
char buf[1024];
char level[2];
node = xmlNewNode (NULL, "pointmsg");
xmlNodeSetContent (node, msg);
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'point' node
sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
point = xmlNewNode (NULL, "point");
xmlNodeSetContent (point, buf);
xmlAddChild (node, point);
xml_SendNode (node);
sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
Error (buf);
}
#define WINDING_BUFSIZE 2048
void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
{
xmlNodePtr node, winding;
char buf[WINDING_BUFSIZE];
char smlbuf[128];
char level[2];
int i;
node = xmlNewNode (NULL, "windingmsg");
xmlNodeSetContent (node, msg);
level[0] = (int)'0' + SYS_ERR;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level);
// a 'winding' node
sprintf( buf, "%i ", numpoints);
for(i = 0; i < numpoints; i++)
{
sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
// don't overflow
if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
break;
strcat( buf, smlbuf);
}
winding = xmlNewNode (NULL, "winding");
xmlNodeSetContent (winding, buf);
xmlAddChild (node, winding);
xml_SendNode (node);
if(die)
Error (msg);
else
{
Sys_Printf(msg);
Sys_Printf("\n");
}
}
// in include
#include "stream_version.h"
void Broadcast_Setup( const char *dest )
{
address_t address;
char sMsg[1024];
Net_Setup();
Net_StringToAddress((char *)dest, &address);
brdcst_socket = Net_Connect(&address, 0);
if (brdcst_socket)
{
// send in a header
sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
NMSG_Clear( &msg );
NMSG_WriteString(&msg, sMsg );
Net_Send(brdcst_socket, &msg );
}
}
void Broadcast_Shutdown()
{
if (brdcst_socket)
{
Sys_Printf("Disconnecting\n");
Net_Disconnect(brdcst_socket);
brdcst_socket = NULL;
}
}
// all output ends up through here
void FPrintf (int flag, char *buf)
{
xmlNodePtr node;
static qboolean bGotXML = false;
char level[2];
printf(buf);
// the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
if (flag == SYS_NOXML)
return;
// ouput an XML file of the run
// use the DOM interface to build a tree
/*
<message level='flag'>
message string
.. various nodes to describe corresponding geometry ..
</message>
*/
if (!bGotXML)
{
// initialize
doc = xmlNewDoc("1.0");
doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
bGotXML = true;
}
node = xmlNewNode (NULL, "message");
xmlNodeSetContent (node, buf);
level[0] = (int)'0' + flag;
level[1] = 0;
xmlSetProp (node, "level", (char *)&level );
xml_SendNode (node);
}
#ifdef DBG_XML
void DumpXML()
{
xmlSaveFile( "XMLDump.xml", doc );
}
#endif
void Sys_FPrintf (int flag, const char *format, ...)
{
char out_buffer[4096];
va_list argptr;
if ((flag == SYS_VRB) && (verbose == false))
return;
va_start (argptr, format);
vsprintf (out_buffer, format, argptr);
va_end (argptr);
FPrintf (flag, out_buffer);
}
void Sys_Printf (const char *format, ...)
{
char out_buffer[4096];
va_list argptr;
va_start (argptr, format);
vsprintf (out_buffer, format, argptr);
va_end (argptr);
FPrintf (SYS_STD, out_buffer);
}
/*
=================
Error
For abnormal program terminations
=================
*/
void Error( const char *error, ...)
{
char out_buffer[4096];
char tmp[4096];
va_list argptr;
va_start (argptr,error);
vsprintf (tmp, error, argptr);
va_end (argptr);
sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
FPrintf( SYS_ERR, out_buffer );
#ifdef DBG_XML
DumpXML();
#endif
//++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
// a clean solution is to send a sync request node in the stream and wait for an answer before exiting
Sys_Sleep( 1000 );
Broadcast_Shutdown();
exit (1);
}

View File

@@ -0,0 +1,63 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __INOUT__
#define __INOUT__
// inout is the only stuff relying on xml, include the headers there
#include "libxml/tree.h"
#include "mathlib.h"
// some useful xml routines
xmlNodePtr xml_NodeForVec( vec3_t v );
void xml_SendNode (xmlNodePtr node);
// print a message in q3map output and send the corresponding select information down the xml stream
// bError: do we end with an error on this one or do we go ahead?
void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
// end q3map with an error message and send a point information in the xml stream
// note: we might want to add a boolean to use this as a warning or an error thing..
void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
void xml_Point (char *msg, vec3_t pt);
extern qboolean bNetworkBroadcast;
void Broadcast_Setup( const char *dest );
void Broadcast_Shutdown();
#define SYS_VRB 0 // verbose support (on/off)
#define SYS_STD 1 // standard print level
#define SYS_WRN 2 // warnings
#define SYS_ERR 3 // error
#define SYS_NOXML 4 // don't send that down the XML stream
extern qboolean verbose;
void Sys_Printf (const char *text, ...);
void Sys_FPrintf (int flag, const char *text, ...);
void Error( const char *error, ...);
#ifdef _DEBUG
#define DBG_XML 1
#endif
#ifdef DBG_XML
void DumpXML();
#endif
#endif

View File

@@ -0,0 +1,476 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// l3dslib.c: library for loading triangles from an Alias triangle file
//
#include <stdio.h>
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "trilib.h"
#include "l3dslib.h"
#include "token.h"
#include "fmodel.h"
#include "bspfile.h"
#define MAIN3DS 0x4D4D
#define EDIT3DS 0x3D3D // this is the start of the editor config
#define EDIT_OBJECT 0x4000
#define OBJ_TRIMESH 0x4100
#define TRI_VERTEXL 0x4110
#define TRI_FACEL1 0x4120
#define MAXVERTS 2000
typedef struct {
int v[4];
} tri;
float fverts[MAXVERTS][3];
tri tris[MAXTRIANGLES];
int bytesread, level, numtris, totaltris;
int vertsfound, trisfound;
triangle_t *ptri;
void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles)
{
int pos, bit, i;
if (nodesList)
{
*num_mesh_nodes = 1;
memset(&(*nodesList)[0], 0, sizeof(mesh_node_t));
strcpy((*nodesList)[0].name, "default");
// set all of the tris to be used for the top node
for(i = 0; i < (*numtriangles); i++)
{
pos = (i) >> 3;
bit = 1 << ((i) & 7 );
(*nodesList)[0].tris[pos] |= bit;
}
}
}
// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
// start out with a vertex pool and vertex indices for triangles, we have to convert
// to raw, explicit triangles
void StoreAliasTriangles (void)
{
int i, j, k;
if ((totaltris + numtris) > MAXTRIANGLES)
Error ("Error: Too many triangles");
for (i=0; i<numtris ; i++)
{
for (j=0 ; j<3 ; j++)
{
for (k=0 ; k<3 ; k++)
{
ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
}
}
}
totaltris += numtris;
numtris = 0;
vertsfound = 0;
trisfound = 0;
}
int ParseVertexL (FILE *input)
{
int i, j, startbytesread, numverts;
unsigned short tshort;
if (vertsfound)
Error ("Error: Multiple vertex chunks");
vertsfound = 1;
startbytesread = bytesread;
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
numverts = (int)tshort;
if (numverts > MAXVERTS)
Error ("Error: Too many vertices");
for (i=0 ; i<numverts ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (feof(input))
Error ("Error: unexpected end of file");
fread(&fverts[i][j], sizeof(float), 1, input);
bytesread += sizeof(float);
}
}
if (vertsfound && trisfound)
StoreAliasTriangles ();
return bytesread - startbytesread;
}
int ParseFaceL1 (FILE *input)
{
int i, j, startbytesread;
unsigned short tshort;
if (trisfound)
Error ("Error: Multiple face chunks");
trisfound = 1;
startbytesread = bytesread;
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
numtris = (int)tshort;
if (numtris > MAXTRIANGLES)
Error ("Error: Too many triangles");
for (i=0 ; i<numtris ; i++)
{
for (j=0 ; j<4 ; j++)
{
if (feof(input))
Error ("Error: unexpected end of file");
fread(&tshort, sizeof(tshort), 1, input);
bytesread += sizeof(tshort);
tris[i].v[j] = (int)tshort;
}
}
if (vertsfound && trisfound)
StoreAliasTriangles ();
return bytesread - startbytesread;
}
int ParseChunk (FILE *input)
{
#define BLOCK_SIZE 4096
char temp[BLOCK_SIZE];
unsigned short type;
int i, length, w, t, retval;
level++;
retval = 0;
// chunk type
if (feof(input))
Error ("Error: unexpected end of file");
fread(&type, sizeof(type), 1, input);
bytesread += sizeof(type);
// chunk length
if (feof(input))
Error ("Error: unexpected end of file");
fread (&length, sizeof(length), 1, input);
bytesread += sizeof(length);
w = length - 6;
// process chunk if we care about it, otherwise skip it
switch (type)
{
case TRI_VERTEXL:
w -= ParseVertexL (input);
goto ParseSubchunk;
case TRI_FACEL1:
w -= ParseFaceL1 (input);
goto ParseSubchunk;
case EDIT_OBJECT:
// read the name
i = 0;
do
{
if (feof(input))
Error ("Error: unexpected end of file");
fread (&temp[i], 1, 1, input);
i++;
w--;
bytesread++;
} while (temp[i-1]);
case MAIN3DS:
case OBJ_TRIMESH:
case EDIT3DS:
// parse through subchunks
ParseSubchunk:
while (w > 0)
{
w -= ParseChunk (input);
}
retval = length;
goto Done;
default:
// skip other chunks
while (w > 0)
{
t = w;
if (t > BLOCK_SIZE)
t = BLOCK_SIZE;
if (feof(input))
Error ("Error: unexpected end of file");
fread (&temp, t, 1, input);
bytesread += t;
w -= t;
}
retval = length;
goto Done;
}
Done:
level--;
return retval;
}
void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
{
FILE *input;
short int tshort;
if (nodesList)
{
*num_mesh_nodes = 0;
*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
}
bytesread = 0;
level = 0;
numtris = 0;
totaltris = 0;
vertsfound = 0;
trisfound = 0;
if ((input = fopen(filename, "rb")) == 0) {
fprintf(stderr,"reader: could not open file '%s'\n", filename);
exit(0);
}
fread(&tshort, sizeof(tshort), 1, input);
// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
// no MAIN3DS
if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
fprintf(stderr,"File is not a 3DS file.\n");
exit(0);
}
// back to top of file so we can parse the first chunk descriptor
fseek(input, 0, SEEK_SET);
ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
*pptri = ptri;
// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
ParseChunk (input);
if (vertsfound || trisfound)
Error ("Incomplete triangle set");
*numtriangles = totaltris;
fclose (input);
DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
}
//==========================================================================
//
// LoadASC
//
//==========================================================================
void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
{
int i, j;
int vertexCount;
struct
{
float v[3];
} *vList;
int triCount;
triangle_t *tList;
float x, y, z;
// float x2, y2, z2;
// float rx, ry, rz;
qboolean goodObject;
if (nodesList)
{
*num_mesh_nodes = 0;
*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
}
TK_OpenSource(fileName);
goodObject = false;
while(goodObject == false)
{
TK_Beyond(TK_C_NAMED);
TK_Beyond(TK_OBJECT);
TK_Beyond(TK_C_TRI);
TK_Beyond(TK_MESH);
TK_BeyondRequire(TK_C_VERTICES, TK_COLON);
TK_FetchRequire(TK_INTNUMBER);
vertexCount = tk_IntNumber;
if(vertexCount > 0)
{
goodObject = true;
}
}
TK_BeyondRequire(TK_C_FACES, TK_COLON);
TK_FetchRequire(TK_INTNUMBER);
triCount = tk_IntNumber;
if(triCount >= MAXTRIANGLES)
{
Error("Too many triangles in file %s\n", fileName);
}
*triangleCount = triCount;
tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
*triList = tList;
memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
TK_BeyondRequire(TK_C_VERTEX, TK_LIST);
/* rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
//rx = (rotation[0]/360.0)*2.0*M_PI;
ry = (rotation[1]/360.0)*2.0*M_PI;
rz = (rotation[2]/360.0)*2.0*M_PI;
*/
vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
for(i = 0; i < vertexCount; i++)
{
TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);
if(tk_IntNumber != i)
{
Error("File '%s', line %d:\nVertex index mismatch.\n",
tk_SourceName, tk_Line);
}
TK_FetchRequireFetch(TK_COLON);
TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
x = tk_FloatNumber;
TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
y = tk_FloatNumber;
TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
z = tk_FloatNumber;
/* x2 = x*cos(rz)+y*sin(rz);
y2 = -x*sin(rz)+y*cos(rz);
x = x2;
y = y2;
y2 = y*cos(rx)+z*sin(rx);
z2 = -y*sin(rx)+z*cos(rx);
y = y2;
z = z2;
x2 = x*cos(ry)-z*sin(ry);
z2 = x*sin(ry)+z*cos(ry);
x = x2;
z = z2;
*/
vList[i].v[0] = x;
vList[i].v[1] = y;
vList[i].v[2] = z;
}
TK_BeyondRequire(TK_C_FACE, TK_LIST);
for(i = 0; i < triCount; i++)
{
TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);
if(tk_IntNumber != i)
{
Error("File '%s', line %d:\nTriangle index mismatch.\n",
tk_SourceName, tk_Line);
}
for(j = 0; j < 3; j++)
{
TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);
TK_FetchRequire(TK_INTNUMBER);
if(tk_IntNumber >= vertexCount)
{
Error("File '%s', line %d:\nVertex number"
" > vertexCount: %d\n", tk_SourceName, tk_Line,
tk_IntNumber);
}
tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
#ifdef _QDATA
tList[i].indicies[2-j] = tk_IntNumber;
#endif
}
/* printf("Face %i:\n v0: %f, %f, %f\n v1: %f, %f, %f\n"
" v2: %f, %f, %f\n", i,
tList[i].verts[0][0],
tList[i].verts[0][1],
tList[i].verts[0][2],
tList[i].verts[1][0],
tList[i].verts[1][1],
tList[i].verts[1][2],
tList[i].verts[2][0],
tList[i].verts[2][1],
tList[i].verts[2][2]);
*/
}
DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
}

View File

@@ -0,0 +1,28 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// l3dslib.h: header file for loading triangles from a 3DS triangle file
//
void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles);
void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);
void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// piclib.h
void LoadLBM (char *filename, byte **picture, byte **palette);
void WriteLBMfile (char *filename, byte *data, int width, int height
, byte *palette);
void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
void WritePCXfile (char *filename, byte *data, int width, int height
, byte *palette);
// loads / saves either lbm or pcx, depending on extension
void Load256Image (char *name, byte **pixels, byte **palette,
int *width, int *height);
void Save256Image (char *name, byte *pixels, byte *palette,
int width, int height);
void LoadTGA (char *filename, byte **pixels, int *width, int *height);
qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height);

View File

@@ -0,0 +1,176 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// mathlib.c -- math primitives
#include "cmdlib.h"
#include "mathlib.h"
vec3_t vec3_origin = {0,0,0};
double VectorLength(vec3_t v)
{
int i;
double length;
length = 0;
for (i=0 ; i< 3 ; i++)
length += v[i]*v[i];
length = sqrt (length); // FIXME
return length;
}
qboolean VectorCompare (vec3_t v1, vec3_t v2)
{
int i;
for (i=0 ; i<3 ; i++)
if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
return false;
return true;
}
vec_t Q_rint (vec_t in)
{
return floor (in + 0.5);
}
void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
{
vc[0] = va[0] + scale*vb[0];
vc[1] = va[1] + scale*vb[1];
vc[2] = va[2] + scale*vb[2];
}
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
{
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
vec_t _DotProduct (vec3_t v1, vec3_t v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]-vb[0];
out[1] = va[1]-vb[1];
out[2] = va[2]-vb[2];
}
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
{
out[0] = va[0]+vb[0];
out[1] = va[1]+vb[1];
out[2] = va[2]+vb[2];
}
void _VectorCopy (vec3_t in, vec3_t out)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
{
out[0] = v[0] * scale;
out[1] = v[1] * scale;
out[2] = v[2] * scale;
}
#pragma optimize("g", off) // went back to turning optimization off,
// the bug_fix thing stopped working
vec_t VectorNormalize (vec3_t in, vec3_t out)
{
vec_t length, ilength;
length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
if (length == 0)
{
VectorClear (out);
return 0;
}
ilength = 1.0/length;
out[0] = in[0]*ilength;
out[1] = in[1]*ilength;
out[2] = in[2]*ilength;
return length;
}
vec_t ColorNormalize (vec3_t in, vec3_t out)
{
float max, scale;
max = in[0];
if (in[1] > max)
max = in[1];
if (in[2] > max)
max = in[2];
if (max == 0)
return 0;
scale = 1.0 / max;
VectorScale (in, scale, out);
return max;
}
#pragma optimize("", on)
void VectorInverse (vec3_t v)
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void ClearBounds (vec3_t mins, vec3_t maxs)
{
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
}
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
{
int i;
vec_t val;
for (i=0 ; i<3 ; i++)
{
val = v[i];
if (val < mins[i])
mins[i] = val;
if (val > maxs[i])
maxs[i] = val;
}
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __MATHLIB__
#define __MATHLIB__
// mathlib.h
#include <math.h>
/*
#ifdef DOUBLEVEC_T
typedef double vec_t;
#else
typedef float vec_t;
#endif
typedef vec_t vec3_t[3];
*/
#define SIDE_FRONT 0
#define SIDE_ON 2
#define SIDE_BACK 1
#define SIDE_CROSS -2
#define Q_PI 3.14159265358979323846
extern vec3_t vec3_origin;
#define EQUAL_EPSILON 0.001
qboolean VectorCompare (vec3_t v1, vec3_t v2);
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
vec_t Q_rint (vec_t in);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
void _VectorCopy (vec3_t in, vec3_t out);
void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
double VectorLength(vec3_t v);
void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
vec_t VectorNormalize (vec3_t in, vec3_t out);
vec_t ColorNormalize (vec3_t in, vec3_t out);
void VectorInverse (vec3_t v);
void ClearBounds (vec3_t mins, vec3_t maxs);
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
#endif

View File

@@ -0,0 +1,298 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* GLOBAL.H - RSAREF types and constants */
#include <string.h>
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* MD4.H - header file for MD4C.C */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
All rights reserved.
License to copy and use this software is granted provided that it is identified as the “RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as “derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided “as is” without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* MD4 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD4_CTX;
void MD4Init (MD4_CTX *);
void MD4Update (MD4_CTX *, unsigned char *, unsigned int);
void MD4Final (unsigned char [16], MD4_CTX *);
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
License to copy and use this software is granted provided that it is identified as the
RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as
derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
as is without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* Constants for MD4Transform routine. */
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
static void MD4Transform (UINT4 [4], unsigned char [64]);
static void Encode (unsigned char *, UINT4 *, unsigned int);
static void Decode (UINT4 *, unsigned char *, unsigned int);
static void MD4_memcpy (POINTER, POINTER, unsigned int);
static void MD4_memset (POINTER, int, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = \
ROTATE_LEFT ((a), (s)); }
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
void MD4Init (MD4_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.*/
if (inputLen >= partLen)
{
memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD4Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD4Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
}
/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
void MD4Final (unsigned char digest[16], MD4_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD4Update (context, PADDING, padLen);
/* Append length (before padding) */
MD4Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.*/
memset ((POINTER)context, 0, sizeof (*context));
}
/* MD4 basic transformation. Transforms state based on block. */
static void MD4Transform (UINT4 state[4], unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11); /* 1 */
FF (d, a, b, c, x[ 1], S12); /* 2 */
FF (c, d, a, b, x[ 2], S13); /* 3 */
FF (b, c, d, a, x[ 3], S14); /* 4 */
FF (a, b, c, d, x[ 4], S11); /* 5 */
FF (d, a, b, c, x[ 5], S12); /* 6 */
FF (c, d, a, b, x[ 6], S13); /* 7 */
FF (b, c, d, a, x[ 7], S14); /* 8 */
FF (a, b, c, d, x[ 8], S11); /* 9 */
FF (d, a, b, c, x[ 9], S12); /* 10 */
FF (c, d, a, b, x[10], S13); /* 11 */
FF (b, c, d, a, x[11], S14); /* 12 */
FF (a, b, c, d, x[12], S11); /* 13 */
FF (d, a, b, c, x[13], S12); /* 14 */
FF (c, d, a, b, x[14], S13); /* 15 */
FF (b, c, d, a, x[15], S14); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 0], S21); /* 17 */
GG (d, a, b, c, x[ 4], S22); /* 18 */
GG (c, d, a, b, x[ 8], S23); /* 19 */
GG (b, c, d, a, x[12], S24); /* 20 */
GG (a, b, c, d, x[ 1], S21); /* 21 */
GG (d, a, b, c, x[ 5], S22); /* 22 */
GG (c, d, a, b, x[ 9], S23); /* 23 */
GG (b, c, d, a, x[13], S24); /* 24 */
GG (a, b, c, d, x[ 2], S21); /* 25 */
GG (d, a, b, c, x[ 6], S22); /* 26 */
GG (c, d, a, b, x[10], S23); /* 27 */
GG (b, c, d, a, x[14], S24); /* 28 */
GG (a, b, c, d, x[ 3], S21); /* 29 */
GG (d, a, b, c, x[ 7], S22); /* 30 */
GG (c, d, a, b, x[11], S23); /* 31 */
GG (b, c, d, a, x[15], S24); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 0], S31); /* 33 */
HH (d, a, b, c, x[ 8], S32); /* 34 */
HH (c, d, a, b, x[ 4], S33); /* 35 */
HH (b, c, d, a, x[12], S34); /* 36 */
HH (a, b, c, d, x[ 2], S31); /* 37 */
HH (d, a, b, c, x[10], S32); /* 38 */
HH (c, d, a, b, x[ 6], S33); /* 39 */
HH (b, c, d, a, x[14], S34); /* 40 */
HH (a, b, c, d, x[ 1], S31); /* 41 */
HH (d, a, b, c, x[ 9], S32); /* 42 */
HH (c, d, a, b, x[ 5], S33); /* 43 */
HH (b, c, d, a, x[13], S34); /* 44 */
HH (a, b, c, d, x[ 3], S31); /* 45 */
HH (d, a, b, c, x[11], S32); /* 46 */
HH (c, d, a, b, x[ 7], S33); /* 47 */
HH (b, c, d, a, x[15], S34); /* 48 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.*/
memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
//===================================================================
unsigned Com_BlockChecksum (void *buffer, int length)
{
int digest[4];
unsigned val;
MD4_CTX ctx;
MD4Init (&ctx);
MD4Update (&ctx, (unsigned char *)buffer, length);
MD4Final ( (unsigned char *)digest, &ctx);
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
return val;
}

View File

@@ -0,0 +1,405 @@
/* -------------------------------------------------------------------------------
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Nurail: Swiped from Q3Map2
*/
/* marker */
#define PATH_INIT_C
#if defined( __linux__ ) || defined( __APPLE__ )
#define Q_UNIX
#endif
#ifdef Q_UNIX
#include <unistd.h>
#include <pwd.h>
#include <limits.h>
#endif
/* dependencies */
#include "cmdlib.h"
#include "inout.h"
/* path support */
#define MAX_BASE_PATHS 10
#define MAX_GAME_PATHS 10
char *homePath;
char installPath[ MAX_OS_PATH ];
int numBasePaths;
char *basePaths[ MAX_BASE_PATHS ];
int numGamePaths;
char *gamePaths[ MAX_GAME_PATHS ];
/*
some of this code is based off the original q3map port from loki
and finds various paths. moved here from bsp.c for clarity.
*/
/*
PathLokiGetHomeDir()
gets the user's home dir (for ~/.q3a)
*/
char *LokiGetHomeDir( void )
{
#ifndef Q_UNIX
return NULL;
#else
char *home;
uid_t id;
struct passwd *pwd;
/* get the home environment variable */
home = getenv( "HOME" );
if( home == NULL )
{
/* do some more digging */
id = getuid();
setpwent();
while( (pwd = getpwent()) != NULL )
{
if( pwd->pw_uid == id )
{
home = pwd->pw_dir;
break;
}
}
endpwent();
}
/* return it */
return home;
#endif
}
/*
PathLokiInitPaths()
initializes some paths on linux/os x
*/
void LokiInitPaths( char *argv0 )
{
#ifndef Q_UNIX
/* this is kinda crap, but hey */
strcpy( installPath, "../" );
#else
char temp[ MAX_OS_PATH ];
char *home;
char *path;
char *last;
qboolean found;
/* get home dir */
home = LokiGetHomeDir();
if( home == NULL )
home = ".";
/* do some path divining */
strcpy( temp, argv0 );
if( strrchr( temp, '/' ) )
argv0 = strrchr( argv0, '/' ) + 1;
else
{
/* get path environment variable */
path = getenv( "PATH" );
/* minor setup */
last[ 0 ] = path[ 0 ];
last[ 1 ] = '\0';
found = false;
/* go through each : segment of path */
while( last[ 0 ] != '\0' && found == false )
{
/* null out temp */
temp[ 0 ] = '\0';
/* find next chunk */
last = strchr( path, ':' );
if( last == NULL )
last = path + strlen( path );
/* found home dir candidate */
if( *path == '~' )
{
strcpy( temp, home );
path++;
}
/* concatenate */
if( last > (path + 1) )
{
strncat( temp, path, (last - path) );
strcat( temp, "/" );
}
strcat( temp, "./" );
strcat( temp, argv0 );
/* verify the path */
if( access( temp, X_OK ) == 0 )
found++;
path = last + 1;
}
}
/* flake */
if( realpath( temp, installPath ) )
{
/* q3map is in "tools/" */
*(strrchr( installPath, '/' )) = '\0';
*(strrchr( installPath, '/' ) + 1) = '\0';
}
/* set home path */
homePath = home;
#endif
}
/*
CleanPath() - ydnar
cleans a dos path \ -> /
*/
void CleanPath( char *path )
{
while( *path )
{
if( *path == '\\' )
*path = '/';
path++;
}
}
/*
AddBasePath() - ydnar
adds a base path to the list
*/
void AddBasePath( char *path )
{
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
return;
/* add it to the list */
basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
strcpy( basePaths[ numBasePaths ], path );
CleanPath( basePaths[ numBasePaths ] );
numBasePaths++;
}
/*
AddHomeBasePath() - ydnar
adds a base path to the beginning of the list, prefixed by ~/
*/
void AddHomeBasePath( char *path )
{
#ifdef Q_UNIX
int i;
char temp[ MAX_OS_PATH ];
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' )
return;
/* make a hole */
for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
basePaths[ i + 1 ] = basePaths[ i ];
/* concatenate home dir and path */
sprintf( temp, "%s/%s", homePath, path );
/* add it to the list */
basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
strcpy( basePaths[ 0 ], temp );
CleanPath( basePaths[ 0 ] );
numBasePaths++;
#endif
}
/*
AddGamePath() - ydnar
adds a game path to the list
*/
void AddGamePath( char *path )
{
/* dummy check */
if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
return;
/* add it to the list */
gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
strcpy( gamePaths[ numGamePaths ], path );
CleanPath( gamePaths[ numGamePaths ] );
numGamePaths++;
}
/*
InitPaths() - ydnar
cleaned up some of the path initialization code from bsp.c
will remove any arguments it uses
*/
void InitPaths( int *argc, char **argv )
{
int i, j, k, len, len2;
char temp[ MAX_OS_PATH ];
char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
strcpy(gamePath, "base");
strcpy(game_magic, "h");
strcpy(homeBasePath, ".heretic2");
/* note it */
Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
/* get the install path for backup */
LokiInitPaths( argv[ 0 ] );
/* set game to default (q3a) */
numBasePaths = 0;
numGamePaths = 0;
/* parse through the arguments and extract those relevant to paths */
for( i = 0; i < *argc; i++ )
{
/* check for null */
if( argv[ i ] == NULL )
continue;
/* -fs_basepath */
if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
{
if( ++i >= *argc )
Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
argv[ i - 1 ] = NULL;
AddBasePath( argv[ i ] );
argv[ i ] = NULL;
}
}
/* remove processed arguments */
for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
{
for( j; j < *argc && argv[ j ] == NULL; j++ );
argv[ i ] = argv[ j ];
if( argv[ i ] != NULL )
k++;
}
*argc = k;
/* add standard game path */
AddGamePath( gamePath );
/* if there is no base path set, figure it out */
if( numBasePaths == 0 )
{
/* this is another crappy replacement for SetQdirFromPath() */
len2 = strlen( game_magic );
for( i = 0; i < *argc && numBasePaths == 0; i++ )
{
/* extract the arg */
strcpy( temp, argv[ i ] );
CleanPath( temp );
len = strlen( temp );
Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
/* this is slow, but only done once */
for( j = 0; j < (len - len2); j++ )
{
/* check for the game's magic word */
if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
{
/* now find the next slash and nuke everything after it */
while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
temp[ j ] = '\0';
/* add this as a base path */
AddBasePath( temp );
break;
}
}
}
/* add install path */
if( numBasePaths == 0 )
AddBasePath( installPath );
/* check again */
if( numBasePaths == 0 )
Error( "Failed to find a valid base path." );
}
/* this only affects unix */
AddHomeBasePath( homeBasePath );
/* initialize vfs paths */
if( numBasePaths > MAX_BASE_PATHS )
numBasePaths = MAX_BASE_PATHS;
if( numGamePaths > MAX_GAME_PATHS )
numGamePaths = MAX_GAME_PATHS;
/* walk the list of game paths */
//for( j = 0; j < numGamePaths; j++ )
//{
/* walk the list of base paths */
// for( i = 0; i < numBasePaths; i++ )
// {
/* create a full path and initialize it */
// sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
// vfsInitDirectory( temp );
// }
//}
/* done */
Sys_Printf( "\n" );
}

View File

@@ -0,0 +1,656 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cmdlib.h"
#include "inout.h"
#include "mathlib.h"
#include "polylib.h"
extern int numthreads;
// counters are only bumped when running single threaded,
// because they are an awefull coherence problem
int c_active_windings;
int c_peak_windings;
int c_winding_allocs;
int c_winding_points;
#define BOGUS_RANGE 8192
void pw(winding_t *w)
{
int i;
for (i=0 ; i<w->numpoints ; i++)
printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
}
/*
=============
AllocWinding
=============
*/
winding_t *AllocWinding (int points)
{
winding_t *w;
int s;
if (numthreads == 1)
{
c_winding_allocs++;
c_winding_points += points;
c_active_windings++;
if (c_active_windings > c_peak_windings)
c_peak_windings = c_active_windings;
}
s = sizeof(vec_t)*3*points + sizeof(int);
w = malloc (s);
if (!w)
Error("AllocWinding MALLOC failed! Could not allocate %s bytes.", s);
memset (w, 0, s);
return w;
}
void FreeWinding (winding_t *w)
{
if (*(unsigned *)w == 0xdeaddead)
Error ("FreeWinding: freed a freed winding");
*(unsigned *)w = 0xdeaddead;
if (numthreads == 1)
c_active_windings--;
free (w);
}
/*
============
RemoveColinearPoints
============
*/
int c_removed;
void RemoveColinearPoints (winding_t *w)
{
int i, j, k;
vec3_t v1, v2;
int nump;
vec3_t p[MAX_POINTS_ON_WINDING];
nump = 0;
for (i=0 ; i<w->numpoints ; i++)
{
j = (i+1)%w->numpoints;
k = (i+w->numpoints-1)%w->numpoints;
VectorSubtract (w->p[j], w->p[i], v1);
VectorSubtract (w->p[i], w->p[k], v2);
VectorNormalize(v1,v1);
VectorNormalize(v2,v2);
if (DotProduct(v1, v2) < 0.999)
{
VectorCopy (w->p[i], p[nump]);
nump++;
}
}
if (nump == w->numpoints)
return;
if (numthreads == 1)
c_removed += w->numpoints - nump;
w->numpoints = nump;
memcpy (w->p, p, nump*sizeof(p[0]));
}
/*
============
WindingPlane
============
*/
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
{
vec3_t v1, v2;
VectorSubtract (w->p[1], w->p[0], v1);
VectorSubtract (w->p[2], w->p[0], v2);
CrossProduct (v2, v1, normal);
VectorNormalize (normal, normal);
*dist = DotProduct (w->p[0], normal);
}
/*
=============
WindingArea
=============
*/
vec_t WindingArea (winding_t *w)
{
int i;
vec3_t d1, d2, cross;
vec_t total;
total = 0;
for (i=2 ; i<w->numpoints ; i++)
{
VectorSubtract (w->p[i-1], w->p[0], d1);
VectorSubtract (w->p[i], w->p[0], d2);
CrossProduct (d1, d2, cross);
total += 0.5 * VectorLength ( cross );
}
return total;
}
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
{
vec_t v;
int i,j;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for (i=0 ; i<w->numpoints ; i++)
{
for (j=0 ; j<3 ; j++)
{
v = w->p[i][j];
if (v < mins[j])
mins[j] = v;
if (v > maxs[j])
maxs[j] = v;
}
}
}
/*
=============
WindingCenter
=============
*/
void WindingCenter (winding_t *w, vec3_t center)
{
int i;
float scale;
VectorCopy (vec3_origin, center);
for (i=0 ; i<w->numpoints ; i++)
VectorAdd (w->p[i], center, center);
scale = 1.0/w->numpoints;
VectorScale (center, scale, center);
}
/*
=================
BaseWindingForPlane
=================
*/
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
{
int i, x;
vec_t max, v;
vec3_t org, vright, vup;
winding_t *w;
// find the major axis
max = -BOGUS_RANGE;
x = -1;
for (i=0 ; i<3; i++)
{
v = fabs(normal[i]);
if (v > max)
{
x = i;
max = v;
}
}
if (x==-1)
Error ("BaseWindingForPlane: no axis found");
VectorCopy (vec3_origin, vup);
switch (x)
{
case 0:
case 1:
vup[2] = 1;
break;
case 2:
vup[0] = 1;
break;
}
v = DotProduct (vup, normal);
VectorMA (vup, -v, normal, vup);
VectorNormalize (vup, vup);
VectorScale (normal, dist, org);
CrossProduct (vup, normal, vright);
VectorScale (vup, 8192, vup);
VectorScale (vright, 8192, vright);
// project a really big axis aligned box onto the plane
w = AllocWinding (4);
VectorSubtract (org, vright, w->p[0]);
VectorAdd (w->p[0], vup, w->p[0]);
VectorAdd (org, vright, w->p[1]);
VectorAdd (w->p[1], vup, w->p[1]);
VectorAdd (org, vright, w->p[2]);
VectorSubtract (w->p[2], vup, w->p[2]);
VectorSubtract (org, vright, w->p[3]);
VectorSubtract (w->p[3], vup, w->p[3]);
w->numpoints = 4;
return w;
}
/*
==================
CopyWinding
==================
*/
winding_t *CopyWinding (winding_t *w)
{
int size;
winding_t *c;
c = AllocWinding (w->numpoints);
size = (int)((winding_t *)0)->p[w->numpoints];
memcpy (c, w, size);
return c;
}
/*
==================
ReverseWinding
==================
*/
winding_t *ReverseWinding (winding_t *w)
{
int i;
winding_t *c;
c = AllocWinding (w->numpoints);
for (i=0 ; i<w->numpoints ; i++)
{
VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
}
c->numpoints = w->numpoints;
return c;
}
/*
=============
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back)
{
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f, *b;
int maxpts;
if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*front = *back = NULL;
if (!counts[0])
{
*back = CopyWinding (in);
return;
}
if (!counts[1])
{
*front = CopyWinding (in);
return;
}
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
*front = f = AllocWinding (maxpts);
*back = b = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i] == SIDE_BACK)
{
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (mid, b->p[b->numpoints]);
b->numpoints++;
}
if (f->numpoints > maxpts || b->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
}
/*
=============
ChopWindingInPlace
=============
*/
void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
{
winding_t *in;
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f;
int maxpts;
in = *inout;
counts[0] = counts[1] = counts[2] = 0;
if (!in)
{
printf ("Warning: NULL passed to ChopWindingInPlace\n");
return;
}
if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
Error ("ChopWinding: MAX_POINTS_ON_WINDING");
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
if (!counts[0])
{
FreeWinding (in);
*inout = NULL;
return;
}
if (!counts[1])
return; // inout stays the same
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
f = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
}
if (f->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
FreeWinding (in);
*inout = f;
}
/*
=================
ChopWinding
Returns the fragment of in that is on the front side
of the cliping plane. The original is freed.
=================
*/
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
{
winding_t *f, *b;
ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
FreeWinding (in);
if (b)
FreeWinding (b);
return f;
}
/*
=================
CheckWinding
=================
*/
void CheckWinding (winding_t *w)
{
int i, j;
vec_t *p1, *p2;
vec_t d, edgedist;
vec3_t dir, edgenormal, facenormal;
vec_t area;
vec_t facedist;
if (w->numpoints < 3)
Error ("CheckWinding: %i points",w->numpoints);
area = WindingArea(w);
if (area < 1)
Error ("CheckWinding: %f area", area);
WindingPlane (w, facenormal, &facedist);
for (i=0 ; i<w->numpoints ; i++)
{
p1 = w->p[i];
for (j=0 ; j<3 ; j++)
if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
j = i+1 == w->numpoints ? 0 : i+1;
// check the point is on the face plane
d = DotProduct (p1, facenormal) - facedist;
if (d < -ON_EPSILON || d > ON_EPSILON)
Error ("CheckWinding: point off plane");
// check the edge isnt degenerate
p2 = w->p[j];
VectorSubtract (p2, p1, dir);
if (VectorLength (dir) < ON_EPSILON)
Error ("CheckWinding: degenerate edge");
CrossProduct (facenormal, dir, edgenormal);
VectorNormalize (edgenormal, edgenormal);
edgedist = DotProduct (p1, edgenormal);
edgedist += ON_EPSILON;
// all other points must be on front side
for (j=0 ; j<w->numpoints ; j++)
{
if (j == i)
continue;
d = DotProduct (w->p[j], edgenormal);
if (d > edgedist)
Error ("CheckWinding: non-convex");
}
}
}
/*
============
WindingOnPlaneSide
============
*/
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
{
qboolean front, back;
int i;
vec_t d;
front = false;
back = false;
for (i=0 ; i<w->numpoints ; i++)
{
d = DotProduct (w->p[i], normal) - dist;
if (d < -ON_EPSILON)
{
if (front)
return SIDE_CROSS;
back = true;
continue;
}
if (d > ON_EPSILON)
{
if (back)
return SIDE_CROSS;
front = true;
continue;
}
}
if (back)
return SIDE_BACK;
if (front)
return SIDE_FRONT;
return SIDE_ON;
}

View File

@@ -0,0 +1,55 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedef struct
{
int numpoints;
vec3_t p[4]; // variable sized
} winding_t;
#define MAX_POINTS_ON_WINDING 64
// you can define on_epsilon in the makefile as tighter
#ifndef ON_EPSILON
#define ON_EPSILON 0.1
#endif
winding_t *AllocWinding (int points);
vec_t WindingArea (winding_t *w);
void WindingCenter (winding_t *w, vec3_t center);
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back);
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
winding_t *CopyWinding (winding_t *w);
winding_t *ReverseWinding (winding_t *w);
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
void CheckWinding (winding_t *w);
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
void RemoveColinearPoints (winding_t *w);
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
void FreeWinding (winding_t *w);
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
// frees the original if clipped
void pw(winding_t *w);

View File

@@ -0,0 +1,82 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qfiles.h"
#include "scriplib.h"
//#include <windows.h>
materialtype_t defaultmaterialtypes[] =
{
{"gravel", MATERIAL_GRAVEL},
{"metal", MATERIAL_METAL},
{"stone", MATERIAL_STONE},
{"wood", MATERIAL_WOOD},
{NULL, 0}
};
materialtype_t *materialtypes;
void QFile_ReadMaterialTypes(char* filename)
{
int i;
FILE *f;
f = fopen (filename, "rb");
if (!f)
{
materialtypes = defaultmaterialtypes;
return;
}
fclose (f);
free(materialtypes);
materialtypes = (materialtype_t*)malloc(256 * sizeof(materialtype_t));
LoadScriptFile(filename);
i = 0;
while (i < 255)
{
GetScriptToken (true);
if (endofscript)
{
break;
}
if (strcmp(token, "material") != 0)
{
while (ScriptTokenAvailable())
{
GetScriptToken(false);
}
}
else
{
GetScriptToken(false);
materialtypes[i].name = (char*)malloc(strlen(token) + 1);
strcpy(materialtypes[i].name, token);
GetScriptToken (false);
materialtypes[i].value = atoi(token);
}
i++;
}
materialtypes[i].name = NULL;
materialtypes[i].value = 0;
}

View File

@@ -0,0 +1,619 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QFILES_H
#define _QFILES_H
#include "q_typedef.h"
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
/*
========================================================================
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P')
typedef struct
{
char name[56];
int filepos, filelen;
} dpackfile_t;
typedef struct
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
} dpackheader_t;
#define MAX_FILES_IN_PACK 4096
/*
========================================================================
PCX files are used for as many images as possible
========================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
.MD2 compressed triangle model file format
========================================================================
*/
#define IDJOINTEDALIASHEADER (('2'<<24)+('J'<<16)+('D'<<8)+'I')
/*
========================================================================
.MD2 triangle model file format
========================================================================
*/
#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define ALIAS_VERSION 8
#define MAX_TRIANGLES 2048
#define MAX_VERTS 2048
#define MAX_FRAMES 512
#define MAX_MD2SKINS 64
#define MAX_SKINNAME 64
typedef struct
{
short s;
short t;
} dstvert_t;
typedef struct
{
short index_xyz[3];
short index_st[3];
} dtriangle_t;
typedef struct
{
byte v[3]; // scaled byte to fit in frame mins/maxs
byte lightnormalindex;
} dtrivertx_t;
#define DTRIVERTX_V0 0
#define DTRIVERTX_V1 1
#define DTRIVERTX_V2 2
#define DTRIVERTX_LNI 3
#define DTRIVERTX_SIZE 4
typedef struct
{
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
dtrivertx_t verts[1]; // variable sized
} daliasframe_t;
// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.
typedef struct
{
int ident;
int version;
int skinwidth;
int skinheight;
int framesize; // byte size of each frame
int num_skins;
int num_xyz;
int num_st; // greater than num_xyz for seams
int num_tris;
int num_glcmds; // dwords in strip/fan command list
int num_frames;
int ofs_skins; // each skin is a MAX_SKINNAME string
int ofs_st; // byte offset from start for stverts
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
int ofs_end; // end of file
} dmdl_t;
/*
========================================================================
.BK file format
========================================================================
*/
#define IDBOOKHEADER (('K'<<24)+('O'<<16)+('O'<<8)+'B')
#define BOOK_VERSION 2
typedef struct bookframe_s
{
int x;
int y;
int w;
int h;
char name[MAX_SKINNAME]; // name of gfx file
} bookframe_t;
typedef struct bookheader_s
{
unsigned int ident;
unsigned int version;
int num_segments;
int total_w;
int total_h;
} bookheader_t;
typedef struct book_s
{
bookheader_t bheader;
bookframe_t bframes[MAX_MD2SKINS];
} book_t;
/*
========================================================================
.SP2 sprite file format
========================================================================
*/
#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I')
// little-endian "IDS2"
#define SPRITE_VERSION 2
typedef struct
{
int width, height;
int origin_x, origin_y; // raster coordinates inside pic
char name[MAX_SKINNAME]; // name of pcx file
} dsprframe_t;
typedef struct {
int ident;
int version;
int numframes;
dsprframe_t frames[1]; // variable sized
} dsprite_t;
/*
==============================================================================
.M8 texture file format
==============================================================================
*/
typedef struct palette_s
{
union
{
struct
{
byte r,g,b;
};
};
} palette_t;
#define MIP_VERSION 2
#define PAL_SIZE 256
#define MIPLEVELS 16
typedef struct miptex_s
{
int version;
char name[32];
unsigned width[MIPLEVELS], height[MIPLEVELS];
unsigned offsets[MIPLEVELS]; // four mip maps stored
char animname[32]; // next frame in animation chain
palette_t palette[PAL_SIZE];
int flags;
int contents;
int value;
} miptex_t;
#define MIP32_VERSION 4
#define MIP32_NOMIP_FLAG2 0x00000001
#define MIP32_DETAILER_FLAG2 0x00000002
typedef struct miptex32_s
{
int version;
char name[128];
char altname[128]; // texture substitution
char animname[128]; // next frame in animation chain
char damagename[128]; // image that should be shown when damaged
unsigned width[MIPLEVELS], height[MIPLEVELS];
unsigned offsets[MIPLEVELS];
int flags;
int contents;
int value;
float scale_x, scale_y;
int mip_scale;
// detail texturing info
char dt_name[128]; // detailed texture name
float dt_scale_x, dt_scale_y;
float dt_u, dt_v;
float dt_alpha;
int dt_src_blend_mode, dt_dst_blend_mode;
int flags2;
int unused[19]; // future expansion to maintain compatibility with h2
} miptex32_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I')
// little-endian "IBSP"
#define BSPVERSION 38
// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
#define MAX_MAP_ENTITIES 2048
#define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_TEXINFO 8192
#define MAX_MAP_AREAS 256
#define MAX_MAP_AREAPORTALS 1024
#define MAX_MAP_PLANES 65536
#define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536
#define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536
#define MAX_MAP_FACES 65536
#define MAX_MAP_LEAFFACES 65536
#define MAX_MAP_LEAFBRUSHES 65536
#define MAX_MAP_PORTALS 65536
#define MAX_MAP_EDGES 128000
#define MAX_MAP_SURFEDGES 256000
#define MAX_MAP_LIGHTING 0x200000
#define MAX_MAP_VISIBILITY 0x180000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
typedef struct
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_VERTEXES 2
#define LUMP_VISIBILITY 3
#define LUMP_NODES 4
#define LUMP_TEXINFO 5
#define LUMP_FACES 6
#define LUMP_LIGHTING 7
#define LUMP_LEAFS 8
#define LUMP_LEAFFACES 9
#define LUMP_LEAFBRUSHES 10
#define LUMP_EDGES 11
#define LUMP_SURFEDGES 12
#define LUMP_MODELS 13
#define LUMP_BRUSHES 14
#define LUMP_BRUSHSIDES 15
#define LUMP_POP 16
#define LUMP_AREAS 17
#define LUMP_AREAPORTALS 18
#define HEADER_LUMPS 19
typedef struct
{
int ident;
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3]; // for sounds or lights
int headnode;
int firstface, numfaces; // submodels just draw faces
// without walking the bsp tree
} dmodel_t;
typedef struct
{
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planes (x&~1) and (x&~1)+1 are allways opposites
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_SOLID 0x00000001 // an eye is never valid in a solid
#define CONTENTS_WINDOW 0x00000002 // translucent, but not watery
#define CONTENTS_PUSHPULL 0x00000004
#define CONTENTS_LAVA 0x00000008
#define CONTENTS_SLIME 0x00000010
#define CONTENTS_WATER 0x00000020
#define CONTENTS_MIST 0x00000040 // 64
#define LAST_VISIBLE_CONTENTS 64 // this one worries me a bit JKH
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x00008000
#define CONTENTS_PLAYERCLIP 0x00010000
#define CONTENTS_MONSTERCLIP 0x00020000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x00040000
#define CONTENTS_CURRENT_90 0x00080000
#define CONTENTS_CURRENT_180 0x00100000
#define CONTENTS_CURRENT_270 0x00200000
#define CONTENTS_CURRENT_UP 0x00400000
#define CONTENTS_CURRENT_DOWN 0x00800000
#define CONTENTS_ORIGIN 0x01000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x02000000 // should never be on a brush, only in game
#define CONTENTS_DEADMONSTER 0x04000000
#define CONTENTS_DETAIL 0x08000000 // brushes to be added after vis leafs
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define SURF_LIGHT 0x00000001 // value will hold the light strength
#define SURF_SLICK 0x00000002 // effects game physics
#define SURF_SKY 0x00000004 // don't draw, but add to skybox
#define SURF_WARP 0x00000008 // turbulent water warp
#define SURF_TRANS33 0x00000010
#define SURF_TRANS66 0x00000020
#define SURF_FLOWING 0x00000040 // scroll towards angle
#define SURF_NODRAW 0x00000080 // don't bother referencing the texture
#define SURF_HINT 0x00000100 // make a primary bsp splitter
#define SURF_SKIP 0x00000200 // completely ignore, allowing non-closed brushes
#define SURF_TALL_WALL 0x00000400 // face doesn't get broken up as normal
#define SURF_ALPHA_TEXTURE 0x00000800 // texture has alpha in it, and should show through in bsp process
#define SURF_ANIMSPEED 0x00001000 // value will hold the anim speed in fps
#define SURF_UNDULATE 0x00002000 // rock surface up and down...
#define SURF_SKYREFLECT 0x00004000 // liquid will somewhat reflect the sky - not quite finished....
#define SURF_TYPE_GRAVEL 0x00000000
#define SURF_TYPE_METAL 0x01000000
#define SURF_TYPE_STONE 0x02000000
#define SURF_TYPE_WOOD 0x03000000
#define SURF_MATERIAL 0xFF000000
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for frustom culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
int value; // light emission, etc
char texture[32]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
} texinfo_t;
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
union {
byte styles[MAXLIGHTMAPS];
paletteRGBA_t lighting;
};
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
typedef struct
{
int contents; // OR of all brushes (not needed?)
short cluster;
short area;
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} dleaf_t;
typedef struct
{
unsigned short planenum; // facing out of the leaf
short texinfo;
} dbrushside_t;
typedef struct
{
int firstside;
int numsides;
int contents;
} dbrush_t;
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the visibility lump consists of a header with a count, then
// byte offsets for the PVS and PHS of each cluster, then the raw
// compressed bit vectors
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef struct
{
int numclusters;
int bitofs[8][2]; // bitofs[numclusters][2]
} dvis_t;
// each area has a list of portals that lead into other areas
// when portals are closed, other areas may not be visible or
// hearable even if the vis info says that it should be
typedef struct
{
int portalnum;
int otherarea;
} dareaportal_t;
typedef struct
{
int numareaportals;
int firstareaportal;
} darea_t;
typedef struct
{
char *name;
int value;
} materialtype_t;
enum
{
MATERIAL_GRAVEL,
MATERIAL_METAL,
MATERIAL_STONE,
MATERIAL_WOOD,
};
materialtype_t *materialtypes;
void QFile_ReadMaterialTypes(char* filename);
#endif //_QFILES_H

View File

@@ -0,0 +1,297 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// scriplib.c
#include "cmdlib.h"
#include "inout.h"
#include "scriplib.h"
/*
=============================================================================
PARSING STUFF
=============================================================================
*/
typedef struct
{
char filename[1024];
char *buffer,*script_p,*end_p;
int line;
} script_t;
#define MAX_INCLUDES 8
script_t scriptstack[MAX_INCLUDES];
script_t *script;
int scriptline;
char token[MAXTOKEN];
qboolean endofscript;
qboolean tokenready; // only true if UnGetScriptToken was just called
/*
==============
AddScriptToStack
==============
*/
void AddScriptToStack (char *filename)
{
int size;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, ExpandPath (filename) );
size = LoadFile (script->filename, (void **)&script->buffer);
printf ("entering %s\n", script->filename);
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
}
/*
==============
LoadScriptFile
==============
*/
void LoadScriptFile (char *filename)
{
script = scriptstack;
AddScriptToStack (filename);
endofscript = false;
tokenready = false;
}
/*
==============
ParseFromMemory
==============
*/
void ParseFromMemory (char *buffer, int size)
{
script = scriptstack;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, "memory buffer" );
script->buffer = buffer;
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
endofscript = false;
tokenready = false;
}
/*
==============
UnGetScriptToken
Signals that the current token was not used, and should be reported
for the next GetScriptToken. Note that
GetScriptToken (true);
UnGetScriptToken ();
GetScriptToken (false);
could cross a line boundary.
==============
*/
void UnGetScriptToken (void)
{
tokenready = true;
}
qboolean EndOfScript (qboolean crossline)
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
if (!strcmp (script->filename, "memory buffer"))
{
endofscript = true;
return false;
}
free (script->buffer);
if (script == scriptstack+1)
{
endofscript = true;
return false;
}
script--;
scriptline = script->line;
printf ("returning to %s\n", script->filename);
return GetScriptToken (crossline);
}
/*
==============
GetScriptToken
==============
*/
qboolean GetScriptToken (qboolean crossline)
{
char *token_p;
if (tokenready) // is a token allready waiting?
{
tokenready = false;
return true;
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
//
// skip space
//
skipspace:
while (*script->script_p <= 32)
{
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
if (*script->script_p++ == '\n')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
scriptline = script->line++;
}
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
// ; # // comments
if (*script->script_p == ';' || *script->script_p == '#'
|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
while (*script->script_p++ != '\n')
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
goto skipspace;
}
// /* */ comments
if (script->script_p[0] == '/' && script->script_p[1] == '*')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
script->script_p+=2;
while (script->script_p[0] != '*' && script->script_p[1] != '/')
{
script->script_p++;
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
}
script->script_p += 2;
goto skipspace;
}
//
// copy token
//
token_p = token;
if (*script->script_p == '"')
{
// quoted token
script->script_p++;
while (*script->script_p != '"')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
script->script_p++;
}
else // regular token
while ( *script->script_p > 32 && *script->script_p != ';')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
*token_p = 0;
if (!strcmp (token, "$include"))
{
GetScriptToken (false);
AddScriptToStack (token);
return GetScriptToken (crossline);
}
return true;
}
/*
==============
ScriptTokenAvailable
Returns true if there is another token on the line
==============
*/
qboolean ScriptTokenAvailable (void)
{
char *search_p;
search_p = script->script_p;
if (search_p >= script->end_p)
return false;
while ( *search_p <= 32)
{
if (*search_p == '\n')
return false;
search_p++;
if (search_p == script->end_p)
return false;
}
if (*search_p == ';')
return false;
return true;
}

View File

@@ -0,0 +1,44 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// scriplib.h
#ifndef __CMDLIB__
#include "cmdlib.h"
#endif
#define MAXTOKEN 1024
extern char token[MAXTOKEN];
extern char *scriptbuffer,*script_p,*scriptend_p;
extern int grabbed;
extern int scriptline;
extern qboolean endofscript;
void LoadScriptFile (char *filename);
void ParseFromMemory (char *buffer, int size);
qboolean GetScriptToken (qboolean crossline);
void UnGetScriptToken (void);
qboolean ScriptTokenAvailable (void);

View File

@@ -0,0 +1,620 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIN32
// The below define is necessary to use
// pthreads extensions like pthread_mutexattr_settype
#define _GNU_SOURCE
#include <pthread.h>
#endif
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include "her2_threads.h"
#define MAX_THREADS 64
int dispatch;
int workcount;
int oldf;
qboolean pacifier;
qboolean threaded;
/*
=============
GetThreadWork
=============
*/
int GetThreadWork (void)
{
int r;
int f;
ThreadLock ();
if (dispatch == workcount)
{
ThreadUnlock ();
return -1;
}
f = 10*dispatch / workcount;
if (f != oldf)
{
oldf = f;
if (pacifier)
{
Sys_Printf ("%i...", f);
fflush( stdout ); /* ydnar */
}
}
r = dispatch;
dispatch++;
ThreadUnlock ();
return r;
}
void (*workfunction) (int);
void ThreadWorkerFunction (int threadnum)
{
int work;
while (1)
{
work = GetThreadWork ();
if (work == -1)
break;
//Sys_Printf ("thread %i, work %i\n", threadnum, work);
workfunction(work);
}
}
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
{
if (numthreads == -1)
ThreadSetDefault ();
workfunction = func;
RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
}
/*
===================================================================
WIN32
===================================================================
*/
#ifdef WIN32
#define USED
#include <windows.h>
int numthreads = -1;
CRITICAL_SECTION crit;
static int enter;
void ThreadSetDefault (void)
{
SYSTEM_INFO info;
if (numthreads == -1) // not set manually
{
GetSystemInfo (&info);
numthreads = info.dwNumberOfProcessors;
if (numthreads < 1 || numthreads > 32)
numthreads = 1;
}
Sys_Printf ("%i threads\n", numthreads);
}
void ThreadLock (void)
{
if (!threaded)
return;
EnterCriticalSection (&crit);
if (enter)
Error ("Recursive ThreadLock\n");
enter = 1;
}
void ThreadUnlock (void)
{
if (!threaded)
return;
if (!enter)
Error ("ThreadUnlock without lock\n");
enter = 0;
LeaveCriticalSection (&crit);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int threadid[MAX_THREADS];
HANDLE threadhandle[MAX_THREADS];
int i;
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
//
// run threads in parallel
//
InitializeCriticalSection (&crit);
if (numthreads == 1)
{ // use same thread
func (0);
}
else
{
for (i=0 ; i<numthreads ; i++)
{
threadhandle[i] = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
//0, // DWORD cbStack,
/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
(4096 * 1024),
(LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
(LPVOID)i, // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&threadid[i]);
}
for (i=0 ; i<numthreads ; i++)
WaitForSingleObject (threadhandle[i], INFINITE);
}
DeleteCriticalSection (&crit);
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
===================================================================
OSF1
===================================================================
*/
#ifdef __osf__
#define USED
int numthreads = 4;
void ThreadSetDefault (void)
{
if (numthreads == -1) // not set manually
{
numthreads = 4;
}
}
#include <pthread.h>
pthread_mutex_t *my_mutex;
void ThreadLock (void)
{
if (my_mutex)
pthread_mutex_lock (my_mutex);
}
void ThreadUnlock (void)
{
if (my_mutex)
pthread_mutex_unlock (my_mutex);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
pthread_t work_threads[MAX_THREADS];
pthread_addr_t status;
pthread_attr_t attrib;
pthread_mutexattr_t mattrib;
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
if (pacifier)
setbuf (stdout, NULL);
if (!my_mutex)
{
my_mutex = safe_malloc (sizeof(*my_mutex));
if (pthread_mutexattr_create (&mattrib) == -1)
Error ("pthread_mutex_attr_create failed");
if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
Error ("pthread_mutexattr_setkind_np failed");
if (pthread_mutex_init (my_mutex, mattrib) == -1)
Error ("pthread_mutex_init failed");
}
if (pthread_attr_create (&attrib) == -1)
Error ("pthread_attr_create failed");
if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
Error ("pthread_attr_setstacksize failed");
for (i=0 ; i<numthreads ; i++)
{
if (pthread_create(&work_threads[i], attrib
, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
Error ("pthread_create failed");
}
for (i=0 ; i<numthreads ; i++)
{
if (pthread_join (work_threads[i], &status) == -1)
Error ("pthread_join failed");
}
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
===================================================================
IRIX
===================================================================
*/
#ifdef _MIPS_ISA
#define USED
#include <task.h>
#include <abi_mutex.h>
#include <sys/types.h>
#include <sys/prctl.h>
int numthreads = -1;
abilock_t lck;
void ThreadSetDefault (void)
{
if (numthreads == -1)
numthreads = prctl(PR_MAXPPROCS);
Sys_Printf ("%i threads\n", numthreads);
usconfig (CONF_INITUSERS, numthreads);
}
void ThreadLock (void)
{
spin_lock (&lck);
}
void ThreadUnlock (void)
{
release_lock (&lck);
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
int pid[MAX_THREADS];
int start, end;
start = I_FloatTime ();
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
threaded = true;
if (pacifier)
setbuf (stdout, NULL);
init_lock (&lck);
for (i=0 ; i<numthreads-1 ; i++)
{
pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
, NULL, 0x200000); // 2 meg stacks
if (pid[i] == -1)
{
perror ("sproc");
Error ("sproc failed");
}
}
func(i);
for (i=0 ; i<numthreads-1 ; i++)
wait (NULL);
threaded = false;
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif
/*
=======================================================================
Linux pthreads
=======================================================================
*/
#ifdef __linux__
#define USED
int numthreads = 4;
void ThreadSetDefault (void)
{
if (numthreads == -1) // not set manually
{
/* default to one thread, only multi-thread when specifically told to */
numthreads = 1;
}
if(numthreads > 1)
Sys_Printf("threads: %d\n", numthreads);
}
#include <pthread.h>
typedef struct pt_mutex_s
{
pthread_t *owner;
pthread_mutex_t a_mutex;
pthread_cond_t cond;
unsigned int lock;
} pt_mutex_t;
pt_mutex_t global_lock;
void ThreadLock(void)
{
pt_mutex_t *pt_mutex = &global_lock;
if(!threaded)
return;
pthread_mutex_lock(&pt_mutex->a_mutex);
if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner))
pt_mutex->lock++;
else
{
if((!pt_mutex->owner) && (pt_mutex->lock == 0))
{
pt_mutex->owner = (pthread_t *)pthread_self();
pt_mutex->lock = 1;
}
else
{
while(1)
{
pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
if((!pt_mutex->owner) && (pt_mutex->lock == 0))
{
pt_mutex->owner = (pthread_t *)pthread_self();
pt_mutex->lock = 1;
break;
}
}
}
}
pthread_mutex_unlock(&pt_mutex->a_mutex);
}
void ThreadUnlock(void)
{
pt_mutex_t *pt_mutex = &global_lock;
if(!threaded)
return;
pthread_mutex_lock(&pt_mutex->a_mutex);
pt_mutex->lock--;
if(pt_mutex->lock == 0)
{
pt_mutex->owner = NULL;
pthread_cond_signal(&pt_mutex->cond);
}
pthread_mutex_unlock(&pt_mutex->a_mutex);
}
void recursive_mutex_init(pthread_mutexattr_t attribs)
{
pt_mutex_t *pt_mutex = &global_lock;
pt_mutex->owner = NULL;
if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
Error("pthread_mutex_init failed\n");
if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
Error("pthread_cond_init failed\n");
pt_mutex->lock = 0;
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
pthread_mutexattr_t mattrib;
pthread_t work_threads[MAX_THREADS];
int start, end;
int i=0, status=0;
start = I_FloatTime ();
pacifier = showpacifier;
dispatch = 0;
oldf = -1;
workcount = workcnt;
if(numthreads == 1)
func(0);
else
{
threaded = true;
if(pacifier)
setbuf(stdout, NULL);
if(pthread_mutexattr_init(&mattrib) != 0)
Error("pthread_mutexattr_init failed");
#if __GLIBC_MINOR__ == 1
if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
#else
if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
#endif
Error ("pthread_mutexattr_settype failed");
recursive_mutex_init(mattrib);
for (i=0 ; i<numthreads ; i++)
{
/* Default pthread attributes: joinable & non-realtime scheduling */
if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
Error("pthread_create failed");
}
for (i=0 ; i<numthreads ; i++)
{
if(pthread_join(work_threads[i], (void **)&status) != 0)
Error("pthread_join failed");
}
pthread_mutexattr_destroy(&mattrib);
threaded = false;
}
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif // ifdef __linux__
/*
=======================================================================
SINGLE THREAD
=======================================================================
*/
#ifndef USED
int numthreads = 1;
void ThreadSetDefault (void)
{
numthreads = 1;
}
void ThreadLock (void)
{
}
void ThreadUnlock (void)
{
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
{
int i;
int start, end;
dispatch = 0;
workcount = workcnt;
oldf = -1;
pacifier = showpacifier;
start = I_FloatTime ();
func(0);
end = I_FloatTime ();
if (pacifier)
Sys_Printf (" (%i)\n", end-start);
}
#endif

View File

@@ -0,0 +1,550 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//**************************************************************************
//**
//** token.c
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "token.h"
#include "inout.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
typedef enum
{
CHR_EOF,
CHR_LETTER,
CHR_NUMBER,
CHR_QUOTE,
CHR_SPECIAL
} chr_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void ProcessLetterToken(void);
static void ProcessNumberToken(void);
static void ProcessQuoteToken(void);
static void ProcessSpecialToken(void);
static qboolean CheckForKeyword(void);
static void NextChr(void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
tokenType_t tk_Token;
int tk_Line;
int tk_IntNumber;
float tk_FloatNumber;
char *tk_String;
char tk_SourceName[MAX_FILE_NAME_LENGTH];
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static char Chr;
static char *FileStart;
static char *FilePtr;
static char *FileEnd;
static qboolean SourceOpen;
static char ASCIIToChrCode[256];
static char TokenStringBuffer[MAX_QUOTED_LENGTH];
static qboolean IncLineNumber;
static char TempBuffer[2048];
static struct
{
char *name;
tokenType_t token;
} Keywords[] =
{
"model", TK_MODEL,
"mesh", TK_MESH,
"vertices", TK_VERTICES,
"edges", TK_EDGES,
"position", TK_POSITION,
"polygons", TK_POLYGONS,
"nodes", TK_NODES,
"rotation", TK_ROTATION,
"scaling", TK_SCALING,
"translation", TK_TRANSLATION,
"vertex", TK_VERTEX,
"HRCH", TK_HRCH,
"Softimage", TK_SOFTIMAGE,
"material", TK_MATERIAL,
"spline", TK_SPLINE,
"Named", TK_C_NAMED,
"object", TK_OBJECT,
"Tri", TK_C_TRI,
"Vertices", TK_C_VERTICES,
"Faces", TK_C_FACES,
"Vertex", TK_C_VERTEX,
"list", TK_LIST,
"Face", TK_C_FACE,
"Hexen", TK_C_HEXEN,
"Triangles", TK_C_TRIANGLES,
"Version", TK_C_VERSION,
"faces", TK_FACES,
"face", TK_FACE,
"origin", TK_ORIGIN,
"DK_clusters", TK_CLUSTERS,
"DK_cluster_ncvs", TK_NUM_CLUSTER_VERTICES,
"name", TK_NAME,
"DK_cluster_name", TK_CLUSTER_NAME,
"DK_cluster_state", TK_CLUSTER_STATE,
"actor_data", TK_ACTOR_DATA,
"uvTexture", TK_UVTEXTURE,
NULL, -1
};
static char *TokenNames[] =
{
"<nothing>",
"<unknown_char>",
"<EOF>",
"<identifier>",
"<string>",
"<int_number>",
"<float_number>",
"(",
")",
"{",
"}",
"[",
"]",
":",
"mesh",
"model",
"nodes",
"rotation",
"scaling",
"translation",
"polygons",
"position",
"vertex",
"vertices",
"HRCH",
"Softimage"
};
// CODE --------------------------------------------------------------------
//==========================================================================
//
// TK_Init
//
//==========================================================================
void TK_Init(void)
{
int i;
for(i = 0; i < 256; i++)
{
ASCIIToChrCode[i] = CHR_SPECIAL;
}
for(i = '0'; i <= '9'; i++)
{
ASCIIToChrCode[i] = CHR_NUMBER;
}
for(i = 'A'; i <= 'Z'; i++)
{
ASCIIToChrCode[i] = CHR_LETTER;
}
for(i = 'a'; i <= 'z'; i++)
{
ASCIIToChrCode[i] = CHR_LETTER;
}
ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
tk_String = TokenStringBuffer;
IncLineNumber = FALSE;
SourceOpen = FALSE;
}
//==========================================================================
//
// TK_OpenSource
//
//==========================================================================
void TK_OpenSource(char *fileName)
{
int size;
TK_CloseSource();
size = LoadFile(fileName, (void **)&FileStart);
strcpy(tk_SourceName, fileName);
SourceOpen = TRUE;
FileEnd = FileStart+size;
FilePtr = FileStart;
tk_Line = 1;
tk_Token = TK_NONE;
NextChr();
}
//==========================================================================
//
// TK_CloseSource
//
//==========================================================================
void TK_CloseSource(void)
{
if(SourceOpen)
{
free(FileStart);
SourceOpen = FALSE;
}
}
//==========================================================================
//
// TK_Fetch
//
//==========================================================================
tokenType_t TK_Fetch(void)
{
while(Chr == ASCII_SPACE)
{
NextChr();
}
if(Chr == '-')
{
ProcessNumberToken();
}
else switch(ASCIIToChrCode[(byte)Chr])
{
case CHR_EOF:
tk_Token = TK_EOF;
break;
case CHR_LETTER:
ProcessLetterToken();
break;
case CHR_NUMBER:
ProcessNumberToken();
break;
case CHR_QUOTE:
ProcessQuoteToken();
break;
default:
ProcessSpecialToken();
break;
}
return tk_Token;
}
//==========================================================================
//
// TK_Require
//
//==========================================================================
void TK_Require(tokenType_t tokType)
{
if(tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER)
{
tk_FloatNumber = (float)tk_IntNumber;
tk_Token = TK_FLOATNUMBER;
return;
}
if(tk_Token != tokType)
{
Error("File '%s', line %d:\nExpected '%s', found '%s'.\n",
tk_SourceName, tk_Line, TokenNames[tokType],
TokenNames[tk_Token]);
}
}
void TK_FetchRequire(tokenType_t tokType)
{
TK_Fetch();
TK_Require(tokType);
}
tokenType_t TK_RequireFetch(tokenType_t tokType)
{
TK_Require(tokType);
return TK_Fetch();
}
tokenType_t TK_FetchRequireFetch(tokenType_t tokType)
{
TK_Fetch();
TK_Require(tokType);
return TK_Fetch();
}
tokenType_t TK_Beyond(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
Error("File '%s':\nCould not find token '%s'.\n", // FIXME: TokenNames table not big enuff
tk_SourceName, TokenNames[tokType]);
}
}
return TK_Fetch();
}
void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok)
{
TK_Beyond(bTok);
TK_Require(rTok);
}
tokenType_t TK_Search(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
return TK_EOF;
}
}
return TK_Fetch();
}
tokenType_t TK_Get(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
Error("File '%s':\nCould not find token '%s'.\n",
tk_SourceName, TokenNames[tokType]);
}
}
return tk_Token;
}
//==========================================================================
//
// ProcessLetterToken
//
//==========================================================================
static void ProcessLetterToken(void)
{
int i;
char *text;
i = 0;
text = TokenStringBuffer;
while(ASCIIToChrCode[(byte)Chr] == CHR_LETTER
|| ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
if(++i == MAX_IDENTIFIER_LENGTH)
{
Error("File '%s', line %d:\nIdentifier too long.\n",
tk_SourceName, tk_Line);
}
*text++ = Chr;
NextChr();
}
*text = 0;
if(CheckForKeyword() == FALSE)
{
tk_Token = TK_IDENTIFIER;
}
}
//==========================================================================
//
// CheckForKeyword
//
//==========================================================================
static qboolean CheckForKeyword(void)
{
int i;
for(i = 0; Keywords[i].name != NULL; i++)
{
if(strcmp(tk_String, Keywords[i].name) == 0)
{
tk_Token = Keywords[i].token;
return TRUE;
}
}
return FALSE;
}
//==========================================================================
//
// ProcessNumberToken
//
//==========================================================================
static void ProcessNumberToken(void)
{
char *buffer;
buffer = TempBuffer;
*buffer++ = Chr;
NextChr();
while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
*buffer++ = Chr;
NextChr();
}
if(Chr == '.')
{ // Float
*buffer++ = Chr;
NextChr(); // Skip period
while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
*buffer++ = Chr;
NextChr();
}
*buffer = 0;
tk_FloatNumber = (float)atof(TempBuffer);
tk_Token = TK_FLOATNUMBER;
return;
}
// Integer
*buffer = 0;
tk_IntNumber = atoi(TempBuffer);
tk_Token = TK_INTNUMBER;
}
//==========================================================================
//
// ProcessQuoteToken
//
//==========================================================================
static void ProcessQuoteToken(void)
{
int i;
char *text;
i = 0;
text = TokenStringBuffer;
NextChr();
while(Chr != ASCII_QUOTE)
{
if(Chr == EOF_CHARACTER)
{
Error("File '%s', line %d:\n<EOF> inside string.\n",
tk_SourceName, tk_Line);
}
if(++i > MAX_QUOTED_LENGTH-1)
{
Error("File '%s', line %d:\nString literal too long.\n",
tk_SourceName, tk_Line);
}
*text++ = Chr;
NextChr();
}
*text = 0;
NextChr();
tk_Token = TK_STRING;
}
//==========================================================================
//
// ProcessSpecialToken
//
//==========================================================================
static void ProcessSpecialToken(void)
{
char c;
c = Chr;
NextChr();
switch(c)
{
case '(':
tk_Token = TK_LPAREN;
break;
case ')':
tk_Token = TK_RPAREN;
break;
case '{':
tk_Token = TK_LBRACE;
break;
case '}':
tk_Token = TK_RBRACE;
break;
case '[':
tk_Token = TK_LBRACKET;
break;
case ']':
tk_Token = TK_RBRACKET;
break;
case ':':
tk_Token = TK_COLON;
break;
default:
tk_Token = TK_UNKNOWNCHAR;
break;
}
}
//==========================================================================
//
// NextChr
//
//==========================================================================
static void NextChr(void)
{
if(FilePtr >= FileEnd)
{
Chr = EOF_CHARACTER;
return;
}
if(IncLineNumber == TRUE)
{
tk_Line++;
IncLineNumber = FALSE;
}
Chr = *FilePtr++;
if(Chr < ASCII_SPACE)
{
if(Chr == '\n')
{
IncLineNumber = TRUE;
}
Chr = ASCII_SPACE;
}
}

View File

@@ -0,0 +1,132 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//**************************************************************************
//**
//** token.h
//**
//**************************************************************************
#ifndef __TOKEN_H__
#define __TOKEN_H__
#include "cmdlib.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef YES
#define YES 1
#endif
#ifndef NO
#define NO 0
#endif
#define ASCII_SPACE 32
#define ASCII_QUOTE 34
#define ASCII_UNDERSCORE 95
#define EOF_CHARACTER 127
#define MAX_IDENTIFIER_LENGTH 64
#define MAX_QUOTED_LENGTH 1024
#define MAX_FILE_NAME_LENGTH 1024
typedef enum
{
TK_NONE,
TK_UNKNOWNCHAR,
TK_EOF,
TK_IDENTIFIER, // VALUE: (char *) tk_String
TK_STRING, // VALUE: (char *) tk_String
TK_INTNUMBER, // VALUE: (int) tk_IntNumber
TK_FLOATNUMBER, // VALUE: (float) tk_FloatNumber
TK_LPAREN,
TK_RPAREN,
TK_LBRACE,
TK_RBRACE, // 10
TK_LBRACKET,
TK_RBRACKET,
TK_COLON,
TK_MESH,
TK_MODEL, // 15
TK_NODES,
TK_ROTATION,
TK_SCALING,
TK_TRANSLATION,
TK_POLYGONS, // 20
TK_POSITION,
TK_VERTEX,
TK_VERTICES,
TK_EDGES,
TK_HRCH, // 25
TK_SOFTIMAGE,
TK_MATERIAL,
TK_SPLINE, // 28
TK_C_NAMED,
TK_OBJECT, // 30
TK_C_TRI,
TK_C_VERTICES,
TK_C_FACES,
TK_C_VERTEX,
TK_LIST, // 35
TK_C_FACE,
TK_C_HEXEN,
TK_C_TRIANGLES,
TK_C_VERSION,
TK_FACES, // 40
TK_FACE,
TK_ORIGIN,
TK_CLUSTERS,
TK_NUM_CLUSTER_VERTICES,
TK_NAME, // 45
TK_CLUSTER_NAME,
TK_CLUSTER_STATE,
TK_ACTOR_DATA,
TK_UVTEXTURE,
} tokenType_t;
void TK_Init(void);
void TK_OpenSource(char *fileName);
void TK_CloseSource(void);
tokenType_t TK_Fetch(void);
void TK_Require(tokenType_t tokType);
void TK_FetchRequire(tokenType_t tokType);
tokenType_t TK_RequireFetch(tokenType_t tokType);
tokenType_t TK_FetchRequireFetch(tokenType_t tokType);
tokenType_t TK_Beyond(tokenType_t tokType);
void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok);
tokenType_t TK_Search(tokenType_t tokType);
tokenType_t TK_Get(tokenType_t tokType);
extern tokenType_t tk_Token;
extern int tk_Line;
extern int tk_IntNumber;
extern float tk_FloatNumber;
extern char *tk_String;
extern char tk_SourceName[MAX_FILE_NAME_LENGTH];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// trilib.h: header file for loading triangles from an Alias triangle file
//
#include "fmodel.h"
#define MAXTRIANGLES MAX_FM_TRIANGLES
typedef struct
{
vec3_t verts[3];
#if 1
int indicies[3];
float uv[3][2];
qboolean HasUV;
#endif
} triangle_t;
#define NUM_CLUSTERS 8
typedef struct
{
char name[64];
byte tris[MAXTRIANGLES>>3];
byte verts[MAX_FM_VERTS>>3];
int start_glcmds, num_glcmds;
int *clusters[NUM_CLUSTERS];
struct IntListNode_s *vertLists[NUM_CLUSTERS];
int num_verts[NUM_CLUSTERS + 1];
int new_num_verts[NUM_CLUSTERS + 1];
qboolean clustered;
} mesh_node_t;
void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,572 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include <math.h>
#include "token.h"
#include "joints.h"
#include "angles.h"
#include "inout.h"
char *SKEL_ROOT_NAMES[] =
{
"RAVEN_SPINE"
};
char *SKEL_NAMES[] =
{
"RAVEN_WAIST1",
"RAVEN_WAIST2",
"RAVEN_NECK"
};
int NAME_OFFSETS[] =
{
0
};
int numJointsForSkeleton[] =
{
NUM_JOINTS_RAVEN,
NUM_JOINTS_BOX
};
float g_scaling[3];
float g_rotation[3];
float g_translation[3];
//==========================================================================
//
// LoadHRCClustered
//
//==========================================================================
static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
{
int i, j;
TK_OpenSource(fileName);
TK_FetchRequire(TK_HRCH);
TK_FetchRequire(TK_COLON);
TK_FetchRequire(TK_SOFTIMAGE);
TK_Beyond(TK_CLUSTERS);
while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
{
TK_Require(TK_STRING);
for( i = 0; i < numJointsForSkeleton[skelType]; ++i)
{
if(stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
{
i = -i + numJointsForSkeleton[skelType] - 1;
TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
num_verts[i+1] = tk_IntNumber;
clusterList[i] = (int *) SafeMalloc(num_verts[i+1]*sizeof(int), "LoadHRCClustered");
assert(clusterList[i]);
// currently this function is only called by LoadTriangleListClustered, which in turn is only
// called by Cmd_Base in qdata. This is where the only call to free for this memory is being made.
TK_Beyond(TK_LBRACE);
for(j = 0; j < num_verts[i+1]; ++j)
{
TK_Require(TK_INTNUMBER);
clusterList[i][j] = tk_IntNumber;
TK_Fetch();
}
break;
}
}
}
num_verts[0] = numJointsForSkeleton[skelType];
}
static void LoadHRCGlobals(char *fileName)
{
int i;
TK_OpenSource(fileName);
TK_FetchRequire(TK_HRCH);
TK_FetchRequire(TK_COLON);
TK_FetchRequire(TK_SOFTIMAGE);
TK_Beyond(TK_MODEL);
TK_Beyond(TK_SCALING);
for(i = 0; i < 3; i++)
{
TK_Require(TK_FLOATNUMBER);
g_scaling[i] = tk_FloatNumber;
TK_Fetch();
}
TK_Beyond(TK_ROTATION);
for(i = 0; i < 3; i++)
{
TK_Require(TK_FLOATNUMBER);
g_rotation[i] = tk_FloatNumber;
TK_Fetch();
}
TK_Beyond(TK_TRANSLATION);
for(i = 0; i < 3; i++)
{
TK_Require(TK_FLOATNUMBER);
g_translation[i] = tk_FloatNumber;
TK_Fetch();
}
}
static void ParseVec3(vec3_t in)
{
TK_Require(TK_FLOATNUMBER);
in[1] = tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[2] = tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[0] = tk_FloatNumber;
}
static void ParseRotation3(vec3_t in)
{
TK_Require(TK_FLOATNUMBER);
in[1] = -tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[2] = tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[0] = tk_FloatNumber;
}
static void ParseTranslation3(vec3_t in)
{
TK_Require(TK_FLOATNUMBER);
in[1] = tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[2] = tk_FloatNumber;
TK_FetchRequire(TK_FLOATNUMBER);
in[0] = tk_FloatNumber;
}
static void LoadHRCJointList(char *fileName, QDataJoint_t *jointList, int skelType)
{
#define MAX_STACK 64
int i, j;
vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
int curCorrespondingJoint[MAX_STACK];
int currentStack = 0, stackSize;
int baseJoint;
float cx, sx, cy, sy, cz, sz;
float rx, ry, rz;
float x2, y2, z2;
TK_OpenSource(fileName);
TK_FetchRequire(TK_HRCH);
TK_FetchRequire(TK_COLON);
TK_FetchRequire(TK_SOFTIMAGE);
TK_Beyond(TK_MODEL);
TK_Beyond(TK_MODEL);
/* while(1)
{
TK_Beyond(TK_MODEL);
TK_BeyondRequire(TK_NAME, TK_STRING);
if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
break;
}*/
TK_Beyond(TK_SCALING);
ParseVec3(curScale[currentStack]);
TK_Beyond(TK_ROTATION);
ParseRotation3(curRotation[currentStack]);
TK_Beyond(TK_TRANSLATION);
ParseVec3(curTranslation[currentStack]);
// account for global model translation
curTranslation[currentStack][1] += g_translation[0];
curTranslation[currentStack][2] += g_translation[1];
curTranslation[currentStack][0] += g_translation[2];
++currentStack;
for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
{
while(1)
{
TK_Beyond(TK_MODEL);
// TK_BeyondRequire(TK_NAME, TK_STRING);
// if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
break;
TK_Beyond(TK_SCALING);
ParseVec3(curScale[currentStack]);
TK_Beyond(TK_ROTATION);
ParseRotation3(curRotation[currentStack]);
TK_Beyond(TK_TRANSLATION);
ParseVec3(curTranslation[currentStack]);
curCorrespondingJoint[currentStack] = -1;
++currentStack;
}
TK_Beyond(TK_SCALING);
ParseVec3(curScale[currentStack]);
TK_Beyond(TK_ROTATION);
ParseRotation3(curRotation[currentStack]);
jointList[i].rotation[1] = curRotation[currentStack][1];
jointList[i].rotation[2] = curRotation[currentStack][2];
jointList[i].rotation[0] = curRotation[currentStack][0];
TK_Beyond(TK_TRANSLATION);
ParseVec3(curTranslation[currentStack]);
jointList[i].placement.origin[1] = curTranslation[currentStack][1];
jointList[i].placement.origin[2] = curTranslation[currentStack][2];
jointList[i].placement.origin[0] = curTranslation[currentStack][0];
jointList[i].placement.direction[1] = 7.5;
jointList[i].placement.direction[2] = 0.0;
jointList[i].placement.direction[0] = 0.0;
jointList[i].placement.up[1] = 0.0;
jointList[i].placement.up[2] = 7.5;
jointList[i].placement.up[0] = 0.0;
curCorrespondingJoint[currentStack] = i;
++currentStack;
}
stackSize = currentStack;
for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
{
rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
cx = cos(rx);
sx = sin(rx);
cy = cos(ry);
sy = sin(ry);
cz = cos(rz);
sz = sin(rz);
// y-axis rotation for direction
x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
jointList[i].placement.direction[0] = x2;
jointList[i].placement.direction[2] = z2;
// y-axis rotation for up
x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
jointList[i].placement.up[0] = x2;
jointList[i].placement.up[2] = z2;
// z-axis rotation for direction
x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
jointList[i].placement.direction[0] = x2;
jointList[i].placement.direction[1] = y2;
// z-axis rotation for up
x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
jointList[i].placement.up[0] = x2;
jointList[i].placement.up[1] = y2;
// x-axis rotation for direction vector
y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
jointList[i].placement.direction[1] = y2;
jointList[i].placement.direction[2] = z2;
// x-axis rotation for up vector
y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
jointList[i].placement.up[1] = y2;
jointList[i].placement.up[2] = z2;
// translate to position in model
jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
// translate to position in model
jointList[i].placement.up[0] += jointList[i].placement.origin[0];
jointList[i].placement.up[1] += jointList[i].placement.origin[1];
jointList[i].placement.up[2] += jointList[i].placement.origin[2];
}
baseJoint = NUM_JOINTS_RAVEN;
for(i = stackSize/*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i)
{
rx = curRotation[i-1][0]*ANGLE_TO_RAD;
ry = curRotation[i-1][1]*ANGLE_TO_RAD;
rz = curRotation[i-1][2]*ANGLE_TO_RAD;
cx = cos(rx);
sx = sin(rx);
cy = cos(ry);
sy = sin(ry);
cz = cos(rz);
sz = sin(rz);
for(j = i-1; j < stackSize-1; ++j)
{
// y-axis rotation for origin
x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
jointList[j].placement.origin[0] = x2;
jointList[j].placement.origin[2] = z2;
// y-axis rotation for direction
x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
jointList[j].placement.direction[0] = x2;
jointList[j].placement.direction[2] = z2;
// y-axis rotation for up
x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
jointList[j].placement.up[0] = x2;
jointList[j].placement.up[2] = z2;
// z-axis rotation for origin
x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
jointList[j].placement.origin[0] = x2;
jointList[j].placement.origin[1] = y2;
// z-axis rotation for direction
x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
jointList[j].placement.direction[0] = x2;
jointList[j].placement.direction[1] = y2;
// z-axis rotation for up
x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
jointList[j].placement.up[0] = x2;
jointList[j].placement.up[1] = y2;
// x-axis rotation for origin
y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
jointList[j].placement.origin[1] = y2;
jointList[j].placement.origin[2] = z2;
// x-axis rotation for direction vector
y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
jointList[j].placement.direction[1] = y2;
jointList[j].placement.direction[2] = z2;
// x-axis rotation for up vector
y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
jointList[j].placement.up[1] = y2;
jointList[j].placement.up[2] = z2;
if(curCorrespondingJoint[j+1] != -1)
{
// translate origin
jointList[j].placement.origin[0] += curTranslation[i-1][0];
jointList[j].placement.origin[1] += curTranslation[i-1][1];
jointList[j].placement.origin[2] += curTranslation[i-1][2];
// translate back to local coord
jointList[j].placement.direction[0] += curTranslation[i-1][0];
jointList[j].placement.direction[1] += curTranslation[i-1][1];
jointList[j].placement.direction[2] += curTranslation[i-1][2];
// translate back to local coord
jointList[j].placement.up[0] += curTranslation[i-1][0];
jointList[j].placement.up[1] += curTranslation[i-1][1];
jointList[j].placement.up[2] += curTranslation[i-1][2];
}
}
}
}
void LoadGlobals(char *fileName)
{
FILE *file1;
int dot = '.';
char *dotstart;
char InputFileName[256];
dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
if (!dotstart)
{
strcpy(InputFileName, fileName);
strcat(InputFileName, ".hrc");
if((file1 = fopen(InputFileName, "rb")) != NULL)
{
fclose(file1);
LoadHRCGlobals(InputFileName);
printf(" - assuming .HRC\n");
return;
}
Error("\n Could not open file '%s':\n"
"No HRC match.\n", fileName);
}
else
{
if((file1 = fopen(fileName, "rb")) != NULL)
{
printf("\n");
fclose(file1);
if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
{
LoadHRCGlobals(fileName);
return;
}
}
Error("Could not open file '%s':\n",fileName);
}
}
void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
{
FILE *file1;
int dot = '.';
char *dotstart;
char InputFileName[256];
dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
if (!dotstart)
{
strcpy(InputFileName, fileName);
strcat(InputFileName, ".hrc");
if((file1 = fopen(InputFileName, "rb")) != NULL)
{
fclose(file1);
LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
printf(" - assuming .HRC\n");
return;
}
Error("\n Could not open file '%s':\n"
"No HRC match.\n", fileName);
}
else
{
if((file1 = fopen(fileName, "rb")) != NULL)
{
printf("\n");
fclose(file1);
if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
{
LoadHRCClustered(fileName, clusterList, num_verts, skelType);
return;
}
}
Error("Could not open file '%s':\n",fileName);
}
}
void LoadJointList(char *fileName, QDataJoint_t *jointList, int skelType)
{
FILE *file1;
int dot = '.';
char *dotstart;
char InputFileName[256];
dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
if (!dotstart)
{
strcpy(InputFileName, fileName);
strcat(InputFileName, ".hrc");
if((file1 = fopen(InputFileName, "rb")) != NULL)
{
fclose(file1);
LoadHRCJointList(InputFileName, jointList, skelType);
printf(" - assuming .HRC\n");
return;
}
Error("\n Could not open file '%s':\n"
"No HRC.\n", fileName);
}
else
{
if((file1 = fopen(fileName, "rb")) != NULL)
{
printf("\n");
fclose(file1);
if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
{
LoadHRCJointList(fileName, jointList, skelType);
return;
}
}
Error("Could not open file '%s':\n",fileName);
}
}

View File

@@ -0,0 +1,35 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _JOINTED_H
#define _JOINTED_H
#include "joints.h"
void LoadGlobals(char *fileName);
void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skel_type);
void LoadJointList(char *fileName, struct QDataJoint_s *jointList, int num_verts);
#define NUM_CLUSTERS 8
#define NOT_JOINTED -1
#endif //_JOINTED_H

View File

@@ -0,0 +1,144 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef JOINTS_H
#define JOINTS_H
#ifdef _HERETIC2_
#include "angles.h"
#endif
//typedef float vec3_t[3];
//typedef unsigned char byte;
#ifndef _WIN32
#define stricmp strcasecmp
#define strcmpi strcasecmp
#endif
typedef struct Placement_s
{
vec3_t origin;
vec3_t direction;
vec3_t up;
} Placement_t;
#if 1
typedef struct QDataJoint_s
{
Placement_t placement;
vec3_t rotation;
} QDataJoint_t;
#endif
typedef struct ArrayedListNode_s
{
int data;
int next;
int inUse;
} ArrayedListNode_t;
#define ARRAYEDLISTNODE_NULL -1
typedef struct JointAngles_s
{
float angles[3];
int children;
int created;
} JointAngles_t;
typedef struct JointAngles2_s
{
float angles[3];
int children;
int changed[3];
int inUse;
} JointAngles2_t;
#define MAX_MODELJOINTS 256
#define MAX_MODELJOINTNODES 255
extern JointAngles_t jointAngles[MAX_MODELJOINTS];
extern JointAngles2_t jointAngles2[MAX_MODELJOINTS];
extern ArrayedListNode_t jointAngleNodes[MAX_MODELJOINTNODES];
// Skeletal structures enums
enum {
SKEL_RAVEN = 0,
SKEL_BOX,
NUM_SKELETONS
};
// Raven Skeletal structures enums
enum {
RAVEN_WAIST1 = 0,
RAVEN_WAIST2 = 1,
RAVEN_HEAD = 2,
NUM_JOINTS_RAVEN
};
// Box Skeletal structures enums
enum {
BOX_CENTER = 0,
NUM_JOINTS_BOX
};
extern int numJointsForSkeleton[];
extern char *RAVEN_SKEL_NAMES[];
#define J_NEW_SKELETON 0x00001000
#define J_YAW_CHANGED 0x00002000
#define J_PITCH_CHANGED 0x00004000
#define J_ROLL_CHANGED 0x00008000
#define MAX_JOINTS 0x00000fff
/*
inline int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
{ // yeah, I know this is a sucky, inefficient way to do this, but I didn't feel like taking the time to write a real resource manager in C
int i;
for(i = 0; i < max; ++i)
{
if(!nodeArray[i].inUse)
{
nodeArray[i].inUse = 1;
return i;
}
}
assert(0);
return -1;
}
inline void FreeNode(ArrayedListNode_t *nodeArray, int index)
{
nodeArray[index].inUse = 0;
}
*/
int CreateSkeleton(int structure);
void CreateSkeletonAtIndex(int structure, int index);
void FreeSkeleton(int structure, int index);
void SetJointAngle(int jointIndex, int angleIndex, float angle);
float ModifyJointAngle(int jointIndex, int angleIndex, float deltaAngle);
int ZeroJointAngle(int jointIndex, int angleIndex, float angVel);
int ApplyAngVelToJoint(int jointIndex, int angleIndex, float angVel, float destAng);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "qdata.h"
byte *byteimage, *lbmpalette;
int byteimagewidth, byteimageheight;
qboolean TrueColorImage;
unsigned *longimage;
int longimagewidth, longimageheight;
char pic_prefix[1024];
extern char *g_outputDir;
/*
===============
Cmd_Pic
===============
*/
void Cmd_Pic (void)
{
int xl,yl,xh,yh,w,h;
byte *dest, *source;
int flags, value, contents;
char lumpname[128];
char animname[128];
byte buffer[256*256];
unsigned bufferl[256*256];
char filename[1024];
unsigned *destl, *sourcel;
int linedelta, x, y;
int size;
miptex_t *qtex;
miptex32_t *qtex32;
float scale_x, scale_y;
GetScriptToken (false);
strcpy (lumpname, token);
GetScriptToken (false);
xl = atoi (token);
GetScriptToken (false);
yl = atoi (token);
GetScriptToken (false);
w = atoi (token);
GetScriptToken (false);
h = atoi (token);
total_x += w;
total_y += h;
total_textures++;
if ( (w & 7) || (h & 7) )
Error ("line %i: miptex sizes must be multiples of 8", scriptline);
flags = 0;
contents = 0;
value = 0;
animname[0] = 0;
scale_x = scale_y = 0.5;
if (TrueColorImage)
{
sprintf (filename, "%spics/%s/%s.m32", g_outputDir, pic_prefix, lumpname);
if (g_release)
return; // textures are only released by $maps
xh = xl+w;
yh = yl+h;
if (xl >= longimagewidth || xh > longimagewidth ||
yl >= longimageheight || yh > longimageheight)
{
Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
}
sourcel = longimage + (yl*longimagewidth) + xl;
destl = bufferl;
linedelta = (longimagewidth - w);
for (y=yl ; y<yh ; y++)
{
for (x=xl ; x<xh ; x++)
{
*destl++ = *sourcel++; // RGBA
}
sourcel += linedelta;
}
qtex32 = CreateMip32(bufferl, w, h, &size, false);
qtex32->flags |= LittleLong(flags);
qtex32->contents = contents;
qtex32->value = value;
qtex32->scale_x = scale_x;
qtex32->scale_y = scale_y;
sprintf (qtex32->name, "%s/%s", pic_prefix, lumpname);
if (animname[0])
sprintf (qtex32->animname, "%s/%s", pic_prefix, animname);
//
// write it out
//
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)qtex32, size);
free (qtex32);
}
else
{
sprintf (filename, "%spics/%s/%s.m8", g_outputDir, pic_prefix, lumpname);
if (g_release)
return; // textures are only released by $maps
xh = xl+w;
yh = yl+h;
if (xl >= byteimagewidth || xh > byteimagewidth ||
yl >= byteimageheight || yh > byteimageheight)
{
Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
}
source = byteimage + yl*byteimagewidth + xl;
dest = buffer;
linedelta = byteimagewidth - w;
for (y=yl ; y<yh ; y++)
{
for (x=xl ; x<xh ; x++)
{
*dest++ = *source++;
}
source += linedelta;
}
qtex = CreateMip(buffer, w, h, lbmpalette, &size, false);
qtex->flags = flags;
qtex->contents = contents;
qtex->value = value;
sprintf (qtex->name, "%s/%s", pic_prefix, lumpname);
if (animname[0])
sprintf (qtex->animname, "%s/%s", pic_prefix, animname);
//
// write it out
//
printf ("writing %s\n", filename);
SaveFile (filename, (byte *)qtex, size);
free (qtex);
}
}
/*
===============
Cmd_picdir
===============
*/
void Cmd_Picdir (void)
{
char filename[1024];
GetScriptToken (false);
strcpy (pic_prefix, token);
// create the directory if needed
sprintf (filename, "%sPics", g_outputDir);
Q_mkdir (filename);
sprintf (filename, "%sPics/%s", g_outputDir, pic_prefix);
Q_mkdir (filename);
}

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