mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 00:49:29 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
789
tools/quake2/common/bspfile.c
Normal file
789
tools/quake2/common/bspfile.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
128
tools/quake2/common/bspfile.h
Normal file
128
tools/quake2/common/bspfile.h
Normal 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
1221
tools/quake2/common/cmdlib.c
Normal file
File diff suppressed because it is too large
Load Diff
170
tools/quake2/common/cmdlib.h
Normal file
170
tools/quake2/common/cmdlib.h
Normal 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
367
tools/quake2/common/inout.c
Normal 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);
|
||||
}
|
||||
|
||||
63
tools/quake2/common/inout.h
Normal file
63
tools/quake2/common/inout.h
Normal 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
|
||||
300
tools/quake2/common/l3dslib.c
Normal file
300
tools/quake2/common/l3dslib.c
Normal 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);
|
||||
}
|
||||
|
||||
25
tools/quake2/common/l3dslib.h
Normal file
25
tools/quake2/common/l3dslib.h
Normal 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);
|
||||
|
||||
837
tools/quake2/common/lbmlib.c
Normal file
837
tools/quake2/common/lbmlib.c
Normal 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);
|
||||
}
|
||||
38
tools/quake2/common/lbmlib.h
Normal file
38
tools/quake2/common/lbmlib.h
Normal 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);
|
||||
172
tools/quake2/common/mathlib.c
Normal file
172
tools/quake2/common/mathlib.c
Normal 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;
|
||||
}
|
||||
}
|
||||
75
tools/quake2/common/mathlib.h
Normal file
75
tools/quake2/common/mathlib.h
Normal 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
297
tools/quake2/common/md4.c
Normal 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;
|
||||
}
|
||||
404
tools/quake2/common/path_init.c
Normal file
404
tools/quake2/common/path_init.c
Normal 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" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
642
tools/quake2/common/polylib.c
Normal file
642
tools/quake2/common/polylib.c
Normal 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;
|
||||
}
|
||||
|
||||
54
tools/quake2/common/polylib.h
Normal file
54
tools/quake2/common/polylib.h
Normal 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);
|
||||
34
tools/quake2/common/q2_threads.h
Normal file
34
tools/quake2/common/q2_threads.h
Normal 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
|
||||
563
tools/quake2/common/qfiles.h
Normal file
563
tools/quake2/common/qfiles.h
Normal 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;
|
||||
296
tools/quake2/common/scriplib.c
Normal file
296
tools/quake2/common/scriplib.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
43
tools/quake2/common/scriplib.h
Normal file
43
tools/quake2/common/scriplib.h
Normal 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);
|
||||
|
||||
|
||||
622
tools/quake2/common/threads.c
Normal file
622
tools/quake2/common/threads.c
Normal 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
|
||||
186
tools/quake2/common/trilib.c
Normal file
186
tools/quake2/common/trilib.c
Normal 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);
|
||||
}
|
||||
|
||||
31
tools/quake2/common/trilib.h
Normal file
31
tools/quake2/common/trilib.h
Normal 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);
|
||||
|
||||
1329
tools/quake2/q2map/brushbsp.c
Normal file
1329
tools/quake2/q2map/brushbsp.c
Normal file
File diff suppressed because it is too large
Load Diff
634
tools/quake2/q2map/csg.c
Normal file
634
tools/quake2/q2map/csg.c
Normal 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
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
787
tools/quake2/q2map/flow.c
Normal 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
231
tools/quake2/q2map/gldraw.c
Normal 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
148
tools/quake2/q2map/glfile.c
Normal 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);
|
||||
}
|
||||
|
||||
180
tools/quake2/q2map/leakfile.c
Normal file
180
tools/quake2/q2map/leakfile.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
1315
tools/quake2/q2map/lightmap.c
Normal file
1315
tools/quake2/q2map/lightmap.c
Normal file
File diff suppressed because it is too large
Load Diff
721
tools/quake2/q2map/main.c
Normal file
721
tools/quake2/q2map/main.c
Normal 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
1017
tools/quake2/q2map/map.c
Normal file
File diff suppressed because it is too large
Load Diff
46
tools/quake2/q2map/nodraw.c
Normal file
46
tools/quake2/q2map/nodraw.c
Normal 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)
|
||||
{
|
||||
}
|
||||
603
tools/quake2/q2map/patches.c
Normal file
603
tools/quake2/q2map/patches.c
Normal 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
1110
tools/quake2/q2map/portals.c
Normal file
File diff suppressed because it is too large
Load Diff
286
tools/quake2/q2map/prtfile.c
Normal file
286
tools/quake2/q2map/prtfile.c
Normal 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);
|
||||
}
|
||||
|
||||
290
tools/quake2/q2map/q2map.dsp
Normal file
290
tools/quake2/q2map/q2map.dsp
Normal 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
|
||||
50
tools/quake2/q2map/q2map.h
Normal file
50
tools/quake2/q2map/q2map.h
Normal 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 ();
|
||||
330
tools/quake2/q2map/q2map.vcproj
Normal file
330
tools/quake2/q2map/q2map.vcproj
Normal 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;"..\..\..\..\libxml2-2.6\include""
|
||||
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=""..\..\..\..\libxml2-2.6\win32\lib""
|
||||
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 "$(TargetPath)" "$(SolutionDir)install""/>
|
||||
<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;"..\..\..\..\libxml2-2.6\include""
|
||||
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=""..\..\..\..\libxml2-2.6\win32\lib""
|
||||
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 "$(TargetPath)" "$(SolutionDir)install""/>
|
||||
<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 "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
426
tools/quake2/q2map/qbsp.c
Normal file
426
tools/quake2/q2map/qbsp.c
Normal 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
390
tools/quake2/q2map/qbsp.h
Normal 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
647
tools/quake2/q2map/qrad.c
Normal 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
184
tools/quake2/q2map/qrad.h
Normal 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
581
tools/quake2/q2map/qvis.c
Normal 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
169
tools/quake2/q2map/qvis.h
Normal 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;
|
||||
249
tools/quake2/q2map/textures.c
Normal file
249
tools/quake2/q2map/textures.c
Normal 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
298
tools/quake2/q2map/trace.c
Normal 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
218
tools/quake2/q2map/tree.c
Normal 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);
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
591
tools/quake2/q2map/writebsp.c
Normal file
591
tools/quake2/q2map/writebsp.c
Normal 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
162
tools/quake2/qdata/anorms.h
Normal 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
763
tools/quake2/qdata/images.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
81
tools/quake2/qdata/makefile
Normal file
81
tools/quake2/qdata/makefile
Normal 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
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
553
tools/quake2/qdata/qdata.c
Normal 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;
|
||||
}
|
||||
|
||||
93
tools/quake2/qdata/qdata.h
Normal file
93
tools/quake2/qdata/qdata.h
Normal 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;
|
||||
218
tools/quake2/qdata/qdata3.dsp
Normal file
218
tools/quake2/qdata/qdata3.dsp
Normal 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
|
||||
231
tools/quake2/qdata/qdata3.vcproj
Normal file
231
tools/quake2/qdata/qdata3.vcproj
Normal 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;"..\..\..\..\libxml2\win32\binaries-debug""
|
||||
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;"..\..\..\..\libxml2\win32\binaries-release""
|
||||
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>
|
||||
228
tools/quake2/qdata/sprites.c
Normal file
228
tools/quake2/qdata/sprites.c
Normal 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
171
tools/quake2/qdata/tables.c
Normal 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
1259
tools/quake2/qdata/video.c
Normal file
File diff suppressed because it is too large
Load Diff
49
tools/quake2/qdata_heretic2/adpcm.h
Normal file
49
tools/quake2/qdata_heretic2/adpcm.h
Normal 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
|
||||
351
tools/quake2/qdata_heretic2/animcomp.c
Normal file
351
tools/quake2/qdata_heretic2/animcomp.c
Normal 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);
|
||||
}
|
||||
43
tools/quake2/qdata_heretic2/animcomp.h
Normal file
43
tools/quake2/qdata_heretic2/animcomp.h
Normal 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
|
||||
|
||||
184
tools/quake2/qdata_heretic2/anorms.h
Normal file
184
tools/quake2/qdata_heretic2/anorms.h
Normal 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},
|
||||
|
||||
372
tools/quake2/qdata_heretic2/book.c
Normal file
372
tools/quake2/qdata_heretic2/book.c
Normal 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
|
||||
793
tools/quake2/qdata_heretic2/common/bspfile.c
Normal file
793
tools/quake2/qdata_heretic2/common/bspfile.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
133
tools/quake2/qdata_heretic2/common/bspfile.h
Normal file
133
tools/quake2/qdata_heretic2/common/bspfile.h
Normal 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
|
||||
1238
tools/quake2/qdata_heretic2/common/cmdlib.c
Normal file
1238
tools/quake2/qdata_heretic2/common/cmdlib.c
Normal file
File diff suppressed because it is too large
Load Diff
177
tools/quake2/qdata_heretic2/common/cmdlib.h
Normal file
177
tools/quake2/qdata_heretic2/common/cmdlib.h
Normal 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
|
||||
35
tools/quake2/qdata_heretic2/common/her2_threads.h
Normal file
35
tools/quake2/qdata_heretic2/common/her2_threads.h
Normal 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
|
||||
367
tools/quake2/qdata_heretic2/common/inout.c
Normal file
367
tools/quake2/qdata_heretic2/common/inout.c
Normal 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);
|
||||
}
|
||||
|
||||
63
tools/quake2/qdata_heretic2/common/inout.h
Normal file
63
tools/quake2/qdata_heretic2/common/inout.h
Normal 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
|
||||
476
tools/quake2/qdata_heretic2/common/l3dslib.c
Normal file
476
tools/quake2/qdata_heretic2/common/l3dslib.c
Normal 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);
|
||||
}
|
||||
28
tools/quake2/qdata_heretic2/common/l3dslib.h
Normal file
28
tools/quake2/qdata_heretic2/common/l3dslib.h
Normal 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);
|
||||
1052
tools/quake2/qdata_heretic2/common/lbmlib.c
Normal file
1052
tools/quake2/qdata_heretic2/common/lbmlib.c
Normal file
File diff suppressed because it is too large
Load Diff
41
tools/quake2/qdata_heretic2/common/lbmlib.h
Normal file
41
tools/quake2/qdata_heretic2/common/lbmlib.h
Normal 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);
|
||||
176
tools/quake2/qdata_heretic2/common/mathlib.c
Normal file
176
tools/quake2/qdata_heretic2/common/mathlib.c
Normal 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;
|
||||
}
|
||||
}
|
||||
76
tools/quake2/qdata_heretic2/common/mathlib.h
Normal file
76
tools/quake2/qdata_heretic2/common/mathlib.h
Normal 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
|
||||
298
tools/quake2/qdata_heretic2/common/md4.c
Normal file
298
tools/quake2/qdata_heretic2/common/md4.c
Normal 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;
|
||||
}
|
||||
405
tools/quake2/qdata_heretic2/common/path_init.c
Normal file
405
tools/quake2/qdata_heretic2/common/path_init.c
Normal 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" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
656
tools/quake2/qdata_heretic2/common/polylib.c
Normal file
656
tools/quake2/qdata_heretic2/common/polylib.c
Normal 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;
|
||||
}
|
||||
|
||||
55
tools/quake2/qdata_heretic2/common/polylib.h
Normal file
55
tools/quake2/qdata_heretic2/common/polylib.h
Normal 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);
|
||||
82
tools/quake2/qdata_heretic2/common/qfiles.c
Normal file
82
tools/quake2/qdata_heretic2/common/qfiles.c
Normal 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;
|
||||
}
|
||||
619
tools/quake2/qdata_heretic2/common/qfiles.h
Normal file
619
tools/quake2/qdata_heretic2/common/qfiles.h
Normal 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
|
||||
297
tools/quake2/qdata_heretic2/common/scriplib.c
Normal file
297
tools/quake2/qdata_heretic2/common/scriplib.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
44
tools/quake2/qdata_heretic2/common/scriplib.h
Normal file
44
tools/quake2/qdata_heretic2/common/scriplib.h
Normal 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);
|
||||
|
||||
|
||||
620
tools/quake2/qdata_heretic2/common/threads.c
Normal file
620
tools/quake2/qdata_heretic2/common/threads.c
Normal 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
|
||||
550
tools/quake2/qdata_heretic2/common/token.c
Normal file
550
tools/quake2/qdata_heretic2/common/token.c
Normal 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;
|
||||
}
|
||||
}
|
||||
132
tools/quake2/qdata_heretic2/common/token.h
Normal file
132
tools/quake2/qdata_heretic2/common/token.h
Normal 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
|
||||
1077
tools/quake2/qdata_heretic2/common/trilib.c
Normal file
1077
tools/quake2/qdata_heretic2/common/trilib.c
Normal file
File diff suppressed because it is too large
Load Diff
56
tools/quake2/qdata_heretic2/common/trilib.h
Normal file
56
tools/quake2/qdata_heretic2/common/trilib.h
Normal 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);
|
||||
3404
tools/quake2/qdata_heretic2/fmodels.c
Normal file
3404
tools/quake2/qdata_heretic2/fmodels.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
tools/quake2/qdata_heretic2/icon1.ico
Normal file
BIN
tools/quake2/qdata_heretic2/icon1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
1397
tools/quake2/qdata_heretic2/images.c
Normal file
1397
tools/quake2/qdata_heretic2/images.c
Normal file
File diff suppressed because it is too large
Load Diff
572
tools/quake2/qdata_heretic2/jointed.c
Normal file
572
tools/quake2/qdata_heretic2/jointed.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
35
tools/quake2/qdata_heretic2/jointed.h
Normal file
35
tools/quake2/qdata_heretic2/jointed.h
Normal 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
|
||||
144
tools/quake2/qdata_heretic2/joints.h
Normal file
144
tools/quake2/qdata_heretic2/joints.h
Normal 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
|
||||
2050
tools/quake2/qdata_heretic2/models.c
Normal file
2050
tools/quake2/qdata_heretic2/models.c
Normal file
File diff suppressed because it is too large
Load Diff
198
tools/quake2/qdata_heretic2/pics.c
Normal file
198
tools/quake2/qdata_heretic2/pics.c
Normal 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
Reference in New Issue
Block a user