From: Thomas Debesse Date: Fri, 5 Jul 2019 22:33:50 +0000 (+0200) Subject: tools/heretic2: move heretic2 stuff to its own directory X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0a780d5e3586c9116b7d8bacaee711853931367a;p=xonotic%2Fnetradiant.git tools/heretic2: move heretic2 stuff to its own directory --- diff --git a/Makefile b/Makefile index 85049a8b..cdfbff0f 100644 --- a/Makefile +++ b/Makefile @@ -1019,38 +1019,38 @@ $(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): \ contrib/bkgrnd2d/plugin.o \ $(INSTALLDIR)/heretic2/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML) -$(INSTALLDIR)/heretic2/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/quake2/qdata_heretic2/common -Itools/quake2/qdata_heretic2/qcommon -Itools/quake2/qdata_heretic2 -Itools/quake2/common -Ilibs -Iinclude +$(INSTALLDIR)/heretic2/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/heretic2/common -Itools/heretic2/qcommon -Itools/heretic2/h2data -Itools/quake2/common -Ilibs -Iinclude $(INSTALLDIR)/heretic2/h2data.$(EXE): \ - tools/quake2/qdata_heretic2/common/bspfile.o \ - tools/quake2/qdata_heretic2/common/cmdlib.o \ - tools/quake2/qdata_heretic2/common/inout.o \ - tools/quake2/qdata_heretic2/common/l3dslib.o \ - tools/quake2/qdata_heretic2/common/lbmlib.o \ - tools/quake2/qdata_heretic2/common/mathlib.o \ - tools/quake2/qdata_heretic2/common/md4.o \ - tools/quake2/qdata_heretic2/common/path_init.o \ - tools/quake2/qdata_heretic2/common/qfiles.o \ - tools/quake2/qdata_heretic2/common/scriplib.o \ - tools/quake2/qdata_heretic2/common/threads.o \ - tools/quake2/qdata_heretic2/common/token.o \ - tools/quake2/qdata_heretic2/common/trilib.o \ - tools/quake2/qdata_heretic2/qcommon/reference.o \ - tools/quake2/qdata_heretic2/qcommon/resourcemanager.o \ - tools/quake2/qdata_heretic2/qcommon/skeletons.o \ - tools/quake2/qdata_heretic2/animcomp.o \ - tools/quake2/qdata_heretic2/book.o \ - tools/quake2/qdata_heretic2/fmodels.o \ - tools/quake2/qdata_heretic2/images.o \ - tools/quake2/qdata_heretic2/jointed.o \ - tools/quake2/qdata_heretic2/models.o \ - tools/quake2/qdata_heretic2/pics.o \ - tools/quake2/qdata_heretic2/qdata.o \ - tools/quake2/qdata_heretic2/qd_skeletons.o \ - tools/quake2/qdata_heretic2/sprites.o \ - tools/quake2/qdata_heretic2/svdcmp.o \ - tools/quake2/qdata_heretic2/tables.o \ - tools/quake2/qdata_heretic2/tmix.o \ - tools/quake2/qdata_heretic2/video.o \ + tools/heretic2/common/bspfile.o \ + tools/heretic2/common/cmdlib.o \ + tools/heretic2/common/inout.o \ + tools/heretic2/common/l3dslib.o \ + tools/heretic2/common/lbmlib.o \ + tools/heretic2/common/mathlib.o \ + tools/heretic2/common/md4.o \ + tools/heretic2/common/path_init.o \ + tools/heretic2/common/qfiles.o \ + tools/heretic2/common/scriplib.o \ + tools/heretic2/common/threads.o \ + tools/heretic2/common/token.o \ + tools/heretic2/common/trilib.o \ + tools/heretic2/qcommon/reference.o \ + tools/heretic2/qcommon/resourcemanager.o \ + tools/heretic2/qcommon/skeletons.o \ + tools/heretic2/h2data/animcomp.o \ + tools/heretic2/h2data/book.o \ + tools/heretic2/h2data/fmodels.o \ + tools/heretic2/h2data/images.o \ + tools/heretic2/h2data/jointed.o \ + tools/heretic2/h2data/models.o \ + tools/heretic2/h2data/pics.o \ + tools/heretic2/h2data/qdata.o \ + tools/heretic2/h2data/qd_skeletons.o \ + tools/heretic2/h2data/sprites.o \ + tools/heretic2/h2data/svdcmp.o \ + tools/heretic2/h2data/tables.o \ + tools/heretic2/h2data/tmix.o \ + tools/heretic2/h2data/video.o \ libl_net.$(A) \ $(if $(findstring $(OS),Win32),icons/h2data.o,) \ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b36bb6cf..b8f85654 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") add_subdirectory(quake2) -add_subdirectory(quake2/qdata_heretic2) +add_subdirectory(heretic2) add_subdirectory(quake3) add_custom_target(tools) diff --git a/tools/heretic2/CMakeLists.txt b/tools/heretic2/CMakeLists.txt new file mode 100644 index 00000000..0cb9cb4d --- /dev/null +++ b/tools/heretic2/CMakeLists.txt @@ -0,0 +1,73 @@ +include_directories(BEFORE h2data common qcommon) + +find_package(OpenGL REQUIRED) + +find_package(LibXml2 REQUIRED) +include_directories(${LIBXML2_INCLUDE_DIR}) + +radiant_tool(h2data + h2data/h2data.rc + + common/bspfile.c common/bspfile.h + common/cmdlib.c common/cmdlib.h + common/inout.c common/inout.h + common/l3dslib.c common/l3dslib.h + common/lbmlib.c common/lbmlib.h + common/mathlib.c common/mathlib.h + common/md4.c common/md4.h + common/path_init.c + common/polylib.c common/polylib.h + common/qfiles.c common/qfiles.h + common/scriplib.c common/scriplib.h + common/threads.c common/her2_threads.h + common/token.c common/token.h + common/trilib.c common/trilib.h + + qcommon/angles.h + qcommon/arrayedlist.h + qcommon/flex.h + qcommon/fmodel.h + qcommon/h2common.h + qcommon/placement.h + qcommon/qfiles.h + qcommon/q_typedef.h + qcommon/reference.c qcommon/reference.h + qcommon/resourcemanager.c qcommon/resourcemanager.h + qcommon/skeletons.c qcommon/skeletons.h + + h2data/adpcm.h + h2data/animcomp.c h2data/animcomp.h + h2data/anorms.h + h2data/book.c + h2data/fmodels.c h2data/qd_fmodel.h + h2data/images.c + h2data/jointed.c + h2data/jointed.h + h2data/joints.h + h2data/models.c + h2data/pics.c + h2data/qdata.c h2data/qdata.h + h2data/qd_skeletons.c h2data/qd_skeletons.h + h2data/resource.h + h2data/sprites.c + h2data/svdcmp.c + h2data/tables.c + h2data/tmix.c + h2data/video.c +) + +target_compile_definitions(h2data + PRIVATE +) + +target_link_libraries(h2data + ${LIBXML2_LIBRARIES} + l_net +) + +add_custom_target(heretic2) +add_dependencies(heretic2 h2data) + +if (UNIX) + target_link_libraries(h2data pthread m) +endif () diff --git a/tools/heretic2/common/bspfile.c b/tools/heretic2/common/bspfile.c new file mode 100644 index 00000000..add0ef30 --- /dev/null +++ b/tools/heretic2/common/bspfile.c @@ -0,0 +1,793 @@ +/* + Copyright (C) 1999-2007 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; +} diff --git a/tools/heretic2/common/bspfile.h b/tools/heretic2/common/bspfile.h new file mode 100644 index 00000000..f66659b5 --- /dev/null +++ b/tools/heretic2/common/bspfile.h @@ -0,0 +1,133 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/common/cmdlib.c b/tools/heretic2/common/cmdlib.c new file mode 100644 index 00000000..c45ff161 --- /dev/null +++ b/tools/heretic2/common/cmdlib.c @@ -0,0 +1,1186 @@ +/* + Copyright (C) 1999-2007 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 quake3/common + +#include "cmdlib.h" +#include "globaldefs.h" +#include "mathlib.h" +#include "inout.h" +#include +#include + +#if GDEF_OS_WINDOWS +#include +#include +#elif GDEF_OS_NEXT +#include +#else // OTHER OSES +#include +#endif // OTHER OSES + +#if !GDEF_OS_WINDOWS +#define strlwr strlower +#endif // !GDEF_OS_WINDOWS + +#define BASEDIRNAME "h" +#define PATHSEPERATOR '/' + +extern qboolean verbose; + +qboolean g_dokeypress = false; + +qboolean g_nomkdir = false; + + +#ifdef SAFE_MALLOC +void *safe_malloc( size_t size ){ + void *p; + + p = malloc( size ); + if ( !p ) { + Error( "safe_malloc failed on allocation of %i bytes", size ); + } + + return p; +} + +void *safe_malloc_info( size_t size, char* info ){ + void *p; + + p = malloc( size ); + if ( !p ) { + Error( "%s: safe_malloc failed on allocation of %i bytes", info, size ); + } + + return p; +} +#endif // !SAFE_MALLOC + +void *SafeMalloc( size_t n, char *desc ){ + void *p; + + if ( ( p = malloc( n ) ) == NULL ) { + Error( "Failed to allocate %d bytes for '%s'.\n", n, desc ); + } + memset( p, 0, n ); + return p; +} + +// set these before calling CheckParm +int myargc; +char **myargv; + +char com_token[1024]; +qboolean com_eof; + +qboolean archive; +char archivedir[1024]; + + +/* + =================== + ExpandWildcards + + Mimic unix command line expansion + =================== + */ +#define MAX_EX_ARGC 1024 + +int ex_argc; +char *ex_argv[MAX_EX_ARGC]; + +#if GDEF_OS_WINDOWS +#include "io.h" +void ExpandWildcards( int *argc, char ***argv ){ + struct _finddata_t fileinfo; + int handle; + int i; + char filename[1024]; + char filebase[1024]; + char *path; + + ex_argc = 0; + for ( i = 0 ; i < *argc ; i++ ) + { + path = ( *argv )[i]; + if ( path[0] == '-' + || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) { + ex_argv[ex_argc++] = path; + continue; + } + + handle = _findfirst( path, &fileinfo ); + if ( handle == -1 ) { + return; + } + + ExtractFilePath( path, filebase ); + + do + { + sprintf( filename, "%s%s", filebase, fileinfo.name ); + ex_argv[ex_argc++] = copystring( filename ); + } while ( _findnext( handle, &fileinfo ) != -1 ); + + _findclose( handle ); + } + + *argc = ex_argc; + *argv = ex_argv; +} +#else // !GDEF_OS_WINDOWS +void ExpandWildcards( int *argc, char ***argv ){ +} +#endif // !GDEF_OS_WINDOWS + +/* + + qdir will hold the path up to the quake directory, including the slash + + f:\quake\ + /raid/quake/ + + gamedir will hold qdir + the game directory (id1, id2, etc) + + */ + +char qdir[1024]; +char gamedir[1024]; +char writedir[1024]; + +void SetQdirFromPath( const char *path ){ + char temp[1024]; + const char *c; + const char *sep; + int len, count; + + if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial + Q_getwd( temp ); + strcat( temp, path ); + path = temp; + } + + // search for "quake2" in path + + len = strlen( BASEDIRNAME ); + for ( c = path + strlen( path ) - 1 ; c != path ; c-- ) + { + int i; + + if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) { + // + //strncpy (qdir, path, c+len+2-path); + // the +2 assumes a 2 or 3 following quake which is not the + // case with a retail install + // so we need to add up how much to the next separator + sep = c + len; + count = 1; + while ( *sep && *sep != '/' && *sep != '\\' ) + { + sep++; + count++; + } + strncpy( qdir, path, c + len + count - path ); + Sys_Printf( "qdir: %s\n", qdir ); + for ( i = 0; i < strlen( qdir ); i++ ) + { + if ( qdir[i] == '\\' ) { + qdir[i] = '/'; + } + } + + c += len + count; + while ( *c ) + { + if ( *c == '/' || *c == '\\' ) { + strncpy( gamedir, path, c + 1 - path ); + + for ( i = 0; i < strlen( gamedir ); i++ ) + { + if ( gamedir[i] == '\\' ) { + gamedir[i] = '/'; + } + } + + Sys_Printf( "gamedir: %s\n", gamedir ); + + if ( !writedir[0] ) { + strcpy( writedir, gamedir ); + } + else if ( writedir[strlen( writedir ) - 1] != '/' ) { + writedir[strlen( writedir )] = '/'; + writedir[strlen( writedir ) + 1] = 0; + } + + return; + } + c++; + } + Error( "No gamedir in %s", path ); + return; + } + } + Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path ); +} + +char *ExpandArg( const char *path ){ + static char full[1024]; + + if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) { + Q_getwd( full ); + strcat( full, path ); + } + else{ + strcpy( full, path ); + } + return full; +} + +char *ExpandPath( const char *path ){ + static char full[1024]; + if ( !qdir ) { + Error( "ExpandPath called without qdir set" ); + } + if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) { + strcpy( full, path ); + return full; + } + sprintf( full, "%s%s", qdir, path ); + return full; +} + +char *ExpandGamePath( const char *path ){ + static char full[1024]; + if ( !qdir ) { + Error( "ExpandGamePath called without qdir set" ); + } + if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) { + strcpy( full, path ); + return full; + } + sprintf( full, "%s%s", gamedir, path ); + return full; +} + +char *ExpandPathAndArchive( const char *path ){ + char *expanded; + char archivename[1024]; + + expanded = ExpandPath( path ); + + if ( archive ) { + sprintf( archivename, "%s/%s", archivedir, path ); + QCopyFile( expanded, archivename ); + } + return expanded; +} + + +char *copystring( const char *s ){ + char *b; + b = safe_malloc( strlen( s ) + 1 ); + strcpy( b, s ); + return b; +} + + + +/* + ================ + I_FloatTime + ================ + */ +double I_FloatTime( void ){ + time_t t; + + time( &t ); + + return t; +#if 0 +// more precise, less portable + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday( &tp, &tzp ); + + if ( !secbase ) { + secbase = tp.tv_sec; + return tp.tv_usec / 1000000.0; + } + + return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0; +#endif +} + +void Q_getwd( char *out ){ + int i = 0; + +#if GDEF_OS_WINDOWS + _getcwd( out, 256 ); + strcat( out, "\\" ); +#else // !GDEF_OS_WINDOWS + // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow + getcwd( out, 256 ); + strcat( out, "/" ); +#endif // !GDEF_OS_WINDOWS + while ( out[i] != 0 ) + { + if ( out[i] == '\\' ) { + out[i] = '/'; + } + i++; + } +} + + +void Q_mkdir( const char *path ){ +#if GDEF_OS_WINDOWS + if ( _mkdir( path ) != -1 ) { + return; + } +#else // !GDEF_OS_WINDOWS + if ( mkdir( path, 0777 ) != -1 ) { + return; + } +#endif // !GDEF_OS_WINDOWS + if ( errno != EEXIST ) { + Error( "mkdir %s: %s",path, strerror( errno ) ); + } +} + +/* + ============ + FileTime + + returns -1 if not present + ============ + */ +int FileTime( const char *path ){ + struct stat buf; + + if ( stat( path,&buf ) == -1 ) { + return -1; + } + + return buf.st_mtime; +} + + + +/* + ============== + COM_Parse + + Parse a token out of a string + ============== + */ +char *COM_Parse( char *data ){ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if ( !data ) { + return NULL; + } + +// skip whitespace +skipwhite: + while ( ( c = *data ) <= ' ' ) + { + if ( c == 0 ) { + com_eof = true; + return NULL; // end of file; + } + data++; + } + +// skip // comments + if ( c == '/' && data[1] == '/' ) { + while ( *data && *data != '\n' ) + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if ( c == '\"' ) { + data++; + do + { + c = *data++; + if ( c == '\"' ) { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } while ( 1 ); + } + +// parse single characters + if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { + com_token[len] = c; + len++; + com_token[len] = 0; + return data + 1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { + break; + } + } while ( c > 32 ); + + com_token[len] = 0; + return data; +} + +int Q_strncasecmp( const char *s1, const char *s2, int n ){ + int c1, c2; + + do + { + c1 = *s1++; + c2 = *s2++; + + if ( !n-- ) { + return 0; // strings are equal until end point + + } + if ( c1 != c2 ) { + if ( c1 >= 'a' && c1 <= 'z' ) { + c1 -= ( 'a' - 'A' ); + } + if ( c2 >= 'a' && c2 <= 'z' ) { + c2 -= ( 'a' - 'A' ); + } + if ( c1 != c2 ) { + return -1; // strings not equal + } + } + } while ( c1 ); + + return 0; // strings are equal +} + +int Q_stricmp( const char *s1, const char *s2 ){ + return Q_strncasecmp( s1, s2, 99999 ); +} + +int Q_strcasecmp( const char *s1, const char *s2 ){ + return Q_strncasecmp( s1, s2, 99999 ); +} + +// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config +// started getting warnings about that function, prolly a duplicate with the runtime function +// maybe we still need to have it in linux builds +/* + char *strupr (char *start) + { + char *in; + in = start; + while (*in) + { + *in = toupper(*in); + in++; + } + return start; + } + */ + +char *strlower( char *start ){ + char *in; + in = start; + while ( *in ) + { + *in = tolower( *in ); + in++; + } + return start; +} + + +/* + ============================================================================= + + MISC FUNCTIONS + + ============================================================================= + */ + + +/* + ================= + CheckParm + + Checks for the given parameter in the program's command line arguments + Returns the argument number (1 to argc-1) or 0 if not present + ================= + */ +int CheckParm( const char *check ){ + int i; + + for ( i = 1; i < myargc; i++ ) + { + if ( !Q_stricmp( check, myargv[i] ) ) { + return i; + } + } + + return 0; +} + + + +/* + ================ + Q_filelength + ================ + */ +int Q_filelength( FILE *f ){ + int pos; + int end; + + pos = ftell( f ); + fseek( f, 0, SEEK_END ); + end = ftell( f ); + fseek( f, pos, SEEK_SET ); + + return end; +} + + +FILE *SafeOpenWrite( const char *filename ){ + FILE *f; + + f = fopen( filename, "wb" ); + + if ( !f ) { + Error( "Error opening %s: %s",filename,strerror( errno ) ); + } + + return f; +} + +FILE *SafeOpenRead( const char *filename ){ + FILE *f; + + f = fopen( filename, "rb" ); + + if ( !f ) { + Error( "Error opening %s: %s",filename,strerror( errno ) ); + } + + return f; +} + + +void SafeRead( FILE *f, void *buffer, int count ){ + if ( fread( buffer, 1, count, f ) != (size_t)count ) { + Error( "File read failure" ); + } +} + + +void SafeWrite( FILE *f, const void *buffer, int count ){ + if ( fwrite( buffer, 1, count, f ) != (size_t)count ) { + Error( "File write failure" ); + } +} + + +/* + ============== + FileExists + ============== + */ +qboolean FileExists( const char *filename ){ + FILE *f; + + f = fopen( filename, "r" ); + if ( !f ) { + return false; + } + fclose( f ); + return true; +} + +/* + ============== + LoadFile + ============== + */ +int LoadFile( const char *filename, void **bufferptr ){ + FILE *f; + int length; + void *buffer; + + f = SafeOpenRead( filename ); + length = Q_filelength( f ); + buffer = safe_malloc( length + 1 ); + ( (char *)buffer )[length] = 0; + SafeRead( f, buffer, length ); + fclose( f ); + + *bufferptr = buffer; + return length; +} + + +/* + ============== + LoadFileBlock + - + rounds up memory allocation to 4K boundry + - + ============== + */ +int LoadFileBlock( const char *filename, void **bufferptr ){ + FILE *f; + int length, nBlock, nAllocSize; + void *buffer; + + f = SafeOpenRead( filename ); + length = Q_filelength( f ); + nAllocSize = length; + nBlock = nAllocSize % MEM_BLOCKSIZE; + if ( nBlock > 0 ) { + nAllocSize += MEM_BLOCKSIZE - nBlock; + } + buffer = safe_malloc( nAllocSize + 1 ); + memset( buffer, 0, nAllocSize + 1 ); + SafeRead( f, buffer, length ); + fclose( f ); + + *bufferptr = buffer; + return length; +} + + +/* + ============== + TryLoadFile + + Allows failure + ============== + */ +int TryLoadFile( const char *filename, void **bufferptr ){ + FILE *f; + int length; + void *buffer; + + *bufferptr = NULL; + + f = fopen( filename, "rb" ); + if ( !f ) { + return -1; + } + length = Q_filelength( f ); + buffer = safe_malloc( length + 1 ); + ( (char *)buffer )[length] = 0; + SafeRead( f, buffer, length ); + fclose( f ); + + *bufferptr = buffer; + return length; +} + + +/* + ============== + SaveFile + ============== + */ +void SaveFile( const char *filename, const void *buffer, int count ){ + FILE *f; + + f = SafeOpenWrite( filename ); + SafeWrite( f, buffer, count ); + fclose( f ); +} + + + +void DefaultExtension( char *path, const char *extension ){ + char *src; +// +// if path doesnt have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen( path ) - 1; + + while ( *src != '/' && *src != '\\' && src != path ) + { + if ( *src == '.' ) { + return; // it has an extension + } + src--; + } + + strcat( path, extension ); +} + + +void DefaultPath( char *path, const char *basepath ){ + char temp[128]; + + if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) { + return; // absolute path location + } + strcpy( temp,path ); + strcpy( path,basepath ); + strcat( path,temp ); +} + + +void StripFilename( char *path ){ + int length; + + length = strlen( path ) - 1; + while ( length > 0 && path[length] != '/' && path[ length ] != '\\' ) + length--; + path[length] = 0; +} + +void StripExtension( char *path ){ + int length; + + length = strlen( path ) - 1; + while ( length > 0 && path[length] != '.' ) + { + length--; + if ( path[length] == '/' || path[ length ] == '\\' ) { + return; // no extension + } + } + if ( length ) { + path[length] = 0; + } +} + + +/* + ==================== + Extract file parts + ==================== + */ + +// FIXME: should include the slash, otherwise +// backing to an empty path will be wrong when appending a slash +void ExtractFilePath( const char *path, char *dest ){ + const char *src; + + src = path + strlen( path ) - 1; + +// +// back up until a \ or the start +// + while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' ) + src--; + + memcpy( dest, path, src - path ); + dest[src - path] = 0; +} + +void ExtractFileBase( const char *path, char *dest ){ + const char *src; + + src = path + strlen( path ) - 1; + +// +// back up until a \ or the start +// + while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' ) + src--; + + while ( *src && *src != '.' ) + { + *dest++ = *src++; + } + *dest = 0; +} + +void ExtractFileExtension( const char *path, char *dest ){ + const char *src; + + src = path + strlen( path ) - 1; + +// +// back up until a . or the start +// + while ( src != path && *( src - 1 ) != '.' ) + src--; + if ( src == path ) { + *dest = 0; // no extension + return; + } + + strcpy( dest,src ); +} + + +/* + ============== + ParseNum / ParseHex + ============== + */ +int ParseHex( const char *hex ){ + const char *str; + int num; + + num = 0; + str = hex; + + while ( *str ) + { + num <<= 4; + if ( *str >= '0' && *str <= '9' ) { + num += *str - '0'; + } + else if ( *str >= 'a' && *str <= 'f' ) { + num += 10 + *str - 'a'; + } + else if ( *str >= 'A' && *str <= 'F' ) { + num += 10 + *str - 'A'; + } + else{ + Error( "Bad hex number: %s",hex ); + } + str++; + } + + return num; +} + + +int ParseNum( const char *str ){ + if ( str[0] == '$' ) { + return ParseHex( str + 1 ); + } + if ( str[0] == '0' && str[1] == 'x' ) { + return ParseHex( str + 2 ); + } + return atol( str ); +} +/* + // all output ends up through here + void FPrintf (int flag, char *buf) + { + printf(buf); + + } + + 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 ); + + exit (1); + } + + */ + +/* + ============================================================================ + + BYTE ORDER FUNCTIONS + + ============================================================================ + */ + +#if GDEF_ARCH_ENDIAN_BIG + +short LittleShort( short l ){ + byte b1,b2; + + b1 = l & 255; + b2 = ( l >> 8 ) & 255; + + return ( b1 << 8 ) + b2; +} + +short BigShort( short l ){ + return l; +} + + +int LittleLong( int l ){ + byte b1,b2,b3,b4; + + b1 = l & 255; + b2 = ( l >> 8 ) & 255; + b3 = ( l >> 16 ) & 255; + b4 = ( l >> 24 ) & 255; + + return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4; +} + +int BigLong( int l ){ + return l; +} + + +float LittleFloat( float l ){ + union {byte b[4]; float f; } in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float BigFloat( float l ){ + return l; +} + + +#else // !GDEF_ARCH_ENDIAN_BIG + + +short BigShort( short l ){ + byte b1,b2; + + b1 = l & 255; + b2 = ( l >> 8 ) & 255; + + return ( b1 << 8 ) + b2; +} + +short LittleShort( short l ){ + return l; +} + + +int BigLong( int l ){ + byte b1,b2,b3,b4; + + b1 = l & 255; + b2 = ( l >> 8 ) & 255; + b3 = ( l >> 16 ) & 255; + b4 = ( l >> 24 ) & 255; + + return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4; +} + +int LittleLong( int l ){ + return l; +} + +float BigFloat( float l ){ + union {byte b[4]; float f; } in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float LittleFloat( float l ){ + return l; +} + +#endif // ! GDEF_ARCH_ENDIAN_BIG + + +//======================================================= + + +// FIXME: byte swap? + +// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 +// and the initial and final xor values shown below... in other words, the +// CCITT standard CRC used by XMODEM + +#define CRC_INIT_VALUE 0xffff +#define CRC_XOR_VALUE 0x0000 + +static unsigned short crctable[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +void CRC_Init( unsigned short *crcvalue ){ + *crcvalue = CRC_INIT_VALUE; +} + +void CRC_ProcessByte( unsigned short *crcvalue, byte data ){ + *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data]; +} + +unsigned short CRC_Value( unsigned short crcvalue ){ + return crcvalue ^ CRC_XOR_VALUE; +} +//============================================================================= + +/* + ============ + CreatePath + ============ + */ +void CreatePath( const char *path ){ + const char *ofs; + char c; + char dir[1024]; + +#if GDEF_OS_WINDOWS + int olddrive = -1; + + if ( path[1] == ':' ) { + olddrive = _getdrive(); + _chdrive( toupper( path[0] ) - 'A' + 1 ); + } +#endif // !GDEF_OS_WINDOWS + + if ( path[1] == ':' ) { + path += 2; + } + + for ( ofs = path + 1 ; *ofs ; ofs++ ) + { + c = *ofs; + if ( c == '/' || c == '\\' ) { // create the directory + memcpy( dir, path, ofs - path ); + dir[ ofs - path ] = 0; + Q_mkdir( dir ); + } + } + +#if GDEF_OS_WINDOWS + if ( olddrive != -1 ) { + _chdrive( olddrive ); + } +#endif // !GDEF_OS_WINDOWS +} + + +/* + ============ + QCopyFile + + Used to archive source files + ============ + */ +void QCopyFile( const char *from, const char *to ){ + void *buffer; + int length; + + length = LoadFile( from, &buffer ); + CreatePath( to ); + SaveFile( to, buffer, length ); + free( buffer ); +} + +void Sys_Sleep( int n ){ +#if GDEF_OS_WINDOWS + Sleep( n ); +#else // !GDEF_OS_WINDOWS + usleep( n * 1000 ); +#endif // !GDEF_OS_WINDOWS +} diff --git a/tools/heretic2/common/cmdlib.h b/tools/heretic2/common/cmdlib.h new file mode 100644 index 00000000..b8b1aa3d --- /dev/null +++ b/tools/heretic2/common/cmdlib.h @@ -0,0 +1,181 @@ +/* + Copyright (C) 1999-2007 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__ + +#if GDEF_COMPILER_MSVC +#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 +#include +#include +#include +#include +#include +#include + +#if GDEF_COMPILER_MSVC + +#pragma intrinsic( memset, memcpy ) + +#endif + +#ifndef __BYTEBOOL__ + #define __BYTEBOOL__ +//typedef enum {false, true} qboolean; +//typedef unsigned char byte; + #include "q_typedef.h" +#endif + +#ifdef PATH_MAX +#define MAX_OS_PATH PATH_MAX +#else +#define MAX_OS_PATH 1024 +#endif +#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 diff --git a/tools/heretic2/common/her2_threads.h b/tools/heretic2/common/her2_threads.h new file mode 100644 index 00000000..6027a695 --- /dev/null +++ b/tools/heretic2/common/her2_threads.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/common/inout.c b/tools/heretic2/common/inout.c new file mode 100644 index 00000000..e0c14841 --- /dev/null +++ b/tools/heretic2/common/inout.c @@ -0,0 +1,357 @@ +/* + Copyright (C) 1999-2007 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 "globaldefs.h" +#include "cmdlib.h" +#include "mathlib.h" +#include "polylib.h" +#include "inout.h" +#include +#include + +#if GDEF_OS_WINDOWS +#include +#include +#endif + +// network broadcasting +#include "l_net/l_net.h" +#include "libxml/tree.h" + +#if GDEF_OS_WINDOWS +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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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" ); + xmlNodeAddContent( 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, "" ); + 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 string + .. various nodes to describe corresponding geometry .. + + */ + if ( !bGotXML ) { + // initialize + doc = xmlNewDoc( "1.0" ); + doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL ); + bGotXML = true; + } + node = xmlNewNode( NULL, "message" ); + xmlNodeAddContent( 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 ); +} diff --git a/tools/heretic2/common/inout.h b/tools/heretic2/common/inout.h new file mode 100644 index 00000000..934189f2 --- /dev/null +++ b/tools/heretic2/common/inout.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 1999-2007 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__ + +#include "globaldefs.h" +// 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, ... ); + +#if GDEF_DEBUG +#define DBG_XML 1 +#endif + +#ifdef DBG_XML +void DumpXML(); +#endif + +#endif diff --git a/tools/heretic2/common/l3dslib.c b/tools/heretic2/common/l3dslib.c new file mode 100644 index 00000000..708577a1 --- /dev/null +++ b/tools/heretic2/common/l3dslib.c @@ -0,0 +1,478 @@ +/* + Copyright (C) 1999-2007 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 +#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 ); +} diff --git a/tools/heretic2/common/l3dslib.h b/tools/heretic2/common/l3dslib.h new file mode 100644 index 00000000..0b1b5379 --- /dev/null +++ b/tools/heretic2/common/l3dslib.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 1999-2007 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 ); diff --git a/tools/heretic2/common/lbmlib.c b/tools/heretic2/common/lbmlib.c new file mode 100644 index 00000000..7eabd19c --- /dev/null +++ b/tools/heretic2/common/lbmlib.c @@ -0,0 +1,1043 @@ +/* + Copyright (C) 1999-2007 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" + +// Ups the palette values so no pixels except 0 appear transparent +// Need a value of 8 to cater for 16bit renderers + +typedef struct +{ + byte r; + byte g; + byte b; +} paletteRGB_t; + + +void CorrectPalette( byte *pal ){ + paletteRGB_t *p; + + p = (paletteRGB_t *)pal; + // Color 0 always transparent + p->r = 0; + p->g = 0; + p->b = 0; +} + +/* + ============================================================================ + + 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 ); + CorrectPalette( cmapbuffer ); + 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 ); + CorrectPalette( *palette ); + } + + 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 StuffPackedByte( int curRepCount, byte curByte, byte** packPtr ){ + byte* pack; + + pack = *packPtr; + + while ( curRepCount > 0 ) + { + if ( curRepCount == 1 ) { + if ( ( curByte & 0xc0 ) != 0xc0 ) { + *pack++ = curByte; + } + else + { + *pack++ = 0xc1; + *pack++ = curByte; + } + break; + } + if ( curRepCount < 0x0040 ) { + *pack++ = ( 0x00c0 | curRepCount ); + curRepCount = 0; + } + else + { + *pack++ = 0xff; + curRepCount -= 0x003f; + } + *pack++ = curByte; + } + *packPtr = pack; +} + +void WritePCXfile( char *filename, byte *data, + int width, int height, byte *palette ){ + int i, j, length; + pcx_t *pcx; + byte *pack; + byte curByte; + int curRepCount; + + pcx = malloc( width * height * 2 + 1000 ); + memset( pcx, 0, sizeof( *pcx ) ); + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // RLE + 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( 1 ); // not a grey scale + + // pack the image + pack = &pcx->data; + +/* for (i=0 ; i= rows ) { + goto breakOut; + } + pixbuf += rowOffset; + rowBuf = pixbuf; + } + } + } + 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 ); + rowBuf[0] = red; + rowBuf[1] = green; + rowBuf[2] = blue; + rowBuf[3] = 255; + rowBuf += pixDirection; + break; + case 32: + blue = getc( fin ); + green = getc( fin ); + red = getc( fin ); + alphabyte = getc( fin ); + rowBuf[0] = red; + rowBuf[1] = green; + rowBuf[2] = blue; + rowBuf[3] = alphabyte; + rowBuf += pixDirection; + break; + } + column++; + if ( column == columns ) { // pixel packet run spans across rows + column = 0; + row++; + if ( row >= rows ) { + goto breakOut; + } + pixbuf += rowOffset; + rowBuf = pixbuf; + } + } + } + } +breakOut:; + pixbuf += rowOffset; + } + } + fclose( fin ); +} + +void MergeAlpha( byte *pix, byte *alpha, byte *pal, byte **out, int width, int height ){ + int size, i; + byte *data, *src, *srca; + + size = width * height; + data = malloc( size * 4 ); + if ( !data ) { + Error( "Could not allocate memory for true color image" ); + } + + *out = data; + src = pix; + srca = alpha; + + for ( i = 0; i < size; i++, src++, srca++ ) + { + *data++ = pal[*src * 3 + 0]; // r + *data++ = pal[*src * 3 + 1]; // g + *data++ = pal[*src * 3 + 2]; // b + *data++ = *srca; // a + } + free( pix ); + free( alpha ); + free( pal ); +} + +/* + ============== + LoadAnyImage + + Return Value: + false: paletted texture + true: true color RGBA image (no palette) + ============== + */ +qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height ){ + char ext[128]; + int len; + int alpha_width, alpha_height; + char alpha_name[128]; + byte *alpha_pixels; + + ExtractFileExtension( name, ext ); + + if ( palette ) { + *palette = NULL; + } + + if ( !Q_strcasecmp( ext, "lbm" ) ) { + LoadLBM( name, pixels, palette ); + if ( width ) { + *width = bmhd.w; + } + if ( height ) { + *height = bmhd.h; + } + return false; + } + else if ( !Q_strcasecmp( ext, "pcx" ) ) { + len = strlen( name ); + strcpy( alpha_name, name ); + strcpy( &alpha_name[len - 4], "_a.pcx" ); // Alpha map name (may not exist) + + if ( FileExists( alpha_name ) ) { + LoadPCX( name, pixels, palette, width, height ); // Load in image + LoadPCX( alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height ); // Load in alpha map + if ( ( *width != alpha_width ) || ( *height != alpha_height ) ) { + Error( "Alpha image dimensions not equal to graphic image dimensions" ); + } + MergeAlpha( *pixels, alpha_pixels, *palette, pixels, *width, *height ); + *palette = NULL; //Merge Frees pal + return true; + } + else + { + LoadPCX( name, pixels, palette, width, height ); // Load in image + return false; + } + } + else if ( !Q_strcasecmp( ext, "tga" ) ) { + LoadTGA( name, pixels, width, height ); + if ( palette ) { + *palette = NULL; + } + + return true; + } + else{ + Error( "%s doesn't have a known image extension", name ); + } + + return false; +} diff --git a/tools/heretic2/common/lbmlib.h b/tools/heretic2/common/lbmlib.h new file mode 100644 index 00000000..5ee2909f --- /dev/null +++ b/tools/heretic2/common/lbmlib.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 1999-2007 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 ); diff --git a/tools/heretic2/common/mathlib.c b/tools/heretic2/common/mathlib.c new file mode 100644 index 00000000..8243d86d --- /dev/null +++ b/tools/heretic2/common/mathlib.c @@ -0,0 +1,170 @@ +/* + Copyright (C) 1999-2007 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; +} + +#if GDEF_COMPILER_MSVC +#pragma optimize("g", off) // went back to turning optimization off, + // the bug_fix thing stopped working +#endif + +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; +} + +#if GDEF_COMPILER_MSVC +#pragma optimize("", on) +#endif + +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; + } + } +} diff --git a/tools/heretic2/common/mathlib.h b/tools/heretic2/common/mathlib.h new file mode 100644 index 00000000..cd989ea3 --- /dev/null +++ b/tools/heretic2/common/mathlib.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 1999-2007 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 +/* + #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 diff --git a/tools/heretic2/common/md4.c b/tools/heretic2/common/md4.c new file mode 100644 index 00000000..f5034220 --- /dev/null +++ b/tools/heretic2/common/md4.c @@ -0,0 +1,219 @@ +/* + mdfour.c + + An implementation of MD4 designed for use in the samba SMB + authentication protocol + + Copyright (C) 1997-1998 Andrew Tridgell + + This program 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. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id: mdfour.c 7689 2007-11-12 14:28:40Z divverent $ + */ + +#include /* XoXus: needed for memset call */ +#include "md4.h" + +/* NOTE: This code makes no attempt to be fast! + + It assumes that a int is at least 32 bits long + */ + +static struct mdfour *m; + +#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 ) ) +#ifdef LARGE_INT32 +#define lshift( x,s ) ( ( ( ( x ) << ( s ) ) & 0xFFFFFFFF ) | ( ( ( x ) >> ( 32 - ( s ) ) ) & 0xFFFFFFFF ) ) +#else +#define lshift( x,s ) ( ( ( x ) << ( s ) ) | ( ( x ) >> ( 32 - ( s ) ) ) ) +#endif + +#define ROUND1( a,b,c,d,k,s ) a = lshift( a + F( b,c,d ) + X[k], s ) +#define ROUND2( a,b,c,d,k,s ) a = lshift( a + G( b,c,d ) + X[k] + 0x5A827999,s ) +#define ROUND3( a,b,c,d,k,s ) a = lshift( a + H( b,c,d ) + X[k] + 0x6ED9EBA1,s ) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64( uint32 *M ){ + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; + uint32 A,B,C,D; + + for ( j = 0; j < 16; j++ ) + X[j] = M[j]; + + A = m->A; B = m->B; C = m->C; D = m->D; + AA = A; BB = B; CC = C; DD = D; + + ROUND1( A,B,C,D, 0, 3 ); ROUND1( D,A,B,C, 1, 7 ); + ROUND1( C,D,A,B, 2, 11 ); ROUND1( B,C,D,A, 3, 19 ); + ROUND1( A,B,C,D, 4, 3 ); ROUND1( D,A,B,C, 5, 7 ); + ROUND1( C,D,A,B, 6, 11 ); ROUND1( B,C,D,A, 7, 19 ); + ROUND1( A,B,C,D, 8, 3 ); ROUND1( D,A,B,C, 9, 7 ); + ROUND1( C,D,A,B, 10, 11 ); ROUND1( B,C,D,A, 11, 19 ); + ROUND1( A,B,C,D, 12, 3 ); ROUND1( D,A,B,C, 13, 7 ); + ROUND1( C,D,A,B, 14, 11 ); ROUND1( B,C,D,A, 15, 19 ); + + ROUND2( A,B,C,D, 0, 3 ); ROUND2( D,A,B,C, 4, 5 ); + ROUND2( C,D,A,B, 8, 9 ); ROUND2( B,C,D,A, 12, 13 ); + ROUND2( A,B,C,D, 1, 3 ); ROUND2( D,A,B,C, 5, 5 ); + ROUND2( C,D,A,B, 9, 9 ); ROUND2( B,C,D,A, 13, 13 ); + ROUND2( A,B,C,D, 2, 3 ); ROUND2( D,A,B,C, 6, 5 ); + ROUND2( C,D,A,B, 10, 9 ); ROUND2( B,C,D,A, 14, 13 ); + ROUND2( A,B,C,D, 3, 3 ); ROUND2( D,A,B,C, 7, 5 ); + ROUND2( C,D,A,B, 11, 9 ); ROUND2( B,C,D,A, 15, 13 ); + + ROUND3( A,B,C,D, 0, 3 ); ROUND3( D,A,B,C, 8, 9 ); + ROUND3( C,D,A,B, 4, 11 ); ROUND3( B,C,D,A, 12, 15 ); + ROUND3( A,B,C,D, 2, 3 ); ROUND3( D,A,B,C, 10, 9 ); + ROUND3( C,D,A,B, 6, 11 ); ROUND3( B,C,D,A, 14, 15 ); + ROUND3( A,B,C,D, 1, 3 ); ROUND3( D,A,B,C, 9, 9 ); + ROUND3( C,D,A,B, 5, 11 ); ROUND3( B,C,D,A, 13, 15 ); + ROUND3( A,B,C,D, 3, 3 ); ROUND3( D,A,B,C, 11, 9 ); + ROUND3( C,D,A,B, 7, 11 ); ROUND3( B,C,D,A, 15, 15 ); + + A += AA; B += BB; C += CC; D += DD; + +#ifdef LARGE_INT32 + A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; + C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; +#endif + + for ( j = 0; j < 16; j++ ) + X[j] = 0; + + m->A = A; m->B = B; m->C = C; m->D = D; +} + +static void copy64( uint32 *M, unsigned char *in ){ + int i; + + for ( i = 0; i < 16; i++ ) + M[i] = ( in[i * 4 + 3] << 24 ) | ( in[i * 4 + 2] << 16 ) | + ( in[i * 4 + 1] << 8 ) | ( in[i * 4 + 0] << 0 ); +} + +static void copy4( unsigned char *out,uint32 x ){ + out[0] = x & 0xFF; + out[1] = ( x >> 8 ) & 0xFF; + out[2] = ( x >> 16 ) & 0xFF; + out[3] = ( x >> 24 ) & 0xFF; +} + +void mdfour_begin( struct mdfour *md ){ + md->A = 0x67452301; + md->B = 0xefcdab89; + md->C = 0x98badcfe; + md->D = 0x10325476; + md->totalN = 0; +} + + +static void mdfour_tail( unsigned char *in, int n ){ + unsigned char buf[128]; + uint32 M[16]; + uint32 b; + + m->totalN += n; + + b = m->totalN * 8; + + memset( buf, 0, 128 ); + if ( n ) { + memcpy( buf, in, n ); + } + buf[n] = 0x80; + + if ( n <= 55 ) { + copy4( buf + 56, b ); + copy64( M, buf ); + mdfour64( M ); + } + else { + copy4( buf + 120, b ); + copy64( M, buf ); + mdfour64( M ); + copy64( M, buf + 64 ); + mdfour64( M ); + } +} + +void mdfour_update( struct mdfour *md, unsigned char *in, int n ){ + uint32 M[16]; + +// start of edit by Forest 'LordHavoc' Hale +// commented out to prevent crashing when length is 0 +// if (n == 0) mdfour_tail(in, n); +// end of edit by Forest 'LordHavoc' Hale + + m = md; + + while ( n >= 64 ) { + copy64( M, in ); + mdfour64( M ); + in += 64; + n -= 64; + m->totalN += 64; + } + + mdfour_tail( in, n ); +} + + +void mdfour_result( struct mdfour *md, unsigned char *out ){ + m = md; + + copy4( out, m->A ); + copy4( out + 4, m->B ); + copy4( out + 8, m->C ); + copy4( out + 12, m->D ); +} + + +void mdfour( unsigned char *out, unsigned char *in, int n ){ + struct mdfour md; + mdfour_begin( &md ); + mdfour_update( &md, in, n ); + mdfour_result( &md, out ); +} + +/////////////////////////////////////////////////////////////// +// MD4-based checksum utility functions +// +// Copyright (C) 2000 Jeff Teunissen +// +// Author: Jeff Teunissen +// Date: 01 Jan 2000 + +unsigned Com_BlockChecksum( void *buffer, int length ){ + int digest[4]; + unsigned val; + + mdfour( (unsigned char *) digest, (unsigned char *) buffer, length ); + + val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; + + return val; +} + +void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ){ + mdfour( outbuf, (unsigned char *) buffer, len ); +} diff --git a/tools/heretic2/common/md4.h b/tools/heretic2/common/md4.h new file mode 100644 index 00000000..6f64c289 --- /dev/null +++ b/tools/heretic2/common/md4.h @@ -0,0 +1,56 @@ +/* + mdfour.h + + an implementation of MD4 designed for use in the SMB authentication + protocol + + Copyright (C) Andrew Tridgell 1997-1998 + + This program 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. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + */ + +#ifndef _MDFOUR_H +#define _MDFOUR_H + +#ifndef int32 +#define int32 int +#endif + +#if SIZEOF_INT > 4 +#define LARGE_INT32 +#endif + +#ifndef uint32 +#define uint32 unsigned int32 +#endif + +struct mdfour { + uint32 A, B, C, D; + uint32 totalN; +}; + +void mdfour_begin( struct mdfour *md ); // old: MD4Init +void mdfour_update( struct mdfour *md, unsigned char *in, int n ); //old: MD4Update +void mdfour_result( struct mdfour *md, unsigned char *out ); // old: MD4Final +void mdfour( unsigned char *out, unsigned char *in, int n ); + +unsigned Com_BlockChecksum( void *buffer, int length ); +void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ); + +#endif // _MDFOUR_H diff --git a/tools/heretic2/common/path_init.c b/tools/heretic2/common/path_init.c new file mode 100644 index 00000000..254977bc --- /dev/null +++ b/tools/heretic2/common/path_init.c @@ -0,0 +1,391 @@ +/* ------------------------------------------------------------------------------- + + Copyright (C) 1999-2007 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 + */ + +#include "globaldefs.h" + +#if !GDEF_OS_WINDOWS + #include + #include + #include +#endif // !GDEF_OS_WINDOWS + +/* 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 ){ + #if GDEF_OS_WINDOWS + return NULL; + #else // !GDEF_OS_WINDOWS + 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 // !GDEF_OS_WINDOWS +} + + + +/* + PathLokiInitPaths() + initializes some paths on linux/os x + */ + +void LokiInitPaths( char *argv0 ){ + #if GDEF_OS_WINDOWS + /* this is kinda crap, but hey */ + strcpy( installPath, "../" ); + #else // !GDEF_OS_WINDOWS + 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 // !GDEF_OS_WINDOWS +} + + + +/* + 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 ){ + #if !GDEF_OS_WINDOWS + 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 // !GDEF_OS_WINDOWS +} + + + +/* + 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" ); +} diff --git a/tools/heretic2/common/polylib.c b/tools/heretic2/common/polylib.c new file mode 100644 index 00000000..af5df499 --- /dev/null +++ b/tools/heretic2/common/polylib.c @@ -0,0 +1,665 @@ +/* + Copyright (C) 1999-2007 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; +} diff --git a/tools/heretic2/common/polylib.h b/tools/heretic2/common/polylib.h new file mode 100644 index 00000000..00b7b394 --- /dev/null +++ b/tools/heretic2/common/polylib.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 1999-2007 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 ); diff --git a/tools/heretic2/common/qfiles.c b/tools/heretic2/common/qfiles.c new file mode 100644 index 00000000..53452f36 --- /dev/null +++ b/tools/heretic2/common/qfiles.c @@ -0,0 +1,78 @@ +/* + Copyright (C) 1999-2007 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 + +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; +} diff --git a/tools/heretic2/common/qfiles.h b/tools/heretic2/common/qfiles.h new file mode 100644 index 00000000..bee4b4fc --- /dev/null +++ b/tools/heretic2/common/qfiles.h @@ -0,0 +1,619 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/common/scriplib.c b/tools/heretic2/common/scriplib.c new file mode 100644 index 00000000..af5e5716 --- /dev/null +++ b/tools/heretic2/common/scriplib.c @@ -0,0 +1,300 @@ +/* + Copyright (C) 1999-2007 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; +} diff --git a/tools/heretic2/common/scriplib.h b/tools/heretic2/common/scriplib.h new file mode 100644 index 00000000..8c441c8b --- /dev/null +++ b/tools/heretic2/common/scriplib.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 1999-2007 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 ); diff --git a/tools/heretic2/common/threads.c b/tools/heretic2/common/threads.c new file mode 100644 index 00000000..239226b7 --- /dev/null +++ b/tools/heretic2/common/threads.c @@ -0,0 +1,606 @@ +/* + Copyright (C) 1999-2007 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 "globaldefs.h" + +#if !GDEF_OS_WINDOWS +// The below define is necessary to use +// pthreads extensions like pthread_mutexattr_settype +#define _GNU_SOURCE +#endif // !GDEF_OS_WINDOWS + +#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 ); +} + + +#if GDEF_OS_WINDOWS + +/* + =================================================================== + + WIN32 + + =================================================================== + */ + +#include + +// 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 ); + } +} + + +#elif GDEF_OS_OSF1 + +/* + =================================================================== + + OSF1 + + =================================================================== + */ + +int numthreads = 4; + +void ThreadSetDefault( void ){ + if ( numthreads == -1 ) { // not set manually + numthreads = 4; + } +} + + +#include + +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 ); + } +} + + +#elif GDEF_OS_IRIX + +/* + =================================================================== + + IRIX + + =================================================================== + */ + +#include +#include +#include +#include + +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 ); + } +} + + +#elif GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS + +/* + ======================================================================= + + Linux pthreads + + ======================================================================= + */ + +// 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 + +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 ( pthread_mutexattr_settype( &mattrib, PTHREAD_MUTEX_ERRORCHECK ) != 0 ) { + 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 ); + } +} + + +#else // UNKNOWN OS + +/* + ======================================================================= + + SINGLE THREAD + + ======================================================================= + */ + +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 // UNKNOWN OS diff --git a/tools/heretic2/common/token.c b/tools/heretic2/common/token.c new file mode 100644 index 00000000..632cfe40 --- /dev/null +++ b/tools/heretic2/common/token.c @@ -0,0 +1,515 @@ +/* + Copyright (C) 1999-2007 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[] = +{ + "", + "", + "", + "", + "", + "", + "", + "(", + ")", + "{", + "}", + "[", + "]", + ":", + "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 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; + } +} diff --git a/tools/heretic2/common/token.h b/tools/heretic2/common/token.h new file mode 100644 index 00000000..6dca1a1a --- /dev/null +++ b/tools/heretic2/common/token.h @@ -0,0 +1,132 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/common/trilib.c b/tools/heretic2/common/trilib.c new file mode 100644 index 00000000..29acab6f --- /dev/null +++ b/tools/heretic2/common/trilib.c @@ -0,0 +1,1039 @@ +/* + Copyright (C) 1999-2007 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 +#include "cmdlib.h" +#include "inout.h" +#include "mathlib.h" +#include "trilib.h" +#include "token.h" +#include "l3dslib.h" +#include "fmodel.h" +#if 1 +#include "qd_skeletons.h" +#endif + +// on disk representation of a face +#define FLOAT_START 99999.0 +#define FLOAT_END -FLOAT_START +#define MAGIC 123322 +#ifndef M_PI + #define M_PI 3.14159265 +#endif + +float FixHTRRotateX = 0.0; +float FixHTRRotateY = 0.0; +float FixHTRRotateZ = 0.0; +float FixHTRTranslateX = 0.0; +float FixHTRTranslateY = 0.0; +float FixHTRTranslateZ = 0.0; + +//#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 LoadTRI( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){ + 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; + + if ( nodesList ) { + *num_mesh_nodes = 0; + *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); + } + + 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 ); + + DefaultNodesList( nodesList,num_mesh_nodes,numtriangles ); +} + + +//========================================================================== +// +// LoadHRC +// +//========================================================================== + +float scaling[3]; +float rotation[3]; +float translation[3]; +static char *hrc_name; + +struct +{ + float v[3]; +} vList[8192]; + +void HandleHRCModel( triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes, + int ActiveNode, int Depth, int numVerts ){ + void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ); + + int i, j; + int vertexCount; + int triCount; + triangle_t *tList; + mesh_node_t *meshNode; + float x, y, z; + float x2, y2, z2; + float rx, ry, rz; + tokenType_t nextToken; + float orig_scaling[3]; + float orig_rotation[3]; + float orig_translation[3]; + int start_tri; + int pos,bit; + int vertIndexBase; + + // Update Node Info + if ( nodesList ) { + TK_BeyondRequire( TK_NAME, TK_STRING ); + + if ( Depth == 0 || tk_String[0] == '_' ) { // Root + ActiveNode = *num_mesh_nodes; + ( *num_mesh_nodes )++; + if ( ( *num_mesh_nodes ) > MAX_FM_MESH_NODES ) { + Error( "Too many mesh nodes in file %s\n", hrc_name ); + } + meshNode = &( *nodesList )[ActiveNode]; + +// memset(meshNode, 0, sizeof(mesh_node_t)); + strcpy( meshNode->name, tk_String ); + + memset( meshNode->tris, 0, sizeof( meshNode->tris ) ); + memset( meshNode->verts, 0, sizeof( meshNode->verts ) ); + + meshNode->start_glcmds = 0; + meshNode->num_glcmds = 0; + vertIndexBase = 0; + } + else + { // Childs under the children + meshNode = &( *nodesList )[ActiveNode]; + vertIndexBase = numVerts; + } + } + else + { + meshNode = NULL; + } + + + // Get the scaling, rotation, and translation values + TK_Beyond( TK_SCALING ); + for ( i = 0; i < 3; i++ ) + { + orig_scaling[i] = scaling[i]; + + TK_Require( TK_FLOATNUMBER ); + scaling[i] *= tk_FloatNumber; + + TK_Fetch(); + } + TK_Beyond( TK_ROTATION ); + for ( i = 0; i < 3; i++ ) + { + orig_rotation[i] = rotation[i]; + + TK_Require( TK_FLOATNUMBER ); + rotation[i] = tk_FloatNumber; + + TK_Fetch(); + } + TK_Beyond( TK_TRANSLATION ); + for ( i = 0; i < 3; i++ ) + { + orig_translation[i] = translation[i]; + + TK_Require( TK_FLOATNUMBER ); + translation[i] += tk_FloatNumber; + + TK_Fetch(); + } + + rx = ( ( rotation[0] - 90.0 ) / 360.0 ) * 2.0 * M_PI; + ry = ( rotation[2] / 360.0 ) * 2.0 * M_PI; + rz = ( rotation[1] / 360.0 ) * 2.0 * M_PI; + + // rjr - might not work if there an item doesn't have a mesh + nextToken = tk_Token; + if ( nextToken == TK_ACTOR_DATA ) { + while ( nextToken != TK_MODEL && nextToken != TK_RBRACE ) + { + nextToken = TK_Fetch(); + } + } + + while ( nextToken == TK_SPLINE ) + { // spline node has two right braces + nextToken = TK_Beyond( TK_RBRACE ); + nextToken = TK_Beyond( TK_RBRACE ); + } + + while ( nextToken == TK_MATERIAL ) + { + nextToken = TK_Beyond( TK_RBRACE ); + } + + while ( nextToken == TK_MODEL ) + { + HandleHRCModel( triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth + 1, 0 ); + + nextToken = TK_Fetch(); + } + + if ( nextToken == TK_MESH ) { + // Get all the tri and vertex info + TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER ); + vertexCount = tk_IntNumber; + for ( i = 0; i < vertexCount; i++ ) + { + TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); + if ( tk_IntNumber != i ) { + Error( "File '%s', line %d:\nVertex index mismatch.\n", + tk_SourceName, tk_Line ); + } + TK_Beyond( TK_POSITION ); + // Apply the scaling, rotation, and translation in the order + // specified in the HRC file. This could be wrong. + TK_Require( TK_FLOATNUMBER ); + x = tk_FloatNumber * scaling[0]; + TK_FetchRequire( TK_FLOATNUMBER ); + y = tk_FloatNumber * scaling[1]; + TK_FetchRequire( TK_FLOATNUMBER ); + z = tk_FloatNumber * scaling[2]; + + 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; + + x2 = x * cos( rz ) + y*sin( rz ); + y2 = -x*sin( rz ) + y*cos( rz ); + x = x2; + y = y2; + + vList[i].v[0] = x + translation[0]; + vList[i].v[1] = y - translation[2]; + vList[i].v[2] = z + translation[1]; + } + TK_BeyondRequire( TK_POLYGONS, TK_INTNUMBER ); + triCount = tk_IntNumber; + if ( triCount >= MAXTRIANGLES ) { + Error( "Too many triangles in file %s\n", hrc_name ); + } + + start_tri = *triangleCount; + *triangleCount += triCount; + + tList = *triList; + + for ( i = 0; i < triCount; i++ ) + { + if ( meshNode ) { // Update the node + pos = ( i + start_tri ) >> 3; + bit = 1 << ( ( i + start_tri ) & 7 ); + meshNode->tris[pos] |= bit; + } + + TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); + if ( tk_IntNumber != i ) { + Error( "File '%s', line %d:\nTriangle index mismatch.\n", + tk_SourceName, tk_Line ); + } + TK_BeyondRequire( TK_NODES, TK_INTNUMBER ); + if ( tk_IntNumber != 3 ) { + Error( "File '%s', line %d:\nBad polygon vertex count: %d.", + tk_SourceName, tk_Line, tk_IntNumber ); + } + tList[i + start_tri].HasUV = true; + for ( j = 0; j < 3; j++ ) + { + TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); + if ( tk_IntNumber != j ) { + Error( "File '%s', line %d:\nTriangle vertex index" + " mismatch. %d should be %d\n", tk_SourceName, tk_Line, + tk_IntNumber, j ); + } + TK_BeyondRequire( TK_VERTEX, TK_INTNUMBER ); + + tList[i + start_tri].verts[2 - j][0] = vList[tk_IntNumber].v[0]; + tList[i + start_tri].verts[2 - j][1] = vList[tk_IntNumber].v[1]; + tList[i + start_tri].verts[2 - j][2] = vList[tk_IntNumber].v[2]; +#if 1 + tList[i + start_tri].indicies[2 - j] = tk_IntNumber + vertIndexBase; +#endif + TK_BeyondRequire( TK_UVTEXTURE, TK_FLOATNUMBER ); + tList[i + start_tri].uv[2 - j][0] = tk_FloatNumber; + TK_Fetch(); + TK_Require( TK_FLOATNUMBER ); + tList[i + start_tri].uv[2 - j][1] = tk_FloatNumber; + } + + /* 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]); + */ + } + + TK_Beyond( TK_RBRACE ); + TK_Beyond( TK_RBRACE ); + + if ( tk_Token == TK_EDGES ) { + // TK_Beyond(TK_EDGES); + TK_Beyond( TK_RBRACE ); + } + + scaling[0] = scaling[1] = scaling[2] = 1.0; + // rotation[0] = rotation[1] = rotation[2] = 0.0; + // translation[0] = translation[1] = translation[2] = 0.0; + + // See if there are any other models belonging to this node + +#if 1 + TK_Fetch(); + + nextToken = tk_Token; + if ( nextToken == TK_CLUSTERS ) { + if ( g_skelModel.clustered == -1 ) { + ReadHRCClusterList( meshNode, vertIndexBase ); + } + else + { + nextToken = TK_Get( TK_CLUSTER_NAME ); + + while ( nextToken == TK_CLUSTER_NAME ) + { + TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER ); + nextToken = TK_Fetch(); + } + } + + // one right brace follow the list of clusters + nextToken = TK_Beyond( TK_RBRACE ); + } + else + { + if ( g_skelModel.clustered == -1 && !vertIndexBase ) { + meshNode->clustered = false; + } + } +#endif + + nextToken = tk_Token; + if ( nextToken == TK_SPLINE ) { + while ( nextToken == TK_SPLINE ) + { // spline node has two right braces + nextToken = TK_Beyond( TK_RBRACE ); + nextToken = TK_Beyond( TK_RBRACE ); + } + + nextToken = TK_Beyond( TK_RBRACE ); + } + + while ( nextToken == TK_MATERIAL ) + { + nextToken = TK_Beyond( TK_RBRACE ); + } + + while ( nextToken == TK_MODEL ) + { + HandleHRCModel( triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth + 1, vertexCount + vertIndexBase ); + + nextToken = TK_Fetch(); + } + } + + for ( i = 0; i < 3; i++ ) + { + scaling[i] = orig_scaling[i]; + rotation[i] = orig_rotation[i]; + translation[i] = orig_translation[i]; + } +} + +static void LoadHRC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){ + if ( nodesList ) { + *num_mesh_nodes = 0; + + if ( !*nodesList ) { + *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); + } + } + + hrc_name = fileName; + + scaling[0] = scaling[1] = scaling[2] = 1.0; + rotation[0] = rotation[1] = rotation[2] = 0.0; + translation[0] = translation[1] = translation[2] = 0.0; + + *triangleCount = 0; + *triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" ); + memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) ); + + TK_OpenSource( fileName ); + TK_FetchRequire( TK_HRCH ); + TK_FetchRequire( TK_COLON ); + TK_FetchRequire( TK_SOFTIMAGE ); + + // prime it + TK_Beyond( TK_MODEL ); + + HandleHRCModel( triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0 ); + TK_CloseSource(); +} + +//========================================================================== +// +// LoadHTR +// +//========================================================================== +/* + static int Version2; + + void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes, + int ActiveNode, int Depth, int numVerts) + { + int i, j; + int vertexCount; + int vertexNum; + int triCount; + float origin[3]; + triangle_t *tList; + float x, y, z; + float x2, y2, z2; + float rx, ry, rz; + mesh_node_t *meshNode; + int pos,bit; + int vertIndexBase; + int start_tri; + + if (nodesList) + { + TK_BeyondRequire(TK_NAME, TK_STRING); + + if (Depth == 0 || tk_String[0] == '_') + { // Root + ActiveNode = *num_mesh_nodes; + (*num_mesh_nodes)++; + if ((*num_mesh_nodes) > MAX_FM_MESH_NODES) + { + Error("Too many mesh nodes in file %s\n", hrc_name); + } + meshNode = &(*nodesList)[ActiveNode]; + + // memset(meshNode, 0, sizeof(mesh_node_t)); + strcpy(meshNode->name, tk_String); + + memset(meshNode->tris, 0, sizeof(meshNode->tris)); + memset(meshNode->verts, 0, sizeof(meshNode->verts)); + + meshNode->start_glcmds = 0; + meshNode->num_glcmds = 0; + vertIndexBase = 0; + } + else + { // Childs under the children + meshNode = &(*nodesList)[ActiveNode]; + vertIndexBase = numVerts; + } + } + else + { + meshNode = NULL; + } + + // Get vertex count + TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER); + vertexCount = tk_IntNumber; + + // Get triangle count + TK_BeyondRequire(TK_FACES, TK_INTNUMBER); + triCount = tk_IntNumber; + if(triCount >= MAXTRIANGLES) + { + Error("Too many triangles in file %s\n", hrc_name); + } + + // Get origin + TK_Beyond(TK_ORIGIN); + TK_Require(TK_FLOATNUMBER); + origin[0] = tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + origin[1] = tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + origin[2] = tk_FloatNumber; + + //rx = 90.0/360.0*2.0*M_PI; + rx = FixHTRRotateX/360.0*2.0*M_PI; + ry = FixHTRRotateY/360.0*2.0*M_PI; + rz = FixHTRRotateZ/360.0*2.0*M_PI; + + // Get vertex list + for(i = 0; i < vertexCount; i++) + { + TK_FetchRequire(TK_VERTEX); + TK_FetchRequire(TK_FLOATNUMBER); + x = tk_FloatNumber-origin[0]; + TK_FetchRequire(TK_FLOATNUMBER); + y = tk_FloatNumber-origin[1]; + TK_FetchRequire(TK_FLOATNUMBER); + z = tk_FloatNumber-origin[2]; + + x += FixHTRTranslateX; + y += FixHTRTranslateY; + z += FixHTRTranslateZ; + + 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; + x2 = x*cos(rz)-y*sin(rz); + y2 = x*sin(rz)+y*cos(rz); + x = x2; + y = y2; + + vList[i].v[0] = x; + vList[i].v[1] = y; + vList[i].v[2] = z; + } + + start_tri = *triangleCount; + *triangleCount += triCount; + + tList = *triList; + + // Get face list + for(i = 0; i < triCount; i++) + { + if (meshNode) + { // Update the node + pos = (i + start_tri) >> 3; + bit = 1 << ((i + start_tri) & 7 ); + meshNode->tris[pos] |= bit; + } + + TK_FetchRequire(TK_FACE); + TK_FetchRequire(TK_LPAREN); + for(j = 0; j < 3; j++) + { + TK_FetchRequire(TK_INTNUMBER); + vertexNum = tk_IntNumber-1; + if(vertexNum >= vertexCount) + { + Error("File '%s', line %d:\nVertex number" + " >= vertexCount: %d\n", tk_SourceName, tk_Line, + tk_IntNumber); + } + tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0]; + tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1]; + tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2]; + } + TK_FetchRequire(TK_RPAREN); + #ifdef _QDATA + if (Version2) + { + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[0][0]=tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[0][1]=tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[1][0]=tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[1][1]=tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[2][0]=tk_FloatNumber; + TK_FetchRequire(TK_FLOATNUMBER); + tList[i+start_tri].uv[2][1]=tk_FloatNumber; + tList[i+start_tri].HasUV=1; + } + else + tList[i+start_tri].HasUV=0; + #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]); + + } + + TK_Fetch(); + + if (tk_Token == TK_VERTICES) + { + HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase); + } + } + + static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes) + { + if (nodesList) + { + *num_mesh_nodes = 0; + + if(!*nodesList) + { + *nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List"); + } + } + + hrc_name = fileName; + + scaling[0] = scaling[1] = scaling[2] = 1.0; + rotation[0] = rotation[1] = rotation[2] = 0.0; + translation[0] = translation[1] = translation[2] = 0.0; + + *triangleCount = 0; + *triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list"); + memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t)); + + TK_OpenSource(fileName); + + TK_Beyond(TK_C_HEXEN); + TK_Beyond(TK_C_TRIANGLES); + TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER); + if(tk_IntNumber != 1&&tk_IntNumber != 2) + { + Error("Unsupported version (%d) in file %s\n", tk_IntNumber, + fileName); + } + Version2=(tk_IntNumber==2); + + + HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0); + } + + */ + +static void LoadHTR( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){ + int Version2 = 0; + int i, j; + int vertexCount; + int vertexNum; + struct + { + float v[3]; + } *vList; + int triCount; + float origin[3]; + triangle_t *tList; + float x, y, z; + float x2, y2, z2; + float rx, ry, rz; + + 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 ); + + TK_Beyond( TK_C_HEXEN ); + TK_Beyond( TK_C_TRIANGLES ); + TK_BeyondRequire( TK_C_VERSION, TK_INTNUMBER ); + if ( tk_IntNumber != 1 && tk_IntNumber != 2 ) { + Error( "Unsupported version (%d) in file %s\n", tk_IntNumber, + fileName ); + } + Version2 = ( tk_IntNumber == 2 ); + + + // Get vertex count + TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER ); + vertexCount = tk_IntNumber; + vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" ); + + // Get triangle count + TK_BeyondRequire( TK_FACES, 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 ) ); + + // Get origin + TK_Beyond( TK_ORIGIN ); + TK_Require( TK_FLOATNUMBER ); + origin[0] = tk_FloatNumber; + TK_FetchRequire( TK_FLOATNUMBER ); + origin[1] = tk_FloatNumber; + TK_FetchRequire( TK_FLOATNUMBER ); + origin[2] = tk_FloatNumber; + + //rx = 90.0/360.0*2.0*M_PI; + rx = FixHTRRotateX / 360.0 * 2.0 * M_PI; + ry = FixHTRRotateY / 360.0 * 2.0 * M_PI; + rz = FixHTRRotateZ / 360.0 * 2.0 * M_PI; + + // Get vertex list + for ( i = 0; i < vertexCount; i++ ) + { + TK_FetchRequire( TK_VERTEX ); + TK_FetchRequire( TK_FLOATNUMBER ); + x = tk_FloatNumber - origin[0]; + TK_FetchRequire( TK_FLOATNUMBER ); + y = tk_FloatNumber - origin[1]; + TK_FetchRequire( TK_FLOATNUMBER ); + z = tk_FloatNumber - origin[2]; + + x += FixHTRTranslateX; + y += FixHTRTranslateY; + z += FixHTRTranslateZ; + + 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; + x2 = x * cos( rz ) - y*sin( rz ); + y2 = x * sin( rz ) + y*cos( rz ); + x = x2; + y = y2; + + vList[i].v[0] = x; + vList[i].v[1] = y; + vList[i].v[2] = z; + } + + // Get face list + for ( i = 0; i < triCount; i++ ) + { + TK_FetchRequire( TK_FACE ); + TK_FetchRequire( TK_LPAREN ); + for ( j = 0; j < 3; j++ ) + { + TK_FetchRequire( TK_INTNUMBER ); + vertexNum = tk_IntNumber - 1; + if ( vertexNum >= vertexCount ) { + Error( "File '%s', line %d:\nVertex number" + " >= vertexCount: %d\n", tk_SourceName, tk_Line, + tk_IntNumber ); + } + tList[i].verts[2 - j][0] = vList[vertexNum].v[0]; + tList[i].verts[2 - j][1] = vList[vertexNum].v[1]; + tList[i].verts[2 - j][2] = vList[vertexNum].v[2]; + } + TK_FetchRequire( TK_RPAREN ); +#if 1 + if ( Version2 ) { + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[2][0] = fmod( 1000 + tk_FloatNumber,1 ); + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[2][1] = fmod( 1000 + tk_FloatNumber,1 ); + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[1][0] = fmod( 1000 + tk_FloatNumber,1 ); + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[1][1] = fmod( 1000 + tk_FloatNumber,1 ); + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[0][0] = fmod( 1000 + tk_FloatNumber,1 ); + TK_FetchRequire( TK_FLOATNUMBER ); + tList[i].uv[0][1] = fmod( 1000 + tk_FloatNumber,1 ); + tList[i].HasUV = 1; + } + else{ + tList[i].HasUV = 0; + } +#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]); + */ + } + + free( vList ); + TK_CloseSource(); + DefaultNodesList( nodesList,num_mesh_nodes,triangleCount ); +} + +//========================================================================== +// +// LoadTriangleList +// +//========================================================================== + +void LoadTriangleList( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes ){ + 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 ); + LoadHRC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + printf( " - assuming .HRC\n" ); + return; + } + + strcpy( InputFileName, fileName ); + strcat( InputFileName, ".asc" ); + if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { + fclose( file1 ); + LoadASC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + printf( " - assuming .ASC\n" ); + return; + } + + strcpy( InputFileName, fileName ); + strcat( InputFileName, ".tri" ); + if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { + fclose( file1 ); + LoadTRI( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + printf( " - assuming .TRI\n" ); + return; + } + + strcpy( InputFileName, fileName ); + strcat( InputFileName, ".3ds" ); + if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { + fclose( file1 ); + Load3DSTriangleList( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + printf( " - assuming .3DS\n" ); + return; + } + + strcpy( InputFileName, fileName ); + strcat( InputFileName, ".htr" ); + if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { + fclose( file1 ); + LoadHTR( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + printf( " - assuming .HTR\n" ); + return; + } + Error( "\n Could not open file '%s':\n" + "No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName ); + } + else + { + if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) { + printf( "\n" ); + fclose( file1 ); + if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) { + LoadHRC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + } + else if ( strcmp( dotstart,".asc" ) == 0 || strcmp( dotstart,".ASC" ) == 0 ) { + LoadASC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + } + else if ( strcmp( dotstart,".tri" ) == 0 || strcmp( dotstart,".TRI" ) == 0 ) { + LoadTRI( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + } + else if ( strcmp( dotstart,".3ds" ) == 0 || strcmp( dotstart,".3DS" ) == 0 ) { + Load3DSTriangleList( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + } + else if ( strcmp( dotstart,".htr" ) == 0 || strcmp( dotstart,".HTR" ) == 0 ) { + LoadHTR( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); + } + else + { + Error( "Could not open file '%s':\n",fileName ); + return; + } + } + else //failed to load file + { + Error( "Could not open file '%s':\n",fileName ); + } + + } +} diff --git a/tools/heretic2/common/trilib.h b/tools/heretic2/common/trilib.h new file mode 100644 index 00000000..8dfd6d28 --- /dev/null +++ b/tools/heretic2/common/trilib.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 1999-2007 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 ); diff --git a/tools/heretic2/h2data/adpcm.h b/tools/heretic2/h2data/adpcm.h new file mode 100644 index 00000000..aad74eaa --- /dev/null +++ b/tools/heretic2/h2data/adpcm.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/h2data/animcomp.c b/tools/heretic2/h2data/animcomp.c new file mode 100644 index 00000000..a7619325 --- /dev/null +++ b/tools/heretic2/h2data/animcomp.c @@ -0,0 +1,364 @@ +/* + Copyright (C) 1999-2007 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 +#include +#include +#include +#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 ); +} diff --git a/tools/heretic2/h2data/animcomp.h b/tools/heretic2/h2data/animcomp.h new file mode 100644 index 00000000..36ea3b1f --- /dev/null +++ b/tools/heretic2/h2data/animcomp.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/h2data/anorms.h b/tools/heretic2/h2data/anorms.h new file mode 100644 index 00000000..65e92ef1 --- /dev/null +++ b/tools/heretic2/h2data/anorms.h @@ -0,0 +1,183 @@ +/* + Copyright (C) 1999-2007 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}, diff --git a/tools/heretic2/h2data/book.c b/tools/heretic2/h2data/book.c new file mode 100644 index 00000000..412aefe8 --- /dev/null +++ b/tools/heretic2/h2data/book.c @@ -0,0 +1,364 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/h2data/fmodels.c b/tools/heretic2/h2data/fmodels.c new file mode 100644 index 00000000..7d8df18a --- /dev/null +++ b/tools/heretic2/h2data/fmodels.c @@ -0,0 +1,3311 @@ +/* + Copyright (C) 1999-2007 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 "qd_fmodel.h" +#include "animcomp.h" +#include "qd_skeletons.h" +#include "skeletons.h" +#include "qdata.h" +#include "flex.h" +#include "reference.h" + +#include + +/* + ======================================================================== + + .FM triangle flexible model file format + + ======================================================================== + */ + +//================================================================= + +#define NUMVERTEXNORMALS 162 + +extern float avertexnormals[NUMVERTEXNORMALS][3]; + +#define MAX_GROUPS 128 + +typedef struct +{ + triangle_t triangle; + int group; +} trigroup_t; + +#define TRIVERT_DIST .1 + +typedef struct +{ + int start_frame; + int num_frames; + int degrees; + char *mat; + char *ccomp; + char *cbase; + float *cscale; + float *coffset; + float trans[3]; + float scale[3]; + float bmin[3]; + float bmax[3]; +} fmgroup_t; + +//================================================================ + +// Initial +fmheader_t fmheader; + +// Skin +extern char g_skins[MAX_FM_SKINS][64]; + +// ST Coord +extern fmstvert_t base_st[MAX_FM_VERTS]; + +// Triangles +extern fmtriangle_t triangles[MAX_FM_TRIANGLES]; + +// Frames +fmframe_t g_frames[MAX_FM_FRAMES]; +//fmframe_t *g_FMframes; + +// GL Commands +extern int commands[16384]; +extern int numcommands; + + +// +// varibles set by commands +// +extern float scale_up; // set by $scale +extern vec3_t adjust; // set by $origin +extern int g_fixedwidth, g_fixedheight; // set by $skinsize +extern char modelname[64]; // set by $modelname + + +extern char *g_outputDir; + + +// Mesh Nodes +mesh_node_t *pmnodes = NULL; +fmmeshnode_t mesh_nodes[MAX_FM_MESH_NODES]; + +fmgroup_t groups[MAX_GROUPS]; +int num_groups; +int frame_to_group[MAX_FM_FRAMES]; + +// +// variables set by command line arguments +// +qboolean g_no_opimizations = false; + + +// +// base frame info +// +static int triangle_st[MAX_FM_TRIANGLES][3][2]; + + +// number of gl vertices +extern int numglverts; +// indicates if a triangle has already been used in a glcmd +extern int used[MAX_FM_TRIANGLES]; +// indicates if a triangle has translucency in it or not +static qboolean translucent[MAX_FM_TRIANGLES]; + +// main output file handle +extern FILE *headerouthandle; +// output sizes of buildst() +static int skin_width, skin_height; + + +// statistics +static int total_skin_pixels; +static int skin_pixels_used; + +int ShareVertex( trigroup_t trione, trigroup_t tritwo ); +float DistBetween( vec3_t point1, vec3_t point2 ); +int GetNumTris( trigroup_t *tris, int group ); +void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ); +void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ); +void NewDrawLine( int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height ); + +#if !GDEF_OS_WINDOWS + +void strupr( char *string ){ + int i; + + for ( i = 0 ; i < strlen( string ); i++ ) + toupper( string[i] ); + + return; +} + +#endif +//============================================================== + +/* + =============== + ClearModel + =============== + */ +static void ClearModel( void ){ + memset( &fmheader, 0, sizeof( fmheader ) ); + + modelname[0] = 0; + scale_up = 1.0; + VectorCopy( vec3_origin, adjust ); + g_fixedwidth = g_fixedheight = 0; + g_skipmodel = false; + num_groups = 0; + + if ( pmnodes ) { + free( pmnodes ); + pmnodes = NULL; + } + + ClearSkeletalModel(); +} + + +extern void H_printf( char *fmt, ... ); + + +void WriteHeader( FILE *FH, char *Ident, int Version, int Size, void *Data ){ + header_t header; + static long pos = -1; + long CurrentPos; + + if ( Size == 0 ) { // Don't write out empty packets + return; + } + + if ( pos != -1 ) { + CurrentPos = ftell( FH ); + Size = CurrentPos - pos + sizeof( header_t ); + fseek( FH, pos, SEEK_SET ); + pos = -2; + } + else if ( Size == -1 ) { + pos = ftell( FH ); + } + + memset( &header,0,sizeof( header ) ); + strcpy( header.ident,Ident ); + header.version = Version; + header.size = Size; + + SafeWrite( FH, &header, sizeof( header ) ); + + if ( Data ) { + SafeWrite( FH, Data, Size ); + } + + if ( pos == -2 ) { + pos = -1; + fseek( FH, 0, SEEK_END ); + } +} + +/* + ============ + WriteModelFile + ============ + */ +static void WriteModelFile( FILE *modelouthandle ){ + int i; + int j, k; + fmframe_t *in; + fmaliasframe_t *out; + byte buffer[MAX_FM_VERTS * 4 + 128]; + float v; + int c_on, c_off; + IntListNode_t *current, *toFree; + qboolean framesWritten = false; + size_t temp,size = 0; + + // probably should do this dynamically one of these days + struct + { + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + } outFrames[MAX_FM_FRAMES]; + +#define DATA_SIZE 0x60000 // 384K had better be enough, particularly for the reference points + byte data[DATA_SIZE]; + byte data2[DATA_SIZE]; + + fmheader.num_glcmds = numcommands; + fmheader.framesize = (int)&( (fmaliasframe_t *)0 )->verts[fmheader.num_xyz]; + + WriteHeader( modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof( fmheader ), &fmheader ); + + // + // write out the skin names + // + + WriteHeader( modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins ); + + // + // write out the texture coordinates + // + c_on = c_off = 0; + for ( i = 0 ; i < fmheader.num_st ; i++ ) + { + base_st[i].s = LittleShort( base_st[i].s ); + base_st[i].t = LittleShort( base_st[i].t ); + } + + WriteHeader( modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof( base_st[0] ), base_st ); + + // + // write out the triangles + // + WriteHeader( modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof( fmtriangle_t ), NULL ); + + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + int j; + fmtriangle_t tri; + + for ( j = 0 ; j < 3 ; j++ ) + { + tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); + tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); + } + + SafeWrite( modelouthandle, &tri, sizeof( tri ) ); + } + + if ( !num_groups ) { + // + // write out the frames + // + WriteHeader( modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL ); + // WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL); + + for ( i = 0 ; i < fmheader.num_frames ; i++ ) + { + in = &g_frames[i]; + out = (fmaliasframe_t *)buffer; + + strcpy( out->name, in->name ); + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; + out->translate[j] = in->mins[j]; + + outFrames[i].scale[j] = out->scale[j]; + outFrames[i].translate[j] = out->translate[j]; + } + + for ( j = 0 ; j < fmheader.num_xyz ; j++ ) + { + // all of these are byte values, so no need to deal with endianness + out->verts[j].lightnormalindex = in->v[j].lightnormalindex; + + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + if ( v < 0 ) { + v = 0; + } + out->verts[j].v[k] = v; + } + } + + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = LittleFloat( out->scale[j] ); + out->translate[j] = LittleFloat( out->translate[j] ); + } + + SafeWrite( modelouthandle, out, fmheader.framesize ); + } + + // Go back and finish the header + // WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL); + } + else + { + WriteHeader( modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN * fmheader.num_frames, NULL ); + for ( i = 0 ; i < fmheader.num_frames ; i++ ) + { + in = &g_frames[i]; + SafeWrite( modelouthandle,in->name,FRAME_NAME_LEN ); + } + WriteHeader( modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL ); + in = &g_frames[0]; + for ( j = 0 ; j < fmheader.num_xyz ; j++ ) + SafeWrite( modelouthandle,&in->v[j].lightnormalindex,1 ); + } + + // + // write out glcmds + // + WriteHeader( modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands * 4, commands ); + + // + // write out mesh nodes + // + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { + memcpy( mesh_nodes[i].tris, pmnodes[i].tris, sizeof( mesh_nodes[i].tris ) ); + memcpy( mesh_nodes[i].verts, pmnodes[i].verts, sizeof( mesh_nodes[i].verts ) ); + mesh_nodes[i].start_glcmds = LittleShort( (short)pmnodes[i].start_glcmds ); + mesh_nodes[i].num_glcmds = LittleShort( (short)pmnodes[i].num_glcmds ); + } + + WriteHeader( modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof( fmmeshnode_t ) * fmheader.num_mesh_nodes, mesh_nodes ); + + if ( num_groups ) { + +/* + typedef struct + { + int start_frame; + int num_frames; + int degrees; + char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char) + char *ccomp; g->num_frames*g->degrees*sizeof(char) + char *cbase; fmheader.num_xyz*3*sizeof(unsigned char) + float *cscale; g->degrees*sizeof(float) + float *coffset; g->degrees*sizeof(float) + float trans[3]; 3*sizeof(float) + float scale[3]; 3*sizeof(float) + } fmgroup_t; + */ + int tmp,k; + fmgroup_t *g; + size = sizeof( int ) + fmheader.num_frames * sizeof( int ); + for ( k = 0; k < num_groups; k++ ) + { + g = &groups[k]; + size += sizeof( int ) * 3; + size += fmheader.num_xyz * 3 * g->degrees * sizeof( char ); + size += g->num_frames * g->degrees * sizeof( char ); + size += fmheader.num_xyz * 3 * sizeof( unsigned char ); + size += g->degrees * sizeof( float ); + size += g->degrees * sizeof( float ); + size += 12 * sizeof( float ); + } + WriteHeader( modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL ); + SafeWrite( modelouthandle,&num_groups,sizeof( int ) ); + SafeWrite( modelouthandle,frame_to_group,sizeof( int ) * fmheader.num_frames ); + + for ( k = 0; k < num_groups; k++ ) + { + g = &groups[k]; + tmp = LittleLong( g->start_frame ); + SafeWrite( modelouthandle,&tmp,sizeof( int ) ); + tmp = LittleLong( g->num_frames ); + SafeWrite( modelouthandle,&tmp,sizeof( int ) ); + tmp = LittleLong( g->degrees ); + SafeWrite( modelouthandle,&tmp,sizeof( int ) ); + + SafeWrite( modelouthandle,g->mat,fmheader.num_xyz * 3 * g->degrees * sizeof( char ) ); + SafeWrite( modelouthandle,g->ccomp,g->num_frames * g->degrees * sizeof( char ) ); + SafeWrite( modelouthandle,g->cbase,fmheader.num_xyz * 3 * sizeof( unsigned char ) ); + SafeWrite( modelouthandle,g->cscale,g->degrees * sizeof( float ) ); + SafeWrite( modelouthandle,g->coffset,g->degrees * sizeof( float ) ); + SafeWrite( modelouthandle,g->trans,3 * sizeof( float ) ); + SafeWrite( modelouthandle,g->scale,3 * sizeof( float ) ); + SafeWrite( modelouthandle,g->bmin,3 * sizeof( float ) ); + SafeWrite( modelouthandle,g->bmax,3 * sizeof( float ) ); + free( g->mat ); + free( g->ccomp ); + free( g->cbase ); + free( g->cscale ); + free( g->coffset ); + } + } + + // write the skeletal info + if ( g_skelModel.type != SKEL_NULL ) { + size = 0; + + temp = sizeof( int ); // change this to a byte + memcpy( data + size, &g_skelModel.type, temp ); + size += temp; + + // number of joints + temp = sizeof( int ); // change this to a byte + memcpy( data + size, &numJointsInSkeleton[g_skelModel.type], temp ); + size += temp; + + // number of verts in each joint cluster + temp = sizeof( int ) * numJointsInSkeleton[g_skelModel.type]; // change this to shorts + memcpy( data + size, &g_skelModel.new_num_verts[1], temp ); + size += temp; + + // cluster verts + for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) + { + current = g_skelModel.vertLists[i]; + while ( current ) + { + temp = sizeof( int ); // change this to a short + memcpy( data + size, ¤t->data, temp ); + size += temp; + toFree = current; + current = current->next; + free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base + } + } + + if ( !num_groups ) { // joints are stored with regular verts for compressed models + framesWritten = true; + + temp = sizeof( int ); // change this to a byte + memcpy( data + size, &framesWritten, temp ); + size += temp; + + for ( i = 0; i < fmheader.num_frames; ++i ) + { + in = &g_frames[i]; + + for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j ) + { + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data + size, &v, temp ); + size += temp; + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data + size, &v, temp ); + size += temp; + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data + size, &v, temp ); + size += temp; + } + } + } + + } + else + { + temp = sizeof( int ); // change this to a byte + memcpy( data + size, &framesWritten, temp ); + size += temp; + } + + WriteHeader( modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data ); + } + + if ( g_skelModel.references != REF_NULL ) { + int refnum; + + size = 0; + if ( RefPointNum <= 0 ) { // Hard-coded labels + refnum = numReferences[g_skelModel.references]; + } + else + { // Labels indicated in QDT + refnum = RefPointNum; + } + + temp = sizeof( int ); // change this to a byte + memcpy( data2 + size, &g_skelModel.references, temp ); + size += temp; + + if ( !num_groups ) { + framesWritten = true; + + temp = sizeof( int ); // change this to a byte + memcpy( data2 + size, &framesWritten, temp ); + size += temp; + + for ( i = 0; i < fmheader.num_frames; ++i ) + { + in = &g_frames[i]; + + for ( j = 0 ; j < refnum; ++j ) + { + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->references[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data2 + size, &v, temp ); + size += temp; + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->references[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data2 + size, &v, temp ); + size += temp; + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->references[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // write out origin as a float since they arn't clamped + temp = sizeof( float ); // change this to a short + assert( size + temp < DATA_SIZE ); + memcpy( data2 + size, &v, temp ); + size += temp; + } + } + } + } + else // FINISH ME: references need to be stored with regular verts for compressed models + { + framesWritten = false; + + temp = sizeof( int ); // change this to a byte + memcpy( data2 + size, &framesWritten, temp ); + size += temp; + } + + WriteHeader( modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2 ); + } +} + +static void CompressFrames(){ + fmgroup_t *g; + int i,j,k; + fmframe_t *in; + + j = 0; + for ( i = 0; i < fmheader.num_frames; i++ ) + { + while ( i >= groups[j].start_frame + groups[j].num_frames && j < num_groups - 1 ) + j++; + frame_to_group[i] = j; + } + + for ( k = 0; k < num_groups; k++ ) + { + g = &groups[k]; + + printf( "\nCompressing Frames for group %i...\n", k ); + AnimCompressInit( g->num_frames,fmheader.num_xyz,g->degrees ); + for ( i = 0; i < g->num_frames; i++ ) + { + in = &g_frames[i + g->start_frame]; + for ( j = 0; j < fmheader.num_xyz; j++ ) + AnimSetFrame( i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2] ); + } + AnimCompressDoit(); + g->mat = (char *) SafeMalloc( fmheader.num_xyz * 3 * g->degrees * sizeof( char ), "CompressFrames" ); + g->ccomp = (char *) SafeMalloc( g->num_frames * g->degrees * sizeof( char ), "CompressFrames" ); + g->cbase = (char *) SafeMalloc( fmheader.num_xyz * 3 * sizeof( unsigned char ), "CompressFrames" ); + g->cscale = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" ); + g->coffset = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" ); + AnimCompressToBytes( g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax ); + AnimCompressEnd(); + } +} + +static void OptimizeVertices( void ){ + qboolean vert_used[MAX_FM_VERTS]; + short vert_replacement[MAX_FM_VERTS]; + int i,j,k,l,pos,bit,set_pos,set_bit; + fmframe_t *in; + qboolean Found; + int num_unique; + static IntListNode_t *newVertLists[NUM_CLUSTERS]; + static int newNum_verts[NUM_CLUSTERS]; + IntListNode_t *current, *next; + + printf( "Optimizing vertices..." ); + + memset( vert_used, 0, sizeof( vert_used ) ); + + if ( g_skelModel.clustered == true ) { + memset( newNum_verts, 0, sizeof( newNum_verts ) ); + memset( newVertLists, 0, sizeof( newVertLists ) ); + } + + num_unique = 0; + + // search for common points among all the frames + for ( i = 0 ; i < fmheader.num_frames ; i++ ) + { + in = &g_frames[i]; + + for ( j = 0; j < fmheader.num_xyz; j++ ) + { + for ( k = 0,Found = false; k < j; k++ ) + { // starting from the beginning always ensures vert_replacement points to the first point in the array + if ( in->v[j].v[0] == in->v[k].v[0] && + in->v[j].v[1] == in->v[k].v[1] && + in->v[j].v[2] == in->v[k].v[2] ) { + Found = true; + vert_replacement[j] = k; + break; + } + + } + + if ( !Found ) { + if ( !vert_used[j] ) { + num_unique++; + } + vert_used[j] = true; + } + } + } + + // recompute the light normals + for ( i = 0 ; i < fmheader.num_frames ; i++ ) + { + in = &g_frames[i]; + + for ( j = 0; j < fmheader.num_xyz; j++ ) + { + if ( !vert_used[j] ) { + k = vert_replacement[j]; + + VectorAdd( in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum ); + in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++; + } + } + + for ( j = 0 ; j < fmheader.num_xyz ; j++ ) + { + vec3_t v; + float maxdot; + int maxdotindex; + int c; + + c = in->v[j].vnorm.numnormals; + if ( !c ) { + Error( "Vertex with no triangles attached" ); + } + + VectorScale( in->v[j].vnorm.normalsum, 1.0 / c, v ); + VectorNormalize( v, v ); + + maxdot = -999999.0; + maxdotindex = -1; + + for ( k = 0 ; k < NUMVERTEXNORMALS ; k++ ) + { + float dot; + + dot = DotProduct( v, avertexnormals[k] ); + if ( dot > maxdot ) { + maxdot = dot; + maxdotindex = k; + } + } + + in->v[j].lightnormalindex = maxdotindex; + } + } + + // create substitution list + num_unique = 0; + for ( i = 0; i < fmheader.num_xyz; i++ ) + { + if ( vert_used[i] ) { + vert_replacement[i] = num_unique; + num_unique++; + } + else + { + vert_replacement[i] = vert_replacement[vert_replacement[i]]; + } + + // vert_replacement[i] is the new index, i is the old index + // need to add the new index to the cluster list if old index was in it + if ( g_skelModel.clustered == true ) { + for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k ) + { + for ( l = 0, current = g_skelModel.vertLists[k]; + l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next ) + { + if ( current->data == i ) { + IntListNode_t *current2; + int m; + qboolean added = false; + + for ( m = 0, current2 = newVertLists[k]; m < newNum_verts[k + 1]; + ++m, current2 = current2->next ) + { + if ( current2->data == vert_replacement[i] ) { + added = true; + break; + } + } + + if ( !added ) { + ++newNum_verts[k + 1]; + + next = newVertLists[k]; + + newVertLists[k] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "OptimizeVertices" ); + // freed after model write out + + newVertLists[k]->data = vert_replacement[i]; + newVertLists[k]->next = next; + } + break; + } + } + } + } + } + + // substitute + for ( i = 0 ; i < fmheader.num_frames ; i++ ) + { + in = &g_frames[i]; + + for ( j = 0; j < fmheader.num_xyz; j++ ) + { + in->v[vert_replacement[j]] = in->v[j]; + } + + } + + for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) + { + IntListNode_t *toFree; + current = g_skelModel.vertLists[i]; + + while ( current ) + { + toFree = current; + current = current->next; + free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base + } + + g_skelModel.vertLists[i] = newVertLists[i]; + g_skelModel.new_num_verts[i + 1] = newNum_verts[i + 1]; + } + +#ifndef NDEBUG + for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k ) + { + for ( l = 0, current = g_skelModel.vertLists[k]; + l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next ) + { + IntListNode_t *current2; + int m; + + for ( m = l + 1, current2 = current->next; m < newNum_verts[k + 1]; + ++m, current2 = current2->next ) + { + if ( current->data == current2->data ) { + printf( "Warning duplicate vertex: %d\n", current->data ); + break; + } + } + } + } +#endif + + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { // reset the vert bits + memset( pmnodes[i].verts,0,sizeof( pmnodes[i].verts ) ); + } + + // repleace the master triangle list vertex indexes and update the vert bits for each mesh node + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + pos = i >> 3; + bit = 1 << ( i & 7 ); + + for ( j = 0 ; j < 3 ; j++ ) + { + set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]]; + + set_pos >>= 3; + set_bit = 1 << ( set_bit & 7 ); + + for ( k = 0; k < fmheader.num_mesh_nodes; k++ ) + { + if ( !( pmnodes[k].tris[pos] & bit ) ) { + continue; + } + pmnodes[k].verts[set_pos] |= set_bit; + } + } + } + + for ( i = 0; i < numcommands; i++ ) + { + j = commands[i]; + if ( !j ) { + continue; + } + + j = abs( j ); + for ( i++; j; j--,i += 3 ) + { + commands[i + 2] = vert_replacement[commands[i + 2]]; + } + i--; + } + + printf( "Reduced by %d\n",fmheader.num_xyz - num_unique ); + + fmheader.num_xyz = num_unique; + if ( num_groups ) { + // tack on the reference verts to the regular verts + if ( g_skelModel.references != REF_NULL ) { + fmframe_t *in; + int index; + int refnum; + + if ( RefPointNum <= 0 ) { // Hard-coded labels + refnum = numReferences[g_skelModel.references]; + } + else + { // Labels indicated in QDT + refnum = RefPointNum; + } + + + for ( i = 0; i < fmheader.num_frames; ++i ) + { + in = &g_frames[i]; + index = fmheader.num_xyz; + + for ( j = 0 ; j < refnum; ++j ) + { + VectorCopy( in->references[j].placement.origin, in->v[index].v ); + index++; + + VectorCopy( in->references[j].placement.direction, in->v[index].v ); + index++; + + VectorCopy( in->references[j].placement.up, in->v[index].v ); + index++; + } + } + + fmheader.num_xyz += refnum * 3; + } + + // tack on the skeletal joint verts to the regular verts + if ( g_skelModel.type != SKEL_NULL ) { + fmframe_t *in; + int index; + + for ( i = 0; i < fmheader.num_frames; ++i ) + { + in = &g_frames[i]; + index = fmheader.num_xyz; + + for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j ) + { + VectorCopy( in->joints[j].placement.origin, in->v[index].v ); + index++; + + VectorCopy( in->joints[j].placement.direction, in->v[index].v ); + index++; + + VectorCopy( in->joints[j].placement.up, in->v[index].v ); + index++; + } + } + + fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type] * 3; + } + + CompressFrames(); + } +} + + +/* + =============== + FinishModel + =============== + */ +void FMFinishModel( void ){ + FILE *modelouthandle; + int i,j,length,tris,verts,bit,pos,total_tris,total_verts; + char name[1024]; + int trans_count; + + if ( !fmheader.num_frames ) { + return; + } + +// +// copy to release directory tree if doing a release build +// + if ( g_release ) { + if ( modelname[0] ) { + sprintf( name, "%s", modelname ); + } + else{ + sprintf( name, "%s/tris.fm", cdpartial ); + } + ReleaseFile( name ); + + for ( i = 0 ; i < fmheader.num_skins ; i++ ) + { + ReleaseFile( g_skins[i] ); + } + fmheader.num_frames = 0; + return; + } + + printf( "\n" ); + + trans_count = 0; + for ( i = 0; i < fmheader.num_tris; i++ ) + if ( translucent[i] ) { + trans_count++; + } + + if ( !g_no_opimizations ) { + OptimizeVertices(); + } + +// +// write the model output file +// + if ( modelname[0] ) { + sprintf( name, "%s%s", g_outputDir, modelname ); + } + else{ + sprintf( name, "%s/tris.fm", g_outputDir ); + } + printf( "saving to %s\n", name ); + CreatePath( name ); + modelouthandle = SafeOpenWrite( name ); + + WriteModelFile( modelouthandle ); + + printf( "%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight ); + printf( "First frame boundaries:\n" ); + printf( " minimum x: %3f\n", g_frames[0].mins[0] ); + printf( " maximum x: %3f\n", g_frames[0].maxs[0] ); + printf( " minimum y: %3f\n", g_frames[0].mins[1] ); + printf( " maximum y: %3f\n", g_frames[0].maxs[1] ); + printf( " minimum z: %3f\n", g_frames[0].mins[2] ); + printf( " maximum z: %3f\n", g_frames[0].maxs[2] ); + printf( "%4d vertices\n", fmheader.num_xyz ); + printf( "%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count ); + printf( "%4d frame\n", fmheader.num_frames ); + printf( "%4d glverts\n", numglverts ); + printf( "%4d glcmd\n", fmheader.num_glcmds ); + printf( "%4d skins\n", fmheader.num_skins ); + printf( "%4d mesh nodes\n", fmheader.num_mesh_nodes ); + printf( "wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used, + total_skin_pixels, (double)( total_skin_pixels - skin_pixels_used ) / (double)total_skin_pixels * 100.0 ); + + printf( "file size: %d\n", (int)ftell( modelouthandle ) ); + printf( "---------------------\n" ); + + if ( g_verbose ) { + if ( fmheader.num_mesh_nodes ) { + total_tris = total_verts = 0; + printf( "Node Name Tris Verts\n" ); + printf( "--------------------------------- ---- -----\n" ); + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { + tris = 0; + verts = 0; + for ( j = 0; j < MAXTRIANGLES; j++ ) + { + pos = ( j ) >> 3; + bit = 1 << ( ( j ) & 7 ); + if ( pmnodes[i].tris[pos] & bit ) { + tris++; + } + } + for ( j = 0; j < MAX_FM_VERTS; j++ ) + { + pos = ( j ) >> 3; + bit = 1 << ( ( j ) & 7 ); + if ( pmnodes[i].verts[pos] & bit ) { + verts++; + } + } + + printf( "%-33s %4d %5d\n",pmnodes[i].name,tris,verts ); + + total_tris += tris; + total_verts += verts; + } + printf( "--------------------------------- ---- -----\n" ); + printf( "%-33s %4d %5d\n","TOTALS",total_tris,total_verts ); + } + } + fclose( modelouthandle ); + + // finish writing header file + H_printf( "\n" ); + + // scale_up is usefull to allow step distances to be adjusted + H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up ); + + // mesh nodes + if ( fmheader.num_mesh_nodes ) { + H_printf( "\n" ); + H_printf( "#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes ); + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { + strcpy( name, pmnodes[i].name ); + strupr( name ); + length = strlen( name ); + for ( j = 0; j < length; j++ ) + { + if ( name[j] == ' ' ) { + name[j] = '_'; + } + } + H_printf( "#define MESH_%s\t\t%d\n", name, i ); + } + } + + fclose( headerouthandle ); + headerouthandle = NULL; + free( pmnodes ); +} + + +/* + ================================================================= + + ALIAS MODEL DISPLAY LIST GENERATION + + ================================================================= + */ + +extern int strip_xyz[128]; +extern int strip_st[128]; +extern int strip_tris[128]; +extern int stripcount; + +/* + ================ + StripLength + ================ + */ +static int StripLength( int starttri, int startv, int num_tris, int node ){ + int m1, m2; + int st1, st2; + int j; + fmtriangle_t *last, *check; + int k; + int pos, bit; + + used[starttri] = 2; + + last = &triangles[starttri]; + + strip_xyz[0] = last->index_xyz[( startv ) % 3]; + strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; + strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; + strip_st[0] = last->index_st[( startv ) % 3]; + strip_st[1] = last->index_st[( startv + 1 ) % 3]; + strip_st[2] = last->index_st[( startv + 2 ) % 3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[( startv + 2 ) % 3]; + st1 = last->index_st[( startv + 2 ) % 3]; + m2 = last->index_xyz[( startv + 1 ) % 3]; + st2 = last->index_st[( startv + 1 ) % 3]; + + // look for a matching triangle +nexttri: + for ( j = starttri + 1, check = &triangles[starttri + 1] + ; j < num_tris ; j++, check++ ) + { + pos = j >> 3; + bit = 1 << ( j & 7 ); + if ( !( pmnodes[node].tris[pos] & bit ) ) { + continue; + } + for ( k = 0 ; k < 3 ; k++ ) + { + if ( check->index_xyz[k] != m1 ) { + continue; + } + if ( check->index_st[k] != st1 ) { + continue; + } + if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { + continue; + } + if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { + continue; + } + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if ( used[j] || translucent[j] != translucent[starttri] ) { + goto done; + } + + // the new edge + if ( stripcount & 1 ) { + m2 = check->index_xyz[ ( k + 2 ) % 3 ]; + st2 = check->index_st[ ( k + 2 ) % 3 ]; + } + else + { + m1 = check->index_xyz[ ( k + 2 ) % 3 ]; + st1 = check->index_st[ ( k + 2 ) % 3 ]; + } + + strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ]; + strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ]; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for ( j = starttri + 1 ; j < num_tris ; j++ ) + if ( used[j] == 2 ) { + used[j] = 0; + } + + return stripcount; +} + + +/* + =========== + FanLength + =========== + */ +static int FanLength( int starttri, int startv, int num_tris, int node ){ + int m1, m2; + int st1, st2; + int j; + fmtriangle_t *last, *check; + int k; + int pos, bit; + + used[starttri] = 2; + + last = &triangles[starttri]; + + strip_xyz[0] = last->index_xyz[( startv ) % 3]; + strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; + strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; + strip_st[0] = last->index_st[( startv ) % 3]; + strip_st[1] = last->index_st[( startv + 1 ) % 3]; + strip_st[2] = last->index_st[( startv + 2 ) % 3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[( startv + 0 ) % 3]; + st1 = last->index_st[( startv + 0 ) % 3]; + m2 = last->index_xyz[( startv + 2 ) % 3]; + st2 = last->index_st[( startv + 2 ) % 3]; + + + // look for a matching triangle +nexttri: + for ( j = starttri + 1, check = &triangles[starttri + 1] + ; j < num_tris ; j++, check++ ) + { + pos = j >> 3; + bit = 1 << ( j & 7 ); + if ( !( pmnodes[node].tris[pos] & bit ) ) { + continue; + } + for ( k = 0 ; k < 3 ; k++ ) + { + if ( check->index_xyz[k] != m1 ) { + continue; + } + if ( check->index_st[k] != st1 ) { + continue; + } + if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { + continue; + } + if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { + continue; + } + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if ( used[j] || translucent[j] != translucent[starttri] ) { + goto done; + } + + // the new edge + m2 = check->index_xyz[ ( k + 2 ) % 3 ]; + st2 = check->index_st[ ( k + 2 ) % 3 ]; + + strip_xyz[stripcount + 2] = m2; + strip_st[stripcount + 2] = st2; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for ( j = starttri + 1 ; j < num_tris ; j++ ) + if ( used[j] == 2 ) { + used[j] = 0; + } + + return stripcount; +} + + + +/* + ================ + BuildGlCmds + + Generate a list of trifans or strips + for the model, which holds for all frames + ================ + */ +static void BuildGlCmds( void ){ + int i, j, k, l; + int startv; + float s, t; + int len, bestlen, besttype; + int best_xyz[1024]; + int best_st[1024]; + int best_tris[1024]; + int type; + int trans_check; + int bit,pos; + + // + // build tristrips + // + numcommands = 0; + numglverts = 0; + + + for ( l = 0; l < fmheader.num_mesh_nodes; l++ ) + { + memset( used, 0, sizeof( used ) ); + + pmnodes[l].start_glcmds = numcommands; + + for ( trans_check = 0; trans_check < 2; trans_check++ ) + { + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + pos = i >> 3; + bit = 1 << ( i & 7 ); + if ( !( pmnodes[l].tris[pos] & bit ) ) { + continue; + } + + // pick an unused triangle and start the trifan + if ( used[i] || trans_check != translucent[i] ) { + continue; + } + + bestlen = 0; + for ( type = 0 ; type < 2 ; type++ ) + // type = 1; + { + for ( startv = 0 ; startv < 3 ; startv++ ) + { + if ( type == 1 ) { + len = StripLength( i, startv, fmheader.num_tris, l ); + } + else{ + len = FanLength( i, startv, fmheader.num_tris, l ); + } + if ( len > bestlen ) { + besttype = type; + bestlen = len; + for ( j = 0 ; j < bestlen + 2 ; j++ ) + { + best_st[j] = strip_st[j]; + best_xyz[j] = strip_xyz[j]; + } + for ( j = 0 ; j < bestlen ; j++ ) + best_tris[j] = strip_tris[j]; + } + } + } + + // mark the tris on the best strip/fan as used + for ( j = 0 ; j < bestlen ; j++ ) + used[best_tris[j]] = 1; + + if ( besttype == 1 ) { + commands[numcommands++] = ( bestlen + 2 ); + } + else{ + commands[numcommands++] = -( bestlen + 2 ); + } + + numglverts += bestlen + 2; + + for ( j = 0 ; j < bestlen + 2 ; j++ ) + { + // emit a vertex into the reorder buffer + k = best_st[j]; + + // emit s/t coords into the commands stream + s = base_st[k].s; + t = base_st[k].t; + + s = ( s ) / fmheader.skinwidth; + t = ( t ) / fmheader.skinheight; + + *(float *)&commands[numcommands++] = s; + *(float *)&commands[numcommands++] = t; + *(int *)&commands[numcommands++] = best_xyz[j]; + } + } + } + commands[numcommands++] = 0; // end of list marker + pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds; + } +} + + +/* + =============================================================== + + BASE FRAME SETUP + + =============================================================== + */ + + +#define LINE_NORMAL 1 +#define LINE_FAT 2 +#define LINE_DOTTED 3 + + +#define ASCII_SPACE 32 + +int LineType = LINE_NORMAL; +extern unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768]; +unsigned char LineColor = 255; +int ScaleWidth, ScaleHeight; + + +static char *CharDefs[] = +{ + "-------------------------", + "-------------------------", // ! + "-------------------------", // " + "-------------------------", // # + "-------------------------", // $ + "-------------------------", // % + "-------------------------", // & + "--*----*-----------------", // ' + "-*---*----*----*-----*---", // ( + "*-----*----*----*---*----", // ) + "-----*--*--**---**--*--*-", // * + "-------------------------", // + + "----------------**--**---", // , + "-------------------------", // - + "----------------**---**--", // . + "-------------------------", // / + " *** * *** * *** * *** ", // 0 + " * ** * * * ", + "**** * *** * *****", + "**** * *** ***** ", + " ** * * * * ***** * ", + "**** * **** ***** ", + " *** * **** * * *** ", + "***** * * * * ", + " *** * * *** * * *** ", + " *** * * **** * *** ", // 9 + "-**---**--------**---**--", // : + "-------------------------", // ; + "-------------------------", // < + "-------------------------", // = + "-------------------------", // > + "-------------------------", // ? + "-------------------------", // @ + "-***-*---*******---**---*", // A + "****-*---*****-*---*****-", + "-*****----*----*-----****", + "****-*---**---**---*****-", + "******----****-*----*****", + "******----****-*----*----", + "-*****----*--***---*-****", + "*---**---*******---**---*", + "-***---*----*----*---***-", + "----*----*----**---*-***-", + "-*--*-*-*--**---*-*--*--*", + "-*----*----*----*----****", + "*---***-***-*-**---**---*", + "*---***--**-*-**--***---*", + "-***-*---**---**---*-***-", + "****-*---*****-*----*----", + "-***-*---**---*-***----**", + "****-*---*****-*-*--*--**", + "-*****-----***-----*****-", + "*****--*----*----*----*--", + "*---**---**---**---******", + "*---**---**---*-*-*---*--", + "*---**---**-*-***-***---*", + "*---*-*-*---*---*-*-*---*", + "*---**---*-*-*---*----*--", + "*****---*---*---*---*****" // Z +}; + +void DrawLine( int x1, int y1, int x2, int y2 ){ + int dx, dy; + int adx, ady; + int count; + float xfrac, yfrac, xstep, ystep; + unsigned sx, sy; + float u, v; + + dx = x2 - x1; + dy = y2 - y1; + adx = abs( dx ); + ady = abs( dy ); + + count = adx > ady ? adx : ady; + count++; + + if ( count > 300 ) { + printf( "Bad count\n" ); + return; // don't ever hang up on bad data + } + + xfrac = x1; + yfrac = y1; + + xstep = (float)dx / count; + ystep = (float)dy / count; + + switch ( LineType ) + { + case LINE_NORMAL: + do + { + if ( xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT ) { + pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor; + } + xfrac += xstep; + yfrac += ystep; + count--; + } while ( count > 0 ); + break; + case LINE_FAT: + do + { + for ( u = -0.1 ; u <= 0.9 ; u += 0.999 ) + { + for ( v = -0.1 ; v <= 0.9 ; v += 0.999 ) + { + sx = xfrac + u; + sy = yfrac + v; + if ( sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT ) { + pic[sy * SKINPAGE_WIDTH + sx] = LineColor; + } + } + } + xfrac += xstep; + yfrac += ystep; + count--; + } while ( count > 0 ); + break; + case LINE_DOTTED: + do + { + if ( count & 1 && xfrac < SKINPAGE_WIDTH && + yfrac < SKINPAGE_HEIGHT ) { + pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor; + } + xfrac += xstep; + yfrac += ystep; + count--; + } while ( count > 0 ); + break; + default: + Error( "Unknown %d.\n", LineType ); + } +} + +//========================================================================== +// +// DrawCharacter +// +//========================================================================== + +static void DrawCharacter( int x, int y, int character ){ + int r, c; + char *def; + + character = toupper( character ); + if ( character < ASCII_SPACE || character > 'Z' ) { + character = ASCII_SPACE; + } + character -= ASCII_SPACE; + for ( def = CharDefs[character], r = 0; r < 5; r++ ) + { + for ( c = 0; c < 5; c++ ) + { + pic[( y + r ) * SKINPAGE_WIDTH + x + c] = *def++ == '*' ? 255 : 0; + } + } +} + +//========================================================================== +// +// DrawTextChar +// +//========================================================================== + +void DrawTextChar( int x, int y, char *text ){ + int c; + + while ( ( c = *text++ ) != '\0' ) + { + DrawCharacter( x, y, c ); + x += 6; + } +} + + +extern void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ); + +//========================================================================== +// ExtractDigit + +static int ExtractDigit( byte *pic, int x, int y ){ + int i; + int r, c; + char digString[32]; + char *buffer; + byte backColor; + char **DigitDefs; + + backColor = pic[( SKINPAGE_HEIGHT - 1 ) * SKINPAGE_WIDTH]; + DigitDefs = &CharDefs['0' - ASCII_SPACE]; + + buffer = digString; + for ( r = 0; r < 5; r++ ) + { + for ( c = 0; c < 5; c++ ) + { + *buffer++ = ( pic[( y + r ) * SKINPAGE_WIDTH + x + c] == backColor ) ? ' ' : '*'; + } + } + *buffer = '\0'; + for ( i = 0; i < 10; i++ ) + { + if ( strcmp( DigitDefs[i], digString ) == 0 ) { + return i; + } + } + + Error( "Unable to extract scaling info from skin PCX." ); + return 0; +} + +//========================================================================== +// ExtractNumber + +int ExtractNumber( byte *pic, int x, int y ){ + return ExtractDigit( pic, x, y ) * 100 + ExtractDigit( pic, x + 6, y ) * 10 + ExtractDigit( pic, x + 12, y ); +} + + + + + +/* + ============ + BuildST + + Builds the triangle_st array for the base frame and + fmheader.skinwidth / fmheader.skinheight + + FIXME: allow this to be loaded from a file for + arbitrary mappings + ============ + */ +static void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ + int backface_flag; + int i, j; + int width, height, iwidth, iheight, swidth; + float basex, basey; + float scale; + vec3_t mins, maxs; + float *pbasevert; + vec3_t vtemp1, vtemp2, normal; + float s_scale, t_scale; + float scWidth; + float scHeight; + int skinwidth; + int skinheight; + + // + // find bounds of all the verts on the base frame + // + ClearBounds( mins, maxs ); + backface_flag = false; + + if ( ptri[0].HasUV ) { // if we have the uv already, we don't want to double up or scale + iwidth = ScaleWidth; + iheight = ScaleHeight; + + t_scale = s_scale = 1.0; + } + else + { + for ( i = 0 ; i < numtri ; i++ ) + for ( j = 0 ; j < 3 ; j++ ) + AddPointToBounds( ptri[i].verts[j], mins, maxs ); + + for ( i = 0 ; i < 3 ; i++ ) + { + mins[i] = floor( mins[i] ); + maxs[i] = ceil( maxs[i] ); + } + + width = maxs[0] - mins[0]; + height = maxs[2] - mins[2]; + + for ( i = 0 ; i < numtri ; i++ ) + { + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + if ( normal[1] > 0 ) { + backface_flag = true; + break; + } + } + scWidth = ScaleWidth * SCALE_ADJUST_FACTOR; + if ( backface_flag ) { //we are doubling + scWidth /= 2; + } + + scHeight = ScaleHeight * SCALE_ADJUST_FACTOR; + + scale = scWidth / width; + + if ( height * scale >= scHeight ) { + scale = scHeight / height; + } + + iwidth = ceil( width * scale ) + 4; + iheight = ceil( height * scale ) + 4; + + s_scale = (float)( iwidth - 4 ) / width; + t_scale = (float)( iheight - 4 ) / height; + t_scale = s_scale; + } + if ( DrawSkin ) { + if ( backface_flag ) { + DrawScreen( s_scale, t_scale, iwidth * 2, iheight ); + } + else{ + DrawScreen( s_scale, t_scale, iwidth, iheight ); + } + } + if ( backface_flag ) { + skinwidth = iwidth * 2; + } + else{ + skinwidth = iwidth; + } + skinheight = iheight; + + +/* if (!g_fixedwidth) + { // old style + scale = 8; + if (width*scale >= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + + s_scale = t_scale = scale; + + iwidth = ceil(width*s_scale); + iheight = ceil(height*t_scale); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + }*/ + +// +// determine which side of each triangle to map the texture to +// + basey = 2; + for ( i = 0 ; i < numtri ; i++ ) + { + if ( ptri[i].HasUV ) { + for ( j = 0 ; j < 3 ; j++ ) + { + triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * skinwidth ); + triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * skinheight ); + } + } + else + { + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + if ( normal[1] > 0 ) { + basex = iwidth + 2; + } + else + { + basex = 2; + } + + for ( j = 0 ; j < 3 ; j++ ) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); + triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); + } + } + + if ( DrawSkin ) { + DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], + triangle_st[i][1][0], triangle_st[i][1][1] ); + DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], + triangle_st[i][2][0], triangle_st[i][2][1] ); + DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], + triangle_st[i][0][0], triangle_st[i][0][1] ); + } + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + + swidth = iwidth; + if ( backface_flag ) { + swidth *= 2; + } + fmheader.skinwidth = ( swidth + 3 ) & ~3; + fmheader.skinheight = iheight; + + skin_width = iwidth; + skin_height = iheight; +} + + +static void BuildNewST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ + int i, j; + + for ( i = 0 ; i < numtri ; i++ ) + { + if ( ptri[i].HasUV ) { + for ( j = 0 ; j < 3 ; j++ ) + { + triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * ( ScaleWidth - 1 ) ); + triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * ( ScaleHeight - 1 ) ); + } + } + + if ( DrawSkin ) { + DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], + triangle_st[i][1][0], triangle_st[i][1][1] ); + DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], + triangle_st[i][2][0], triangle_st[i][2][1] ); + DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], + triangle_st[i][0][0], triangle_st[i][0][1] ); + } + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + + fmheader.skinwidth = ( ScaleWidth + 3 ) & ~3; + fmheader.skinheight = ScaleHeight; + + skin_width = ScaleWidth; + skin_height = ScaleHeight; +} + + + + +byte *BasePalette; +byte *BasePixels,*TransPixels; +int BaseWidth, BaseHeight, TransWidth, TransHeight; +qboolean BaseTrueColor; +static qboolean SetPixel = false; + +int CheckTransRecursiveTri( int *lp1, int *lp2, int *lp3 ){ + int *temp; + int d; + int new[2]; + + d = lp2[0] - lp1[0]; + if ( d < -1 || d > 1 ) { + goto split; + } + d = lp2[1] - lp1[1]; + if ( d < -1 || d > 1 ) { + goto split; + } + + d = lp3[0] - lp2[0]; + if ( d < -1 || d > 1 ) { + goto split2; + } + d = lp3[1] - lp2[1]; + if ( d < -1 || d > 1 ) { + goto split2; + } + + d = lp1[0] - lp3[0]; + if ( d < -1 || d > 1 ) { + goto split3; + } + d = lp1[1] - lp3[1]; + if ( d < -1 || d > 1 ) { +split3: + temp = lp1; + lp1 = lp3; + lp3 = lp2; + lp2 = temp; + + goto split; + } + + return 0; // entire tri is filled + +split2: + temp = lp1; + lp1 = lp2; + lp2 = lp3; + lp3 = temp; + +split: +// split this edge + new[0] = ( lp1[0] + lp2[0] ) >> 1; + new[1] = ( lp1[1] + lp2[1] ) >> 1; + +// draw the point if splitting a leading edge + if ( lp2[1] > lp1[1] ) { + goto nodraw; + } + if ( ( lp2[1] == lp1[1] ) && ( lp2[0] < lp1[0] ) ) { + goto nodraw; + } + + if ( SetPixel ) { + assert( ( new[1] * BaseWidth ) + new[0] < BaseWidth * BaseHeight ); + + if ( BaseTrueColor ) { + BasePixels[( ( new[1] * BaseWidth ) + new[0] ) * 4] = 1; + } + else + { + BasePixels[( new[1] * BaseWidth ) + new[0]] = 1; + } + } + else + { + if ( TransPixels ) { + if ( TransPixels[( new[1] * TransWidth ) + new[0]] != 255 ) { + return 1; + } + } + else if ( BaseTrueColor ) { + if ( BasePixels[( ( ( new[1] * BaseWidth ) + new[0] ) * 4 ) + 3] != 255 ) { + return 1; + } + } + else + { +// pixel = BasePixels[(new[1]*BaseWidth) + new[0]]; + } + } + +nodraw: +// recursively continue + if ( CheckTransRecursiveTri( lp3, lp1, new ) ) { + return 1; + } + + return CheckTransRecursiveTri( lp3, new, lp2 ); +} + +static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters, + IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){ + int i, j; + IntListNode_t *next; + + for ( j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j ) + { + if ( !clusters[j] ) { + continue; + } + + for ( i = 0; i < num_verts[j + 1]; ++i ) + { + if ( clusters[j][i] == oldindex ) { + ++new_num_verts[j + 1]; + + next = vertLists[j]; + + vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" ); + // Currently freed in WriteJointedModelFile only + + vertLists[j]->data = newIndex; + vertLists[j]->next = next; + } + } + } +} + +#define FUDGE_EPSILON 0.002 + +qboolean VectorFudgeCompare( vec3_t v1, vec3_t v2 ){ + int i; + + for ( i = 0 ; i < 3 ; i++ ) + if ( fabs( v1[i] - v2[i] ) > FUDGE_EPSILON ) { + return false; + } + + return true; +} + +/* + ================= + Cmd_Base + ================= + */ +void Cmd_FMBase( qboolean GetST ){ + triangle_t *ptri, *st_tri; + int num_st_tris; + int i, j, k, l; + int x,y,z; +// int time1; + char file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256]; + vec3_t base_xyz[MAX_FM_VERTS]; + FILE *FH; + int pos,bit; + qboolean NewSkin; + + GetScriptToken( false ); + + if ( g_skipmodel || g_release || g_archive ) { + return; + } + + printf( "---------------------\n" ); + sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext ); + printf( "%s ", file1 ); + + ExpandPathAndArchive( file1 ); + + // Use the input filepath for this one. + sprintf( file1, "%s/%s", cddir, token ); + +// time1 = FileTime (file1); +// if (time1 == -1) +// Error ("%s doesn't exist", file1); + +// +// load the base triangles +// + if ( do3ds ) { + Load3DSTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); + } + else{ + LoadTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); + } + + if ( g_ignoreTriUV ) { + for ( i = 0; i < fmheader.num_tris; i++ ) + { + ptri[i].HasUV = 0; + } + } + + GetScriptToken( false ); + sprintf( file2, "%s/%s", cddir, token ); + sprintf( trans_file, "%s/!%s_a.pcx", cddir, token ); + + ExtractFileExtension( file2, extension ); + if ( extension[0] == 0 ) { + strcat( file2, ".pcx" ); + } + printf( "skin: %s\n", file2 ); + + BaseTrueColor = LoadAnyImage( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight ); + + NewSkin = false; + if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) { + if ( g_allow_newskin ) { + ScaleWidth = BaseWidth; + ScaleHeight = BaseHeight; + NewSkin = true; + } + else + { + Error( "Invalid skin page size: (%d,%d) should be (%d,%d)", + BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT ); + } + } + else if ( !BaseTrueColor ) { + ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X, + ENCODED_WIDTH_Y ); + ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X, + ENCODED_HEIGHT_Y ); + } + else + { + Error( "Texture coordinates not supported on true color image" ); + } + + if ( GetST ) { + GetScriptToken( false ); + + sprintf( stfile, "%s/%s.%s", cdarchive, token, trifileext ); + printf( "ST: %s ", stfile ); + + sprintf( stfile, "%s/%s", cddir, token ); + + if ( do3ds ) { + Load3DSTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL ); + } + else{ + LoadTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL ); + } + + if ( num_st_tris != fmheader.num_tris ) { + Error( "num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris ); + } + + printf( " matching triangles...\n" ); + for ( i = 0; i < fmheader.num_tris; i++ ) + { + k = -1; + for ( j = 0; j < num_st_tris; j++ ) + { + for ( x = 0; x < 3; x++ ) + { + for ( y = 0; y < 3; y++ ) + { + if ( x == y ) { + continue; + } + for ( z = 0; z < 3; z++ ) + { + if ( z == x || z == y ) { + continue; + } + + if ( VectorFudgeCompare( ptri[i].verts[0], st_tri[j].verts[x] ) && + VectorFudgeCompare( ptri[i].verts[1], st_tri[j].verts[y] ) && + VectorFudgeCompare( ptri[i].verts[2], st_tri[j].verts[z] ) ) { + if ( k == -1 ) { + k = j; + ptri[i].HasUV = st_tri[k].HasUV; + ptri[i].uv[0][0] = st_tri[k].uv[x][0]; + ptri[i].uv[0][1] = st_tri[k].uv[x][1]; + ptri[i].uv[1][0] = st_tri[k].uv[y][0]; + ptri[i].uv[1][1] = st_tri[k].uv[y][1]; + ptri[i].uv[2][0] = st_tri[k].uv[z][0]; + ptri[i].uv[2][1] = st_tri[k].uv[z][1]; + x = y = z = 999; + } + else if ( k != j ) { + printf( "Duplicate triangle %d found in st file: %d and %d\n",i,k,j ); + printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", + ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2], + ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2], + ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2] ); + printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", + st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2], + st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2], + st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2] ); + printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", + st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2], + st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2], + st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2] ); + } + } + } + } + } + } + if ( k == -1 ) { + printf( "No matching triangle %d\n",i ); + } + } + free( st_tri ); + } + +// +// get the ST values +// + if ( ptri && ptri[0].HasUV ) { + if ( !NewSkin ) { + Error( "Base has UVs with old style skin page\nMaybe you want to use -ignoreUV" ); + } + else + { + BuildNewST( ptri, fmheader.num_tris, false ); + } + } + else + { + if ( NewSkin ) { + Error( "Base has new style skin without UVs" ); + } + else + { + BuildST( ptri, fmheader.num_tris, false ); + } + } + + TransPixels = NULL; + if ( !BaseTrueColor ) { + FH = fopen( trans_file,"rb" ); + if ( FH ) { + fclose( FH ); + Load256Image( trans_file, &TransPixels, NULL, &TransWidth, &TransHeight ); + if ( TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight ) { + Error( "source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight ); + } + } + } + +// +// run through all the base triangles, storing each unique vertex in the +// base vertex list and setting the indirect triangles to point to the base +// vertices +// + for ( l = 0; l < fmheader.num_mesh_nodes; l++ ) + { + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + pos = i >> 3; + bit = 1 << ( i & 7 ); + if ( !( pmnodes[l].tris[pos] & bit ) ) { + continue; + } + + for ( j = 0 ; j < 3 ; j++ ) + { + // get the xyz index + for ( k = 0 ; k < fmheader.num_xyz ; k++ ) + { + if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) { + break; // this vertex is already in the base vertex list + } + } + + if ( k == fmheader.num_xyz ) { // new index + VectorCopy( ptri[i].verts[j], base_xyz[fmheader.num_xyz] ); + + if ( pmnodes[l].clustered == true ) { + ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts ); + } + + fmheader.num_xyz++; + } + + pos = k >> 3; + bit = 1 << ( k & 7 ); + pmnodes[l].verts[pos] |= bit; + + triangles[i].index_xyz[j] = k; + + // get the st index + for ( k = 0 ; k < fmheader.num_st ; k++ ) + { + if ( triangle_st[i][j][0] == base_st[k].s + && triangle_st[i][j][1] == base_st[k].t ) { + break; // this vertex is already in the base vertex list + } + } + + if ( k == fmheader.num_st ) { // new index + base_st[fmheader.num_st].s = triangle_st[i][j][0]; + base_st[fmheader.num_st].t = triangle_st[i][j][1]; + fmheader.num_st++; + } + + triangles[i].index_st[j] = k; + } + + if ( TransPixels || BaseTrueColor ) { + translucent[i] = CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); + } + else + { + translucent[i] = false; + } + } + } + + if ( !BaseTrueColor ) { + SetPixel = true; + memset( BasePixels,0,BaseWidth * BaseHeight ); + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); + } + SetPixel = false; + + skin_pixels_used = 0; + for ( i = 0; i < fmheader.skinheight; i++ ) + { + for ( j = 0; j < fmheader.skinwidth; j++ ) + { + skin_pixels_used += BasePixels[( i * BaseWidth ) + j]; + } + } + total_skin_pixels = fmheader.skinheight * fmheader.skinwidth; + } + else + { + SetPixel = true; + memset( BasePixels,0,BaseWidth * BaseHeight * 4 ); + for ( i = 0 ; i < fmheader.num_tris ; i++ ) + { + CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); + } + SetPixel = false; + + skin_pixels_used = 0; + for ( i = 0; i < fmheader.skinheight; i++ ) + { + for ( j = 0; j < fmheader.skinwidth; j++ ) + { + skin_pixels_used += BasePixels[( ( i * BaseWidth ) + j ) * 4]; + } + } + total_skin_pixels = fmheader.skinheight * fmheader.skinwidth; + } + + // build triangle strips / fans + BuildGlCmds(); + + if ( TransPixels ) { + free( TransPixels ); + } + free( BasePixels ); + if ( BasePalette ) { + free( BasePalette ); + } + free( ptri ); +} + +void Cmd_FMNodeOrder( void ){ + mesh_node_t *newnodes, *pos; + int i,j; + + if ( !pmnodes ) { + Error( "Base has not been established yet" ); + } + + pos = newnodes = malloc( sizeof( mesh_node_t ) * fmheader.num_mesh_nodes ); + + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { + GetScriptToken( false ); + + for ( j = 0; j < fmheader.num_mesh_nodes; j++ ) + { + if ( strcmpi( pmnodes[j].name, token ) == 0 ) { + *pos = pmnodes[j]; + pos++; + break; + } + } + if ( j >= fmheader.num_mesh_nodes ) { + Error( "Node '%s' not in base list!\n", token ); + } + } + + free( pmnodes ); + pmnodes = newnodes; +} + +//=============================================================== + +extern char *FindFrameFile( char *frame ); + + +/* + =============== + GrabFrame + =============== + */ +void GrabFrame( char *frame ){ + triangle_t *ptri; + int i, j; + fmtrivert_t *ptrivert; + int num_tris; + char file1[1024]; + fmframe_t *fr; + int index_xyz; + char *framefile; + + // the frame 'run1' will be looked for as either + // run.1 or run1.tri, so the new alias sequence save + // feature an be used + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "grabbing %s ", file1 ); + + if ( fmheader.num_frames >= MAX_FM_FRAMES ) { + Error( "fmheader.num_frames >= MAX_FM_FRAMES" ); + } + fr = &g_frames[fmheader.num_frames]; + fmheader.num_frames++; + + strcpy( fr->name, frame ); + +// +// load the frame +// + if ( do3ds ) { + Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL ); + } + else{ + LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL ); + } + + if ( num_tris != fmheader.num_tris ) { + Error( "%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris ); + } + +// +// allocate storage for the frame's vertices +// + ptrivert = fr->v; + + for ( i = 0 ; i < fmheader.num_xyz ; i++ ) + { + ptrivert[i].vnorm.numnormals = 0; + VectorClear( ptrivert[i].vnorm.normalsum ); + } + ClearBounds( fr->mins, fr->maxs ); + +// +// store the frame's vertices in the same order as the base. This assumes the +// triangles and vertices in this frame are in exactly the same order as in the +// base +// + for ( i = 0 ; i < num_tris ; i++ ) + { + vec3_t vtemp1, vtemp2, normal; + float ftemp; + + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + VectorNormalize( normal, normal ); + + // rotate the normal so the model faces down the positive x axis + ftemp = normal[0]; + normal[0] = -normal[1]; + normal[1] = ftemp; + + for ( j = 0 ; j < 3 ; j++ ) + { + index_xyz = triangles[i].index_xyz[j]; + + // rotate the vertices so the model faces down the positive x axis + // also adjust the vertices to the desired origin + ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) + + adjust[0]; + ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) + + adjust[1]; + ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) + + adjust[2]; + + AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs ); + + VectorAdd( ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum ); + ptrivert[index_xyz].vnorm.numnormals++; + } + } + +// +// calculate the vertex normals, match them to the template list, and store the +// index of the best match +// + for ( i = 0 ; i < fmheader.num_xyz ; i++ ) + { + int j; + vec3_t v; + float maxdot; + int maxdotindex; + int c; + + c = ptrivert[i].vnorm.numnormals; + if ( !c ) { + Error( "Vertex with no triangles attached" ); + } + + VectorScale( ptrivert[i].vnorm.normalsum, 1.0 / c, v ); + VectorNormalize( v, v ); + + maxdot = -999999.0; + maxdotindex = -1; + + for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ ) + { + float dot; + + dot = DotProduct( v, avertexnormals[j] ); + if ( dot > maxdot ) { + maxdot = dot; + maxdotindex = j; + } + } + + ptrivert[i].lightnormalindex = maxdotindex; + } + + free( ptri ); +} + +/* + =============== + Cmd_Frame + =============== + */ +void Cmd_FMFrame( void ){ + while ( ScriptTokenAvailable() ) + { + GetScriptToken( false ); + if ( g_skipmodel ) { + continue; + } + if ( g_release || g_archive ) { + fmheader.num_frames = 1; // don't skip the writeout + continue; + } + + H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames ); + + if ( ( g_skelModel.type != SKEL_NULL ) || ( g_skelModel.references != REF_NULL ) ) { + GrabModelTransform( token ); + } + + GrabFrame( token ); + + if ( g_skelModel.type != SKEL_NULL ) { + GrabSkeletalFrame( token ); + } + + if ( g_skelModel.references != REF_NULL ) { + GrabReferencedFrame( token ); + } + + // need to add the up and dir points to the frame bounds here + // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs); + // then remove fudge in determining scale on frame write out + } +} + +/* + =============== + Cmd_Skin + + Skins aren't actually stored in the file, only a reference + is saved out to the header file. + =============== + */ +void Cmd_FMSkin( void ){ + byte *palette; + byte *pixels; + int width, height; + byte *cropped; + int y; + char name[1024], savename[1024], transname[1024], extension[256]; + miptex32_t *qtex32; + int size; + FILE *FH; + qboolean TrueColor; + + GetScriptToken( false ); + + if ( fmheader.num_skins == MAX_FM_SKINS ) { + Error( "fmheader.num_skins == MAX_FM_SKINS" ); + } + + if ( g_skipmodel ) { + return; + } + + sprintf( name, "%s/%s", cdarchive, token ); + strcpy( name, ExpandPathAndArchive( name ) ); +// sprintf (name, "%s/%s.lbm", cddir, token); + + if ( ScriptTokenAvailable() ) { + GetScriptToken( false ); + sprintf( g_skins[fmheader.num_skins], "!%s", token ); + sprintf( savename, "%s!%s", g_outputDir, token ); + sprintf( transname, "%s!%s_a.pcx", gamedir, token ); + } + else + { + sprintf( g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token ); + sprintf( savename, "%s/!%s", g_outputDir, token ); + sprintf( transname, "%s/!%s_a.pcx", cddir, token ); + } + + fmheader.num_skins++; + + if ( g_skipmodel || g_release || g_archive ) { + return; + } + + // load the image + printf( "loading %s\n", name ); + ExtractFileExtension( name, extension ); + if ( extension[0] == 0 ) { + strcat( name, ".pcx" ); + } + + + TrueColor = LoadAnyImage( name, &pixels, &palette, &width, &height ); +// RemapZero (pixels, palette, width, height); + + // crop it to the proper size + + if ( !TrueColor ) { + cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight, "Cmd_FMSkin" ); + for ( y = 0 ; y < fmheader.skinheight ; y++ ) + { + memcpy( cropped + y * fmheader.skinwidth, + pixels + y * width, fmheader.skinwidth ); + } + + TransPixels = NULL; + FH = fopen( transname,"rb" ); + if ( FH ) { + fclose( FH ); + + strcat( g_skins[fmheader.num_skins - 1],".pcx" ); + strcat( savename,".pcx" ); + + // save off the new image + printf( "saving %s\n", savename ); + CreatePath( savename ); + WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette ); + } + else + { + #if 1 + miptex_t *qtex; + qtex = CreateMip( cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true ); + + strcat( g_skins[fmheader.num_skins - 1],".m8" ); + strcat( savename,".m8" ); + + printf( "saving %s\n", savename ); + CreatePath( savename ); + SaveFile( savename, (byte *)qtex, size ); + free( qtex ); + #else + strcat( g_skins[fmheader.num_skins - 1],".pcx" ); + strcat( savename,".pcx" ); + + // save off the new image + printf( "saving %s\n", savename ); + CreatePath( savename ); + WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette ); + #endif + } + } + else + { + cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight * 4, "Cmd_FMSkin" ); + for ( y = 0 ; y < fmheader.skinheight ; y++ ) + { + memcpy( cropped + ( ( y * fmheader.skinwidth ) * 4 ), pixels + ( y * width * 4 ), fmheader.skinwidth * 4 ); + } + + qtex32 = CreateMip32( (unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true ); + + StripExtension( g_skins[fmheader.num_skins - 1] ); + strcat( g_skins[fmheader.num_skins - 1],".m32" ); + StripExtension( savename ); + strcat( savename,".m32" ); + + printf( "saving %s\n", savename ); + CreatePath( savename ); + SaveFile( savename, (byte *)qtex32, size ); + } + + free( pixels ); + if ( palette ) { + free( palette ); + } + free( cropped ); +} + + +/* + =============== + Cmd_Cd + =============== + */ +void Cmd_FMCd( void ){ + char temp[256]; + + FinishModel(); + ClearModel(); + + GetScriptToken( false ); + + // this is a silly mess... + sprintf( cdpartial, "models/%s", token ); + sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token ); + sprintf( cddir, "%s%s", gamedir, cdpartial ); + + // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too. + sprintf( temp, "%s%s", g_outputDir, cdpartial ); + strcpy( g_outputDir, temp ); + + // if -only was specified and this cd doesn't match, + // skip the model (you only need to match leading chars, + // so you could regrab all monsters with -only monsters) + if ( !g_only[0] ) { + return; + } + if ( strncmp( token, g_only, strlen( g_only ) ) ) { + g_skipmodel = true; + printf( "skipping %s\n", cdpartial ); + } +} + + +/* + + //======================= + // NEW GEN + //======================= + + void NewGen (char *ModelFile, char *OutputName, int width, int height) + { + trigroup_t *triangles; + triangle_t *ptri; + triangle_t *grouptris; + mesh_node_t *pmnodes; + + vec3_t *vertices; + vec3_t *uvs; + vec3_t aveNorm, crossvect; + vec3_t diffvect1, diffvect2; + vec3_t v0, v1, v2; + vec3_t n, u, v; + vec3_t base, zaxis, yaxis; + vec3_t uvwMin, uvwMax; + vec3_t groupMin, groupMax; + vec3_t uvw; + + float *uFinal, *vFinal; + unsigned char *newpic; + + int finalstart = 0, finalcount = 0; + int xbase = 0, xwidth = 0, ywidth = 0; + int *todo, *done, finished; + int i, j, k, l; //counters + int groupnum, numtris, numverts, num; + int count; + FILE *grpfile; + long datasize; + + for ( i = 0; i<3; i++) + { + aveNorm[i] = 0; + uvwMin[i] = 1e30f; + uvwMax[i] = -1e30f; + } + + pmnodes = NULL; + ptri = NULL; + triangles = NULL; + + zaxis[0] = 0; + zaxis[1] = 0; + zaxis[2] = 1; + + yaxis[0] = 0; + yaxis[1] = 1; + yaxis[2] = 0; + + LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes); + + todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen"); + done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen"); + triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen"); + + for ( i=0; i < fmheader.num_tris; i++) + { + todo[i] = false; + done[i] = false; + triangles[i].triangle = ptri[i]; + triangles[i].group = 0; + } + + groupnum = 0; + + // transitive closure algorithm follows + // put all triangles who transitively share vertices into separate groups + + while (1) + { + for ( i = 0; i < fmheader.num_tris; i++) + { + if (!done[i]) + { + break; + } + } + if ( i == fmheader.num_tris) + { + break; + } + finished = false; + todo[i] = true; + while (!finished) + { + finished = true; + for ( i = 0; i < fmheader.num_tris; i++) + { + if (todo[i]) + { + done[i] = true; + triangles[i].group = groupnum; + todo[i] = false; + for ( j = 0; j < fmheader.num_tris; j++) + { + if ((!done[j]) && (ShareVertex(triangles[i],triangles[j]))) + { + todo[j] = true; + finished = false; + } + } + } + } + } + groupnum++; + } + uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen"); + vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen"); + + grpfile = fopen("grpdebug.txt","w"); + + + for (i = 0; i < groupnum; i++) + { + + fprintf(grpfile,"Group Number: %d\n", i); + + numtris = GetNumTris(triangles, i); // number of triangles in group i + numverts = numtris * 3; + + fprintf(grpfile,"%d triangles.\n", numtris); + + vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen"); + uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen"); + grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen"); + + for (count = 0; count < fmheader.num_tris; count++) + { + if (triangles[count].group == i) + { + fprintf(grpfile,"Triangle %d\n", count); + } + } + fprintf(grpfile,"\n"); + + + + + GetOneGroup(triangles, i, grouptris); + + num = 0; + for (j = 0; j < numtris; j++) + { + VectorCopy(grouptris[j].verts[0], v0); + VectorCopy(grouptris[j].verts[1], v1); + VectorCopy(grouptris[j].verts[2], v2); + VectorSubtract(v1, v0, diffvect1); + VectorSubtract(v2, v1, diffvect2); + CrossProduct( diffvect1, diffvect2, crossvect); + VectorAdd(aveNorm, crossvect, aveNorm); + VectorCopy(v0,vertices[num]); + num++; // FIXME + VectorCopy(v1,vertices[num]); + num++; // add routine to add only verts that + VectorCopy(v2,vertices[num]); + num++; // have not already been added + } + + assert (num >= 3); + // figure out the best plane projections + DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base); + + if (DotProduct(aveNorm,n) < 0.0f) + { + VectorScale(n, -1.0f, n); + } + VectorNormalize(n,n); + if (fabs(n[2]) < .57) + { + CrossProduct( zaxis, n, crossvect); + VectorCopy(crossvect, u); + } + else + { + CrossProduct( yaxis, n, crossvect); + VectorCopy(crossvect, u); + } + VectorNormalize(u,u); + CrossProduct( n, u, crossvect); + VectorCopy(crossvect, v); + VectorNormalize(v,v); + + num = 0; + + for ( j = 0; j < 3; j++) + { + groupMin[j] = 1e30f; + groupMax[j] = -1e30f; + } + + for ( j = 0; j < numtris; j++) + { + for ( k = 0; k < 3; k++) + { + VectorCopy(grouptris[j].verts[k],v0); + VectorSubtract(v0, base, v0); + uvw[0] = DotProduct(v0, u); + uvw[1] = DotProduct(v0, v); + uvw[2] = DotProduct(v0, n); + VectorCopy(uvw,uvs[num]); + num++; + for ( l = 0; l < 3; l++) + { + if (uvw[l] < groupMin[l]) + { + groupMin[l] = uvw[l]; + } + if (uvw[l] > groupMax[l]) + { + groupMax[l] = uvw[l]; + } + } + } + } + + xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap + ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin + + for ( j=0; j < numverts; j++) + { + uFinal[finalcount] = uvs[j][0] + xwidth + xbase; + vFinal[finalcount] = uvs[j][1] + ywidth; + if (uFinal[finalcount] < uvwMin[0]) + { + uvwMin[0] = uFinal[finalcount]; + } + if (uFinal[finalcount] > uvwMax[0]) + { + uvwMax[0] = uFinal[finalcount]; + } + if (vFinal[finalcount] < uvwMin[1]) + { + uvwMin[1] = vFinal[finalcount]; + } + if (vFinal[finalcount] > uvwMax[1]) + { + uvwMax[1] = vFinal[finalcount]; + } + finalcount++; + } + + fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth); + fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth); + + finalcount = finalstart; + + for ( count = 0; count < numverts; count++) + { + fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]); + fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]); + } + + finalstart = finalcount; + + fprintf(grpfile,"\n"); + + free(vertices); + free(uvs); + free(grouptris); + + xbase += ceil(groupMax[0] - groupMin[0]) + 2; + + } + + fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]); + fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]); + + + ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount); + + for (k = 0; k < finalcount; k++) + { + fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]); + } + + // i've got the array of vertices in uFinal and vFinal. Now I need to write them and draw lines + + datasize = width * height*sizeof(unsigned char); + newpic = (unsigned char*)SafeMalloc(datasize, "NewGen"); + memset(newpic,0,datasize); + memset(pic_palette,0,sizeof(pic_palette)); + pic_palette[767] = pic_palette[766] = pic_palette[765] = 255; + + k = 0; + while (k < finalcount) + { + NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height); + k++; + NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height); + k++; + NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height); + k++; + fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k); + } + + WritePCXfile (OutputName, newpic, width, height, pic_palette); + + fclose(grpfile); + + free(todo); + free(done); + free(triangles); + free(newpic); + return; + } + void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height) + { + long dx, dy; + long adx, ady; + long count; + float xfrac, yfrac, xstep, ystep; + unsigned long sx, sy; + float u, v; + + dx = x2 - x1; + dy = y2 - y1; + adx = abs(dx); + ady = abs(dy); + + count = adx > ady ? adx : ady; + count++; + + if(count > 300) + { + printf("Bad count\n"); + return; // don't ever hang up on bad data + } + + xfrac = x1; + yfrac = y1; + + xstep = (float)dx/count; + ystep = (float)dy/count; + + switch(LineType) + { + case LINE_NORMAL: + do + { + if(xfrac < width && yfrac < height) + { + picture[(long)yfrac*width+(long)xfrac] = LineColor; + } + xfrac += xstep; + yfrac += ystep; + count--; + } while (count > 0); + break; + case LINE_FAT: + do + { + for (u=-0.1 ; u<=0.9 ; u+=0.999) + { + for (v=-0.1 ; v<=0.9 ; v+=0.999) + { + sx = xfrac+u; + sy = yfrac+v; + if(sx < width && sy < height) + { + picture[sy*width+sx] = LineColor; + } + } + } + xfrac += xstep; + yfrac += ystep; + count--; + } while (count > 0); + break; + case LINE_DOTTED: + do + { + if(count&1 && xfrac < width && + yfrac < height) + { + picture[(long)yfrac*width+(long)xfrac] = LineColor; + } + xfrac += xstep; + yfrac += ystep; + count--; + } while (count > 0); + break; + default: + Error("Unknown %d.\n", LineType); + } + } + */ +void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ){ + + int i; + float hscale, vscale; + float scale; + + hscale = max[0]; + vscale = max[1]; + + hscale = ( Width - 2 ) / max[0]; + vscale = ( Height - 2 ) / max[1]; + + scale = hscale; + if ( scale > vscale ) { + scale = vscale; + } + for ( i = 0; i < verts; i++ ) + { + u[i] *= scale; + v[i] *= scale; + } + return; +} + + +void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ){ + int i; + int j; + + j = 0; + for ( i = 0; i < fmheader.num_tris; i++ ) + { + if ( tris[i].group == grp ) { + triangles[j++] = tris[i].triangle; + } + } + return; +} + + +int GetNumTris( trigroup_t *tris, int grp ){ + int i; + int verts; + + verts = 0; + for ( i = 0; i < fmheader.num_tris; i++ ) + { + if ( tris[i].group == grp ) { + verts++; + } + } + return verts; +} + + +int ShareVertex( trigroup_t trione, trigroup_t tritwo ){ + int i; + int j; + + i = 1; + j = 1; + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) + { + if ( DistBetween( trione.triangle.verts[i],tritwo.triangle.verts[j] ) < TRIVERT_DIST ) { + return true; + } + } + } + return false; +} + + +float DistBetween( vec3_t point1, vec3_t point2 ){ + float dist; + + dist = ( point1[0] - point2[0] ); + dist *= dist; + dist += ( point1[1] - point2[1] ) * ( point1[1] - point2[1] ); + dist += ( point1[2] - point2[2] ) * ( point1[2] - point2[2] ); + dist = sqrt( dist ); + return dist; +} + + +void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ){ + triangle_t *ptri; + mesh_node_t *pmnodes; + int i; + + pmnodes = NULL; + ptri = NULL; + + LoadTriangleList( ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); + if ( g_ignoreTriUV ) { + for ( i = 0; i < fmheader.num_tris; i++ ) + { + ptri[i].HasUV = 0; + } + } + + memset( pic,0,sizeof( pic ) ); + memset( pic_palette,0,sizeof( pic_palette ) ); + pic_palette[767] = pic_palette[766] = pic_palette[765] = 255; + + ScaleWidth = Width; + ScaleHeight = Height; + + BuildST( ptri, fmheader.num_tris, true ); + + WritePCXfile( OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette ); + + printf( "Gen Skin Stats:\n" ); + printf( " Input Base: %s\n",ModelFile ); + printf( " Input Dimensions: %d,%d\n",Width,Height ); + printf( "\n" ); + printf( " Output File: %s\n",OutputName ); + printf( " Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight ); + + if ( fmheader.num_mesh_nodes ) { + printf( "\nNodes:\n" ); + for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) + { + printf( " %s\n",pmnodes[i].name ); + } + } + + free( ptri ); + free( pmnodes ); +} + + +void Cmd_FMBeginGroup( void ){ + GetScriptToken( false ); + + g_no_opimizations = false; + + groups[num_groups].start_frame = fmheader.num_frames; + groups[num_groups].num_frames = 0; + + groups[num_groups].degrees = atol( token ); + if ( groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32 ) { + Error( "Degrees of freedom out of range: %d",groups[num_groups].degrees ); + } +} + +void Cmd_FMEndGroup( void ){ + groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame; + + if ( num_groups < MAX_GROUPS - 1 ) { + num_groups++; + } + else + { + Error( "Number of compression groups exceded: %i\n", MAX_GROUPS ); + } +} diff --git a/tools/heretic2/h2data/h2data.rc b/tools/heretic2/h2data/h2data.rc new file mode 100644 index 00000000..21540bc2 --- /dev/null +++ b/tools/heretic2/h2data/h2data.rc @@ -0,0 +1,115 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "..\\..\\..\\icons\\h2data.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Heavily modified from original ID tool\0" + VALUE "CompanyName", "Raven Software\0" + VALUE "FileDescription", "qdata\0" + VALUE "FileVersion", "2.0\0" + VALUE "InternalName", "qdata\0" + VALUE "LegalCopyright", "Copyright © 1998\0" + VALUE "OriginalFilename", "qdata.exe\0" + VALUE "ProductName", "Raven Software qdata\0" + VALUE "ProductVersion", "2.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tools/heretic2/h2data/images.c b/tools/heretic2/h2data/images.c new file mode 100644 index 00000000..555303bc --- /dev/null +++ b/tools/heretic2/h2data/images.c @@ -0,0 +1,1409 @@ +/* + Copyright (C) 1999-2007 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" + +#if GDEF_OS_WINDOWS + #include +#endif + +#if GDEF_OS_MACOS && !defined( XWINDOWS ) +#include +#else +#include +#endif + +#if 1 +extern char *g_outputDir; +#endif // _QDATA + +char mip_prefix[1024]; // directory to dump the textures in + +qboolean colormap_issued; +byte colormap_palette[768]; + +unsigned total_x = 0; +unsigned total_y = 0; +unsigned total_textures = 0; + +#define MAX_IMAGE_SIZE 512 + +#if 0 +/* + ============== + 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; + } +} + +#endif + + +// ******************************************************************** +// ** Mip Map Pre-Processing Routines +// ******************************************************************** + +#define intensity_value 1 + +static unsigned image_pal[256]; + +#define MAX_LAST 25 + +long palette_r[256], palette_g[256], palette_b[256]; +long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place; + +long cached; + +void PrepareConvert( unsigned *palette ){ + int i; + + for ( i = 0; i < 256; i++ ) + { + palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16; + palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8; + palette_b[i] = ( palette[i] & 0x000000ff ); + } + + for ( i = 0; i < MAX_LAST; i++ ) + last_r[i] = -1; + + last_place = -1; +} + +int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){ + int i; + long min_dist; + int min_index; + long dist; + long dr, dg, db, biggest_delta; + + for ( i = 0; i < MAX_LAST; i++ ) + if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) { + cached++; + return last_i[i]; + } + + min_dist = 256 * 256 + 256 * 256 + 256 * 256; + biggest_delta = 256 * 256; + min_index = 0; + + for ( i = 0; i < 256; i++ ) + { + dr = abs( palette_r[i] - r ); + if ( dr > biggest_delta ) { + continue; + } + dg = abs( palette_g[i] - g ); + if ( dg > biggest_delta ) { + continue; + } + db = abs( palette_b[i] - b ); + if ( db > biggest_delta ) { + continue; + } + + dist = dr * dr + dg * dg + db * db; + if ( dist < min_dist ) { + min_dist = dist; + min_index = i; + if ( min_dist == 0 ) { + break; + } + + dist = dr; + if ( dg > dist ) { + dist = dg; + } + if ( db > dist ) { + dist = db; + } + if ( dist < biggest_delta ) { + biggest_delta = dist; + } + } + } + + last_place++; + if ( last_place >= MAX_LAST ) { + last_place = 0; + } + + last_r[last_place] = r; + last_g[last_place] = g; + last_b[last_place] = b; + last_i[last_place] = min_index; + + return min_index; +} + + +void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out, + int outwidth, int outheight, palette_t *palette ){ + int i, j; + byte *inrow, *inrow2; + unsigned frac, fracstep; + unsigned p1[1024], p2[1024], *p1p, *p2p; + palette_t *c1,*c2,*c3,*c4; + unsigned r,g,b; + + fracstep = inwidth * 0x10000 / outwidth; + + frac = fracstep >> 2; + for ( i = 0 ; i < outwidth ; i++ ) + { + p1[i] = frac >> 16; + frac += fracstep; + } + frac = 3 * ( fracstep >> 2 ); + for ( i = 0 ; i < outwidth ; i++ ) + { + p2[i] = frac >> 16; + frac += fracstep; + } + + cached = 0; + + for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth) + { + inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight ); + inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight ); + + p1p = p1; + p2p = p2; + for ( j = 0 ; j < outwidth ; j++ ) + { + c1 = &palette[*( (byte *)inrow + ( *p1p ) )]; + c2 = &palette[*( (byte *)inrow + ( *p2p ) )]; + c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )]; + c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )]; + + r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2; + g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2; + b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2; + + *out++ = ConvertTrueColorToPal( r,g,b ); + } + } +} + +void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){ + int i, j; + palette_t *c1,*c2,*c3,*c4; + unsigned r,g,b; + + cached = 0; + memset( out, 0, 256 * 256 ); + width <<= 1; + height <<= 1; + + for ( i = 0; i < height; i += 2, in += width ) + { + for ( j = 0; j < width; j += 2 ) + { + c1 = &palette[in[0]]; + c3 = &palette[in[width]]; + in++; + c2 = &palette[in[0]]; + c4 = &palette[in[width]]; + in++; + + r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2; + g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2; + b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2; + + *out++ = ConvertTrueColorToPal( r, g, b ); + } + } +} + + +miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){ + int scaled_width, scaled_height; + int i,j,r,g,b; + byte intensitytable[256]; + byte scaled[256 * 256]; + byte out[256 * 256]; + int miplevel; + miptex_t *mp; + byte *pos; + int size; + + for ( i = 0 ; i < 256 ; i++ ) + { + j = i * intensity_value; + if ( j > 255 ) { + j = 255; + } + intensitytable[i] = j; + } + + for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 ) + ; + if ( 1 && scaled_width > width && 1 ) { + scaled_width >>= 1; + } + for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 ) + ; + if ( 1 && scaled_height > height && 1 ) { + scaled_height >>= 1; + } + + // don't ever bother with >256 textures + if ( scaled_width > 256 ) { + scaled_width = 256; + } + if ( scaled_height > 256 ) { + scaled_height = 256; + } + + if ( scaled_width < 1 ) { + scaled_width = 1; + } + if ( scaled_height < 1 ) { + scaled_height = 1; + } + + size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 ); + mp = (miptex_t *)SafeMalloc( size, "CreateMip" ); + memset( mp,0,size ); + + mp->version = MIP_VERSION; + + for ( i = j = 0; i < 256; i++,j += 3 ) + { + mp->palette[i].r = r = intensitytable[palette[j]]; + mp->palette[i].g = g = intensitytable[palette[j + 1]]; + mp->palette[i].b = b = intensitytable[palette[j + 2]]; + image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b ); + } + + PrepareConvert( image_pal ); + + if ( scaled_width == width && scaled_height == height ) { + memcpy( scaled, data, width * height ); + } + else{ + GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette ); + } + + pos = (byte *)( mp + 1 ); + miplevel = 0; + + while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) ) + { + if ( scaled_width < 1 ) { + scaled_width = 1; + } + if ( scaled_height < 1 ) { + scaled_height = 1; + } + + if ( miplevel > 0 ) { + GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette ); + } + else{ + memcpy( out, scaled, 256 * 256 ); + } + + mp->width[miplevel] = scaled_width; + mp->height[miplevel] = scaled_height; + mp->offsets[miplevel] = pos - ( (byte *)( mp ) ); + memcpy( pos, out, scaled_width * scaled_height ); + memcpy( scaled, out, 256 * 256 ); + pos += scaled_width * scaled_height; + + scaled_width >>= 1; + scaled_height >>= 1; + + miplevel++; + } + + *FinalSize = pos - ( (byte *)( mp ) ); + + return mp; +} + + +void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){ + int i, j; + unsigned *inrow, *inrow2; + unsigned frac, fracstep; + unsigned p1[1024], p2[1024]; + byte *pix1, *pix2, *pix3, *pix4; + + fracstep = inwidth * 0x10000 / outwidth; + + frac = fracstep >> 2; + for ( i = 0 ; i < outwidth ; i++ ) + { + p1[i] = 4 * ( frac >> 16 ); + frac += fracstep; + } + frac = 3 * ( fracstep >> 2 ); + for ( i = 0 ; i < outwidth ; i++ ) + { + p2[i] = 4 * ( frac >> 16 ); + frac += fracstep; + } + + for ( i = 0 ; i < outheight ; i++, out += outwidth ) + { + inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight ); + inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight ); + frac = fracstep >> 1; + for ( j = 0 ; j < outwidth ; j++ ) + { + pix1 = (byte *)inrow + p1[j]; + pix2 = (byte *)inrow + p2[j]; + pix3 = (byte *)inrow2 + p1[j]; + pix4 = (byte *)inrow2 + p2[j]; + ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2; + ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2; + ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2; + ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2; + } + } +} + +void GL_MipMap( byte *out, byte *in, int width, int height ){ + int i, j; + + width <<= 3; + height <<= 1; + for ( i = 0 ; i < height ; i++, in += width ) + { + for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 ) + { + out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2; + out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2; + out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2; + out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2; + } + } +} + +miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){ + int scaled_width, scaled_height; + unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; + unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; + int miplevel; + miptex32_t *mp; + byte *pos; + int size; + paletteRGBA_t *test; + + for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 ) + ; + if ( 1 && scaled_width > width && 1 ) { + scaled_width >>= 1; + } + for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 ) + ; + if ( 1 && scaled_height > height && 1 ) { + scaled_height >>= 1; + } + + // don't ever bother with >256 textures + if ( scaled_width > MAX_IMAGE_SIZE ) { + scaled_width = MAX_IMAGE_SIZE; + } + if ( scaled_height > MAX_IMAGE_SIZE ) { + scaled_height = MAX_IMAGE_SIZE; + } + + if ( scaled_width < 1 ) { + scaled_width = 1; + } + if ( scaled_height < 1 ) { + scaled_height = 1; + } + + size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 ); + mp = (miptex32_t *)SafeMalloc( size, "CreateMip" ); + memset( mp,0,size ); + + mp->version = MIP32_VERSION; + + size = width * height; + test = (paletteRGBA_t *)data; + while ( size ) + { + if ( test->a != 255 ) { + mp->flags |= LittleLong( SURF_ALPHA_TEXTURE ); + break; + } + + size--; + test++; + } + + if ( scaled_width == width && scaled_height == height ) { + memcpy( scaled, data, width * height * 4 ); + } + else{ + GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height ); + } + + pos = (byte *)( mp + 1 ); + miplevel = 0; + + while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) ) + { + if ( scaled_width < 1 ) { + scaled_width = 1; + } + if ( scaled_height < 1 ) { + scaled_height = 1; + } + + if ( miplevel > 0 ) { + GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height ); + } + else + { + memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 ); + } + + mp->width[miplevel] = scaled_width; + mp->height[miplevel] = scaled_height; + mp->offsets[miplevel] = pos - ( (byte *)( mp ) ); + memcpy( pos, out, scaled_width * scaled_height * 4 ); + memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 ); + pos += scaled_width * scaled_height * 4; + + scaled_width >>= 1; + scaled_height >>= 1; + + miplevel++; + } + + *FinalSize = pos - ( (byte *)( mp ) ); + + return mp; +} + +/* + ============== + 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]; + + GetScriptToken( 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; + } + + GetScriptToken( false ); + xl = atoi( token ); + GetScriptToken( false ); + yl = atoi( token ); + GetScriptToken( false ); + w = atoi( token ); + GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Grab" ); + 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]; + + GetScriptToken( false ); + + sprintf( savename, "%s%s.lmp", gamedir, token ); + + if ( g_release ) { + sprintf( dest, "%s.lmp", token ); + ReleaseFile( dest ); + return; + } + + GetScriptToken( false ); + xl = atoi( token ); + GetScriptToken( false ); + yl = atoi( token ); + GetScriptToken( false ); + w = atoi( token ); + GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Raw" ); + 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 ( !ScriptTokenAvailable() ) { // just setting colormap_issued + return; + } + + GetScriptToken( 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 = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" ); + 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_altnamevalue, + pt_damagenamevalue, + pt_flagvalue, + pt_materialvalue, + pt_scale, + pt_mip, + pt_detail, + pt_gl, + pt_nomip, + pt_detailer, +} parmtype_t; + +typedef struct +{ + char *name; + int flags; + parmtype_t type; +} mipparm_t; + +mipparm_t mipparms[] = +{ + // utility content attributes + {"pushpull",CONTENTS_PUSHPULL, pt_contents}, + {"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 + + {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps + + // texture chaining + {"anim", 0, pt_animvalue}, // animname is the next animation + {"alt", 0, pt_altnamevalue}, // altname is the alternate texture + {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture + {"scale", 0, pt_scale}, // next two values are for scale + {"mip", 0, pt_mip}, + {"detail", 0, pt_detail}, + + {"GL_ZERO", GL_ZERO, pt_gl}, + {"GL_ONE", GL_ONE, pt_gl}, + {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl}, + {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl}, + {"GL_DST_COLOR", GL_DST_COLOR, pt_gl}, + {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl}, + {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl}, + {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl}, + {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl}, + {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl}, + {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl}, + + // 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 + {"alpha", SURF_ALPHA_TEXTURE, pt_flags}, + {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down... + {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished.... + + {"material", SURF_MATERIAL, pt_materialvalue}, + {"metal", SURF_TYPE_METAL, pt_flags}, + {"stone", SURF_TYPE_STONE, pt_flags}, + {"wood", SURF_TYPE_WOOD, pt_flags}, + + {"m_nomip", 0, pt_nomip}, + {"m_detail", 0, pt_detailer}, + + {NULL, 0, pt_contents} +}; + +/* + ============== + Cmd_Mip + + $mip filename x y width height + must be multiples of sixteen + SURF_WINDOW + ============== + */ + +void Cmd_Mip( void ){ + int xl,yl,xh,yh,w,h; + byte *dest, *source; + int flags, value, contents; + mipparm_t *mp; + char lumpname[128]; + char altname[128]; + char animname[128]; + char damagename[128]; + byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; + unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; + materialtype_t *mat; + char filename[1024]; + unsigned *destl, *sourcel; + int linedelta, x, y; + int size; + miptex_t *qtex; + miptex32_t *qtex32; + float scale_x, scale_y; + int mip_scale; + // detail texturing + char dt_name[128]; + 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; + + + 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 & 15 ) || ( h & 15 ) ) { + Error( "line %i: miptex sizes must be multiples of 16", scriptline ); + } + + flags = 0; + flags2 = 0; + contents = 0; + value = 0; + mip_scale = 0; + + altname[0] = animname[0] = damagename[0] = 0; + + scale_x = scale_y = 0.5; + + // detail texturing + dt_name[0] = 0; + dt_scale_x = dt_scale_y = 0.0; + dt_u = dt_v = 0.0; + dt_alpha = 0.0; + dt_src_blend_mode = dt_dst_blend_mode = 0; + + // get optional flags and values + while ( ScriptTokenAvailable() ) + { + GetScriptToken( false ); + + for ( mp = mipparms ; mp->name ; mp++ ) + { + if ( !strcmp( mp->name, token ) ) { + switch ( mp->type ) + { + case pt_animvalue: + GetScriptToken( false ); // specify the next animation frame + strcpy( animname, token ); + break; + case pt_altnamevalue: + GetScriptToken( false ); // specify the alternate texture + strcpy( altname, token ); + break; + case pt_damagenamevalue: + GetScriptToken( false ); // specify the damage texture + strcpy( damagename, token ); + break; + case pt_flags: + flags |= mp->flags; + break; + case pt_contents: + contents |= mp->flags; + break; + case pt_flagvalue: + flags |= mp->flags; + GetScriptToken( false ); // specify the light value + value = atoi( token ); + break; + case pt_materialvalue: + GetScriptToken( false ); + for ( mat = materialtypes ; mat->name ; mat++ ) + { + if ( !strcmp( mat->name, token ) ) { + // assumes SURF_MATERIAL is in top 8 bits + flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 ); + break; + } + } + break; + case pt_scale: + GetScriptToken( false ); // specify the x scale + scale_x = atof( token ); + GetScriptToken( false ); // specify the y scale + scale_y = atof( token ); + break; + + case pt_mip: + mip_scale = 1; + break; + + case pt_detailer: + flags2 |= MIP32_DETAILER_FLAG2; + break; + + case pt_nomip: + flags2 |= MIP32_NOMIP_FLAG2; + break; + + case pt_detail: + GetScriptToken( false ); + strcpy( dt_name, token ); + GetScriptToken( false ); + dt_scale_x = atof( token ); + GetScriptToken( false ); + dt_scale_y = atof( token ); + GetScriptToken( false ); + dt_u = atof( token ); + GetScriptToken( false ); + dt_v = atof( token ); + GetScriptToken( false ); + dt_alpha = atof( token ); + GetScriptToken( false ); + for ( mp = mipparms ; mp->name ; mp++ ) + { + if ( !strcmp( mp->name, token ) ) { + if ( mp->type == pt_gl ) { + dt_src_blend_mode = mp->flags; + break; + } + } + } + if ( !mp->name ) { + Error( "line %i: invalid gl blend mode %s", scriptline, token ); + } + GetScriptToken( false ); + for ( mp = mipparms ; mp->name ; mp++ ) + { + if ( !strcmp( mp->name, token ) ) { + if ( mp->type == pt_gl ) { + dt_dst_blend_mode = mp->flags; + break; + } + } + } + if ( !mp->name ) { + Error( "line %i: invalid gl blend mode %s", scriptline, token ); + } + break; + } + break; + } + } + if ( !mp->name ) { + Error( "line %i: unknown parm %s", scriptline, token ); + } + } + + if ( g_release ) { + return; // textures are only released by $maps + + } + xh = xl + w; + yh = yl + h; + if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) { + Error( "line %i image %s: image is too big!", scriptline, lumpname ); + } + + if ( TrueColorImage ) { + if ( xl >= longimagewidth || xh > longimagewidth || + yl >= longimageheight || yh > longimageheight ) { + Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, 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, true ); + + qtex32->flags |= LittleLong( flags ); + qtex32->flags2 |= LittleLong( flags2 ); + qtex32->contents = LittleLong( contents ); + qtex32->value = LittleLong( value ); + qtex32->scale_x = scale_x; + qtex32->scale_y = scale_y; + qtex32->mip_scale = mip_scale; + sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname ); + if ( animname[0] ) { + sprintf( qtex32->animname, "%s/%s", mip_prefix, animname ); + } + if ( altname[0] ) { + sprintf( qtex32->altname, "%s/%s", mip_prefix, altname ); + } + if ( damagename[0] ) { + sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename ); + } + if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) { + sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name ); + qtex32->dt_scale_x = dt_scale_x; + qtex32->dt_scale_y = dt_scale_y; + qtex32->dt_u = dt_u; + qtex32->dt_v = dt_v; + qtex32->dt_alpha = dt_alpha; + qtex32->dt_src_blend_mode = dt_src_blend_mode; + qtex32->dt_dst_blend_mode = dt_dst_blend_mode; + } + + // + // write it out + // + sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname ); + if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) { + printf( "writing %s with ALPHA\n", filename ); + } + else{ + printf( "writing %s\n", filename ); + } + SaveFile( filename, (byte *)qtex32, size ); + + free( qtex32 ); + } + else + { + 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, true ); + + 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 ); + } + + // + // write it out + // + sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname ); + printf( "writing %s\n", filename ); + SaveFile( filename, (byte *)qtex, size ); + + 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]; + + GetScriptToken( false ); + strcpy( mip_prefix, token ); + // create the directory if needed + sprintf( filename, "%stextures", g_outputDir ); + Q_mkdir( filename ); + sprintf( filename, "%stextures/%s", g_outputDir, 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; + + GetScriptToken( 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 ); + } + } +} diff --git a/tools/heretic2/h2data/jointed.c b/tools/heretic2/h2data/jointed.c new file mode 100644 index 00000000..de8b802a --- /dev/null +++ b/tools/heretic2/h2data/jointed.c @@ -0,0 +1,548 @@ +/* + Copyright (C) 1999-2007 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 +#include +#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 ); + } +} diff --git a/tools/heretic2/h2data/jointed.h b/tools/heretic2/h2data/jointed.h new file mode 100644 index 00000000..264d3175 --- /dev/null +++ b/tools/heretic2/h2data/jointed.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 1999-2007 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 diff --git a/tools/heretic2/h2data/joints.h b/tools/heretic2/h2data/joints.h new file mode 100644 index 00000000..f8e64bf5 --- /dev/null +++ b/tools/heretic2/h2data/joints.h @@ -0,0 +1,146 @@ +/* + Copyright (C) 1999-2007 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 + +#include "globaldefs.h" + +#ifdef _HERETIC2_ +#include "angles.h" +#endif + +//typedef float vec3_t[3]; +//typedef unsigned char byte; + +#if !GDEF_OS_WINDOWS +#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 diff --git a/tools/heretic2/h2data/models.c b/tools/heretic2/h2data/models.c new file mode 100644 index 00000000..244f24ac --- /dev/null +++ b/tools/heretic2/h2data/models.c @@ -0,0 +1,2041 @@ +/* + Copyright (C) 1999-2007 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 +#include "jointed.h" +#include "fmodel.h" + +//================================================================= + +typedef struct +{ + int numnormals; + vec3_t normalsum; +} vertexnormals_t; + +typedef struct +{ + vec3_t v; + int lightnormalindex; +} trivert_t; + +typedef struct +{ + vec3_t mins, maxs; + char name[16]; + trivert_t v[MAX_VERTS]; + QDataJoint_t joints[NUM_CLUSTERS]; // ,this +} frame_t; + +// ,and all of this should get out of here, need to use new stuff in fmodels instead + +typedef struct IntListNode_s +{ + int data; + struct IntListNode_s *next; +} IntListNode_t; // gaak + +typedef struct +{ + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this +} PartialAliasFrame_t; + +int jointed; +int clustered; + +int *clusters[NUM_CLUSTERS]; +IntListNode_t *vertLists[NUM_CLUSTERS]; +int num_verts[NUM_CLUSTERS + 1]; +int new_num_verts[NUM_CLUSTERS + 1]; + +// end that + +//================================================================ + +frame_t g_frames[MAX_FRAMES]; +//frame_t *g_frames; + +static dmdl_t model; + + +float scale_up; // set by $scale +vec3_t adjust; // set by $origin +int g_fixedwidth, g_fixedheight; // set by $skinsize + + +// +// base frame info +// +dstvert_t base_st[MAX_VERTS]; +dtriangle_t triangles[MAX_TRIANGLES]; + +static int triangle_st[MAX_TRIANGLES][3][2]; + +// the command list holds counts, s/t values, and xyz indexes +// that are valid for every frame +int commands[16384]; +int numcommands; +int numglverts; +int used[MAX_TRIANGLES]; + +char g_skins[MAX_MD2SKINS][64]; + +char cdarchive[1024]; +char cdpartial[1024]; +char cddir[1024]; + +char modelname[64]; // empty unless $modelname issued (players) + +extern char *g_outputDir; + +#define NUMVERTEXNORMALS 162 + +float avertexnormals[NUMVERTEXNORMALS][3] = +{ + #include "anorms.h" +}; + +unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768]; + +FILE *headerouthandle = NULL; + +//============================================================== + +/* + =============== + ClearModel + =============== + */ +static void ClearModel( void ){ + memset( &model, 0, sizeof( model ) ); + + modelname[0] = 0; + jointed = NOT_JOINTED; + clustered = 0; + scale_up = 1.0; + VectorCopy( vec3_origin, adjust ); + g_fixedwidth = g_fixedheight = 0; + g_skipmodel = false; +} + + +void H_printf( char *fmt, ... ){ + va_list argptr; + char name[1024]; + + if ( !headerouthandle ) { + sprintf( name, "%s/tris.h", cddir ); + headerouthandle = SafeOpenWrite( name ); + fprintf( headerouthandle, "// %s\n\n", cddir ); + fprintf( headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n" ); + } + + va_start( argptr, fmt ); + vfprintf( headerouthandle, fmt, argptr ); + va_end( argptr ); +} + +#if 1 +/* + ============ + WriteModelFile + ============ + */ +void WriteCommonModelFile( FILE *modelouthandle, PartialAliasFrame_t *outFrames ){ + int i; + dmdl_t modeltemp; + int j, k; + frame_t *in; + daliasframe_t *out; + byte buffer[MAX_VERTS * 4 + 128]; + float v; + int c_on, c_off; + + model.version = ALIAS_VERSION; + model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz]; + model.num_glcmds = numcommands; + model.ofs_skins = sizeof( dmdl_t ); + model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; + model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t ); + model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t ); + model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize; + model.ofs_end = model.ofs_glcmds + model.num_glcmds * sizeof( int ); + // + // write out the model header + // + for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ ) + ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] ); + + SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) ); + + // + // write out the skin names + // + SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME ); + + // + // write out the texture coordinates + // + c_on = c_off = 0; + for ( i = 0 ; i < model.num_st ; i++ ) + { + base_st[i].s = LittleShort( base_st[i].s ); + base_st[i].t = LittleShort( base_st[i].t ); + } + + SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) ); + + // + // write out the triangles + // + for ( i = 0 ; i < model.num_tris ; i++ ) + { + int j; + dtriangle_t tri; + + for ( j = 0 ; j < 3 ; j++ ) + { + tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); + tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); + } + + SafeWrite( modelouthandle, &tri, sizeof( tri ) ); + } + + // + // write out the frames + // + for ( i = 0 ; i < model.num_frames ; i++ ) + { + in = &g_frames[i]; + out = (daliasframe_t *)buffer; + + strcpy( out->name, in->name ); + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; + out->translate[j] = in->mins[j]; + + if ( outFrames ) { + outFrames[i].scale[j] = out->scale[j]; + outFrames[i].translate[j] = out->translate[j]; + } + } + + for ( j = 0 ; j < model.num_xyz ; j++ ) + { + // all of these are byte values, so no need to deal with endianness + out->verts[j].lightnormalindex = in->v[j].lightnormalindex; + + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + if ( v < 0 ) { + v = 0; + } + out->verts[j].v[k] = v; + } + } + + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = LittleFloat( out->scale[j] ); + out->translate[j] = LittleFloat( out->translate[j] ); + } + + SafeWrite( modelouthandle, out, model.framesize ); + } + + // + // write out glcmds + // + SafeWrite( modelouthandle, commands, numcommands * 4 ); +} + +/* + ============ + WriteModelFile + ============ + */ +void WriteModelFile( FILE *modelouthandle ){ + model.ident = IDALIASHEADER; + + WriteCommonModelFile( modelouthandle, NULL ); +} + +/* + ============ + WriteJointedModelFile + ============ + */ +void WriteJointedModelFile( FILE *modelouthandle ){ + int i; + int j, k; + frame_t *in; + float v; + IntListNode_t *current, *toFree; + PartialAliasFrame_t outFrames[MAX_FRAMES]; + + model.ident = IDJOINTEDALIASHEADER; + + WriteCommonModelFile( modelouthandle, outFrames ); + + // Skeletal Type + SafeWrite( modelouthandle, &jointed, sizeof( int ) ); + + // number of joints + SafeWrite( modelouthandle, &numJointsForSkeleton[jointed], sizeof( int ) ); + + // number of verts in each cluster + SafeWrite( modelouthandle, &new_num_verts[1], sizeof( int ) * numJointsForSkeleton[jointed] ); + + // cluster verts + for ( i = 0; i < new_num_verts[0]; ++i ) + { + current = vertLists[i]; + while ( current ) + { + SafeWrite( modelouthandle, ¤t->data, sizeof( int ) ); + toFree = current; + current = current->next; + free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base + } + } + + for ( i = 0 ; i < model.num_frames ; i++ ) + { + in = &g_frames[i]; + + for ( j = 0 ; j < new_num_verts[0]; ++j ) + { + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + + if ( v < 0 ) { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite( modelouthandle, &v, sizeof( float ) ); + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + + if ( v < 0 ) { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite( modelouthandle, &v, sizeof( float ) ); + } + + for ( k = 0 ; k < 3 ; k++ ) + { + v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + + if ( v < 0 ) { + v = 0; + } + + // write out origin as a float (there's only a few per model, so it's not really + // a size issue) + SafeWrite( modelouthandle, &v, sizeof( float ) ); + } + } + } +} +#else +/* + ============ + WriteModelFile + ============ + */ +static void WriteModelFile( FILE *modelouthandle ){ + int i; + dmdl_t modeltemp; + int j, k; + frame_t *in; + daliasframe_t *out; + byte buffer[MAX_VERTS * 4 + 128]; + float v; + int c_on, c_off; + + model.ident = IDALIASHEADER; + model.version = ALIAS_VERSION; + model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz]; + model.num_glcmds = numcommands; + model.ofs_skins = sizeof( dmdl_t ); + model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; + model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t ); + model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t ); + model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize; + model.ofs_end = model.ofs_glcmds + model.num_glcmds * 4; + + // + // write out the model header + // + for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ ) + ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] ); + + SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) ); + + // + // write out the skin names + // + SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME ); + + // + // write out the texture coordinates + // + c_on = c_off = 0; + for ( i = 0 ; i < model.num_st ; i++ ) + { + base_st[i].s = LittleShort( base_st[i].s ); + base_st[i].t = LittleShort( base_st[i].t ); + } + + SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) ); + + // + // write out the triangles + // + for ( i = 0 ; i < model.num_tris ; i++ ) + { + int j; + dtriangle_t tri; + + for ( j = 0 ; j < 3 ; j++ ) + { + tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); + tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); + } + + SafeWrite( modelouthandle, &tri, sizeof( tri ) ); + } + + // + // write out the frames + // + for ( i = 0 ; i < model.num_frames ; i++ ) + { + in = &g_frames[i]; + out = (daliasframe_t *)buffer; + + strcpy( out->name, in->name ); + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; + out->translate[j] = in->mins[j]; + } + + for ( j = 0 ; j < model.num_xyz ; j++ ) + { + // all of these are byte values, so no need to deal with endianness + out->verts[j].lightnormalindex = in->v[j].lightnormalindex; + + for ( k = 0 ; k < 3 ; k++ ) + { + // scale to byte values & min/max check + v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if ( v > 255.0 ) { + v = 255.0; + } + if ( v < 0 ) { + v = 0; + } + out->verts[j].v[k] = v; + } + } + + for ( j = 0 ; j < 3 ; j++ ) + { + out->scale[j] = LittleFloat( out->scale[j] ); + out->translate[j] = LittleFloat( out->translate[j] ); + } + + SafeWrite( modelouthandle, out, model.framesize ); + } + + // + // write out glcmds + // + SafeWrite( modelouthandle, commands, numcommands * 4 ); +} +#endif + +/* + =============== + FinishModel + =============== + */ +void FinishModel( void ){ + FILE *modelouthandle; + int i; + char name[1024]; + + if ( !model.num_frames ) { + return; + } + +// +// copy to release directory tree if doing a release build +// + if ( g_release ) { + if ( modelname[0] ) { + sprintf( name, "%s", modelname ); + } + else{ + sprintf( name, "%s/tris.md2", cdpartial ); + } + ReleaseFile( name ); + + for ( i = 0 ; i < model.num_skins ; i++ ) + { + ReleaseFile( g_skins[i] ); + } + model.num_frames = 0; + return; + } + +// +// write the model output file +// + if ( modelname[0] ) { + sprintf( name, "%s%s", g_outputDir, modelname ); + } + else{ + sprintf( name, "%s/tris.md2", g_outputDir ); + } + printf( "saving to %s\n", name ); + CreatePath( name ); + modelouthandle = SafeOpenWrite( name ); + +#if 1 + if ( jointed != NOT_JOINTED ) { + WriteJointedModelFile( modelouthandle ); + } + else +#endif + WriteModelFile( modelouthandle ); + + printf( "%3dx%3d skin\n", model.skinwidth, model.skinheight ); + printf( "First frame boundaries:\n" ); + printf( " minimum x: %3f\n", g_frames[0].mins[0] ); + printf( " maximum x: %3f\n", g_frames[0].maxs[0] ); + printf( " minimum y: %3f\n", g_frames[0].mins[1] ); + printf( " maximum y: %3f\n", g_frames[0].maxs[1] ); + printf( " minimum z: %3f\n", g_frames[0].mins[2] ); + printf( " maximum z: %3f\n", g_frames[0].maxs[2] ); + printf( "%4d vertices\n", model.num_xyz ); + printf( "%4d triangles\n", model.num_tris ); + printf( "%4d frame\n", model.num_frames ); + printf( "%4d glverts\n", numglverts ); + printf( "%4d glcmd\n", model.num_glcmds ); + printf( "%4d skins\n", model.num_skins ); + printf( "file size: %d\n", (int)ftell( modelouthandle ) ); + printf( "---------------------\n" ); + + fclose( modelouthandle ); + + // finish writing header file + H_printf( "\n" ); + + // scale_up is usefull to allow step distances to be adjusted + H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up ); + + fclose( headerouthandle ); + headerouthandle = NULL; +} + + +/* + ================================================================= + + ALIAS MODEL DISPLAY LIST GENERATION + + ================================================================= + */ + +int strip_xyz[128]; +int strip_st[128]; +int strip_tris[128]; +int stripcount; + +/* + ================ + StripLength + ================ + */ +static int StripLength( int starttri, int startv ){ + int m1, m2; + int st1, st2; + int j; + dtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + strip_xyz[0] = last->index_xyz[( startv ) % 3]; + strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; + strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; + strip_st[0] = last->index_st[( startv ) % 3]; + strip_st[1] = last->index_st[( startv + 1 ) % 3]; + strip_st[2] = last->index_st[( startv + 2 ) % 3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[( startv + 2 ) % 3]; + st1 = last->index_st[( startv + 2 ) % 3]; + m2 = last->index_xyz[( startv + 1 ) % 3]; + st2 = last->index_st[( startv + 1 ) % 3]; + + // look for a matching triangle +nexttri: + for ( j = starttri + 1, check = &triangles[starttri + 1] + ; j < model.num_tris ; j++, check++ ) + { + for ( k = 0 ; k < 3 ; k++ ) + { + if ( check->index_xyz[k] != m1 ) { + continue; + } + if ( check->index_st[k] != st1 ) { + continue; + } + if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { + continue; + } + if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { + continue; + } + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if ( used[j] ) { + goto done; + } + + // the new edge + if ( stripcount & 1 ) { + m2 = check->index_xyz[ ( k + 2 ) % 3 ]; + st2 = check->index_st[ ( k + 2 ) % 3 ]; + } + else + { + m1 = check->index_xyz[ ( k + 2 ) % 3 ]; + st1 = check->index_st[ ( k + 2 ) % 3 ]; + } + + strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ]; + strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ]; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for ( j = starttri + 1 ; j < model.num_tris ; j++ ) + if ( used[j] == 2 ) { + used[j] = 0; + } + + return stripcount; +} + + +/* + =========== + FanLength + =========== + */ +static int FanLength( int starttri, int startv ){ + int m1, m2; + int st1, st2; + int j; + dtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + strip_xyz[0] = last->index_xyz[( startv ) % 3]; + strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; + strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; + strip_st[0] = last->index_st[( startv ) % 3]; + strip_st[1] = last->index_st[( startv + 1 ) % 3]; + strip_st[2] = last->index_st[( startv + 2 ) % 3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[( startv + 0 ) % 3]; + st1 = last->index_st[( startv + 0 ) % 3]; + m2 = last->index_xyz[( startv + 2 ) % 3]; + st2 = last->index_st[( startv + 2 ) % 3]; + + + // look for a matching triangle +nexttri: + for ( j = starttri + 1, check = &triangles[starttri + 1] + ; j < model.num_tris ; j++, check++ ) + { + for ( k = 0 ; k < 3 ; k++ ) + { + if ( check->index_xyz[k] != m1 ) { + continue; + } + if ( check->index_st[k] != st1 ) { + continue; + } + if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { + continue; + } + if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { + continue; + } + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if ( used[j] ) { + goto done; + } + + // the new edge + m2 = check->index_xyz[ ( k + 2 ) % 3 ]; + st2 = check->index_st[ ( k + 2 ) % 3 ]; + + strip_xyz[stripcount + 2] = m2; + strip_st[stripcount + 2] = st2; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for ( j = starttri + 1 ; j < model.num_tris ; j++ ) + if ( used[j] == 2 ) { + used[j] = 0; + } + + return stripcount; +} + + + +/* + ================ + BuildGlCmds + + Generate a list of trifans or strips + for the model, which holds for all frames + ================ + */ +static void BuildGlCmds( void ){ + int i, j, k; + int startv; + float s, t; + int len, bestlen, besttype; + int best_xyz[1024]; + int best_st[1024]; + int best_tris[1024]; + int type; + + // + // build tristrips + // + numcommands = 0; + numglverts = 0; + memset( used, 0, sizeof( used ) ); + for ( i = 0 ; i < model.num_tris ; i++ ) + { + // pick an unused triangle and start the trifan + if ( used[i] ) { + continue; + } + + bestlen = 0; + for ( type = 0 ; type < 2 ; type++ ) +// type = 1; + { + for ( startv = 0 ; startv < 3 ; startv++ ) + { + if ( type == 1 ) { + len = StripLength( i, startv ); + } + else{ + len = FanLength( i, startv ); + } + if ( len > bestlen ) { + besttype = type; + bestlen = len; + for ( j = 0 ; j < bestlen + 2 ; j++ ) + { + best_st[j] = strip_st[j]; + best_xyz[j] = strip_xyz[j]; + } + for ( j = 0 ; j < bestlen ; j++ ) + best_tris[j] = strip_tris[j]; + } + } + } + + // mark the tris on the best strip/fan as used + for ( j = 0 ; j < bestlen ; j++ ) + used[best_tris[j]] = 1; + + if ( besttype == 1 ) { + commands[numcommands++] = ( bestlen + 2 ); + } + else{ + commands[numcommands++] = -( bestlen + 2 ); + } + + numglverts += bestlen + 2; + + for ( j = 0 ; j < bestlen + 2 ; j++ ) + { + // emit a vertex into the reorder buffer + k = best_st[j]; + + // emit s/t coords into the commands stream + s = base_st[k].s; + t = base_st[k].t; + + s = ( s + 0.5 ) / model.skinwidth; + t = ( t + 0.5 ) / model.skinheight; + + *(float *)&commands[numcommands++] = s; + *(float *)&commands[numcommands++] = t; + *(int *)&commands[numcommands++] = best_xyz[j]; + } + } + + commands[numcommands++] = 0; // end of list marker +} + + +/* + =============================================================== + + BASE FRAME SETUP + + =============================================================== + */ + +/* + ============ + BuildST + + Builds the triangle_st array for the base frame and + model.skinwidth / model.skinheight + + FIXME: allow this to be loaded from a file for + arbitrary mappings + ============ + */ +#if 0 +static void OldBuildST( triangle_t *ptri, int numtri ){ + int i, j; + int width, height, iwidth, iheight, swidth; + float basex, basey; + float s_scale, t_scale; + float scale; + vec3_t mins, maxs; + float *pbasevert; + vec3_t vtemp1, vtemp2, normal; + + // + // find bounds of all the verts on the base frame + // + ClearBounds( mins, maxs ); + + for ( i = 0 ; i < numtri ; i++ ) + for ( j = 0 ; j < 3 ; j++ ) + AddPointToBounds( ptri[i].verts[j], mins, maxs ); + + for ( i = 0 ; i < 3 ; i++ ) + { + mins[i] = floor( mins[i] ); + maxs[i] = ceil( maxs[i] ); + } + + width = maxs[0] - mins[0]; + height = maxs[2] - mins[2]; + + if ( !g_fixedwidth ) { // old style + scale = 8; + if ( width * scale >= 150 ) { + scale = 150.0 / width; + } + if ( height * scale >= 190 ) { + scale = 190.0 / height; + } + + s_scale = t_scale = scale; + + iwidth = ceil( width * s_scale ); + iheight = ceil( height * t_scale ); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)( iwidth - 4 ) / width; + t_scale = (float)( iheight - 4 ) / height; + } + +// +// determine which side of each triangle to map the texture to +// + for ( i = 0 ; i < numtri ; i++ ) + { + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + if ( normal[1] > 0 ) { + basex = iwidth + 2; + } + else + { + basex = 2; + } + basey = 2; + + for ( j = 0 ; j < 3 ; j++ ) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); + triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); + } + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + swidth = iwidth * 2; + model.skinwidth = ( swidth + 3 ) & ~3; + model.skinheight = iheight; +} +#endif + +//========================================================================== +// +// DrawScreen +// +//========================================================================== + +void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ){ + int i; + byte *scrpos; + char buffer[256]; + + // Divider + scrpos = &pic[( INFO_Y - 2 ) * SKINPAGE_WIDTH]; + for ( i = 0; i < SKINPAGE_WIDTH; i++ ) + { + *scrpos++ = 255; + } + + sprintf( buffer, "GENSKIN: " ); + DrawTextChar( 16, INFO_Y, buffer ); + + sprintf( buffer, "( %03d * %03d ) SCALE %f %f, SKINWIDTH %d," + " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth * 2, (int)iheight ); + DrawTextChar( 80, INFO_Y, buffer ); +} + +/* + ============ + BuildST + + Builds the triangle_st array for the base frame and + model.skinwidth / model.skinheight + + FIXME: allow this to be loaded from a file for + arbitrary mappings + ============ + */ +void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ + int i, j; + int width, height, iwidth, iheight, swidth; + float basex, basey; + float scale; + vec3_t mins, maxs; + float *pbasevert; + vec3_t vtemp1, vtemp2, normal; + float s_scale, t_scale; + float scWidth; + float scHeight; + + // + // find bounds of all the verts on the base frame + // + ClearBounds( mins, maxs ); + + for ( i = 0 ; i < numtri ; i++ ) + for ( j = 0 ; j < 3 ; j++ ) + AddPointToBounds( ptri[i].verts[j], mins, maxs ); + + for ( i = 0 ; i < 3 ; i++ ) + { + mins[i] = floor( mins[i] ); + maxs[i] = ceil( maxs[i] ); + } + + width = maxs[0] - mins[0]; + height = maxs[2] - mins[2]; + + + scWidth = ( ScaleWidth / 2 ) * SCALE_ADJUST_FACTOR; + scHeight = ScaleHeight * SCALE_ADJUST_FACTOR; + + scale = scWidth / width; + + if ( height * scale >= scHeight ) { + scale = scHeight / height; + } + + iwidth = ceil( width * scale ) + 4; + iheight = ceil( height * scale ) + 4; + + s_scale = (float)( iwidth - 4 ) / width; + t_scale = (float)( iheight - 4 ) / height; + t_scale = s_scale; + + if ( DrawSkin ) { + DrawScreen( s_scale, t_scale, iwidth, iheight ); + } + + +/* if (!g_fixedwidth) + { // old style + scale = 8; + if (width*scale >= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + + s_scale = t_scale = scale; + + iwidth = ceil(width*s_scale); + iheight = ceil(height*t_scale); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + }*/ + +// +// determine which side of each triangle to map the texture to +// + for ( i = 0 ; i < numtri ; i++ ) + { + if ( ptri[i].HasUV ) { + for ( j = 0 ; j < 3 ; j++ ) + { + triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * iwidth ); + triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * iheight ); + } + } + else + { + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + if ( normal[1] > 0 ) { + basex = iwidth + 2; + } + else + { + basex = 2; + } + basey = 2; + + for ( j = 0 ; j < 3 ; j++ ) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); + triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); + } + } + + DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], + triangle_st[i][1][0], triangle_st[i][1][1] ); + DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], + triangle_st[i][2][0], triangle_st[i][2][1] ); + DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], + triangle_st[i][0][0], triangle_st[i][0][1] ); + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + + swidth = iwidth * 2; + model.skinwidth = ( swidth + 3 ) & ~3; + model.skinheight = iheight; +} + + +static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters, + IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){ + int i, j; + IntListNode_t *next; + + for ( j = 0; j < num_verts[0]; ++j ) + { + for ( i = 0; i < num_verts[j + 1]; ++i ) + { + if ( clusters[j][i] == oldindex ) { + ++new_num_verts[j + 1]; + + next = vertLists[j]; + + vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" ); + // Currently freed in WriteJointedModelFile only + + vertLists[j]->data = newIndex; + vertLists[j]->next = next; + } + } + } +} + +/* + ================= + Cmd_Base + ================= + */ +void Cmd_Base( void ){ + vec3_t base_xyz[MAX_VERTS]; + triangle_t *ptri; + int i, j, k; +#if 1 +#else + int time1; +#endif + char file1[1024]; + char file2[1024]; + + GetScriptToken( false ); + + if ( g_skipmodel || g_release || g_archive ) { + return; + } + + printf( "---------------------\n" ); +#if 1 + sprintf( file1, "%s/%s", cdpartial, token ); + printf( "%s ", file1 ); + + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s", cddir, token ); +#else + sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext ); + printf( "%s\n", file1 ); + + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s.%s", cddir, token, trifileext ); + + time1 = FileTime( file1 ); + if ( time1 == -1 ) { + Error( "%s doesn't exist", file1 ); + } +#endif +// +// load the base triangles +// + if ( do3ds ) { + Load3DSTriangleList( file1, &ptri, &model.num_tris, NULL, NULL ); + } + else{ + LoadTriangleList( file1, &ptri, &model.num_tris, NULL, NULL ); + } + + + GetScriptToken( false ); + sprintf( file2, "%s/%s.pcx", cddir, token ); +// sprintf (trans_file, "%s/!%s_a.pcx", cddir, token); + + printf( "skin: %s\n", file2 ); + Load256Image( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight ); + + if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) { + if ( g_allow_newskin ) { + ScaleWidth = BaseWidth; + ScaleHeight = BaseHeight; + } + else + { + Error( "Invalid skin page size: (%d,%d) should be (%d,%d)", + BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT ); + } + } + else + { + ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X, + ENCODED_WIDTH_Y ); + ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X, + ENCODED_HEIGHT_Y ); + } + +// +// get the ST values +// + BuildST( ptri, model.num_tris,false ); + +// +// run through all the base triangles, storing each unique vertex in the +// base vertex list and setting the indirect triangles to point to the base +// vertices +// + for ( i = 0 ; i < model.num_tris ; i++ ) + { + for ( j = 0 ; j < 3 ; j++ ) + { + // get the xyz index + for ( k = 0 ; k < model.num_xyz ; k++ ) + if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) { + break; + } // this vertex is already in the base vertex list + + if ( k == model.num_xyz ) { // new index + VectorCopy( ptri[i].verts[j], base_xyz[model.num_xyz] ); + + if ( clustered ) { + ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts ); + } + + model.num_xyz++; + } + + triangles[i].index_xyz[j] = k; + + // get the st index + for ( k = 0 ; k < model.num_st ; k++ ) + if ( triangle_st[i][j][0] == base_st[k].s + && triangle_st[i][j][1] == base_st[k].t ) { + break; + } // this vertex is already in the base vertex list + + if ( k == model.num_st ) { // new index + base_st[model.num_st].s = triangle_st[i][j][0]; + base_st[model.num_st].t = triangle_st[i][j][1]; + model.num_st++; + } + + triangles[i].index_st[j] = k; + } + } + + // build triangle strips / fans + BuildGlCmds(); +} + +//=============================================================== + +char *FindFrameFile( char *frame ){ + int time1; + char file1[1024]; + static char retname[1024]; + char base[32]; + char suffix[32]; + char *s; + + if ( strstr( frame, "." ) ) { + return frame; // allready in dot format + + } + // split 'run1' into 'run' and '1' + s = frame + strlen( frame ) - 1; + + while ( s != frame && *s >= '0' && *s <= '9' ) + s--; + + strcpy( suffix, s + 1 ); + strcpy( base, frame ); + base[s - frame + 1] = 0; + + sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "hrc" ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s%s.%s", base, suffix, "hrc" ); + return retname; + } + + sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "asc" ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s%s.%s", base, suffix, "asc" ); + return retname; + } + + sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "tri" ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s%s.%s", base, suffix, "tri" ); + return retname; + } + + sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "3ds" ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s%s.%s", base, suffix, "3ds" ); + return retname; + } + + sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "htr" ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s%s.%s", base, suffix, "htr" ); + return retname; + } + + // check for 'run.1' + sprintf( file1, "%s/%s.%s",cddir, base, suffix ); + time1 = FileTime( file1 ); + if ( time1 != -1 ) { + sprintf( retname, "%s.%s", base, suffix ); + return retname; + } + + Error( "frame %s could not be found",frame ); + return NULL; +} + +/* + =============== + GrabFrame + =============== + */ +static void GrabFrame( char *frame ){ + triangle_t *ptri; + int i, j; + trivert_t *ptrivert; + int num_tris; + char file1[1024]; + frame_t *fr; + vertexnormals_t vnorms[MAX_VERTS]; + int index_xyz; + char *framefile; + + // the frame 'run1' will be looked for as either + // run.1 or run1.tri, so the new alias sequence save + // feature an be used + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "grabbing %s ", file1 ); + + if ( model.num_frames >= MAX_FRAMES ) { + Error( "model.num_frames >= MAX_FRAMES" ); + } + fr = &g_frames[model.num_frames]; + model.num_frames++; + + strcpy( fr->name, frame ); + +// +// load the frame +// + if ( do3ds ) { + Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL ); + } + else{ + LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL ); + } + + if ( num_tris != model.num_tris ) { + Error( "%s: number of triangles doesn't match base frame\n", file1 ); + } + +// +// allocate storage for the frame's vertices +// + ptrivert = fr->v; + + for ( i = 0 ; i < model.num_xyz ; i++ ) + { + vnorms[i].numnormals = 0; + VectorClear( vnorms[i].normalsum ); + } + ClearBounds( fr->mins, fr->maxs ); + +// +// store the frame's vertices in the same order as the base. This assumes the +// triangles and vertices in this frame are in exactly the same order as in the +// base +// + for ( i = 0 ; i < num_tris ; i++ ) + { + vec3_t vtemp1, vtemp2, normal; + float ftemp; + + VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); + VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); + CrossProduct( vtemp1, vtemp2, normal ); + + VectorNormalize( normal, normal ); + + // rotate the normal so the model faces down the positive x axis + ftemp = normal[0]; + normal[0] = -normal[1]; + normal[1] = ftemp; + + for ( j = 0 ; j < 3 ; j++ ) + { + index_xyz = triangles[i].index_xyz[j]; + + // rotate the vertices so the model faces down the positive x axis + // also adjust the vertices to the desired origin + ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) + + adjust[0]; + ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) + + adjust[1]; + ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) + + adjust[2]; + + AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs ); + + VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum ); + vnorms[index_xyz].numnormals++; + } + } + +// +// calculate the vertex normals, match them to the template list, and store the +// index of the best match +// + for ( i = 0 ; i < model.num_xyz ; i++ ) + { + int j; + vec3_t v; + float maxdot; + int maxdotindex; + int c; + + c = vnorms[i].numnormals; + if ( !c ) { + Error( "Vertex with no triangles attached" ); + } + + VectorScale( vnorms[i].normalsum, 1.0 / c, v ); + VectorNormalize( v, v ); + + maxdot = -999999.0; + maxdotindex = -1; + + for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ ) + { + float dot; + + dot = DotProduct( v, avertexnormals[j] ); + if ( dot > maxdot ) { + maxdot = dot; + maxdotindex = j; + } + } + + ptrivert[i].lightnormalindex = maxdotindex; + } + + free( ptri ); +} + +/* + =============== + GrabJointedFrame + =============== + */ +void GrabJointedFrame( char *frame ){ + char file1[1024]; + char *framefile; + frame_t *fr; + + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "grabbing %s\n", file1 ); + + fr = &g_frames[model.num_frames - 1]; // last frame read in + + LoadJointList( file1, fr->joints, jointed ); +} + +/* + =============== + GrabGlobals + =============== + */ +void GrabGlobals( char *frame ){ + char file1[1024]; + char *framefile; + frame_t *fr; + + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "grabbing %s\n", file1 ); + + fr = &g_frames[model.num_frames - 1]; // last frame read in + + LoadGlobals( file1 ); +} + +/* + =============== + Cmd_Frame + =============== + */ +void Cmd_Frame( void ){ + while ( ScriptTokenAvailable() ) + { + GetScriptToken( false ); + if ( g_skipmodel ) { + continue; + } + if ( g_release || g_archive ) { + model.num_frames = 1; // don't skip the writeout + continue; + } + + H_printf( "#define FRAME_%-16s\t%i\n", token, model.num_frames ); + + GrabFrame( token ); + } +} + +/* + =============== + Cmd_Skin + + Skins aren't actually stored in the file, only a reference + is saved out to the header file. + =============== + */ +void Cmd_Skin( void ){ + byte *palette; + byte *pixels; + int width, height; + byte *cropped; + int y; + char name[1024], savename[1024]; + + GetScriptToken( false ); + + if ( model.num_skins == MAX_MD2SKINS ) { + Error( "model.num_skins == MAX_MD2SKINS" ); + } + + if ( g_skipmodel ) { + return; + } + +#if 1 + sprintf( name, "%s/%s.pcx", cddir, token ); + sprintf( savename, "%s/!%s.pcx", g_outputDir, token ); + sprintf( g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token ); +#else + sprintf( name, "%s/%s.lbm", cdarchive, token ); + strcpy( name, ExpandPathAndArchive( name ) ); +// sprintf (name, "%s/%s.lbm", cddir, token); + + if ( ScriptTokenAvailable() ) { + GetScriptToken( false ); + sprintf( g_skins[model.num_skins], "%s.pcx", token ); + sprintf( savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins] ); + } + else + { + sprintf( savename, "%s/%s.pcx", g_outputDir, token ); + sprintf( g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token ); + } +#endif + + model.num_skins++; + + if ( g_skipmodel || g_release || g_archive ) { + return; + } + + // load the image + printf( "loading %s\n", name ); + Load256Image( name, &pixels, &palette, &width, &height ); +// RemapZero (pixels, palette, width, height); + + // crop it to the proper size + cropped = (byte *) SafeMalloc( model.skinwidth * model.skinheight, "Cmd_Skin" ); + for ( y = 0 ; y < model.skinheight ; y++ ) + { + memcpy( cropped + y * model.skinwidth, + pixels + y * width, model.skinwidth ); + } + + // save off the new image + printf( "saving %s\n", savename ); + CreatePath( savename ); + WritePCXfile( savename, cropped, model.skinwidth, + model.skinheight, palette ); + + free( pixels ); + free( palette ); + free( cropped ); +} + + +/* + ================= + Cmd_Origin + ================= + */ +void Cmd_Origin( void ){ + // rotate points into frame of reference so model points down the + // positive x axis + GetScriptToken( false ); + adjust[1] = -atof( token ); + + GetScriptToken( false ); + adjust[0] = atof( token ); + + GetScriptToken( false ); + adjust[2] = -atof( token ); +} + + +/* + ================= + Cmd_ScaleUp + ================= + */ +void Cmd_ScaleUp( void ){ + GetScriptToken( false ); + scale_up = atof( token ); + if ( g_skipmodel || g_release || g_archive ) { + return; + } + + printf( "Scale up: %f\n", scale_up ); +} + + +/* + ================= + Cmd_Skinsize + + Set a skin size other than the default + ================= + */ +void Cmd_Skinsize( void ){ + GetScriptToken( false ); + g_fixedwidth = atoi( token ); + GetScriptToken( false ); + g_fixedheight = atoi( token ); +} + +/* + ================= + Cmd_Modelname + + Gives a different name/location for the file, instead of the cddir + ================= + */ +void Cmd_Modelname( void ){ + GetScriptToken( false ); + strcpy( modelname, token ); +} + +/* + =============== + Cmd_Cd + =============== + */ +void Cmd_Cd( void ){ + char temp[256]; + + FinishModel(); + ClearModel(); + + GetScriptToken( false ); + + // this is a silly mess... + sprintf( cdpartial, "models/%s", token ); + sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token ); + sprintf( cddir, "%s%s", gamedir, cdpartial ); + + // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too. + sprintf( temp, "%s%s", g_outputDir, cdpartial ); + strcpy( g_outputDir, temp ); + + // if -only was specified and this cd doesn't match, + // skip the model (you only need to match leading chars, + // so you could regrab all monsters with -only monsters) + if ( !g_only[0] ) { + return; + } + if ( strncmp( token, g_only, strlen( g_only ) ) ) { + g_skipmodel = true; + printf( "skipping %s\n", cdpartial ); + } +} + +/* + ================= + Cmd_Cluster + ================= + */ +void Cmd_Cluster(){ + char file1[1024]; + + GetScriptToken( false ); + + printf( "---------------------\n" ); + sprintf( file1, "%s/%s", cdpartial, token ); + printf( "%s\n", file1 ); + + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s", cddir, token ); + + LoadClusters( file1, (int **)&clusters, (int *)&num_verts, jointed ); + + new_num_verts[0] = num_verts[0]; + + clustered = 1; +} + +// Model construction cover functions. +void MODELCMD_Modelname( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + Cmd_Modelname(); +/* + switch(modeltype) + { + case MODEL_MD2: + Cmd_Modelname (); + break; + case MODEL_FM: + Cmd_FMModelname (); + break; + } + */ +} + +void MODELCMD_Cd( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Cd(); + break; + case MODEL_FM: + Cmd_FMCd(); + break; + } +} + +void MODELCMD_Origin( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + Cmd_Origin(); +/* switch(modeltype) + { + case MODEL_MD2: + Cmd_Origin (); + break; + case MODEL_FM: + Cmd_FMOrigin (); + break; + } + */ +} + +void MODELCMD_Cluster( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Cluster(); + break; + case MODEL_FM: + Cmd_FMCluster(); + break; + } +} + +void MODELCMD_Base( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Base(); + break; + case MODEL_FM: + Cmd_FMBase( false ); + break; + } +} + +void MODELCMD_BaseST( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Base(); + break; + case MODEL_FM: + Cmd_FMBase( true ); + break; + } +} + +void MODELCMD_ScaleUp( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + Cmd_ScaleUp(); +/* switch(modeltype) + { + case MODEL_MD2: + Cmd_ScaleUp (); + break; + case MODEL_FM: + Cmd_FMScaleUp (); + break; + } + */ +} + +void MODELCMD_Frame( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Frame(); + break; + case MODEL_FM: + Cmd_FMFrame(); + break; + } +} + +void MODELCMD_Skin( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + Cmd_Skin(); + break; + case MODEL_FM: + Cmd_FMSkin(); + break; + } +} + +void MODELCMD_Skinsize( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + Cmd_Skinsize(); +/* + switch(modeltype) + { + case MODEL_MD2: + Cmd_Skinsize (); + break; + case MODEL_FM: + Cmd_FMSkinsize (); + break; + } + */ +} + +void MODELCMD_Skeleton( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + break; + case MODEL_FM: + Cmd_FMSkeleton(); + break; + } +} + +void MODELCMD_BeginGroup( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + break; + case MODEL_FM: + Cmd_FMBeginGroup(); + break; + } +} + +void MODELCMD_EndGroup( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + break; + case MODEL_FM: + Cmd_FMEndGroup(); + break; + } +} + +void MODELCMD_Referenced( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + break; + case MODEL_FM: + Cmd_FMReferenced(); + break; + } +} + +void MODELCMD_NodeOrder( int modeltype ){ + if ( g_forcemodel ) { + modeltype = g_forcemodel; + } + + switch ( modeltype ) + { + case MODEL_MD2: + break; + case MODEL_FM: + Cmd_FMNodeOrder(); + break; + } +} diff --git a/tools/heretic2/h2data/pics.c b/tools/heretic2/h2data/pics.c new file mode 100644 index 00000000..e9e91c27 --- /dev/null +++ b/tools/heretic2/h2data/pics.c @@ -0,0 +1,196 @@ +/* + Copyright (C) 1999-2007 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 ); +} diff --git a/tools/heretic2/h2data/qd_fmodel.h b/tools/heretic2/h2data/qd_fmodel.h new file mode 100644 index 00000000..286fb071 --- /dev/null +++ b/tools/heretic2/h2data/qd_fmodel.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 1999-2007 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 FMODEL_H +#define FMODEL_H +#include "fmodel.h" +#endif +#include "qd_skeletons.h" + +typedef struct +{ + int numnormals; + vec3_t normalsum; +} fmvertexnormals_t; + +typedef struct +{ + vec3_t v; + int lightnormalindex; + fmvertexnormals_t vnorm; +} fmtrivert_t; + +#define FRAME_NAME_LEN ( 16 ) + +typedef struct +{ + vec3_t mins, maxs; + char name[FRAME_NAME_LEN]; + fmtrivert_t v[MAX_FM_VERTS]; + struct QD_SkeletalJoint_s joints[NUM_CLUSTERS]; + struct QD_SkeletalJoint_s references[NUM_REFERENCES]; +} fmframe_t; + +extern fmframe_t g_frames[MAX_FM_FRAMES]; + +extern fmheader_t fmheader; +extern char cdarchive[1024]; // set by $fmcd +extern char cdpartial[1024]; // set by $fmcd +extern char cddir[1024]; // set by $fmcd + +void GrabFrame( char *frame ); +void H_printf( char *fmt, ... ); +char *FindFrameFile( char *frame ); diff --git a/tools/heretic2/h2data/qd_skeletons.c b/tools/heretic2/h2data/qd_skeletons.c new file mode 100644 index 00000000..97e2a1f8 --- /dev/null +++ b/tools/heretic2/h2data/qd_skeletons.c @@ -0,0 +1,1231 @@ +/* + Copyright (C) 1999-2007 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 "qd_skeletons.h" +#include "skeletons.h" +#include "qd_fmodel.h" +#include "angles.h" +#include "token.h" +#include "qdata.h" +#include "reference.h" + +#include +#include +#include + + +// We're assuming no more than 16 reference points, with no more than 32 characters in the name +char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN]; +int RefPointNum = 0; + +Skeletalfmheader_t g_skelModel; + +void ClearSkeletalModel(){ + g_skelModel.type = SKEL_NULL; + g_skelModel.clustered = false; + g_skelModel.references = REF_NULL; +} + +//========================================================================== +// +// LoadHRCClustered +// +//========================================================================== + +// Places the null terminated src string into the dest string less any trailing digits or underscores +void StripTrailingDigits( char *src, char *dest ){ +#ifndef NDEBUG + int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files +#endif + int i = 0; + + while ( src[i] != '\0' ) + { + ++i; +#ifndef NDEBUG + assert( i < max ); +#endif + } + + while ( ( src[--i] >= '0' && src[i] <= '9' ) || src[i] == '_' ) + { + + } + + memcpy( dest, src, ++i ); + + dest[i] = '\0'; +} + +static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){ + extern void HandleHRCModel( triangle_t **triList, int *triangleCount, + mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth ); + + extern mesh_node_t *pmnodes; + + triangle_t *triList; +// mesh_node_t *nodesList; + int num_mesh_nodes = 0, triangleCount = 0; + +#if 0 + int i; + int j, numVerts; + char stripped[SKELETAL_NAME_MAX]; + + for ( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i ) + { + num_verts[i] = 0; + } + + 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 ); + + StripTrailingDigits( tk_String, stripped ); + + for ( i = 0; i < numJointsInSkeleton[skelType]; ++i ) + { + if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) { + i = -i + numJointsInSkeleton[skelType] - 1; + + TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER ); + + numVerts = tk_IntNumber; + + if ( !num_verts[i + 1] ) { // first set of verts for cluster + clusterList[i] = SafeMalloc( numVerts * sizeof( int ), "LoadHRCClustered" ); + assert( clusterList[i] ); + } + else // any later sets of verts need to copy current + { + int *temp; + + temp = SafeMalloc( ( num_verts[i + 1] + numVerts ) * sizeof( int ), "LoadHRCClustered" ); + assert( temp ); + + memcpy( temp + numVerts, clusterList[i], num_verts[i + 1] * sizeof( int ) ); + + free( clusterList[i] ); + + clusterList[i] = temp; + } + + // currently this function is only called by LoadModelClusters. + // Apparently the matching free has disappeared, + // should probably be free at the end of FMCmd_Base + + TK_Beyond( TK_LBRACE ); + + for ( j = 0; j < numVerts; ++j ) + { + TK_Require( TK_INTNUMBER ); + clusterList[i][j] = tk_IntNumber; + TK_Fetch(); + } + + num_verts[i + 1] += numVerts; + + break; + } + } + } + + num_verts[0] = numJointsInSkeleton[skelType]; +#endif + +#if 1 // get the index number localized to the root +// for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i) +// { +// g_skelModel.num_verts[i] = 0; +// } + + TK_OpenSource( fileName ); + TK_FetchRequire( TK_HRCH ); + TK_FetchRequire( TK_COLON ); + TK_FetchRequire( TK_SOFTIMAGE ); + + // prime it + TK_Beyond( TK_MODEL ); + + triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" ); + memset( triList,0,MAXTRIANGLES * sizeof( triangle_t ) ); +// nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List"); + pmnodes = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); + + memset( pmnodes, 0, MAX_FM_MESH_NODES * sizeof( mesh_node_t ) ); + + // this should eventually use a stripped down version of this + HandleHRCModel( &triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0 ); + +// free(nodesList); + free( triList ); + + num_verts[0] = numJointsInSkeleton[skelType]; +#endif +} + +void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ){ + int i, j, numVerts; + tokenType_t nextToken; + char stripped[SKELETAL_NAME_MAX]; + + meshNode->clustered = true; + + nextToken = TK_Get( TK_CLUSTER_NAME ); + + while ( nextToken == TK_CLUSTER_NAME ) + { + TK_FetchRequire( TK_STRING ); + + StripTrailingDigits( tk_String, stripped ); + + for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) + { + if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type] + i] ) == 0 ) { + i = -i + numJointsInSkeleton[g_skelModel.type] - 1; + + TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER ); + + numVerts = tk_IntNumber; + + if ( !baseIndex ) { + meshNode->clusters[i] = (int *) SafeMalloc( numVerts * sizeof( int ), "ReadHRCClusterList" ); + assert( meshNode->clusters[i] ); + } + else + { + int *temp; + + temp = meshNode->clusters[i]; + meshNode->clusters[i] = (int *) SafeMalloc( ( meshNode->num_verts[i + 1] + numVerts ) * sizeof( int ), "ReadHRCClusterList" ); + assert( meshNode->clusters[i] ); + + memcpy( meshNode->clusters[i], temp, meshNode->num_verts[i + 1] * sizeof( int ) ); + free( temp ); + } + + // currently this function is only called by LoadModelClusters. + // Apparently the matching free has disappeared, + // should probably be free at the end of FMCmd_Base + + TK_Beyond( TK_LBRACE ); + + for ( j = 0; j < numVerts; ++j ) + { + TK_Require( TK_INTNUMBER ); + meshNode->clusters[i][baseIndex + j] = tk_IntNumber + baseIndex; + TK_Fetch(); + } + + if ( baseIndex ) { + meshNode->num_verts[i + 1] += numVerts; + } + else + { + meshNode->num_verts[i + 1] = numVerts; + } + + break; + } + } + + TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER ); + nextToken = TK_Fetch(); + } +} + +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_skelModel.scaling[i] = tk_FloatNumber; + TK_Fetch(); + } + + TK_Beyond( TK_ROTATION ); + for ( i = 0; i < 3; i++ ) + { + TK_Require( TK_FLOATNUMBER ); + g_skelModel.rotation[i] = tk_FloatNumber; + TK_Fetch(); + } + + TK_Beyond( TK_TRANSLATION ); + for ( i = 0; i < 3; i++ ) + { + TK_Require( TK_FLOATNUMBER ); + g_skelModel.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 ParseVec3d( vec3d_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 ParseRotation3d( vec3d_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 ParseTranslation3d( vec3d_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, QD_SkeletalJoint_t *jointList, int skelType ){ +#define MAX_STACK 64 + int i, j; + vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK]; + int curCorrespondingJoint[MAX_STACK]; + int currentStack = 0, stackSize; + double cx, sx, cy, sy, cz, sz; + double rx, ry, rz; + double x2, y2, z2; + char stripped[SKELETAL_NAME_MAX]; + Placement_d_t *placement; + + TK_OpenSource( fileName ); + TK_FetchRequire( TK_HRCH ); + TK_FetchRequire( TK_COLON ); + TK_FetchRequire( TK_SOFTIMAGE ); + + TK_Beyond( TK_MODEL ); + + while ( TK_Search( TK_NAME ) != TK_EOF ) + { + TK_Require( TK_STRING ); + + StripTrailingDigits( tk_String, stripped ); + + if ( stricmp( stripped, skeletonRootNames[skeletonRNameOffsets[skelType]] ) == 0 ) { + break; + } + } + + if ( tk_Token == TK_EOF ) { + Error( "Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]] ); + return; + } + + TK_Beyond( TK_SCALING ); + + ParseVec3d( curScale[currentStack] ); + + TK_Beyond( TK_ROTATION ); + + ParseRotation3d( curRotation[currentStack] ); + + TK_Beyond( TK_TRANSLATION ); + + ParseVec3d( curTranslation[currentStack] ); + + // account for global model translation + curTranslation[currentStack][1] += g_skelModel.translation[0]; + curTranslation[currentStack][2] += g_skelModel.translation[1]; + curTranslation[currentStack][0] += g_skelModel.translation[2]; + + curCorrespondingJoint[currentStack] = -1; + + ++currentStack; + + for ( i = 0; i < numJointsInSkeleton[skelType]; ++i ) + { + while ( 1 ) + { + TK_Beyond( TK_MODEL ); + + TK_BeyondRequire( TK_NAME, TK_STRING ); + + StripTrailingDigits( tk_String, stripped ); + + if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) { + break; + } + + TK_Beyond( TK_SCALING ); + + ParseVec3d( curScale[currentStack] ); + + TK_Beyond( TK_ROTATION ); + + ParseRotation3d( curRotation[currentStack] ); + + TK_Beyond( TK_TRANSLATION ); + + ParseVec3d( curTranslation[currentStack] ); + + curCorrespondingJoint[currentStack] = -1; + + ++currentStack; + } + + TK_Beyond( TK_SCALING ); + + ParseVec3d( curScale[currentStack] ); + + TK_Beyond( TK_ROTATION ); + + ParseRotation3d( 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 ); + + ParseVec3d( 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.origin[1] = 0.0; + jointList[i].placement.origin[2] = 0.0; + jointList[i].placement.origin[0] = 0.0; + + jointList[i].placement.direction[1] = 20.0; + 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] = 20.0; + jointList[i].placement.up[0] = 0.0; + + curCorrespondingJoint[currentStack] = i; + + ++currentStack; + } + + stackSize = currentStack; + +#if 0 + // rotate the direction and up vectors to correspond to the rotation + for ( i = 0; i < numJointsInSkeleton[skelType]; ++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 direction to a point in the 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 up to a point in the 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]; + } +#endif + + for ( i = stackSize - 1; i >= 0; --i ) + { + rx = curRotation[i][0] * ANGLE_TO_RAD; + ry = curRotation[i][1] * ANGLE_TO_RAD; + rz = curRotation[i][2] * ANGLE_TO_RAD; + + cx = cos( rx ); + sx = sin( rx ); + + cy = cos( ry ); + sy = sin( ry ); + + cz = cos( rz ); + sz = sin( rz ); + +#if 1 + for ( j = i; j < stackSize; ++j ) + { + if ( curCorrespondingJoint[j] != -1 ) { + placement = &jointList[curCorrespondingJoint[j]].placement; + + // y-axis rotation for origin + x2 = placement->origin[0] * cy + placement->origin[2] * sy; + z2 = -placement->origin[0] * sy + placement->origin[2] * cy; + placement->origin[0] = x2; + placement->origin[2] = z2; + + // y-axis rotation for direction + x2 = placement->direction[0] * cy + placement->direction[2] * sy; + z2 = -placement->direction[0] * sy + placement->direction[2] * cy; + placement->direction[0] = x2; + placement->direction[2] = z2; + + // y-axis rotation for up + x2 = placement->up[0] * cy + placement->up[2] * sy; + z2 = -placement->up[0] * sy + placement->up[2] * cy; + placement->up[0] = x2; + placement->up[2] = z2; + + // z-axis rotation for origin + x2 = placement->origin[0] * cz - placement->origin[1] * sz; + y2 = placement->origin[0] * sz + placement->origin[1] * cz; + placement->origin[0] = x2; + placement->origin[1] = y2; + + // z-axis rotation for direction + x2 = placement->direction[0] * cz - placement->direction[1] * sz; + y2 = placement->direction[0] * sz + placement->direction[1] * cz; + placement->direction[0] = x2; + placement->direction[1] = y2; + + // z-axis rotation for up + x2 = placement->up[0] * cz - placement->up[1] * sz; + y2 = placement->up[0] * sz + placement->up[1] * cz; + placement->up[0] = x2; + placement->up[1] = y2; + + // x-axis rotation for origin + y2 = placement->origin[1] * cx - placement->origin[2] * sx; + z2 = placement->origin[1] * sx + placement->origin[2] * cx; + placement->origin[1] = y2; + placement->origin[2] = z2; + + // x-axis rotation for direction vector + y2 = placement->direction[1] * cx - placement->direction[2] * sx; + z2 = placement->direction[1] * sx + placement->direction[2] * cx; + placement->direction[1] = y2; + placement->direction[2] = z2; + + // x-axis rotation for up vector + y2 = placement->up[1] * cx - placement->up[2] * sx; + z2 = placement->up[1] * sx + placement->up[2] * cx; + placement->up[1] = y2; + placement->up[2] = z2; + + // translate origin + placement->origin[0] += curTranslation[i][0]; + placement->origin[1] += curTranslation[i][1]; + placement->origin[2] += curTranslation[i][2]; + + // translate back to local coord + placement->direction[0] += curTranslation[i][0]; + placement->direction[1] += curTranslation[i][1]; + placement->direction[2] += curTranslation[i][2]; + + // translate back to local coord + placement->up[0] += curTranslation[i][0]; + placement->up[1] += curTranslation[i][1]; + placement->up[2] += curTranslation[i][2]; + } + } +#else + // This screwed up and needs to be sorted out!!! + // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton + 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]; + } + } +#endif + } +} + +void LoadModelTransform( 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 LoadModelClusters( 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 LoadSkeleton( char *fileName, QD_SkeletalJoint_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 ); + } +} + +/* + =============== + GrabSkeletalFrame + =============== + */ +void GrabSkeletalFrame( char *frame ){ + char file1[1024]; + char *framefile; + fmframe_t *fr; + + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "Grabbing Skeletal Frame %s\n", file1 ); + + fr = &g_frames[fmheader.num_frames - 1]; // last frame read in + + LoadSkeleton( file1, fr->joints, g_skelModel.type ); +} + +/* + =============== + GrabModelTransform + =============== + */ +void GrabModelTransform( char *frame ){ + char file1[1024]; + char *framefile; + fmframe_t *fr; + + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + +// printf ("grabbing %s\n", file1); + + fr = &g_frames[fmheader.num_frames - 1]; // last frame read in + + LoadModelTransform( file1 ); +} + +void Cmd_FMCluster(){ + char file1[1024]; + + GetScriptToken( false ); + + printf( "---------------------\n" ); + sprintf( file1, "%s/%s", cdpartial, token ); + printf( "%s\n", file1 ); + + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s", cddir, token ); + + g_skelModel.clustered = -1; + + LoadModelClusters( file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type ); + + g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0]; + + g_skelModel.clustered = true; +} + +void Cmd_FMSkeleton(){ + GetScriptToken( false ); + g_skelModel.type = atoi( token ); +} + +void Cmd_FMSkeletalFrame(){ + while ( ScriptTokenAvailable() ) + { + GetScriptToken( false ); + if ( g_skipmodel ) { + GetScriptToken( false ); + continue; + } + if ( g_release || g_archive ) { + fmheader.num_frames = 1; // don't skip the writeout + GetScriptToken( false ); + continue; + } + + H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames ); + + GrabModelTransform( token ); + GrabFrame( token ); + GrabSkeletalFrame( token ); + + // need to add the up and dir points to the frame bounds here + // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs); + // then remove fudge in determining scale on frame write out + } +} + +static void LoadHRCReferences( char *fileName, fmframe_t *fr ){ +#define MAX_STACK 64 + int i, j, k; + vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK]; + int curCorrespondingJoint[MAX_STACK]; + int currentStack, stackSize; + double cx, sx, cy, sy, cz, sz; + double rx, ry, rz; + double x2, y2, z2; + char stripped[SKELETAL_NAME_MAX]; + Placement_d_t *placement; + int refnum; + + TK_OpenSource( fileName ); + TK_FetchRequire( TK_HRCH ); + TK_FetchRequire( TK_COLON ); + TK_FetchRequire( TK_SOFTIMAGE ); + + if ( RefPointNum <= 0 ) { // There were no labels indicated in the QDT, so use the hard-coded stuff. + refnum = numReferences[g_skelModel.references]; + } + else + { + refnum = RefPointNum; + } + + for ( k = 0; k < refnum; ++k ) + { + currentStack = 0; + + // Load the root to get translation and initial rotation +// TK_Beyond(TK_MODEL); + + while ( TK_Search( TK_NAME ) != TK_EOF ) + { + TK_Require( TK_STRING ); + + StripTrailingDigits( tk_String, stripped ); + + if ( RefPointNum == 0 ) { // Hard coded refpoint labels + if ( stricmp( stripped, + referenceRootNames[referenceRootNameOffsets[g_skelModel.references] + k] ) == 0 ) { + break; + } + } + else + { // labels indicated by the QDT + if ( stricmp( stripped, RefPointNameList[k] ) == 0 ) { + break; + } + } + } + + if ( tk_Token == TK_EOF ) { + if ( RefPointNum == 0 ) { // Hard coded refpoint labels + Error( "Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]] ); + } + else + { // labels indicated by the QDT + Error( "Bone Chain Root: %s not found\n", RefPointNameList[k] ); + } + return; + } + +// TK_Beyond(TK_SCALING); + +// ParseVec3d(curScale[currentStack]); + + TK_Beyond( TK_ROTATION ); + + ParseRotation3d( curRotation[currentStack] ); + + TK_Beyond( TK_TRANSLATION ); + + ParseVec3d( curTranslation[currentStack] ); + + // account for global model translation + curTranslation[currentStack][1] += g_skelModel.translation[0]; + curTranslation[currentStack][2] += g_skelModel.translation[1]; + curTranslation[currentStack][0] += g_skelModel.translation[2]; + + curCorrespondingJoint[currentStack] = -1; + +// rjr - this one not needed, as there is also a stack increment 20 lines below??? +// ++currentStack; + + // Load the joint to get orientation + TK_Beyond( TK_MODEL ); + +// TK_Beyond(TK_SCALING); + +// ParseVec3d(curScale[currentStack]); + + TK_Beyond( TK_ROTATION ); + + ParseRotation3d( curRotation[currentStack] ); + +// TK_Beyond(TK_TRANSLATION); + +// ParseVec3d(curTranslation[currentStack]); + + fr->references[k].placement.origin[1] = 0.0; + fr->references[k].placement.origin[2] = 0.0; + fr->references[k].placement.origin[0] = 0.0; + + fr->references[k].placement.direction[1] = 20.0; + fr->references[k].placement.direction[2] = 0.0; + fr->references[k].placement.direction[0] = 0.0; + + fr->references[k].placement.up[1] = 0.0; + fr->references[k].placement.up[2] = 20.0; + fr->references[k].placement.up[0] = 0.0; + + curCorrespondingJoint[currentStack] = k; + + ++currentStack; + + stackSize = currentStack; + + for ( i = stackSize - 1; i >= 0; --i ) + { + rx = curRotation[i][0] * ANGLE_TO_RAD; + ry = curRotation[i][1] * ANGLE_TO_RAD; + rz = curRotation[i][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; j < stackSize; ++j ) + { + if ( curCorrespondingJoint[j] != -1 ) { + placement = &fr->references[curCorrespondingJoint[j]].placement; + + // y-axis rotation for origin + x2 = placement->origin[0] * cy + placement->origin[2] * sy; + z2 = -placement->origin[0] * sy + placement->origin[2] * cy; + placement->origin[0] = x2; + placement->origin[2] = z2; + + // y-axis rotation for direction + x2 = placement->direction[0] * cy + placement->direction[2] * sy; + z2 = -placement->direction[0] * sy + placement->direction[2] * cy; + placement->direction[0] = x2; + placement->direction[2] = z2; + + // y-axis rotation for up + x2 = placement->up[0] * cy + placement->up[2] * sy; + z2 = -placement->up[0] * sy + placement->up[2] * cy; + placement->up[0] = x2; + placement->up[2] = z2; + + // z-axis rotation for origin + x2 = placement->origin[0] * cz - placement->origin[1] * sz; + y2 = placement->origin[0] * sz + placement->origin[1] * cz; + placement->origin[0] = x2; + placement->origin[1] = y2; + + // z-axis rotation for direction + x2 = placement->direction[0] * cz - placement->direction[1] * sz; + y2 = placement->direction[0] * sz + placement->direction[1] * cz; + placement->direction[0] = x2; + placement->direction[1] = y2; + + // z-axis rotation for up + x2 = placement->up[0] * cz - placement->up[1] * sz; + y2 = placement->up[0] * sz + placement->up[1] * cz; + placement->up[0] = x2; + placement->up[1] = y2; + + // x-axis rotation for origin + y2 = placement->origin[1] * cx - placement->origin[2] * sx; + z2 = placement->origin[1] * sx + placement->origin[2] * cx; + placement->origin[1] = y2; + placement->origin[2] = z2; + + // x-axis rotation for direction vector + y2 = placement->direction[1] * cx - placement->direction[2] * sx; + z2 = placement->direction[1] * sx + placement->direction[2] * cx; + placement->direction[1] = y2; + placement->direction[2] = z2; + + // x-axis rotation for up vector + y2 = placement->up[1] * cx - placement->up[2] * sx; + z2 = placement->up[1] * sx + placement->up[2] * cx; + placement->up[1] = y2; + placement->up[2] = z2; + + // translate origin + placement->origin[0] += curTranslation[i][0]; + placement->origin[1] += curTranslation[i][1]; + placement->origin[2] += curTranslation[i][2]; + + // translate back to local coord + placement->direction[0] += curTranslation[i][0]; + placement->direction[1] += curTranslation[i][1]; + placement->direction[2] += curTranslation[i][2]; + + // translate back to local coord + placement->up[0] += curTranslation[i][0]; + placement->up[1] += curTranslation[i][1]; + placement->up[2] += curTranslation[i][2]; + + } + } + } + printf( "%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2] ); + } + printf( "\n" ); +} + +void Cmd_FMReferenced(){ + int i; + + GetScriptToken( false ); + g_skelModel.references = atoi( token ); + + // Guess what? Now, we now want a list of strings to look for here instead of a hard-coded list + for ( i = 0; i < REF_MAX_POINTS; i++ ) + { + if ( ScriptTokenAvailable() ) { // There is yet another reference point waiting. + GetScriptToken( false ); + strcpy( RefPointNameList[i], token ); + } + else + { + break; + } + } + + RefPointNum = i; + + if ( RefPointNum > 0 ) { + printf( "Searching for %d different reference points.\n", RefPointNum ); + } + else + { + printf( "Using built-in reference points.\n" ); + } + +} + +void LoadReferences( char *fileName, fmframe_t *fr ){ + 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 ); + + LoadHRCReferences( InputFileName, fr ); + + 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 ) { + LoadHRCReferences( fileName, fr ); + + return; + } + } + + Error( "Could not open file '%s':\n",fileName ); + } +} + +void GrabReferencedFrame( char *frame ){ + char file1[1024]; + char *framefile; + fmframe_t *fr; + + framefile = FindFrameFile( frame ); + + sprintf( file1, "%s/%s", cdarchive, framefile ); + ExpandPathAndArchive( file1 ); + + sprintf( file1, "%s/%s",cddir, framefile ); + + printf( "Grabbing Referenced %s\n", file1 ); + + fr = &g_frames[fmheader.num_frames - 1]; // last frame read in + + LoadReferences( file1, fr ); +} diff --git a/tools/heretic2/h2data/qd_skeletons.h b/tools/heretic2/h2data/qd_skeletons.h new file mode 100644 index 00000000..7765c579 --- /dev/null +++ b/tools/heretic2/h2data/qd_skeletons.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 1999-2007 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 QD_SKELETONS_H +#define QD_SKELETONS_H + +#include "placement.h" + + +typedef struct Placement_d_s +{ + vec3d_t origin; + vec3d_t direction; + vec3d_t up; +} Placement_d_t; + +typedef struct QD_SkeletalJoint_s +{ + Placement_d_t placement; + vec3d_t rotation; +} QD_SkeletalJoint_t; + +#define NUM_CLUSTERS 8 + +typedef struct IntListNode_s +{ + int data; + struct IntListNode_s *next; +} IntListNode_t; // gaak + +typedef struct Skeletalfmheader_s +{ + int type; + int clustered; + int references; + + int *clusters[NUM_CLUSTERS]; + IntListNode_t *vertLists[NUM_CLUSTERS]; + int num_verts[NUM_CLUSTERS + 1]; + int new_num_verts[NUM_CLUSTERS + 1]; + + float scaling[3]; + float rotation[3]; + float translation[3]; +} Skeletalfmheader_t; + +#define SKELETAL_NAME_MAX 32 + +extern Skeletalfmheader_t g_skelModel; + +void ClearSkeletalModel(); +void GrabModelTransform( char *frame ); +void GrabSkeletalFrame( char *frame ); +void GrabReferencedFrame( char *frame ); + +// Reference Stuff +#define NUM_REFERENCES 8 + +#define REF_MAX_POINTS 16 +#define REF_MAX_STRLEN 32 + +// We're assuming no more than 16 reference points, with no more than 32 characters in the name +extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN]; +extern int RefPointNum; + +#endif diff --git a/tools/heretic2/h2data/qdata.c b/tools/heretic2/h2data/qdata.c new file mode 100644 index 00000000..5ec53a9e --- /dev/null +++ b/tools/heretic2/h2data/qdata.c @@ -0,0 +1,764 @@ +/* + Copyright (C) 1999-2007 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 "globaldefs.h" +#include "md4.h" + +void TK_Init(); + +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 +int g_forcemodel = MODEL_AUTO; +qboolean g_verbose = false; +qboolean g_allow_newskin = true; +qboolean g_ignoreTriUV = false; +qboolean g_publishOutput = false; + +char *ext_3ds = "3ds"; +char *ext_tri = "tri"; +char *trifileext; + +char g_materialFile[256] = "none"; // default for Heretic2 +char *g_outputDir; +extern char *g_publishDir; + +extern qboolean g_nomkdir; + +/* + ======================================================= + + PAK FILES + + ======================================================= + */ + +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 ); + + // segment moved to old.c + + 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 ){ + GetScriptToken( false ); + ReleaseFile( token ); +} + +/* + =============== + PackDirectory_r + + =============== + */ +#if GDEF_OS_WINDOWS +#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 +#ifdef NeXT +#include +#else +#include +#endif + +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 ){ + GetScriptToken( 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_strcasecmp( name, rtex[i] ) ) { + 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 ( ScriptTokenAvailable() ) + { + GetScriptToken( 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 + GetScriptToken( true ); + if ( endofscript ) { + return; + } + if ( token[0] == '$' ) { + break; + } + while ( ScriptTokenAvailable() ) + GetScriptToken( false ); + } while ( 1 ); + + // + // model commands + // + if ( !strcmp( token, "$modelname" ) ) { + MODELCMD_Modelname( MODEL_MD2 ); + } + else if ( !strcmp( token, "$cd" ) ) { + MODELCMD_Cd( MODEL_MD2 ); + } + else if ( !strcmp( token, "$origin" ) ) { + MODELCMD_Origin( MODEL_MD2 ); + } + else if ( !strcmp( token, "$cluster" ) ) { + MODELCMD_Cluster( MODEL_MD2 ); + } + else if ( !strcmp( token, "$base" ) ) { + MODELCMD_Base( MODEL_MD2 ); + } + else if ( !strcmp( token, "$scale" ) ) { + MODELCMD_ScaleUp( MODEL_MD2 ); + } + else if ( !strcmp( token, "$frame" ) ) { + MODELCMD_Frame( MODEL_MD2 ); + } + else if ( !strcmp( token, "$skin" ) ) { + MODELCMD_Skin( MODEL_MD2 ); + } + else if ( !strcmp( token, "$skinsize" ) ) { + MODELCMD_Skinsize( MODEL_MD2 ); + } + // + // flexible model commands + // + else if ( !strcmp( token, "$fm_modelname" ) ) { + MODELCMD_Modelname( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_base" ) ) { + MODELCMD_Base( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_basest" ) ) { + MODELCMD_BaseST( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_cd" ) ) { + MODELCMD_Cd( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_origin" ) ) { + MODELCMD_Origin( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_cluster" ) ) { + MODELCMD_Cluster( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_skeleton" ) ) { + MODELCMD_Skeleton( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_scale" ) ) { + MODELCMD_ScaleUp( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_frame" ) ) { + MODELCMD_Frame( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_skeletal_frame" ) ) { // left in for compadibility with qdt already using fm_skeletal_frame + MODELCMD_Frame( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_skin" ) ) { + MODELCMD_Skin( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_skinsize" ) ) { + MODELCMD_Skinsize( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_begin_group" ) ) { + MODELCMD_BeginGroup( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_end_group" ) ) { + MODELCMD_EndGroup( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_referenced" ) ) { + MODELCMD_Referenced( MODEL_FM ); + } + else if ( !strcmp( token, "$fm_node_order" ) ) { + MODELCMD_NodeOrder( MODEL_FM ); + } + + // + // sprite commands + // + else if ( !strcmp( token, "$spritename" ) ) { + Cmd_SpriteName(); + } + else if ( !strcmp( token, "$sprdir" ) ) { + Cmd_Sprdir(); + } + else if ( !strcmp( token, "$load" ) ) { + Cmd_Load(); + } + else if ( !strcmp( token, "$spriteframe" ) ) { + Cmd_SpriteFrame(); + } + // + // image commands + // + else if ( !strcmpi( token, "$grab" ) ) { + Cmd_Grab(); + } + else if ( !strcmpi( token, "$raw" ) ) { + Cmd_Raw(); + } + else if ( !strcmpi( token, "$colormap" ) ) { + Cmd_Colormap(); + } + else if ( !strcmpi( token, "$mippal" ) ) { + Cmd_Mippal(); + } + else if ( !strcmpi( token, "$mipdir" ) ) { + Cmd_Mipdir(); + } + else if ( !strcmpi( token, "$mip" ) ) { + Cmd_Mip(); + } + else if ( !strcmp( token, "$environment" ) ) { + Cmd_Environment(); + } + // + // pics + // + else if ( !strcmp( token, "$picdir" ) ) { + Cmd_Picdir(); + } + else if ( !strcmp( token, "$pic" ) ) { + Cmd_Pic(); + } + // + // book + // + else if ( !strcmp( token, "$bookdir" ) ) { + Cmd_Bookdir(); + } + else if ( !strcmp( token, "$book" ) ) { + Cmd_Book(); + } + // + // tmix + // + else if ( !strcmp( token, "$texturemix" ) ) { + Cmd_TextureMix(); + } + // + // 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 ){ + int i; + char path[1024]; + char *basedir; + double starttime, endtime; + + printf( "Qdata Plus : "__TIME__ " "__DATE__ "\n" ); + + starttime = I_FloatTime(); + basedir = NULL; + + TK_Init(); + ExpandWildcards( &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], "-base" ) ) { + i++; + basedir = argv[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 ( !strcmpi( argv[i], "-keypress" ) ) { + g_dokeypress = true; + } + else if ( !strcmp( argv[i], "-3ds" ) ) { + do3ds = true; + printf( "loading .3ds files\n" ); + } + else if ( !strcmp( argv[i], "-materialfile" ) ) { + strcpy( g_materialFile, argv[i + 1] ); + printf( "Setting material file to %s\n", g_materialFile ); + i++; + } +/* else if (!strcmpi(argv[i], "-newgen")) + { + if (i < argc-4) + { + printf("run new triangle grouping routine here\n"); + NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4])); + } + else + { + printf("qdata -newskin width height\n"); + } + return 0; + } + */ else if ( !strcmpi( argv[i], "-genskin" ) ) { + i++; + if ( i < argc - 3 ) { + GenSkin( argv[i],argv[i + 1],atol( argv[i + 2] ),atol( argv[i + 3] ) ); + } + else + { + printf( "qdata -genskin \n" ); + } + return 0; + + } + else if ( !strcmpi( argv[i], "-noopts" ) ) { + g_no_opimizations = true; + printf( "not performing optimizations\n" ); + } + else if ( !strcmpi( argv[i], "-md2" ) ) { + g_forcemodel = MODEL_MD2; + } + else if ( !strcmpi( argv[i], "-fm" ) ) { + g_forcemodel = MODEL_FM; + } + else if ( !strcmpi( argv[i], "-verbose" ) ) { + g_verbose = true; + } + else if ( !strcmpi( argv[i], "-oldskin" ) ) { + g_allow_newskin = false; + } + else if ( !strcmpi( argv[i], "-ignoreUV" ) ) { + g_ignoreTriUV = true; + } + else if ( !strcmpi( argv[i], "-publish" ) ) { + g_publishOutput = true; + } + else if ( !strcmpi( argv[i], "-nomkdir" ) ) { + g_nomkdir = true; + } + else if ( argv[i][0] == '-' ) { + Error( "Unknown option \"%s\"", argv[i] ); + } + else{ + break; + } + } + + if ( i >= argc ) { + Error( "usage: qdata [-archive ]\n" + " [-release ]\n" + " [-base ]\n" + " [-compress]\n" + " [-pak ]\n" + " [-only ]\n" + " [-keypress]\n" + " [-3ds]\n" + " [-materialfile ]\n" + " [-noopts]\n" + " [-md2]\n" + " [-fm]\n" + " [-verbose]\n" + " [-ignoreUV]\n" + " [-oldskin]\n" + " [-publish]\n" + " [-nomkdir]\n" + " file.qdt\n" + "or\n" + " qdata -genskin " ); + } + + 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" ); + DefaultExtension( g_materialFile, ".mat" ); + SetQdirFromPath( path ); + + printf( "workingdir='%s'\n", gamedir ); + if ( basedir ) { + qdir[0] = 0; + g_outputDir = basedir; + } + + printf( "outputdir='%s'\n", g_outputDir ); + + QFile_ReadMaterialTypes( g_materialFile ); + LoadScriptFile( ExpandArg( path ) ); + + // + // parse it + // + ParseScript(); + + // write out the last model + FinishModel(); + FMFinishModel(); + FinishSprite(); + } + + if ( total_textures ) { + printf( "\n" ); + printf( "Total textures processed: %d\n",total_textures ); + printf( "Average size: %d x %d\n",total_x / total_textures, total_y / total_textures ); + } + + if ( g_pak ) { + FinishPak(); + } + + endtime = I_FloatTime(); + printf( "Time elapsed: %f\n", endtime - starttime ); + + if ( g_dokeypress ) { + printf( "Success! ... Hit a key: " ); + getchar(); + } + + return 0; +} diff --git a/tools/heretic2/h2data/qdata.h b/tools/heretic2/h2data/qdata.h new file mode 100644 index 00000000..0cfa6067 --- /dev/null +++ b/tools/heretic2/h2data/qdata.h @@ -0,0 +1,166 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// qdata.h + +#include "globaldefs.h" +#include +#include +#include +#include +#include + +#include "cmdlib.h" +#include "inout.h" +#include "scriplib.h" +#include "mathlib.h" +#include "trilib.h" +#include "lbmlib.h" +#include "her2_threads.h" +#include "l3dslib.h" +#include "bspfile.h" + +#if !GDEF_OS_WINDOWS +#define stricmp strcasecmp +#define strcmpi strcasecmp +#endif + + +#define MODEL_AUTO 0 +#define MODEL_MD2 1 +#define MODEL_FM 2 + +// Model cover functions (to allow the forcing of a model type) +void MODELCMD_Modelname( int modeltype ); +void MODELCMD_Cd( int modeltype ); +void MODELCMD_Origin( int modeltype ); +void MODELCMD_Jointed( int modeltype ); +void MODELCMD_Cluster( int modeltype ); +void MODELCMD_Base( int modeltype ); +void MODELCMD_BaseST( int modeltype ); +void MODELCMD_ScaleUp( int modeltype ); +void MODELCMD_Frame( int modeltype ); +void MODELCMD_Skin( int modeltype ); +void MODELCMD_Skinsize( int modeltype ); +void MODELCMD_Skeleton( int modeltype ); +void MODELCMD_SkeletalFrame( int modeltype ); +void MODELCMD_BeginGroup( int modeltype ); +void MODELCMD_EndGroup( int modeltype ); +void MODELCMD_Referenced( int modeltype ); +void MODELCMD_NodeOrder( int modeltype ); + +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_Skin( void ); +void Cmd_Skinsize( void ); +void FinishModel( void ); +void Cmd_Cluster( void ); + +// Flexible Models +//void Cmd_FMModelname (void); +void Cmd_FMBase( qboolean GetST ); +void Cmd_FMCd( void ); +//void Cmd_FMOrigin (void); +void Cmd_FMCluster(); +void Cmd_FMSkeleton(); +//void Cmd_FMScaleUp (void); +void Cmd_FMFrame( void ); +void Cmd_FMSkeletalFrame(); +void Cmd_FMSkin( void ); +//void Cmd_FMSkinsize (void); +void Cmd_FMBeginGroup( void ); +void Cmd_FMEndGroup( void ); +void Cmd_FMReferenced(); +void Cmd_FMNodeOrder( void ); +void FMFinishModel( void ); +void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ); +void NewGen( char *ModelFile, char *OutputName, int width, int height ); + + +void Cmd_Inverse16Table( void ); + +void Cmd_SpriteName( void ); +void Cmd_Load( void ); +void Cmd_SpriteFrame( void ); +void Cmd_Sprdir( 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_Picdir( void ); +void Cmd_Pic( void ); + +void Cmd_Bookdir( void ); +void Cmd_Book( void ); + +void Cmd_TextureMix( 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 TrueColorImage; +extern unsigned *longimage; +extern int longimagewidth, longimageheight; + +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 qboolean g_no_opimizations; +extern int g_forcemodel; +extern qboolean g_verbose; +extern qboolean g_allow_newskin; +extern qboolean g_ignoreTriUV; //from qdata.c +extern qboolean g_dokeypress; + +extern char *trifileext; + +extern char g_materialFile[256]; + +extern unsigned total_x; +extern unsigned total_y; +extern unsigned total_textures; + +miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ); +miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ); diff --git a/tools/heretic2/h2data/resource.h b/tools/heretic2/h2data/resource.h new file mode 100644 index 00000000..3d6343e5 --- /dev/null +++ b/tools/heretic2/h2data/resource.h @@ -0,0 +1,18 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/tools/heretic2/h2data/sprites.c b/tools/heretic2/h2data/sprites.c new file mode 100644 index 00000000..ecb9d096 --- /dev/null +++ b/tools/heretic2/h2data/sprites.c @@ -0,0 +1,345 @@ +/* + Copyright (C) 1999-2007 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" + +#define MAX_SPRFRAMES MAX_MD2SKINS + +dsprite_t sprite; +dsprframe_t frames[MAX_SPRFRAMES]; + +byte *byteimage, *lbmpalette; +int byteimagewidth, byteimageheight; + +qboolean TrueColorImage; +unsigned *longimage; +int longimagewidth, longimageheight; + +char spritename[1024]; + + +void FinishSprite( void ); +void Cmd_Spritename( void ); + +char spr_prefix[1024]; +char pic_prefix[1024]; + +extern char *g_outputDir; + + +/* + ============== + 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, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, 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; + + GetScriptToken( false ); + + if ( g_release ) { + return; + } + + name = ExpandPathAndArchive( token ); + + // load the image + printf( "loading %s\n", name ); + TrueColorImage = LoadAnyImage( name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight ); + + if ( !TrueColorImage ) { +// RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight); + } + else + { + if ( longimage ) { + free( longimage ); + } + longimage = (unsigned *)byteimage; + longimagewidth = byteimagewidth; + longimageheight = byteimageheight; + + byteimage = NULL; + byteimagewidth = 0; + byteimageheight = 0; + } +} + + +/* + =============== + Cmd_SpriteFrame + =============== + */ + +void Cmd_SpriteFrame( void ){ + int x,y,xl,yl,xh,yh,w,h; + dsprframe_t *pframe; + int ox, oy, linedelta, size; +// byte *cropped; + char filename[1024]; + miptex_t *qtex; + miptex32_t *qtex32; + unsigned *destl, *sourcel; + unsigned bufferl[256 * 256]; + byte *dest, *source; + byte buffer[256 * 256]; + + GetScriptToken( false ); + xl = atoi( token ); + GetScriptToken( false ); + yl = atoi( token ); + GetScriptToken( false ); + w = atoi( token ); + GetScriptToken( false ); + h = atoi( token ); + + // origin offset is optional + if ( ScriptTokenAvailable() ) { + GetScriptToken( false ); + ox = atoi( token ); + GetScriptToken( false ); + oy = atoi( token ); + } + else + { + ox = w / 2; + oy = h / 2; + } + + if ( ( xl & 0x0f ) || ( yl & 0x0f ) || ( w & 0x0f ) || ( h & 0x0f ) ) { + Error( "Sprite dimensions not multiples of 16\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; + + if ( g_release ) { + ReleaseFile( pframe->name ); + return; + } + + if ( TrueColorImage ) { + sprintf( filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes ); + sprintf( pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes ); + + 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, true ); + + qtex32->contents = 0; + qtex32->value = 0; + strcpy( qtex32->name, pframe->name ); + // + // write it out + // + printf( "writing %s\n", filename ); + SaveFile( filename, (byte *)qtex32, size ); + + free( qtex32 ); + } + else + { + sprintf( filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes ); + sprintf( pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes ); + + 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, true ); + + qtex->flags = 0; + qtex->contents = 0; + qtex->value = 0; + strcpy( qtex->name, pframe->name ); + // + // write it out + // + printf( "writing %s\n", filename ); + SaveFile( filename, (byte *)qtex, size ); + + free( qtex ); + } + + sprite.numframes++; +} + + +/* + ============== + Cmd_SpriteName + ============== + */ +void Cmd_SpriteName( void ){ + if ( sprite.numframes ) { + FinishSprite(); + } + + GetScriptToken( false ); + strcpy( spritename, token ); + memset( &sprite, 0, sizeof( sprite ) ); + memset( &frames, 0, sizeof( frames ) ); +} + + +/* + =============== + Cmd_Sprdir + =============== + */ +void Cmd_Sprdir( void ){ + char filename[1024]; + + GetScriptToken( false ); + strcpy( spr_prefix, token ); + // create the directory if needed + sprintf( filename, "%sSprites", g_outputDir ); + Q_mkdir( filename ); + sprintf( filename, "%sSprites/%s", g_outputDir, spr_prefix ); + Q_mkdir( filename ); +} diff --git a/tools/heretic2/h2data/svdcmp.c b/tools/heretic2/h2data/svdcmp.c new file mode 100644 index 00000000..14865af3 --- /dev/null +++ b/tools/heretic2/h2data/svdcmp.c @@ -0,0 +1,487 @@ +/* + Copyright (C) 1999-2007 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 +#include +#include +#include +#include + +static double at,bt,ct; +#define PYTHAG( a,b ) ( ( at = fabs( a ) ) > ( bt = fabs( b ) ) ? \ + ( ct = bt / at,at * sqrt( 1.0 + ct * ct ) ) : ( bt ? ( ct = at / bt,bt * sqrt( 1.0 + ct * ct ) ) : 0.0 ) ) + +static double maxarg1,maxarg2; +#define MAX( a,b ) ( maxarg1 = ( a ),maxarg2 = ( b ),( maxarg1 ) > ( maxarg2 ) ? \ + ( maxarg1 ) : ( maxarg2 ) ) +#define SIGN( a,b ) ( ( b ) >= 0.0 ? fabs( a ) : -fabs( a ) ) + +void ntrerror( char *s ){ + printf( "%s\n",s ); + exit( 1 ); +} + +double *allocVect( int sz ){ + double *ret; + + ret = calloc( sizeof( double ), (size_t)sz ); + return ret; +} + +void freeVect( double *ret ){ + free( ret ); +} + +double **allocMatrix( int r,int c ){ + double **ret; + + ret = calloc( sizeof( double ), (size_t)( r * c ) ); + return ret; +} + +void freeMatrix( double **ret,int r ){ + free( ret ); +} + +void svdcmp( double** a, int m, int n, double* w, double** v ){ + int flag,i,its,j,jj,k,l,nm; + double c,f,h,s,x,y,z; + double anorm = 0.0,g = 0.0,scale = 0.0; + double *rv1; + void nrerror(); + + if ( m < n ) { + ntrerror( "SVDCMP: You must augment A with extra zero rows" ); + } + rv1 = allocVect( n ); + for ( i = 1; i <= n; i++ ) { + l = i + 1; + rv1[i] = scale * g; + g = s = scale = 0.0; + if ( i <= m ) { + for ( k = i; k <= m; k++ ) scale += fabs( a[k][i] ); + if ( scale ) { + for ( k = i; k <= m; k++ ) { + a[k][i] /= scale; + s += a[k][i] * a[k][i]; + } + f = a[i][i]; + g = -SIGN( sqrt( s ),f ); + h = f * g - s; + a[i][i] = f - g; + if ( i != n ) { + for ( j = l; j <= n; j++ ) { + for ( s = 0.0,k = i; k <= m; k++ ) s += a[k][i] * a[k][j]; + f = s / h; + for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i]; + } + } + for ( k = i; k <= m; k++ ) a[k][i] *= scale; + } + } + w[i] = scale * g; + g = s = scale = 0.0; + if ( i <= m && i != n ) { + for ( k = l; k <= n; k++ ) scale += fabs( a[i][k] ); + if ( scale ) { + for ( k = l; k <= n; k++ ) { + a[i][k] /= scale; + s += a[i][k] * a[i][k]; + } + f = a[i][l]; + g = -SIGN( sqrt( s ),f ); + h = f * g - s; + a[i][l] = f - g; + for ( k = l; k <= n; k++ ) rv1[k] = a[i][k] / h; + if ( i != m ) { + for ( j = l; j <= m; j++ ) { + for ( s = 0.0,k = l; k <= n; k++ ) s += a[j][k] * a[i][k]; + for ( k = l; k <= n; k++ ) a[j][k] += s * rv1[k]; + } + } + for ( k = l; k <= n; k++ ) a[i][k] *= scale; + } + } + anorm = MAX( anorm,( fabs( w[i] ) + fabs( rv1[i] ) ) ); + } + for ( i = n; i >= 1; i-- ) { + if ( i < n ) { + if ( g ) { + for ( j = l; j <= n; j++ ) + v[j][i] = ( a[i][j] / a[i][l] ) / g; + for ( j = l; j <= n; j++ ) { + for ( s = 0.0,k = l; k <= n; k++ ) s += a[i][k] * v[k][j]; + for ( k = l; k <= n; k++ ) v[k][j] += s * v[k][i]; + } + } + for ( j = l; j <= n; j++ ) v[i][j] = v[j][i] = 0.0; + } + v[i][i] = 1.0; + g = rv1[i]; + l = i; + } + for ( i = n; i >= 1; i-- ) { + l = i + 1; + g = w[i]; + if ( i < n ) { + for ( j = l; j <= n; j++ ) a[i][j] = 0.0; + } + if ( g ) { + g = 1.0 / g; + if ( i != n ) { + for ( j = l; j <= n; j++ ) { + for ( s = 0.0,k = l; k <= m; k++ ) s += a[k][i] * a[k][j]; + f = ( s / a[i][i] ) * g; + for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i]; + } + } + for ( j = i; j <= m; j++ ) a[j][i] *= g; + } + else { + for ( j = i; j <= m; j++ ) a[j][i] = 0.0; + } + ++a[i][i]; + } + for ( k = n; k >= 1; k-- ) { + for ( its = 1; its <= 30; its++ ) { + flag = 1; + for ( l = k; l >= 1; l-- ) { + nm = l - 1; + if ( fabs( rv1[l] ) + anorm == anorm ) { + flag = 0; + break; + } + if ( fabs( w[nm] ) + anorm == anorm ) { + break; + } + } + if ( flag ) { + c = 0.0; + s = 1.0; + for ( i = l; i <= k; i++ ) { + f = s * rv1[i]; + if ( fabs( f ) + anorm != anorm ) { + g = w[i]; + h = PYTHAG( f,g ); + w[i] = h; + h = 1.0 / h; + c = g * h; + s = ( -f * h ); + for ( j = 1; j <= m; j++ ) { + y = a[j][nm]; + z = a[j][i]; + a[j][nm] = y * c + z * s; + a[j][i] = z * c - y * s; + } + } + } + } + z = w[k]; + if ( l == k ) { + if ( z < 0.0 ) { + w[k] = -z; + for ( j = 1; j <= n; j++ ) v[j][k] = ( -v[j][k] ); + } + break; + } + if ( its == 30 ) { + ntrerror( "No convergence in 30 SVDCMP iterations" ); + } + x = w[l]; + nm = k - 1; + y = w[nm]; + g = rv1[nm]; + h = rv1[k]; + f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0 * h * y ); + g = PYTHAG( f,1.0 ); + f = ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + SIGN( g,f ) ) ) - h ) ) / x; + c = s = 1.0; + for ( j = l; j <= nm; j++ ) { + i = j + 1; + g = rv1[i]; + y = w[i]; + h = s * g; + g = c * g; + z = PYTHAG( f,h ); + rv1[j] = z; + c = f / z; + s = h / z; + f = x * c + g * s; + g = g * c - x * s; + h = y * s; + y = y * c; + for ( jj = 1; jj <= n; jj++ ) { + x = v[jj][j]; + z = v[jj][i]; + v[jj][j] = x * c + z * s; + v[jj][i] = z * c - x * s; + } + z = PYTHAG( f,h ); + w[j] = z; + if ( z ) { + z = 1.0 / z; + c = f * z; + s = h * z; + } + f = ( c * g ) + ( s * y ); + x = ( c * y ) - ( s * g ); + for ( jj = 1; jj <= m; jj++ ) { + y = a[jj][j]; + z = a[jj][i]; + a[jj][j] = y * c + z * s; + a[jj][i] = z * c - y * s; + } + } + rv1[l] = 0.0; + rv1[k] = f; + w[k] = x; + } + } + freeVect( rv1 ); +} + + + +void svbksb( double** u, double* w, double** v,int m, int n, double* b, double* x ){ + int jj,j,i; + double s,*tmp; + tmp = allocVect( n ); + for ( j = 1; j <= n; j++ ) + { + s = 0.0; + if ( w[j] ) { + for ( i = 1; i <= m; i++ ) + s += u[i][j] * b[i]; + s /= w[j]; + } + tmp[j] = s; + } + for ( j = 1; j <= n; j++ ) + { + s = 0.0; + for ( jj = 1; jj <= n; jj++ ) + s += v[j][jj] * tmp[jj]; + x[j] = s; + } + freeVect( tmp ); +} + +#undef SIGN +#undef MAX +#undef PYTHAG + + +#if 1 +void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){ + int usedfs; + int *remap; + int i,j; + double **da; + double **v; + double *w; + int DOFerr; + float mx; + int bestat; + + if ( nframes > framesize ) { + usedfs = nframes; + } + else{ + usedfs = framesize; + } + + da = allocMatrix( usedfs,nframes ); + v = allocMatrix( nframes,nframes ); + w = allocVect( nframes ); + + DOFerr = 0; //false + for ( i = 0; i < nframes; i++ ) + { + for ( j = 0; j < framesize; j++ ) + da[j + 1][i + 1] = a[i * framesize + j]; + for (; j < usedfs; j++ ) + da[j + 1][i + 1] = 0.0; + } + + svdcmp( da,usedfs,nframes,w,v ); + + remap = calloc( sizeof( int ), (size_t)nframes ); + + + for ( i = 0; i < nframes; i++ ) + remap[i] = -1; + for ( j = 0; j < compressedsize; j++ ) + { + mx = -1.0f; + for ( i = 0; i < nframes; i++ ) + { + if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) { + mx = (float) fabs( w[i + 1] ); + bestat = i; + } + } + + if ( mx > 0 ) { + remap[bestat] = j; + } + else + { + DOFerr = 1; //true + } + } + + if ( DOFerr ) { + printf( "Warning: To many degrees of freedom! File size may increase\n" ); + + for ( i = 0; i < compressedsize; i++ ) + { + values[i] = 0; + for ( j = 0; j < framesize; j++ ) + res[i * framesize + j] = 0; + } + } + + for ( i = 0; i < nframes; i++ ) + { + if ( remap[i] < 0 ) { + w[i + 1] = 0.0; + } + else + { + values[remap[i]] = (float) w[i + 1]; + for ( j = 0; j < framesize; j++ ) + res[remap[i] * framesize + j] = (float) da[j + 1][i + 1]; + } + } + freeVect( w ); + freeMatrix( v,nframes ); + freeMatrix( da,framesize ); + free( remap ); +} + +#else + +void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){ + int *remap; + int i,j; + int nrows; + nrows = nframes; + if ( nrows < framesize ) { + nrows = framesize; + } + double **da = allocMatrix( nrows,framesize ); + double **v = allocMatrix( framesize,framesize ); + double *w = allocVect( framesize ); + float mx; + int bestat; + + for ( j = 0; j < framesize; j++ ) + { + for ( i = 0; i < nframes; i++ ) + da[j + 1][i + 1] = a[i * framesize + j]; + for (; i < nrows; i++ ) + da[j + 1][i + 1] = 0.0; + } + + svdcmp( da,nrows,framesize,w,v ); + + remap = new int[framesize]; + + + for ( i = 0; i < framesize; i++ ) + remap[i] = -1; + for ( j = 0; j < compressedsize; j++ ) + { + mx = -1.0f; + for ( i = 0; i < framesize; i++ ) + { + if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) { + mx = fabs( w[i + 1] ); + bestat = i; + } + } + assert( mx > -.5f ); + remap[bestat] = j; + } + // josh **DO NOT** put your dof>nframes mod here + for ( i = 0; i < framesize; i++ ) + { + if ( remap[i] < 0 ) { + w[i + 1] = 0.0; + } + else + { + values[remap[i]] = w[i + 1]; + for ( j = 0; j < framesize; j++ ) + res[remap[i] * framesize + j] = v[j + 1][i + 1]; + } + } + freeVect( w ); + freeMatrix( v,framesize ); + freeMatrix( da,nrows ); + delete[] remap; +} + +#endif + +void DOsvdPlane( float *pnts,int npnts,float *n,float *base ){ + int i,j; + double **da = allocMatrix( npnts,3 ); + double **v = allocMatrix( 3,3 ); + double *w = allocVect( 3 ); + float mn = 1E30f; + int bestat; + + + assert( npnts >= 3 ); + base[0] = pnts[0]; + base[1] = pnts[1]; + base[2] = pnts[2]; + for ( i = 1; i < npnts; i++ ) + { + for ( j = 0; j < 3; j++ ) + base[j] += pnts[i * 3 + j]; + } + base[0] /= (float)( npnts ); + base[1] /= (float)( npnts ); + base[2] /= (float)( npnts ); + + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < npnts; j++ ) + da[j + 1][i + 1] = pnts[j * 3 + i] - base[i]; + } + + svdcmp( da,npnts,3,w,v ); + for ( i = 0; i < 3; i++ ) + { + if ( fabs( w[i + 1] ) < mn ) { + mn = (float) fabs( w[i + 1] ); + bestat = i; + } + } + n[0] = (float) v[1][bestat + 1]; + n[1] = (float) v[2][bestat + 1]; + n[2] = (float) v[3][bestat + 1]; + freeVect( w ); + freeMatrix( v,3 ); + freeMatrix( da,npnts ); +} diff --git a/tools/heretic2/h2data/tables.c b/tools/heretic2/h2data/tables.c new file mode 100644 index 00000000..ad86c1ee --- /dev/null +++ b/tools/heretic2/h2data/tables.c @@ -0,0 +1,164 @@ +/* + Copyright (C) 1999-2007 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]; + + GetScriptToken( 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 ) ); +} diff --git a/tools/heretic2/h2data/tmix.c b/tools/heretic2/h2data/tmix.c new file mode 100644 index 00000000..936cd6e5 --- /dev/null +++ b/tools/heretic2/h2data/tmix.c @@ -0,0 +1,671 @@ +/* + Copyright (C) 1999-2007 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 "flex.h" + +#define MAXFILES 2048 + +#if !GDEF_OS_WINDOWS +#define strlwr strlower +#endif // !GDEF_OS_WINDOWS + +typedef struct +{ + int x; + int y; + int w; + int h; + int cw; + int ch; + int rw; + int index; + int depth; + int col; + int baseline; + char name[128]; +} Coords; + +int filenum; +int valid; +Coords in[MAXFILES]; +Coords out; +char outscript[256]; +char sourcedir[256]; +char outusage[256]; +char root[32]; + +int destsize = 0; +byte *pixels = NULL; // Buffer to load image +long *outpixels = NULL; // Buffer to store combined textures +long *usagemap = NULL; // Buffer of usage map +void *bmptemp = NULL; // Buffer of usage map +byte *map = NULL; + +int xcharsize; +int ycharsize; +int dosort = 0; +int missed = 0; +int overlap = 0; +int nobaseline = 0; +int percent; + +////////////////////////////////////////////////// +// Setting the char based usage map // +////////////////////////////////////////////////// + +byte TryPlace( Coords *coord ){ + int x, y; + byte entry = 0; + byte *mapitem; + + mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw ); + + for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw ) + { + for ( x = 0; x < coord->cw; x++ ) + { + if ( entry |= *mapitem++ & 8 ) { + return( entry ); + } + } + } + return( entry ); +} + +void SetMap( Coords *coord ){ + int x, y; + byte *mapitem; + + mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw ); + + for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw ) + for ( x = 0; x < coord->cw; x++ ) + *mapitem++ |= 8; +} + +////////////////////////////////////////////////// +// Setting the pixel based usage map // +////////////////////////////////////////////////// + +void CheckOverlap( Coords *coord ){ + int x; + int y; + long *dest; + + x = coord->x; + y = coord->y; + + dest = (long *)( usagemap + x + ( y * out.w ) ); + + for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) + { + for ( x = 0; x < coord->w; x++ ) + { + if ( *dest++ ) { + overlap++; + return; + } + } + } +} + +void SetUsageMap( Coords *coord ){ + int x; + int y; + long *dest; + + x = coord->x; + y = coord->y; + + dest = (long *)( usagemap + x + ( y * out.w ) ); + + for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) + { + for ( x = 0; x < coord->w; x++ ) + { + *dest++ = coord->col; + } + } +} + +////////////////////////////////////////////////// +// Flips the BMP image to the correct way up // +////////////////////////////////////////////////// + +void CopyLine( byte *dest, byte *src, int size ){ + int x; + + for ( x = 0; x < size; x++ ) + *dest++ = *src++; +} + +/****************************************************/ +/* Printing headers etc */ +/****************************************************/ + +void RemoveLeading( char *name ){ + int i; + char temp[128]; + + for ( i = strlen( name ) - 1; i > 0; i-- ) + { + if ( ( name[i] == '\\' ) || ( name[i] == '/' ) ) { + strcpy( temp, name + i + 1 ); + strcpy( name, temp ); + return; + } + } +} + +void RemoveExt( char *name ){ + while ( ( *name != '.' ) && *name ) + name++; + *name = 0; +} + +/****************************************************/ +/* Misc calcualtions */ +/****************************************************/ + +int TotalArea(){ + int i; + int total = 0; + + for ( i = 0; i < ( filenum + 2 ); i++ ) + total += in[i].w * in[i].h; + + return( total ); +} + +/****************************************************/ +/* Setup and checking of all info */ +/****************************************************/ + +void InitVars(){ + filenum = 0; + valid = 0; + dosort = 0; + missed = 0; + overlap = 0; + nobaseline = 0; + + memset( outscript, 0, sizeof( outscript ) ); + memset( outscript, 0, sizeof( sourcedir ) ); + memset( outscript, 0, sizeof( outusage ) ); + memset( outscript, 0, sizeof( root ) ); + + memset( in, 0, sizeof( in ) ); + memset( &out, 0, sizeof( out ) ); +} +void Cleanup(){ + if ( pixels ) { + free( pixels ); + } + if ( usagemap ) { + free( usagemap ); + } + if ( outpixels ) { + free( outpixels ); + } + if ( bmptemp ) { + free( bmptemp ); + } + if ( map ) { + free( map ); + } +} + +typedef struct glxy_s +{ + float xl, yt, xr, yb; + int w, h, baseline; +} glxy_t; + +int SaveScript( char *name ){ + FILE *fp; + int i, j; + glxy_t buff; + + if ( fp = fopen( name, "wb" ) ) { + for ( j = 0; j < filenum; j++ ) + { + for ( i = 0; i < filenum; i++ ) + { + if ( in[i].index == j ) { + if ( in[i].depth ) { + buff.xl = (float)in[i].x / (float)out.w; + buff.yt = (float)in[i].y / (float)out.h; + buff.xr = ( (float)in[i].w + (float)in[i].x ) / (float)out.w; + buff.yb = ( (float)in[i].h + (float)in[i].y ) / (float)out.h; + buff.w = in[i].w; + buff.h = in[i].h; + buff.baseline = in[i].baseline; + } + else + { + memset( &buff, 0, sizeof( glxy_t ) ); + } + fwrite( &buff, 1, sizeof( glxy_t ), fp ); + i = filenum; + } + } + } + fclose( fp ); + return( true ); + } + else{ + return( false ); + } +} + +int GetScriptInfo( char *name ){ + FILE *fp; + char buffer[256]; + char tempbuff[256]; + char delims[] = {" \t,\n"}; + + printf( "Opening script file %s.\n", name ); + + if ( fp = fopen( name, "r" ) ) { + while ( fgets( buffer, 256, fp ) ) + { + if ( strncmp( buffer, "//", 2 ) && strncmp( buffer, "\n", 1 ) ) { + strupr( buffer ); + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "OUTPUT" ) == 0 ) { + strcpy( out.name, strtok( NULL, delims ) ); + strlwr( out.name ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "SOURCEDIR" ) == 0 ) { + strcpy( tempbuff, strtok( NULL, delims ) ); + strcpy( sourcedir, ExpandPathAndArchive( tempbuff ) ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "DOSORT" ) == 0 ) { + dosort = 1; + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "XCHARSIZE" ) == 0 ) { + xcharsize = strtol( strtok( NULL, delims ), NULL, 0 ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "YCHARSIZE" ) == 0 ) { + ycharsize = strtol( strtok( NULL, delims ), NULL, 0 ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "OUTSCRIPT" ) == 0 ) { + strcpy( outscript, strtok( NULL, delims ) ); + strlwr( outscript ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "OUTUSAGE" ) == 0 ) { + strcpy( outusage, strtok( NULL, delims ) ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "POS" ) == 0 ) { + out.w = strtol( strtok( NULL, delims ), NULL, 0 ); + out.h = strtol( strtok( NULL, delims ), NULL, 0 ); + } + + strcpy( tempbuff, buffer ); + if ( strcmp( strtok( tempbuff, delims ), "FILE" ) == 0 ) { + strcpy( in[filenum].name, strtok( NULL, delims ) ); + in[filenum].x = strtol( strtok( NULL, delims ), NULL, 0 ); + in[filenum].y = strtol( strtok( NULL, delims ), NULL, 0 ); + in[filenum].col = strtol( strtok( NULL, delims ), NULL, 0 ); + filenum++; + } + } + } + fclose( fp ); + return( true ); + } + else + { + printf( "ERROR : Could not open script file.\n" ); + return( false ); + } +} + +int CheckVars(){ + int i; + + if ( out.name[0] == 0 ) { + printf( "ERROR : No output name specified.\n" ); + return( false ); + } + if ( ( out.w <= 0 ) || ( out.h <= 0 ) ) { + printf( "ERROR : Invalid VRAM coordinates.\n" ); + return( false ); + } + if ( filenum == 0 ) { + printf( "ERROR : No input files specified.\n" ); + return( false ); + } + for ( i = 0; i < filenum; i++ ) + if ( in[i].name[0] == 0 ) { + printf( "ERROR : Input filename invalid.\n" ); + return( false ); + } + return( true ); +} + +// Makes sure texture is totally within the output area + +int CheckCoords( Coords *coord ){ + if ( ( coord->x + coord->w ) > out.w ) { + return( false ); + } + if ( ( coord->y + coord->h ) > out.h ) { + return( false ); + } + + return( true ); +} +// Gets the width, height, palette width and palette height of each BMP file + +int GetFileDimensions(){ + int i; + int width, height; + char name[128]; + + for ( i = 0; i < filenum; i++ ) + { + in[i].index = i; + + strcpy( name, sourcedir ); + strcat( name, in[i].name ); + printf( "Getting file dimensions, file : %s \r", in[i].name ); + if ( FileExists( name ) ) { + LoadAnyImage( name, NULL, NULL, &width, &height ); + in[i].depth = 32; + in[i].rw = width; + in[i].w = width; // makes it width in + in[i].h = height; + in[i].cw = ( in[i].w + ( xcharsize - 1 ) ) / xcharsize; + in[i].ch = ( in[i].h + ( ycharsize - 1 ) ) / ycharsize; + + if ( !CheckCoords( &in[i] ) && ( in[i].x >= 0 ) ) { + printf( "Error : texture %s out of bounds.\n", in[i].name ); + return( false ); + } + valid++; + } + else + { + in[i].depth = 0; + in[i].x = -1; + in[i].y = -1; + in[i].w = 0; + in[i].h = 0; + } + } + printf( "\n\n" ); + return( true ); +} + +// Sorts files into order for optimal space finding +// Fixed position ones first, followed by the others in descending size +// The theory being that it is easier to find space for smaller textures. +// size = (width + height) +// For space finding it is easier to place a 32x32 than a 128x2 + +#define WEIGHT 0x8000 + +void Swap( Coords *a, Coords *b ){ + Coords c; + + c = *a; + *a = *b; + *b = c; +} + +void SortInNames(){ + int i, j; + int largest, largcount; + int size; + + printf( "Sorting filenames by size.\n\n" ); + + for ( j = 0; j < filenum; j++ ) + { + largest = -1; + largcount = -1; + + for ( i = j; i < filenum; i++ ) + { + if ( in[i].depth ) { + size = in[i].w + in[i].h; + + if ( ( in[i].x < 0 ) && ( size > largest ) ) { + largcount = i; + largest = size; + } + } + } + if ( ( largcount >= 0 ) && ( largcount != j ) ) { + Swap( &in[j], &in[largcount] ); + } + } +} + +int SetVars( char *name ){ + if ( !GetScriptInfo( name ) ) { + return( false ); + } + + if ( !CheckVars() ) { + return( false ); + } + + destsize = out.w * out.h; + + out.cw = out.w / xcharsize; + out.ch = out.h / ycharsize; + + if ( ( usagemap = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { + return( false ); + } + if ( ( outpixels = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { + return( false ); + } + if ( ( bmptemp = (void *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { + return( false ); + } + if ( ( map = (byte *)SafeMalloc( destsize / ( xcharsize * ycharsize ), "" ) ) == NULL ) { + return( false ); + } + + if ( GetFileDimensions() == false ) { + return( false ); + } + + if ( dosort ) { + SortInNames(); + } + + return( true ); +} +/****************************************************/ +/* Actual copying routines */ +/****************************************************/ + +int FindCoords( Coords *coord ){ + int tx, ty; + + if ( coord->x >= 0 ) { + SetMap( coord ); + return( true ); + } + else + { + for ( ty = 0; ty < out.ch; ty++ ) + { + for ( tx = 0; tx < out.cw; tx++ ) + { + coord->x = ( tx * xcharsize ); + coord->y = ( ty * ycharsize ); + + if ( CheckCoords( coord ) && !TryPlace( coord ) ) { + SetMap( coord ); + return( true ); + } + } + } + } + coord->x = -1; + coord->y = -1; + + return( false ); +} + +void CheckBaseline( int i ){ + int y; + long *pix; + + in[i].baseline = -1; + pix = (long *)pixels; + + for ( y = 0; y < in[i].h; y++, pix += in[i].w ) + { + if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) { + in[i].baseline = y; + break; + } + } + pix = (long *)pixels; + for ( y = 0; y < in[i].w * in[i].h; y++, pix++ ) + { + if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) { + *pix = 0; + } + } + + if ( in[i].baseline == -1 ) { + printf( "\nERROR : %s has no baseline\n", in[i].name ); + nobaseline++; + } +} + +void CopyToMain32( Coords *coord ){ + int x; + int y; + long *source; + long *dest; + + x = coord->x; + y = coord->y; + + source = (long *)pixels; + dest = (long *)( outpixels + x + ( y * out.w ) ); + + for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) + { + for ( x = 0; x < coord->w; x++ ) + { + *dest++ = *source++; + } + } +} + +void CreateMain(){ + int i, count; + int width, height; + char name[128]; + + for ( i = 0, count = 0; i < filenum; i++ ) + { + if ( in[i].depth ) { + printf( "\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline ); + count++; + if ( !FindCoords( &in[i] ) ) { + missed++; + } + else + { + strcpy( name, sourcedir ); + strcat( name, in[i].name ); + LoadAnyImage( name, &pixels, NULL, &width, &height ); + CheckBaseline( i ); + CheckOverlap( &in[i] ); + CopyToMain32( &in[i] ); + SetUsageMap( &in[i] ); + } + } + } +} + +void Cmd_TextureMix(){ + miptex32_t *qtex32; + char filename[1024]; + int size; + + InitVars(); + + GetScriptToken( false ); + + strcpy( root, token ); + RemoveExt( root ); + RemoveLeading( root ); + + strcpy( filename, ExpandPathAndArchive( token ) ); + if ( SetVars( filename ) ) { + // Create combined texture + percent = ( ( TotalArea() * 100 ) / ( out.w * out.h ) ); + printf( "Total area consumed : %d%%\n", percent ); + printf( "Texture resolution : %dx%d pixels.\n", xcharsize, ycharsize ); + CreateMain(); + + // Save image as m32 + sprintf( filename, "%spics/misc/%s.m32", gamedir, out.name ); + qtex32 = CreateMip32( (unsigned *)outpixels, out.w, out.h, &size, false ); + + qtex32->contents = 0; + qtex32->value = 0; + qtex32->scale_x = 1.0; + qtex32->scale_y = 1.0; + sprintf( qtex32->name, "misc/%s", out.name ); + + printf( "\n\nwriting %s\n", filename ); + SaveFile( filename, (byte *)qtex32, size ); + free( qtex32 ); + + // Save out script file + sprintf( filename, "%spics/misc/%s.fnt", gamedir, outscript ); + printf( "Writing %s as script file\n", filename ); + if ( !SaveScript( filename ) ) { + printf( "Unable to save output script.\n" ); + } + } + printf( "Everythings groovy.\n" ); + Cleanup(); +} + +// end diff --git a/tools/heretic2/h2data/video.c b/tools/heretic2/h2data/video.c new file mode 100644 index 00000000..51bf4620 --- /dev/null +++ b/tools/heretic2/h2data/video.c @@ -0,0 +1,1154 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// To do + +// Sound error handling (when sound too short) +// rle b4 huffing +// adpcm encoding of sound + +#if 0 +#include "qdata.h" +#include "flex.h" +#include "fc.h" +#include "adpcm.h" + +#define MIN_REPT 15 +#define MAX_REPT 0 +#define HUF_TOKENS ( 256 + MAX_REPT ) + +#define BLOCKSIZE 8 + +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#define SQRT2 1.414213562 + +typedef struct hnode_s +{ + int count; + qboolean used; + int children[2]; +} hnode_t; + +typedef struct +{ + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start +} wavinfo_t; + +// These weren`t picked out my ass.... +// They were defined at http://www.rahul.net/jfm/dct.html +// However, I think he plucked them out of his ass..... + +float Quantise[BLOCKSIZE * BLOCKSIZE]; + +float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] = +{ + 16.0F / 16.0F, 11.0F / 16.0F, 10.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 51.0F / 16.0F, 61.0F / 16.0F, + 12.0F / 16.0F, 13.0F / 16.0F, 14.0F / 16.0F, 19.0F / 16.0F, 26.0F / 16.0F, 58.0F / 16.0F, 60.0F / 16.0F, 55.0F / 16.0F, + 14.0F / 16.0F, 13.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 57.0F / 16.0F, 69.0F / 16.0F, 56.0F / 16.0F, + 14.0F / 16.0F, 17.0F / 16.0F, 22.0F / 16.0F, 29.0F / 16.0F, 51.0F / 16.0F, 87.0F / 16.0F, 80.0F / 16.0F, 62.0F / 16.0F, + 18.0F / 16.0F, 22.0F / 16.0F, 37.0F / 16.0F, 56.0F / 16.0F, 68.0F / 16.0F,109.0F / 16.0F,103.0F / 16.0F, 77.0F / 16.0F, + 24.0F / 16.0F, 35.0F / 16.0F, 55.0F / 16.0F, 64.0F / 16.0F, 81.0F / 16.0F,104.0F / 16.0F,113.0F / 16.0F, 92.0F / 16.0F, + 49.0F / 16.0F, 64.0F / 16.0F, 78.0F / 16.0F, 87.0F / 16.0F,103.0F / 16.0F,121.0F / 16.0F,120.0F / 16.0F,101.0F / 16.0F, + 72.0F / 16.0F, 92.0F / 16.0F, 95.0F / 16.0F, 98.0F / 16.0F,112.0F / 16.0F,100.0F / 16.0F,103.0F / 16.0F, 99.0F / 16.0F +}; + +int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] = +{ + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 +}; + +char base[32]; + +byte *soundtrack; + +byte scaled[256][HUF_TOKENS]; +unsigned int charbits1[256][HUF_TOKENS]; +int charbitscount1[256][HUF_TOKENS]; +hnode_t hnodes1[256][HUF_TOKENS * 2]; +int numhnodes1[256]; +int order0counts[256]; +int numhnodes; +hnode_t hnodes[512]; +unsigned charbits[256]; +int charbitscount[256]; + +CineHead_t cinehead; + +byte *data_p; +byte *iff_end; +byte *last_chunk; +byte *iff_data; +int iff_chunk_len; + +float dctbase[BLOCKSIZE][BLOCKSIZE]; +float red[BLOCKSIZE * BLOCKSIZE]; +float green[BLOCKSIZE * BLOCKSIZE]; +float blue[BLOCKSIZE * BLOCKSIZE]; +float temp[BLOCKSIZE * BLOCKSIZE]; + +wavinfo_t wavinfo; +adpcm_t adpcm; + +/* + =============================================================================== + + WAV loading + + =============================================================================== + */ + +/* Intel ADPCM step variation table */ +static int indexTable[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8, +}; + +static int stepsizeTable[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + +#if 0 +static void adpcm_decoder( char *indata, short *outdata, int len, adpcm_state_t *state ){ + signed char *inp; /* Input buffer pointer */ + short *outp; /* output buffer pointer */ + int sign; /* Current adpcm sign bit */ + int delta; /* Current adpcm output value */ + int step; /* Stepsize */ + int valpred; /* Predicted value */ + int vpdiff; /* Current change to valpred */ + int index; /* Current step change index */ + int inputbuffer; /* place to keep next 4-bit value */ + int bufferstep; /* toggle between inputbuffer/input */ + + outp = outdata; + inp = (signed char *)indata; + + valpred = state->valprev; + index = state->index; + step = stepsizeTable[index]; + + bufferstep = 0; + + for (; len > 0; len-- ) + { + /* Step 1 - get the delta value */ + if ( bufferstep ) { + delta = inputbuffer & 0xf; + } + else + { + inputbuffer = *inp++; + delta = ( inputbuffer >> 4 ) & 0xf; + } + bufferstep = !bufferstep; + + /* Step 2 - Find new index value (for later) */ + index += indexTable[delta]; + if ( index < 0 ) { + index = 0; + } + if ( index > 88 ) { + index = 88; + } + + /* Step 3 - Separate sign and magnitude */ + sign = delta & 8; + delta = delta & 7; + + /* Step 4 - Compute difference and new predicted value */ + /* + ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment + ** in adpcm_coder. + */ + vpdiff = step >> 3; + if ( delta & 4 ) { + vpdiff += step; + } + if ( delta & 2 ) { + vpdiff += step >> 1; + } + if ( delta & 1 ) { + vpdiff += step >> 2; + } + + if ( sign ) { + valpred -= vpdiff; + } + else{ + valpred += vpdiff; + } + + /* Step 5 - clamp output value */ + if ( valpred > 32767 ) { + valpred = 32767; + } + else if ( valpred < -32768 ) { + valpred = -32768; + } + + /* Step 6 - Update step value */ + step = stepsizeTable[index]; + + /* Step 7 - Output value */ + *outp++ = valpred; + } + + state->valprev = valpred; + state->index = index; +} +#endif + +void adpcm_coder( short *inp, adpcm_t *adpcm ){ + int val; /* Current input sample value */ + int sign; /* Current adpcm sign bit */ + int delta; /* Current adpcm output value */ + int diff; /* Difference between val and valprev */ + int step; /* Stepsize */ + int valpred; /* Predicted output value */ + int vpdiff; /* Current change to valpred */ + int index; /* Current step change index */ + int outputbuffer; /* place to keep previous 4-bit value */ + int bufferstep; /* toggle between outputbuffer/output */ + adpcm_state_t *state; + char *outp; + int len; + + state = &adpcm->state; + len = state->count; + outp = adpcm->adpcm; + + valpred = state->in_valprev; + index = state->in_index; + step = stepsizeTable[index]; + + bufferstep = 1; + while ( len-- ) + { + val = *inp++; + + /* Step 1 - compute difference with previous value */ + diff = val - valpred; + sign = ( diff < 0 ) ? 8 : 0; + if ( sign ) { + diff = -diff; + } + + /* Step 2 - Divide and clamp */ + /* Note: + ** This code *approximately* computes: + ** delta = diff*4/step; + ** vpdiff = (delta+0.5)*step/4; + ** but in shift step bits are dropped. The net result of this is + ** that even if you have fast mul/div hardware you cannot put it to + ** good use since the fixup would be too expensive. + */ + delta = 0; + vpdiff = ( step >> 3 ); + + if ( diff >= step ) { + delta = 4; + diff -= step; + vpdiff += step; + } + step >>= 1; + if ( diff >= step ) { + delta |= 2; + diff -= step; + vpdiff += step; + } + step >>= 1; + if ( diff >= step ) { + delta |= 1; + vpdiff += step; + } + + /* Step 3 - Update previous value */ + if ( sign ) { + valpred -= vpdiff; + } + else{ + valpred += vpdiff; + } + + /* Step 4 - Clamp previous value to 16 bits */ + if ( valpred > 32767 ) { + valpred = 32767; + } + else if ( valpred < -32768 ) { + valpred = -32768; + } + + /* Step 5 - Assemble value, update index and step values */ + delta |= sign; + + index += indexTable[delta]; + if ( index < 0 ) { + index = 0; + } + if ( index > 88 ) { + index = 88; + } + step = stepsizeTable[index]; + + /* Step 6 - Output value */ + if ( bufferstep ) { + outputbuffer = ( delta << 4 ) & 0xf0; + } + else{ + *outp++ = ( delta & 0x0f ) | outputbuffer; + } + + bufferstep = !bufferstep; + } + + /* Output last step, if needed */ + if ( !bufferstep ) { + *outp++ = outputbuffer; + } + + state->out_valprev = valpred; + state->out_index = index; +} + +void FindNextChunk( char *name ){ + while ( 1 ) + { + data_p = last_chunk; + + if ( data_p >= iff_end ) { // didn't find the chunk + data_p = NULL; + return; + } + + data_p += 4; + iff_chunk_len = *(long *)data_p; + data_p += 4; + if ( iff_chunk_len < 0 ) { + data_p = NULL; + return; + } + + data_p -= 8; + last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 ); + if ( !strncmp( data_p, name, 4 ) ) { + return; + } + } +} + +void FindChunk( char *name ){ + last_chunk = iff_data; + FindNextChunk( name ); +} + +void DumpChunks( void ){ + char str[5]; + + str[4] = 0; + data_p = iff_data; + do + { + memcpy( str, data_p, 4 ); + data_p += 4; + iff_chunk_len = *(long *)data_p; + data_p += 4; + printf( "0x%x : %s (%d)\n", (int)( data_p - 4 ), str, iff_chunk_len ); + data_p += ( iff_chunk_len + 1 ) & ~1; + } + while ( data_p < iff_end ); +} + +/* + ============ + GetWavinfo + ============ + */ +wavinfo_t GetWavinfo( char *name, byte *wav, int wavlength ){ + wavinfo_t info; + int i; + int format; + int samples; + + memset( &info, 0, sizeof( info ) ); + + if ( !wav ) { + return( info ); + } + + iff_data = wav; + iff_end = wav + wavlength; + +// find "RIFF" chunk + FindChunk( "RIFF" ); + if ( !( data_p && !strncmp( data_p + 8, "WAVE", 4 ) ) ) { + printf( "Missing RIFF/WAVE chunks\n" ); + return( info ); + } + +// get "fmt " chunk + iff_data = data_p + 12; + + FindChunk( "fmt " ); + if ( !data_p ) { + printf( "Missing fmt chunk\n" ); + return( info ); + } + data_p += 8; + format = *(short *)data_p; + data_p += 2; + if ( format != 1 ) { + printf( "Microsoft PCM format only\n" ); + return( info ); + } + + info.channels = *(short *)data_p; + data_p += 2; + info.rate = *(long *)data_p; + data_p += 4; + data_p += 6; + info.width = *(short *)data_p / 8; + data_p += 2; + +// get cue chunk + FindChunk( "cue " ); + if ( data_p ) { + data_p += 32; + info.loopstart = *(long *)data_p; + data_p += 4; + +// if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk( "LIST" ); + if ( data_p ) { +// this is not a proper parse, but it works with cooledit... + if ( !strncmp( data_p + 28, "mark", 4 ) ) { + data_p += 24; + i = *(long *)data_p; // samples in loop + data_p += 4; + info.samples = info.loopstart + i; + } + } + } + else{ + info.loopstart = -1; + } + +// find data chunk + FindChunk( "data" ); + if ( !data_p ) { + printf( "Missing data chunk\n" ); + return( info ); + } + + data_p += 4; + samples = *(long *)data_p; + data_p += 4; + + if ( info.samples ) { + if ( samples < info.samples ) { + Error( "Sound %s has a bad loop length", name ); + } + } + else{ + info.samples = samples; + } + + info.dataofs = data_p - wav; + return( info ); +} + +// ============== +// LoadSoundtrack +// ============== + +void LoadSoundtrack(){ + char name[1024]; + FILE *f; + int len; + + soundtrack = NULL; + sprintf( name, "%svideo/%s/%s.wav", gamedir, base, base ); + printf( "\nLoading sound : %s\n", name ); + f = fopen( name, "rb" ); + if ( !f ) { + printf( "\nNo soundtrack for %s\n", base ); + return; + } + len = Q_filelength( f ); + soundtrack = SafeMalloc( len, "LoadSoundtrack" ); + fread( soundtrack, 1, len, f ); + fclose( f ); + + wavinfo = GetWavinfo( name, soundtrack, len ); + adpcm.state.out_valprev = 0; + adpcm.state.out_index = 0; +} + +// ================== +// WriteSound +// ================== + +int WriteSound( FILE *output, int frame, int numframes ){ + int start, end; + int count; + int empty = 0; + int width; + char *work; + + width = wavinfo.width * wavinfo.channels; + start = ( ( frame * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0; // start sample + end = ( ( ( frame + numframes ) * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0; // end sample + count = end - start; + + work = soundtrack + wavinfo.dataofs + ( start * width ); + adpcm.state.count = count * wavinfo.channels; // Number of samples + adpcm.state.in_valprev = adpcm.state.out_valprev; + adpcm.state.in_index = adpcm.state.out_index; + adpcm_coder( (short *)work, &adpcm ); + WriteHeader( output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, ( adpcm.state.count / 2 ) + sizeof( adpcm_state_t ), (char *)&adpcm ); + return( count / 2 ); +} +// ============================== +// Basic run length encoder +// ============================== + +char *RLEZZ( char *in, char *out ){ + int srun; + char count; + int idx = 0; + + while ( idx < 64 ) + { + srun = idx; // Start of run + + while ( idx < 63 ) + { + if ( in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]] ) { + break; + } + idx++; + } + count = (char)( idx - srun ); // count of repeated bytes + + if ( !count ) { + while ( idx < 63 ) + { + if ( in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]] ) { + break; + } + idx++; + } + if ( idx == 63 ) { + idx++; + } + + count = (char)( idx - srun ); // count of unique bytes + *out++ = count; + while ( count-- ) + *out++ = in[LUT_ZZ[srun++]]; + } + else + { + *out++ = -( count + 1 ); + *out++ = in[LUT_ZZ[idx]]; + idx++; + } + } + return( out ); +} + +// ============================== +// Discrete Cosine Transformation +// ============================== + +void init_base( float quant ){ + int y, x; + + for ( y = 0; y < BLOCKSIZE; y++ ) + for ( x = 0; x < BLOCKSIZE; x++ ) + { + if ( y == 0 ) { + dctbase[y][x] = 1; + } + else{ + dctbase[y][x] = SQRT2 * cos( ( ( x * 2 + 1 ) * y * M_PI ) / ( BLOCKSIZE * 2 ) ); + } + } + + for ( y = 0; y < BLOCKSIZE * BLOCKSIZE; y++ ) + Quantise[y] = LUT_Quantise[y] / quant; +} + +void SplitComponents( byte *src, int width, int height ){ + int i, j; + float *tr = red; + float *tg = green; + float *tb = blue; + + for ( i = 0; i < BLOCKSIZE; i++, src += ( width - BLOCKSIZE ) * 4 ) + for ( j = 0; j < BLOCKSIZE; j++ ) + { + *tr++ = ( (float)*src++ ) - 128.0F; + *tg++ = ( (float)*src++ ) - 128.0F; + *tb++ = ( (float)*src++ ) - 128.0F; + src++; + } +} + +void transferH( float *src, float *dst ){ + int y, dx, dy; + float sum; + float *work; + + for ( y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE ) + { + for ( dy = 0; dy < BLOCKSIZE; dy++ ) + { + sum = 0; + work = src; + for ( dx = 0; dx < BLOCKSIZE; dx++, work++ ) + sum += dctbase[dy][dx] * *work; + + *dst++ = sum / BLOCKSIZE; + } + } +} + +void transferV( float *src, float *dst ){ + int x, dy, fy; + float sum; + float *work; + + for ( x = 0; x < BLOCKSIZE; x++, src++, dst++ ) + { + for ( fy = 0; fy < BLOCKSIZE; fy++ ) + { + sum = 0; + work = src; + for ( dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE ) + sum += dctbase[fy][dy] * *work; + + dst[fy * BLOCKSIZE] = sum / BLOCKSIZE; + } + } +} + +char *Combine( byte *dst, float *p, float *q ){ + int i, j; + byte rlesrc[BLOCKSIZE * BLOCKSIZE]; + int c; + byte *work; + + work = rlesrc; + for ( j = 0; j < BLOCKSIZE; j++ ) + for ( i = 0; i < BLOCKSIZE; i++ ) + { + c = (int)( ( *p++ / *q++ ) + 128.5F ); + c -= 128; + + if ( c < -128 ) { + c = -128; + } + if ( c > 127 ) { + c = 127; + } + + *work++ = (char)c; + } + + dst = RLEZZ( rlesrc, dst ); + return( dst ); +} + +char *CombineComponents( char *dst, int width, int height ){ + dst = Combine( dst, red, Quantise ); + dst = Combine( dst, green, Quantise ); + dst = Combine( dst, blue, Quantise ); + return( dst ); +} + +void DCT( cblock_t *out, cblock_t in, int width, int height ){ + int x, y; + char *cursrc; + char *curdst; + + curdst = out->data; + for ( y = 0; y < height; y += BLOCKSIZE ) + for ( x = 0; x < width; x += BLOCKSIZE ) + { + cursrc = in.data + ( ( y * width ) + x ) * 4; + SplitComponents( cursrc, width, height ); + transferH( red, temp ); + transferV( temp, red ); + transferH( green, temp ); + transferV( temp, green ); + transferH( blue, temp ); + transferV( temp, blue ); + curdst = CombineComponents( curdst, width, height ); + } + out->count = curdst - out->data; +} + +// ================== +// BuildChars1 +// ================== + +void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){ + hnode_t *node; + + if ( nodenum < HUF_TOKENS ) { + if ( bitcount > 32 ) { + Error( "bitcount > 32" ); + } + charbits1[prev][nodenum] = bits; + charbitscount1[prev][nodenum] = bitcount; + return; + } + + node = &hnodes1[prev][nodenum]; + bits <<= 1; + BuildChars1( prev, node->children[0], bits, bitcount + 1 ); + bits |= 1; + BuildChars1( prev, node->children[1], bits, bitcount + 1 ); +} + +// ================== +// SmallestNode1 +// ================== + +int SmallestNode1( hnode_t *hnodes, int numhnodes ){ + int i; + int best, bestnode; + + best = 99999999; + bestnode = -1; + for ( i = 0; i < numhnodes; i++ ) + { + if ( hnodes[i].used ) { + continue; + } + if ( !hnodes[i].count ) { + continue; + } + if ( hnodes[i].count < best ) { + best = hnodes[i].count; + bestnode = i; + } + } + + if ( bestnode == -1 ) { + return( -1 ); + } + + hnodes[bestnode].used = true; + return( bestnode ); +} + +// ================== +// BuildTree1 +// ================== + +void BuildTree1( int prev ){ + hnode_t *node, *nodebase; + int numhnodes; + + // build the nodes + numhnodes = HUF_TOKENS; + nodebase = hnodes1[prev]; + while ( 1 ) + { + node = &nodebase[numhnodes]; + + // pick two lowest counts + node->children[0] = SmallestNode1( nodebase, numhnodes ); + if ( node->children[0] == -1 ) { + break; // no more + + } + node->children[1] = SmallestNode1( nodebase, numhnodes ); + if ( node->children[1] == -1 ) { + break; + } + + node->count = nodebase[node->children[0]].count + + nodebase[node->children[1]].count; + numhnodes++; + } + numhnodes1[prev] = numhnodes - 1; + BuildChars1( prev, numhnodes - 1, 0, 0 ); +} + +// ================== +// Huffman1_Count +// ================== + +void Huffman1_Count( cblock_t in ){ + int i; + int prev; + int v; + int rept; + + prev = 0; + for ( i = 0; i < in.count; i++ ) + { + v = in.data[i]; + order0counts[v]++; + hnodes1[prev][v].count++; + prev = v; + + for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ ) + if ( in.data[i + rept] != v ) { + break; + } + if ( rept > MIN_REPT ) { + hnodes1[prev][255 + rept].count++; + i += rept - 1; + } + } +} + +// ================== +// Huffman1_Build +// ================== + +void Huffman1_Build(){ + int i, j, v; + int max; + int total; + + for ( i = 0; i < 256; i++ ) + { +// normalize and save the counts + max = 0; + for ( j = 0; j < HUF_TOKENS; j++ ) + { + if ( hnodes1[i][j].count > max ) { + max = hnodes1[i][j].count; + } + } + if ( max == 0 ) { + max = 1; + } + total = 0; +// easy to overflow 32 bits here! + for ( j = 0; j < HUF_TOKENS; j++ ) + { + v = ( hnodes1[i][j].count * (double) 255 + max - 1 ) / max; + if ( v > 255 ) { + Error( "v > 255" ); + } + scaled[i][j] = hnodes1[i][j].count = v; + if ( v ) { + total++; + } + } + if ( total == 1 ) { // must have two tokens + if ( !scaled[i][0] ) { + scaled[i][0] = hnodes1[i][0].count = 1; + } + else{ + scaled[i][1] = hnodes1[i][1].count = 1; + } + } + BuildTree1( i ); + } +} + +// ================== +// Huffman1 +// Order 1 compression with pre-built table +// ================== + +cblock_t Huffman1( cblock_t in ){ + int i; + int outbits, c; + unsigned bits; + byte *out_p; + cblock_t out; + int prev; + int v; + int rept; + + out_p = out.data = SafeMalloc( ( in.count * 2 ) + 1024 + 4, "Huffman" ); + memset( out_p, 0, ( in.count * 2 ) + 1024 + 4 ); + + // leave space for compressed count + out_p += 4; + // write count + *(long *)out_p = in.count; + out_p += 4; + + // write bits + outbits = 0; + prev = 0; + for ( i = 0; i < in.count; i++ ) + { + v = in.data[i]; + + c = charbitscount1[prev][v]; + bits = charbits1[prev][v]; + if ( !c ) { + Error( "!bits" ); + } + while ( c ) + { + c--; + if ( bits & ( 1 << c ) ) { + out_p[outbits >> 3] |= 1 << ( outbits & 7 ); + } + outbits++; + } + + prev = v; + // check for repeat encodes + for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ ) + if ( in.data[i + rept] != v ) { + break; + } + if ( rept > MIN_REPT ) { + c = charbitscount1[prev][255 + rept]; + bits = charbits1[prev][255 + rept]; + if ( !c ) { + Error( "!bits" ); + } + while ( c ) + { + c--; + if ( bits & ( 1 << c ) ) { + out_p[outbits >> 3] |= 1 << ( outbits & 7 ); + } + outbits++; + } + i += rept - 1; + } + } + out_p += ( outbits + 7 ) >> 3; + out.count = out_p - out.data; + + out_p = out.data; + *(long *)out_p = out.count; + return( out ); +} +// =================== +// LoadFrame +// =================== + +void LoadFrame( cblock_t *out, char *base, int frame ){ + cblock_t in; + int width, height; + char name[1024]; + FILE *f; + + in.data = NULL; + in.count = -1; + sprintf( name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame ); + + f = fopen( name, "rb" ); + if ( !f ) { + out->data = NULL; + return; + } + fclose( f ); + + LoadTGA( name, &in.data, &width, &height ); + if ( ( width != cinehead.Width ) || ( height != cinehead.Height ) ) { + free( in.data ); + printf( "Invalid picture size\n" ); + out->data = NULL; + return; + } + out->data = SafeMalloc( width * height * 3, "LoadFrame" ); // rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression) + DCT( out, in, width, height ); + free( in.data ); +} + +// ================================== +// Cmd_Video +// +// video +// ================================== + +void Cmd_Video(){ + char savename[256]; + char name[256]; + FILE *output; + int frame; + int width, height; + cblock_t in, huffman; + int size; + float dctconst; + int maxsize, ssize; + int min_rle_size, warnings; + int ave_image, ave_sound; + + GetScriptToken( false ); + strcpy( base, token ); + if ( g_release ) { + return; + } + + GetScriptToken( false ); + dctconst = atof( token ); + GetScriptToken( false ); + maxsize = atoi( token ); + + sprintf( savename, "%svideo/%s.cin", gamedir, base ); + + // clear stuff + memset( charbits1, 0, sizeof( charbits1 ) ); + memset( charbitscount1, 0, sizeof( charbitscount1 ) ); + memset( hnodes1, 0, sizeof( hnodes1 ) ); + memset( numhnodes1, 0, sizeof( numhnodes1 ) ); + memset( order0counts, 0, sizeof( order0counts ) ); + + // load the entire sound wav file if present + LoadSoundtrack(); + + cinehead.SndRate = wavinfo.rate; + cinehead.SndWidth = wavinfo.width; + cinehead.SndChannels = wavinfo.channels; + + sprintf( name, "%svideo/%s/%s0000.tga", gamedir, base, base ); + printf( "Loading sequence : %s\n", name ); + printf( "DCT constant : %f\n", dctconst ); + + LoadTGA( name, NULL, &width, &height ); + + output = fopen( savename, "wb" ); + if ( !output ) { + Error( "Can't open %s", savename ); + } + + if ( ( width % BLOCKSIZE ) || ( height % BLOCKSIZE ) ) { + Error( "Width and height must be a multiple of %d", BLOCKSIZE ); + } + + cinehead.Width = width; + cinehead.Height = height; + init_base( dctconst ); + + // build the dictionary + printf( "Counting : " ); + min_rle_size = 0; + for ( frame = 0; ; frame++ ) + { + printf( "." ); + LoadFrame( &in, base, frame ); + if ( !in.data ) { + break; + } + Huffman1_Count( in ); + if ( in.count > min_rle_size ) { + min_rle_size = in.count; + } + free( in.data ); + } + printf( "\n" ); + cinehead.NumFrames = frame; + printf( "Num Frames : %d\n", frame ); + cinehead.MaxRleSize = ( min_rle_size + 0x1f ) & 0xfffffe0; + cinehead.MaxSndSize = ( ( 4 * wavinfo.rate * wavinfo.channels / 14 ) + 0x1f ) & 0xffffffe0; + + WriteHeader( output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof( CineHead_t ), &cinehead ); + + // build nodes and write counts + Huffman1_Build(); + WriteHeader( output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof( scaled ), scaled ); + WriteHeader( output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof( Quantise ), Quantise ); + + ave_image = 0; + ave_sound = 0; + warnings = 0; + // compress it with the dictionary + if ( soundtrack ) { + ssize = WriteSound( output, frame, 4 ); + ave_sound += ssize; + } + + for ( frame = 0; frame < cinehead.NumFrames; frame++ ) + { + // save some sound samples + printf( "Packing : ", frame ); + LoadFrame( &in, base, frame ); + + // save the image + huffman = Huffman1( in ); + printf( "%d bytes rle, %d bytes huffman", in.count, huffman.count ); + size = ( huffman.count + 3 ) & 0xfffffffc; // round up to longwords + if ( size > maxsize ) { + printf( " ** WARNING **" ); + warnings++; + } + printf( "\n" ); + ave_image += huffman.count; + + WriteHeader( output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data ); + if ( soundtrack ) { + ssize = WriteSound( output, frame + 4, 1 ); + ave_sound += ssize; + } + + free( in.data ); + free( huffman.data ); + } + printf( "\nTotal size: %d (headers + %d image + %d sound)\n", ftell( output ), ave_image, ave_sound ); + printf( "Data rate : %d bytes per sec (image and sound)\n", ( ave_image + ave_sound ) / cinehead.NumFrames ); + printf( "Cin created ok with %d warnings.\n", warnings ); + fclose( output ); + + if ( soundtrack ) { + free( soundtrack ); + } +} +#endif + +void Cmd_Video(){ +} + +// end diff --git a/tools/heretic2/qcommon/angles.h b/tools/heretic2/qcommon/angles.h new file mode 100644 index 00000000..b0baf314 --- /dev/null +++ b/tools/heretic2/qcommon/angles.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// Angles in radians + +#define ANGLE_0 0.0F +#define ANGLE_1 0.017453292F +#define ANGLE_5 0.087266462F +#define ANGLE_10 0.174532925F +#define ANGLE_15 0.261799387F +#define ANGLE_20 0.392699081F +#define ANGLE_30 0.523598775F +#define ANGLE_45 0.785398163F +#define ANGLE_60 1.047197551F +#define ANGLE_72 1.256637061F +#define ANGLE_90 1.570796327F +#define ANGLE_120 2.094395102F +#define ANGLE_135 2.35619449F +#define ANGLE_144 2.513274123F +#define ANGLE_180 3.141592653F +#define ANGLE_225 3.926990817F +#define ANGLE_270 4.71238898F +#define ANGLE_315 5.497787144F +#define ANGLE_360 6.283185307F + +// Angles in degrees + +#define DEGREE_0 0.0F +#define DEGREE_180 180.0F +#define DEGREE_45 ( DEGREE_180 / 4.0F ) +#define DEGREE_90 ( DEGREE_180 / 2.0F ) +#define DEGREE_135 ( DEGREE_90 + DEGREE_45 ) +#define DEGREE_270 ( DEGREE_180 + DEGREE_90 ) +#define DEGREE_360 ( DEGREE_180 * 2.0F ) + +#define DEGREE_225 ( DEGREE_180 + DEGREE_45 ) +#define DEGREE_315 ( DEGREE_270 + DEGREE_45 ) + +#define DEGREE_30 ( DEGREE_180 / 6.0F ) +#define DEGREE_60 ( DEGREE_180 / 3.0F ) +#define DEGREE_120 ( DEGREE_360 / 3.0F ) + +#define DEGREE_1 ( DEGREE_180 / 180.0F ) +#define DEGREE_5 ( DEGREE_180 / 36.0F ) +#define DEGREE_10 ( DEGREE_180 / 18.0F ) +#define DEGREE_15 ( DEGREE_180 / 12.0F ) +#define DEGREE_20 ( DEGREE_180 / 8.0F ) + +// Conversion routines + +#define ANGLE_TO_RAD ANGLE_1 +#define RAD_TO_ANGLE ( 180.0F / ANGLE_180 ) + +#define SHORT_TO_ANGLE ( 360.0 / 65536 ) + +#if GDEF_COMPILER_MSVC +#pragma warning(disable : 4305) // 'initializing' : truncation from 'const double ' to 'float ' +#endif diff --git a/tools/heretic2/qcommon/arrayedlist.h b/tools/heretic2/qcommon/arrayedlist.h new file mode 100644 index 00000000..46663dd5 --- /dev/null +++ b/tools/heretic2/qcommon/arrayedlist.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 1999-2007 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 _ARRAYEDLIST_H +#define _ARRAYEDLIST_H + +#include +#include + +typedef struct ArrayedListNode_s +{ + int data; + int next; + int inUse; +} ArrayedListNode_t; + +#define ARRAYEDLISTNODE_NULL -1 + +static GDEF_ATTRIBUTE_INLINE int GetFreeNode( ArrayedListNode_t *nodeArray, int max ){ + int i; + + for ( i = 0; i < max; ++i ) + { + if ( !nodeArray[i].inUse ) { + nodeArray[i].inUse = 1; + return i; + } + } + + assert( 0 ); + return -1; +} + +static GDEF_ATTRIBUTE_INLINE void FreeNode( ArrayedListNode_t *nodeArray, int index ){ + nodeArray[index].inUse = 0; +} + +#endif //_ARRAYEDLIST_H diff --git a/tools/heretic2/qcommon/flex.h b/tools/heretic2/qcommon/flex.h new file mode 100644 index 00000000..98184e87 --- /dev/null +++ b/tools/heretic2/qcommon/flex.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// Generic flexible format + +typedef struct +{ + char ident[32]; + int version; + int size; +} header_t; + +void WriteHeader( FILE *, char *, int, int, void * ); + +// end diff --git a/tools/heretic2/qcommon/fmodel.h b/tools/heretic2/qcommon/fmodel.h new file mode 100644 index 00000000..e2ebfa8d --- /dev/null +++ b/tools/heretic2/qcommon/fmodel.h @@ -0,0 +1,202 @@ +/* + Copyright (C) 1999-2007 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 + */ + + +/* + ======================================================================== + + .FM triangle flexible model file format + + ======================================================================== + */ + +#ifndef __FMODEL_HEADER +#define __FMODEL_HEADER + +#include "bspfile.h" + +//typedef unsigned char byte; +//typedef int qboolean; +//typedef float vec3_t[3]; + +#define MAX_FM_TRIANGLES 2048 +#define MAX_FM_VERTS 2048 +#define MAX_FM_FRAMES 2048 +#define MAX_FM_SKINS 64 +#define MAX_FM_SKINNAME 64 +#define MAX_FM_MESH_NODES 16 // also defined in game/qshared.h + + +#define DTRIVERTX_V0 0 +#define DTRIVERTX_V1 1 +#define DTRIVERTX_V2 2 +#define DTRIVERTX_LNI 3 +#define DTRIVERTX_SIZE 4 + +#define SKINPAGE_WIDTH 640 +#define SKINPAGE_HEIGHT 480 + +#define ENCODED_WIDTH_X 92 +#define ENCODED_WIDTH_Y 475 +#define ENCODED_HEIGHT_X 128 +#define ENCODED_HEIGHT_Y 475 + +#define SCALE_ADJUST_FACTOR 0.96 + +#define INFO_HEIGHT 5 +#define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT ) + +extern byte *BasePalette; +extern byte *BasePixels,*TransPixels; +extern int BaseWidth, BaseHeight, TransWidth, TransHeight; +extern int ScaleWidth, ScaleHeight; + +int ExtractNumber( byte *pic, int x, int y ); +void DrawTextChar( int x, int y, char *text ); +void DrawLine( int x1, int y1, int x2, int y2 ); + +// 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. + + +// Initial Header +#define FM_HEADER_NAME "header" +#define FM_HEADER_VER 2 + +typedef struct +{ + 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 num_mesh_nodes; +} fmheader_t; + + +// Skin Header +#define FM_SKIN_NAME "skin" +#define FM_SKIN_VER 1 + + +// ST Coord Header +#define FM_ST_NAME "st coord" +#define FM_ST_VER 1 + +typedef struct +{ + short s; + short t; +} fmstvert_t; + + +// Tri Header +#define FM_TRI_NAME "tris" +#define FM_TRI_VER 1 + +typedef struct +{ + short index_xyz[3]; + short index_st[3]; +} fmtriangle_t; + + +// Frame Header +#define FM_FRAME_NAME "frames" +#define FM_FRAME_VER 1 + +// Frame for compression, just the names +#define FM_SHORT_FRAME_NAME "short frames" +#define FM_SHORT_FRAME_VER 1 + +// Normals for compressed frames +#define FM_NORMAL_NAME "normals" +#define FM_NORMAL_VER 1 + +// Compressed Frame Data +#define FM_COMP_NAME "comp data" +#define FM_COMP_VER 1 + +// GL Cmds Header +#define FM_GLCMDS_NAME "glcmds" +#define FM_GLCMDS_VER 1 + + +// Mesh Nodes Header +#define FM_MESH_NAME "mesh nodes" +#define FM_MESH_VER 3 + +// Skeleton Header +#define FM_SKELETON_NAME "skeleton" +#define FM_SKELETON_VER 1 + +// References Header +#define FM_REFERENCES_NAME "references" +#define FM_REFERENCES_VER 1 + +typedef struct +{ + + union + { + + byte tris[MAX_FM_TRIANGLES >> 3]; + + struct { + short *triIndicies; + int num_tris; + }; + + }; + + byte verts[MAX_FM_VERTS >> 3]; + short start_glcmds, num_glcmds; +} fmmeshnode_t; + +//================================================================= + +// Frame info +typedef struct +{ + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; +} fmtrivertx_t; + +typedef struct +{ + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + fmtrivertx_t verts[1]; // variable sized +} fmaliasframe_t; + + +#endif // #define __FMODEL_HEADER diff --git a/tools/heretic2/qcommon/h2common.h b/tools/heretic2/qcommon/h2common.h new file mode 100644 index 00000000..e1f25591 --- /dev/null +++ b/tools/heretic2/qcommon/h2common.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 1999-2007 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 H2COMMON_H +#define H2COMMON_H + #define H2COMMON_API +#endif diff --git a/tools/heretic2/qcommon/placement.h b/tools/heretic2/qcommon/placement.h new file mode 100644 index 00000000..9151183f --- /dev/null +++ b/tools/heretic2/qcommon/placement.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 1999-2007 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 PLACEMENT_H +#define PLACEMENT_H + +#include "q_typedef.h" + +//typedef float vec3_t[3]; + +typedef struct Placement_s +{ + vec3_t origin; + vec3_t direction; + vec3_t up; +} Placement_t; + +#endif diff --git a/tools/heretic2/qcommon/q_typedef.h b/tools/heretic2/qcommon/q_typedef.h new file mode 100644 index 00000000..cbe69dd1 --- /dev/null +++ b/tools/heretic2/qcommon/q_typedef.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 1999-2007 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 Q_TYPEDEF_H +#define Q_TYPEDEF_H + +typedef float vec_t; +typedef vec_t vec2_t[2]; +typedef vec_t vec3_t[3]; +typedef double vec3d_t[3]; +typedef vec_t vec5_t[5]; + +typedef float matrix3_t[3][3]; +typedef float matrix3d_t[3][3]; + +typedef int fixed4_t; +typedef int fixed8_t; +typedef int fixed16_t; + +typedef unsigned char byte; + +#ifndef __cplusplus +typedef enum {false, true} qboolean; +#else +typedef int qboolean; +#endif + +typedef struct edict_s edict_t; + +typedef struct paletteRGBA_s +{ + union + { + struct + { + byte r,g,b,a; + }; + unsigned c; + byte c_array[4]; + }; +} paletteRGBA_t; + +#endif diff --git a/tools/heretic2/qcommon/qfiles.h b/tools/heretic2/qcommon/qfiles.h new file mode 100644 index 00000000..4d0648c1 --- /dev/null +++ b/tools/heretic2/qcommon/qfiles.h @@ -0,0 +1,603 @@ +/* + Copyright (C) 1999-2007 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 + + ======================================================================== + */ + +#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 6144 + + +/* + ======================================================================== + + 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 IDCOMPRESSEDALIASHEADER ( ( '2' << 24 ) + ( 'C' << 16 ) + ( 'D' << 8 ) + 'I' ) + +/* + ======================================================================== + + .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 4096 +#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 +{ + union + { + struct + { + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; + }; + + int vert; + }; +} 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; + +// compressed model +typedef struct dcompmdl_s +{ + dmdl_t header; + short CompressedFrameSize; + short UniqueVerts; + short *remap; + float *translate; // then add this + float *scale; // multiply byte verts by this + char *mat; + char *frames; + char *base; + float *ctranslate; + float *cscale; + char data[1]; +} dcompmdl_t; + +typedef struct +{ + dcompmdl_t compModInfo; + int rootCluster; + int skeletalType; + struct ModelSkeleton_s *skeletons; +} JointedModel_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 + +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 unused[20]; // 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 // Quake 2 original +#define MAX_MAP_BRUSHES 10240 +#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! + +// ************************************************************************************************ +// CONTENTS_XXX +// ------------ +// Contents flags. +// ************************************************************************************************ + +// 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_AUX 0x00000004 +#define CONTENTS_LAVA 0x00000008 +#define CONTENTS_SLIME 0x00000010 +#define CONTENTS_WATER 0x00000020 +#define CONTENTS_MIST 0x00000040 +#define LAST_VISIBLE_CONTENTS CONTENTS_MIST + +// 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 leaves. +#define CONTENTS_TRANSLUCENT 0x10000000 // Auto set if any surface has transparency. +#define CONTENTS_LADDER 0x20000000 +#define CONTENTS_CAMERANOBLOCK 0x40000000 // Camera LOS ignores any brushes with this flag. + +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; diff --git a/tools/heretic2/qcommon/reference.c b/tools/heretic2/qcommon/reference.c new file mode 100644 index 00000000..7be9740d --- /dev/null +++ b/tools/heretic2/qcommon/reference.c @@ -0,0 +1,120 @@ +/* + Copyright (C) 1999-2007 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 +#include "reference.h" +#include "arrayedlist.h" +#include "resourcemanager.h" +#include "skeletons.h" + +char *referenceRootNames[] = +{ + "elf_Lhandroot", //0 + "elf_Rhandroot", + "elf_Rfootroot", + "elf_Lfootroot", + "elf_Bstaffroot", + "elf_bladeroot", + "elf_hellroot", + "StaffBone", //7 + "SwordBone", + "SpearBone", + "RFootBone", + "LFootBone", + "hp_backroot", //12 + "hp_staffroot", + "hp_lhandroot", + "hp_rhandroot", + "hp_rfootroot", + "hp_lfootroot", + "staffroot", //18 + "rfootroot", + "lfootroot", + "rhandroot", + "lhandroot", + "leyeroot", + "reyeroot" +}; + +int referenceRootNameOffsets[NUM_REFERENCED] = +{ + 0, // CORVUS + 7, // INSECT + 12, // HIGH PRIESTESS + 18, // MORCALAVIN +}; + +int numReferences[NUM_REFERENCED] = +{ + NUM_REFERENCES_CORVUS, + NUM_REFERENCES_INSECT, + NUM_REFERENCES_PRIESTESS, + NUM_REFERENCES_MORK, +}; + +int corvusJointIDs[NUM_REFERENCES_CORVUS] = +{ + CORVUS_UPPERBACK, + CORVUS_UPPERBACK, + -1, + -1, + CORVUS_UPPERBACK, + CORVUS_UPPERBACK, + CORVUS_UPPERBACK, +}; + +int *jointIDs[NUM_REFERENCED] = +{ + corvusJointIDs, +}; + +static ResourceManager_t ReferenceMngr; + +void InitReferenceMngr(){ +#define REFERENCE_BLOCK_SIZE 8 + char *dummystr = NULL; + + ResMngr_Con( &ReferenceMngr, sizeof( LERPedReferences_t ), REFERENCE_BLOCK_SIZE, dummystr ); +} + +void ReleaseReferenceMngr(){ + ResMngr_Des( &ReferenceMngr ); +} + +LERPedReferences_t *LERPedReferences_new( int init_refType ){ + LERPedReferences_t *newRefs; + + newRefs = ResMngr_AllocateResource( &ReferenceMngr, sizeof( *newRefs ) ); + newRefs->refType = init_refType; + newRefs->jointIDs = jointIDs[init_refType]; + newRefs->lastUpdate = -( REF_MINCULLTIME * 2.0 ); + + memset( newRefs->references, 0, MAX_REFPOINTS * sizeof( Reference_t ) ); + memset( newRefs->oldReferences, 0, MAX_REFPOINTS * sizeof( Reference_t ) ); + + return newRefs; +} + +void LERPedReferences_delete( LERPedReferences_t *toDelete ){ + ResMngr_DeallocateResource( &ReferenceMngr, toDelete, sizeof( *toDelete ) ); +} + +// end diff --git a/tools/heretic2/qcommon/reference.h b/tools/heretic2/qcommon/reference.h new file mode 100644 index 00000000..747c4d43 --- /dev/null +++ b/tools/heretic2/qcommon/reference.h @@ -0,0 +1,124 @@ +/* + Copyright (C) 1999-2007 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 REFERENCE_H +#define REFERENCE_H + +#include "placement.h" + +#define MAX_REFPOINTS 16 +#define REF_MINCULLTIME 1.0 + +typedef struct Reference_s +{ + int activecount; + Placement_t placement; +} Reference_t; + +typedef struct LERPedReferences_s +{ + int refType; + int *jointIDs; + float lastUpdate; + Reference_t references[MAX_REFPOINTS]; + Reference_t oldReferences[MAX_REFPOINTS]; +} LERPedReferences_t; + +// Reference Types +enum { + REF_NULL = -1, + REF_CORVUS, //0 + REF_INSECT, //1 + REF_PRIESTESS, //2 + REF_MORK, //3 + NUM_REFERENCED //4 +}; + +// Corvus Reference Points +enum { + CORVUS_LEFTHAND, //0 + CORVUS_RIGHTHAND, + CORVUS_LEFTFOOT, + CORVUS_RIGHTFOOT, + CORVUS_STAFF, + CORVUS_BLADE, + CORVUS_HELL_HEAD, + NUM_REFERENCES_CORVUS //7 +}; + +// Tchekrik Reference Points +enum { + INSECT_STAFF, //0 + INSECT_SWORD, + INSECT_SPEAR, + INSECT_RIGHTFOOT, + INSECT_LEFTFOOT, + NUM_REFERENCES_INSECT //5 +}; + +// High Priestess Reference Points +enum { + PRIESTESS_BACK, //0 + PRIESTESS_STAFF, + PRIESTESS_LHAND, + PRIESTESS_RHAND, + PRIESTESS_RFOOT, + PRIESTESS_LFOOT, + NUM_REFERENCES_PRIESTESS //6 +}; + +// Morcalavin Reference Points +enum +{ + MORK_STAFFREF, //0 + MORK_RFOOTREF, //1 + MORK_LFOOTREF, //2 + MORK_RHANDREF, //3 + MORK_LHANDREF, //4 + MORK_LEYEREF, //5 + MORK_REYEREF, //6 + NUM_REFERENCES_MORK //7 +}; + +#define CORVUS_LIMBS_MASK ( ( 1 << CORVUS_LEFTHAND ) | ( 1 << CORVUS_RIGHTHAND ) | ( 1 << CORVUS_LEFTFOOT ) | ( 1 << CORVUS_RIGHTFOOT ) ) +#define CORVUS_WEAPON_MASK ( ( 1 << CORVUS_STAFF ) | ( 1 << CORVUS_BLADE ) | ( 1 << CORVUS_HELL_HEAD ) ) +#define CORVUS_MASK ( CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK ) + +#define INSECT_MASK ( ( 1 << INSECT_STAFF ) | ( 1 << INSECT_SWORD ) | ( 1 << INSECT_SPEAR ) | ( 1 << INSECT_RIGHTFOOT ) | ( 1 << INSECT_LEFTFOOT ) ) + +#define PRIESTESS_MASK ( ( 1 << PRIESTESS_BACK ) | ( 1 << PRIESTESS_STAFF ) | ( 1 << PRIESTESS_LHAND ) | ( 1 << PRIESTESS_RHAND ) | ( 1 << PRIESTESS_RFOOT ) | ( 1 << PRIESTESS_LFOOT ) ) + +#define MORK_MASK ( ( 1 << MORK_STAFFREF ) | ( 1 << MORK_RFOOTREF ) | ( 1 << MORK_LFOOTREF ) | ( 1 << MORK_RHANDREF ) | ( 1 << MORK_LHANDREF ) | ( 1 << MORK_LEYEREF ) | ( 1 << MORK_REYEREF ) ) + +extern char *referenceRootNames[]; +extern int referenceRootNameOffsets[]; +extern int numReferences[]; + +void EnableRefPoints( LERPedReferences_t *refInfo, int mask ); +void DisableRefPoints( LERPedReferences_t *refInfo, int mask ); + +void InitReferenceMngr(); +void ReleaseReferenceMngr(); + +LERPedReferences_t *LERPedReferences_new( int init_refType ); +void LERPedReferences_delete( LERPedReferences_t *toDelete ); + +#endif diff --git a/tools/heretic2/qcommon/resourcemanager.c b/tools/heretic2/qcommon/resourcemanager.c new file mode 100644 index 00000000..2eb01409 --- /dev/null +++ b/tools/heretic2/qcommon/resourcemanager.c @@ -0,0 +1,152 @@ +/* + Copyright (C) 1999-2007 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 + */ + + +// +// ResourceManager.c +// + +#include +#include "resourcemanager.h" +#include + +typedef struct ResMngr_Block_s +{ + char *start; + unsigned int size; + struct ResMngr_Block_s *next; +} ResMngr_Block_t; + +static void ResMngr_CreateBlock( ResourceManager_t *resource ){ + unsigned int _blockSize; + char *block; + char **current; + ResMngr_Block_t *temp; + unsigned int i; + + _blockSize = resource->nodeSize * resource->resPerBlock; + + block = malloc( _blockSize ); + + assert( block ); + + temp = malloc( sizeof( *temp ) ); + + temp->start = block; + temp->size = _blockSize; + temp->next = resource->blockList; + + resource->blockList = temp; + + resource->free = (char **)( block ); + + current = resource->free; + + for ( i = 1; i < resource->resPerBlock; ++i ) + { + // set current->next to point to next node + *current = (char *)( current ) + resource->nodeSize; + + // set current node to current->next + current = (char **)( *current ); + } + + *current = NULL; +} + +H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ){ + resource->resSize = init_resSize; + + resource->resPerBlock = init_resPerBlock; + + resource->nodeSize = resource->resSize + sizeof( *resource->free ); + + resource->blockList = NULL; + + resource->numResourcesAllocated = 0; + + ResMngr_CreateBlock( resource ); +} + +H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ){ + ResMngr_Block_t *toDelete; + +#if 0 + if ( resource->numResourcesAllocated ) { + char mess[100]; + sprintf( mess,"Potential memory leak %d bytes unfreed\n",resource->resSize * resource->numResourcesAllocated ); + OutputDebugString( mess ); + } +#endif + + while ( resource->blockList ) + { + toDelete = resource->blockList; + resource->blockList = resource->blockList->next; + free( toDelete->start ); + free( toDelete ); + } +} + +H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ){ + char **toPop; + + assert( size == resource->resSize ); + + ++resource->numResourcesAllocated; + + assert( resource->free ); // constructor not called; possibly due to a static object + // containing a static ResourceManagerFastLarge member being + // constructed before its own static members + + toPop = resource->free; + + // set unallocated to the next node and check for NULL (end of list) + if ( !( resource->free = (char **)( *resource->free ) ) ) { // if at end create new block + ResMngr_CreateBlock( resource ); + } + + // set next to NULL + *toPop = NULL; + + // return the resource for the node + return (void *)( toPop + 1 ); +} + +H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ){ + char **toPush; + + assert( size == resource->resSize ); + + --resource->numResourcesAllocated; + + toPush = (char **)( toDeallocate ) - 1; + + assert( resource->free ); // see same assert at top of AllocateResource + + // set toPop->next to current unallocated front + *toPush = (char *)( resource->free ); + + // set unallocated to the node removed from allocated + resource->free = toPush; +} + +// end diff --git a/tools/heretic2/qcommon/resourcemanager.h b/tools/heretic2/qcommon/resourcemanager.h new file mode 100644 index 00000000..be82d786 --- /dev/null +++ b/tools/heretic2/qcommon/resourcemanager.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// +// ResourceManager.h +// + +#include "h2common.h" +#include // needed here for size_t + +typedef struct ResourceManager_s +{ + size_t resSize; + unsigned int resPerBlock; + unsigned int nodeSize; + struct ResMngr_Block_s *blockList; + char **free; + char *ResMan_Name; + + unsigned numResourcesAllocated; + +} ResourceManager_t; + +extern H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ); +extern H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ); +extern H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ); +extern H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ); diff --git a/tools/heretic2/qcommon/skeletons.c b/tools/heretic2/qcommon/skeletons.c new file mode 100644 index 00000000..453cb77a --- /dev/null +++ b/tools/heretic2/qcommon/skeletons.c @@ -0,0 +1,225 @@ +/* + Copyright (C) 1999-2007 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 + */ + +// +// Skeletons.c +// + +#include "skeletons.h" + +char *skeletonRootNames[] = +{ + "RAVEN_ROOT", + "BOX_ROOT", + "BEETLE_ROOT", + "ELFLORD_ROOT", + "PLAGUELF_ROOT", + "ELF_BACKROOT", +}; + +int skeletonRNameOffsets[] = +{ + 0, // RAVEN + 1, // BOX + 2, // BEETLE + 3, // ELFLORD + 4, // PLAGUE ELF + 5, // CORVUS +}; + +char *skeletonJointNames[] = +{ + "RAVEN_LOWERBACK", // 0 + "RAVEN_UPPERBACK", + "RAVEN_NECK", + "BOX_CENTER", // 3 + "BEETLE_NECK", // 4 + "BEETLE_HEAD", + "PLAGUELF_BACKB", // 6 + "PLAGUELF_BACKC", + "PLAGUELF_NECK", + "ELF_BACKB", // 9 + "ELF_BACKC", + "ELF_NECKB", +}; + +int skeletonNameOffsets[] = +{ + 0, // RAVEN + 3, // BOX + 4, // BEETLE + -1, // ELFLORD + 6, // PLAGUE ELF + 9, // CORVUS +}; + +char *skeletonEffectorNames[] = +{ + "BEETLE_EYES", // 0 + "CORVUS_EYES", // 1 +}; + +int skeletonENameOffsets[] = +{ + -1, // RAVEN + -1, // BOX + 0, // BEETLE + -1, // ELFLORD + 1, // PLAGUE ELF +}; + +int numJointsInSkeleton[] = +{ + NUM_JOINTS_RAVEN, + NUM_JOINTS_BOX, + NUM_JOINTS_BEETLE, + NUM_JOINTS_ELFLORD, + NUM_JOINTS_PLAGUE_ELF, + NUM_JOINTS_CORVUS, +}; + +int numNodesInSkeleton[] = +{ + 2, // RAVEN + 0, // BOX + 1, // BEETLE + -1, // ELFLORD + 2, // PLAGUE ELF + 2, // CORVUS +}; + +void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root ); +void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root ); +void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); +void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); +void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); + +CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] = +{ + CreateRavenSkel, + CreateBoxSkel, + CreateBeetleSkel, + CreateElfLordSkel, + CreatePlagueElfSkel, + CreatePlagueElfSkel, // Corvus has the same structure as the Plague Elf +}; + +void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ + char *root; + int *children; + int nodeIndex; + + root = (char *)g_skeletalJoints + rootIndex * jointSize; + + children = (int *)( root + RAVEN_HEAD * jointSize ); + *children = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + RAVEN_UPPERBACK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + RAVEN_LOWERBACK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; +} + +void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ + char *root; + int *children; + + root = (char *)g_skeletalJoints + rootIndex * jointSize; + + children = (int *)( root + RAVEN_HEAD * jointSize ); + *children = ARRAYEDLISTNODE_NULL; +} + +void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ + char *root; + int *children; + int nodeIndex; + + root = (char *)g_skeletalJoints + rootIndex * jointSize; + + children = (int *)( root + BEETLE_HEAD * jointSize ); + *children = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + BEETLE_NECK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; +} + +void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ + char *root; + int *children; + int nodeIndex; + + root = (char *)g_skeletalJoints + rootIndex * jointSize; + + children = (int *)( root + BEETLE_HEAD * jointSize ); + *children = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + BEETLE_NECK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; +} + +void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ + char *root; + int *children; + int nodeIndex; + + root = (char *)g_skeletalJoints + rootIndex * jointSize; + + children = (int *)( root + PLAGUE_ELF_HEAD * jointSize ); + *children = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + PLAGUE_ELF_UPPERBACK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; + + nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); + + children = (int *)( root + PLAGUE_ELF_LOWERBACK * jointSize ); + *children = nodeIndex; + + g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK; + g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; +} diff --git a/tools/heretic2/qcommon/skeletons.h b/tools/heretic2/qcommon/skeletons.h new file mode 100644 index 00000000..9d7fe961 --- /dev/null +++ b/tools/heretic2/qcommon/skeletons.h @@ -0,0 +1,105 @@ +/* + Copyright (C) 1999-2007 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 // for size_t +#include "arrayedlist.h" + +#define JN_YAW_CHANGED 0x00000001 +#define JN_PITCH_CHANGED 0x00000002 +#define JN_ROLL_CHANGED 0x00000004 + +// Skeleton types +enum { + SKEL_NULL = -1, + SKEL_RAVEN = 0, + SKEL_BOX, + SKEL_BEETLE, + SKEL_ELFLORD, + SKEL_PLAGUE_ELF, + SKEL_CORVUS, + NUM_SKELETONS +}; + +// Raven Skeletal joints +enum { + RAVEN_LOWERBACK = 0, + RAVEN_UPPERBACK, + RAVEN_HEAD, + NUM_JOINTS_RAVEN +}; + +// Box Skeletal joints +enum { + BOX_CENTER = 0, + NUM_JOINTS_BOX +}; + +// Beetle Skeletal joints +enum { + BEETLE_NECK = 0, + BEETLE_HEAD, + NUM_JOINTS_BEETLE +}; + +// Elflord Skeletal joints +enum { + ELFLORD_, + ELFLORD__, + NUM_JOINTS_ELFLORD +}; + +// Plague Elf Skeletal joints +enum { + PLAGUE_ELF_LOWERBACK, + PLAGUE_ELF_UPPERBACK, + PLAGUE_ELF_HEAD, + NUM_JOINTS_PLAGUE_ELF +}; + +// Corvus Skeletal joints +enum { + CORVUS_LOWERBACK, + CORVUS_UPPERBACK, + CORVUS_HEAD, + NUM_JOINTS_CORVUS +}; + +#define NO_SWAP_FRAME -1 +#define NULL_ROOT_JOINT -1 + +#define MAX_ARRAYED_SKELETAL_JOINTS 255 // has max of 65,535 (if this remains at 255, net code can be changed to reflect) +#define MAX_ARRAYED_JOINT_NODES ( MAX_ARRAYED_SKELETAL_JOINTS - 1 ) + +#define MAX_JOINTS_PER_SKELETON 8 // arbitrary small number +#define MAX_JOINT_NODES_PER_SKELETON ( MAX_JOINTS_PER_SKELETON - 1 ) + +extern char *skeletonRootNames[]; +extern int skeletonRNameOffsets[]; +extern char *skeletonJointNames[]; +extern int skeletonNameOffsets[]; +extern int numJointsInSkeleton[]; +extern char *skeletonEffectorNames[]; +extern int skeletonENameOffsets[]; +extern int numNodesInSkeleton[]; + +typedef void ( *CreateSkeleton_t )( void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex ); + +extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS]; diff --git a/tools/quake2/qdata_heretic2/CMakeLists.txt b/tools/quake2/qdata_heretic2/CMakeLists.txt deleted file mode 100644 index 34131623..00000000 --- a/tools/quake2/qdata_heretic2/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -include_directories(BEFORE . common qcommon) - -find_package(OpenGL REQUIRED) - -find_package(LibXml2 REQUIRED) -include_directories(${LIBXML2_INCLUDE_DIR}) - -radiant_tool(h2data - h2data.rc - - common/bspfile.c common/bspfile.h - common/cmdlib.c common/cmdlib.h - common/inout.c common/inout.h - common/l3dslib.c common/l3dslib.h - common/lbmlib.c common/lbmlib.h - common/mathlib.c common/mathlib.h - common/md4.c common/md4.h - common/path_init.c - common/polylib.c common/polylib.h - common/qfiles.c common/qfiles.h - common/scriplib.c common/scriplib.h - common/threads.c common/her2_threads.h - common/token.c common/token.h - common/trilib.c common/trilib.h - - qcommon/angles.h - qcommon/arrayedlist.h - qcommon/flex.h - qcommon/fmodel.h - qcommon/h2common.h - qcommon/placement.h - qcommon/qfiles.h - qcommon/q_typedef.h - qcommon/reference.c qcommon/reference.h - qcommon/resourcemanager.c qcommon/resourcemanager.h - qcommon/skeletons.c qcommon/skeletons.h - - adpcm.h - animcomp.c animcomp.h - anorms.h - book.c - fmodels.c qd_fmodel.h - images.c - jointed.c - jointed.h - joints.h - models.c - pics.c - qdata.c qdata.h - qd_skeletons.c qd_skeletons.h - resource.h - sprites.c - svdcmp.c - tables.c - tmix.c - video.c -) - -target_compile_definitions(h2data - PRIVATE -) - -target_link_libraries(h2data - ${LIBXML2_LIBRARIES} - l_net -) - -add_custom_target(heretic2) -add_dependencies(heretic2 h2data) - -if (UNIX) - target_link_libraries(h2data pthread m) -endif () diff --git a/tools/quake2/qdata_heretic2/adpcm.h b/tools/quake2/qdata_heretic2/adpcm.h deleted file mode 100644 index aad74eaa..00000000 --- a/tools/quake2/qdata_heretic2/adpcm.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/animcomp.c b/tools/quake2/qdata_heretic2/animcomp.c deleted file mode 100644 index a7619325..00000000 --- a/tools/quake2/qdata_heretic2/animcomp.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include -#include -#include -#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 ); -} diff --git a/tools/quake2/qdata_heretic2/animcomp.h b/tools/quake2/qdata_heretic2/animcomp.h deleted file mode 100644 index 36ea3b1f..00000000 --- a/tools/quake2/qdata_heretic2/animcomp.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/anorms.h b/tools/quake2/qdata_heretic2/anorms.h deleted file mode 100644 index 65e92ef1..00000000 --- a/tools/quake2/qdata_heretic2/anorms.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 1999-2007 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}, diff --git a/tools/quake2/qdata_heretic2/book.c b/tools/quake2/qdata_heretic2/book.c deleted file mode 100644 index 412aefe8..00000000 --- a/tools/quake2/qdata_heretic2/book.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/common/bspfile.c b/tools/quake2/qdata_heretic2/common/bspfile.c deleted file mode 100644 index add0ef30..00000000 --- a/tools/quake2/qdata_heretic2/common/bspfile.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - Copyright (C) 1999-2007 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; -} diff --git a/tools/quake2/qdata_heretic2/common/bspfile.h b/tools/quake2/qdata_heretic2/common/bspfile.h deleted file mode 100644 index f66659b5..00000000 --- a/tools/quake2/qdata_heretic2/common/bspfile.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.c b/tools/quake2/qdata_heretic2/common/cmdlib.c deleted file mode 100644 index c45ff161..00000000 --- a/tools/quake2/qdata_heretic2/common/cmdlib.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - Copyright (C) 1999-2007 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 quake3/common - -#include "cmdlib.h" -#include "globaldefs.h" -#include "mathlib.h" -#include "inout.h" -#include -#include - -#if GDEF_OS_WINDOWS -#include -#include -#elif GDEF_OS_NEXT -#include -#else // OTHER OSES -#include -#endif // OTHER OSES - -#if !GDEF_OS_WINDOWS -#define strlwr strlower -#endif // !GDEF_OS_WINDOWS - -#define BASEDIRNAME "h" -#define PATHSEPERATOR '/' - -extern qboolean verbose; - -qboolean g_dokeypress = false; - -qboolean g_nomkdir = false; - - -#ifdef SAFE_MALLOC -void *safe_malloc( size_t size ){ - void *p; - - p = malloc( size ); - if ( !p ) { - Error( "safe_malloc failed on allocation of %i bytes", size ); - } - - return p; -} - -void *safe_malloc_info( size_t size, char* info ){ - void *p; - - p = malloc( size ); - if ( !p ) { - Error( "%s: safe_malloc failed on allocation of %i bytes", info, size ); - } - - return p; -} -#endif // !SAFE_MALLOC - -void *SafeMalloc( size_t n, char *desc ){ - void *p; - - if ( ( p = malloc( n ) ) == NULL ) { - Error( "Failed to allocate %d bytes for '%s'.\n", n, desc ); - } - memset( p, 0, n ); - return p; -} - -// set these before calling CheckParm -int myargc; -char **myargv; - -char com_token[1024]; -qboolean com_eof; - -qboolean archive; -char archivedir[1024]; - - -/* - =================== - ExpandWildcards - - Mimic unix command line expansion - =================== - */ -#define MAX_EX_ARGC 1024 - -int ex_argc; -char *ex_argv[MAX_EX_ARGC]; - -#if GDEF_OS_WINDOWS -#include "io.h" -void ExpandWildcards( int *argc, char ***argv ){ - struct _finddata_t fileinfo; - int handle; - int i; - char filename[1024]; - char filebase[1024]; - char *path; - - ex_argc = 0; - for ( i = 0 ; i < *argc ; i++ ) - { - path = ( *argv )[i]; - if ( path[0] == '-' - || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) { - ex_argv[ex_argc++] = path; - continue; - } - - handle = _findfirst( path, &fileinfo ); - if ( handle == -1 ) { - return; - } - - ExtractFilePath( path, filebase ); - - do - { - sprintf( filename, "%s%s", filebase, fileinfo.name ); - ex_argv[ex_argc++] = copystring( filename ); - } while ( _findnext( handle, &fileinfo ) != -1 ); - - _findclose( handle ); - } - - *argc = ex_argc; - *argv = ex_argv; -} -#else // !GDEF_OS_WINDOWS -void ExpandWildcards( int *argc, char ***argv ){ -} -#endif // !GDEF_OS_WINDOWS - -/* - - qdir will hold the path up to the quake directory, including the slash - - f:\quake\ - /raid/quake/ - - gamedir will hold qdir + the game directory (id1, id2, etc) - - */ - -char qdir[1024]; -char gamedir[1024]; -char writedir[1024]; - -void SetQdirFromPath( const char *path ){ - char temp[1024]; - const char *c; - const char *sep; - int len, count; - - if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial - Q_getwd( temp ); - strcat( temp, path ); - path = temp; - } - - // search for "quake2" in path - - len = strlen( BASEDIRNAME ); - for ( c = path + strlen( path ) - 1 ; c != path ; c-- ) - { - int i; - - if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) { - // - //strncpy (qdir, path, c+len+2-path); - // the +2 assumes a 2 or 3 following quake which is not the - // case with a retail install - // so we need to add up how much to the next separator - sep = c + len; - count = 1; - while ( *sep && *sep != '/' && *sep != '\\' ) - { - sep++; - count++; - } - strncpy( qdir, path, c + len + count - path ); - Sys_Printf( "qdir: %s\n", qdir ); - for ( i = 0; i < strlen( qdir ); i++ ) - { - if ( qdir[i] == '\\' ) { - qdir[i] = '/'; - } - } - - c += len + count; - while ( *c ) - { - if ( *c == '/' || *c == '\\' ) { - strncpy( gamedir, path, c + 1 - path ); - - for ( i = 0; i < strlen( gamedir ); i++ ) - { - if ( gamedir[i] == '\\' ) { - gamedir[i] = '/'; - } - } - - Sys_Printf( "gamedir: %s\n", gamedir ); - - if ( !writedir[0] ) { - strcpy( writedir, gamedir ); - } - else if ( writedir[strlen( writedir ) - 1] != '/' ) { - writedir[strlen( writedir )] = '/'; - writedir[strlen( writedir ) + 1] = 0; - } - - return; - } - c++; - } - Error( "No gamedir in %s", path ); - return; - } - } - Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path ); -} - -char *ExpandArg( const char *path ){ - static char full[1024]; - - if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) { - Q_getwd( full ); - strcat( full, path ); - } - else{ - strcpy( full, path ); - } - return full; -} - -char *ExpandPath( const char *path ){ - static char full[1024]; - if ( !qdir ) { - Error( "ExpandPath called without qdir set" ); - } - if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) { - strcpy( full, path ); - return full; - } - sprintf( full, "%s%s", qdir, path ); - return full; -} - -char *ExpandGamePath( const char *path ){ - static char full[1024]; - if ( !qdir ) { - Error( "ExpandGamePath called without qdir set" ); - } - if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) { - strcpy( full, path ); - return full; - } - sprintf( full, "%s%s", gamedir, path ); - return full; -} - -char *ExpandPathAndArchive( const char *path ){ - char *expanded; - char archivename[1024]; - - expanded = ExpandPath( path ); - - if ( archive ) { - sprintf( archivename, "%s/%s", archivedir, path ); - QCopyFile( expanded, archivename ); - } - return expanded; -} - - -char *copystring( const char *s ){ - char *b; - b = safe_malloc( strlen( s ) + 1 ); - strcpy( b, s ); - return b; -} - - - -/* - ================ - I_FloatTime - ================ - */ -double I_FloatTime( void ){ - time_t t; - - time( &t ); - - return t; -#if 0 -// more precise, less portable - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday( &tp, &tzp ); - - if ( !secbase ) { - secbase = tp.tv_sec; - return tp.tv_usec / 1000000.0; - } - - return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0; -#endif -} - -void Q_getwd( char *out ){ - int i = 0; - -#if GDEF_OS_WINDOWS - _getcwd( out, 256 ); - strcat( out, "\\" ); -#else // !GDEF_OS_WINDOWS - // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow - getcwd( out, 256 ); - strcat( out, "/" ); -#endif // !GDEF_OS_WINDOWS - while ( out[i] != 0 ) - { - if ( out[i] == '\\' ) { - out[i] = '/'; - } - i++; - } -} - - -void Q_mkdir( const char *path ){ -#if GDEF_OS_WINDOWS - if ( _mkdir( path ) != -1 ) { - return; - } -#else // !GDEF_OS_WINDOWS - if ( mkdir( path, 0777 ) != -1 ) { - return; - } -#endif // !GDEF_OS_WINDOWS - if ( errno != EEXIST ) { - Error( "mkdir %s: %s",path, strerror( errno ) ); - } -} - -/* - ============ - FileTime - - returns -1 if not present - ============ - */ -int FileTime( const char *path ){ - struct stat buf; - - if ( stat( path,&buf ) == -1 ) { - return -1; - } - - return buf.st_mtime; -} - - - -/* - ============== - COM_Parse - - Parse a token out of a string - ============== - */ -char *COM_Parse( char *data ){ - int c; - int len; - - len = 0; - com_token[0] = 0; - - if ( !data ) { - return NULL; - } - -// skip whitespace -skipwhite: - while ( ( c = *data ) <= ' ' ) - { - if ( c == 0 ) { - com_eof = true; - return NULL; // end of file; - } - data++; - } - -// skip // comments - if ( c == '/' && data[1] == '/' ) { - while ( *data && *data != '\n' ) - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if ( c == '\"' ) { - data++; - do - { - c = *data++; - if ( c == '\"' ) { - com_token[len] = 0; - return data; - } - com_token[len] = c; - len++; - } while ( 1 ); - } - -// parse single characters - if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { - com_token[len] = c; - len++; - com_token[len] = 0; - return data + 1; - } - -// parse a regular word - do - { - com_token[len] = c; - data++; - len++; - c = *data; - if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { - break; - } - } while ( c > 32 ); - - com_token[len] = 0; - return data; -} - -int Q_strncasecmp( const char *s1, const char *s2, int n ){ - int c1, c2; - - do - { - c1 = *s1++; - c2 = *s2++; - - if ( !n-- ) { - return 0; // strings are equal until end point - - } - if ( c1 != c2 ) { - if ( c1 >= 'a' && c1 <= 'z' ) { - c1 -= ( 'a' - 'A' ); - } - if ( c2 >= 'a' && c2 <= 'z' ) { - c2 -= ( 'a' - 'A' ); - } - if ( c1 != c2 ) { - return -1; // strings not equal - } - } - } while ( c1 ); - - return 0; // strings are equal -} - -int Q_stricmp( const char *s1, const char *s2 ){ - return Q_strncasecmp( s1, s2, 99999 ); -} - -int Q_strcasecmp( const char *s1, const char *s2 ){ - return Q_strncasecmp( s1, s2, 99999 ); -} - -// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config -// started getting warnings about that function, prolly a duplicate with the runtime function -// maybe we still need to have it in linux builds -/* - char *strupr (char *start) - { - char *in; - in = start; - while (*in) - { - *in = toupper(*in); - in++; - } - return start; - } - */ - -char *strlower( char *start ){ - char *in; - in = start; - while ( *in ) - { - *in = tolower( *in ); - in++; - } - return start; -} - - -/* - ============================================================================= - - MISC FUNCTIONS - - ============================================================================= - */ - - -/* - ================= - CheckParm - - Checks for the given parameter in the program's command line arguments - Returns the argument number (1 to argc-1) or 0 if not present - ================= - */ -int CheckParm( const char *check ){ - int i; - - for ( i = 1; i < myargc; i++ ) - { - if ( !Q_stricmp( check, myargv[i] ) ) { - return i; - } - } - - return 0; -} - - - -/* - ================ - Q_filelength - ================ - */ -int Q_filelength( FILE *f ){ - int pos; - int end; - - pos = ftell( f ); - fseek( f, 0, SEEK_END ); - end = ftell( f ); - fseek( f, pos, SEEK_SET ); - - return end; -} - - -FILE *SafeOpenWrite( const char *filename ){ - FILE *f; - - f = fopen( filename, "wb" ); - - if ( !f ) { - Error( "Error opening %s: %s",filename,strerror( errno ) ); - } - - return f; -} - -FILE *SafeOpenRead( const char *filename ){ - FILE *f; - - f = fopen( filename, "rb" ); - - if ( !f ) { - Error( "Error opening %s: %s",filename,strerror( errno ) ); - } - - return f; -} - - -void SafeRead( FILE *f, void *buffer, int count ){ - if ( fread( buffer, 1, count, f ) != (size_t)count ) { - Error( "File read failure" ); - } -} - - -void SafeWrite( FILE *f, const void *buffer, int count ){ - if ( fwrite( buffer, 1, count, f ) != (size_t)count ) { - Error( "File write failure" ); - } -} - - -/* - ============== - FileExists - ============== - */ -qboolean FileExists( const char *filename ){ - FILE *f; - - f = fopen( filename, "r" ); - if ( !f ) { - return false; - } - fclose( f ); - return true; -} - -/* - ============== - LoadFile - ============== - */ -int LoadFile( const char *filename, void **bufferptr ){ - FILE *f; - int length; - void *buffer; - - f = SafeOpenRead( filename ); - length = Q_filelength( f ); - buffer = safe_malloc( length + 1 ); - ( (char *)buffer )[length] = 0; - SafeRead( f, buffer, length ); - fclose( f ); - - *bufferptr = buffer; - return length; -} - - -/* - ============== - LoadFileBlock - - - rounds up memory allocation to 4K boundry - - - ============== - */ -int LoadFileBlock( const char *filename, void **bufferptr ){ - FILE *f; - int length, nBlock, nAllocSize; - void *buffer; - - f = SafeOpenRead( filename ); - length = Q_filelength( f ); - nAllocSize = length; - nBlock = nAllocSize % MEM_BLOCKSIZE; - if ( nBlock > 0 ) { - nAllocSize += MEM_BLOCKSIZE - nBlock; - } - buffer = safe_malloc( nAllocSize + 1 ); - memset( buffer, 0, nAllocSize + 1 ); - SafeRead( f, buffer, length ); - fclose( f ); - - *bufferptr = buffer; - return length; -} - - -/* - ============== - TryLoadFile - - Allows failure - ============== - */ -int TryLoadFile( const char *filename, void **bufferptr ){ - FILE *f; - int length; - void *buffer; - - *bufferptr = NULL; - - f = fopen( filename, "rb" ); - if ( !f ) { - return -1; - } - length = Q_filelength( f ); - buffer = safe_malloc( length + 1 ); - ( (char *)buffer )[length] = 0; - SafeRead( f, buffer, length ); - fclose( f ); - - *bufferptr = buffer; - return length; -} - - -/* - ============== - SaveFile - ============== - */ -void SaveFile( const char *filename, const void *buffer, int count ){ - FILE *f; - - f = SafeOpenWrite( filename ); - SafeWrite( f, buffer, count ); - fclose( f ); -} - - - -void DefaultExtension( char *path, const char *extension ){ - char *src; -// -// if path doesnt have a .EXT, append extension -// (extension should include the .) -// - src = path + strlen( path ) - 1; - - while ( *src != '/' && *src != '\\' && src != path ) - { - if ( *src == '.' ) { - return; // it has an extension - } - src--; - } - - strcat( path, extension ); -} - - -void DefaultPath( char *path, const char *basepath ){ - char temp[128]; - - if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) { - return; // absolute path location - } - strcpy( temp,path ); - strcpy( path,basepath ); - strcat( path,temp ); -} - - -void StripFilename( char *path ){ - int length; - - length = strlen( path ) - 1; - while ( length > 0 && path[length] != '/' && path[ length ] != '\\' ) - length--; - path[length] = 0; -} - -void StripExtension( char *path ){ - int length; - - length = strlen( path ) - 1; - while ( length > 0 && path[length] != '.' ) - { - length--; - if ( path[length] == '/' || path[ length ] == '\\' ) { - return; // no extension - } - } - if ( length ) { - path[length] = 0; - } -} - - -/* - ==================== - Extract file parts - ==================== - */ - -// FIXME: should include the slash, otherwise -// backing to an empty path will be wrong when appending a slash -void ExtractFilePath( const char *path, char *dest ){ - const char *src; - - src = path + strlen( path ) - 1; - -// -// back up until a \ or the start -// - while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' ) - src--; - - memcpy( dest, path, src - path ); - dest[src - path] = 0; -} - -void ExtractFileBase( const char *path, char *dest ){ - const char *src; - - src = path + strlen( path ) - 1; - -// -// back up until a \ or the start -// - while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' ) - src--; - - while ( *src && *src != '.' ) - { - *dest++ = *src++; - } - *dest = 0; -} - -void ExtractFileExtension( const char *path, char *dest ){ - const char *src; - - src = path + strlen( path ) - 1; - -// -// back up until a . or the start -// - while ( src != path && *( src - 1 ) != '.' ) - src--; - if ( src == path ) { - *dest = 0; // no extension - return; - } - - strcpy( dest,src ); -} - - -/* - ============== - ParseNum / ParseHex - ============== - */ -int ParseHex( const char *hex ){ - const char *str; - int num; - - num = 0; - str = hex; - - while ( *str ) - { - num <<= 4; - if ( *str >= '0' && *str <= '9' ) { - num += *str - '0'; - } - else if ( *str >= 'a' && *str <= 'f' ) { - num += 10 + *str - 'a'; - } - else if ( *str >= 'A' && *str <= 'F' ) { - num += 10 + *str - 'A'; - } - else{ - Error( "Bad hex number: %s",hex ); - } - str++; - } - - return num; -} - - -int ParseNum( const char *str ){ - if ( str[0] == '$' ) { - return ParseHex( str + 1 ); - } - if ( str[0] == '0' && str[1] == 'x' ) { - return ParseHex( str + 2 ); - } - return atol( str ); -} -/* - // all output ends up through here - void FPrintf (int flag, char *buf) - { - printf(buf); - - } - - 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 ); - - exit (1); - } - - */ - -/* - ============================================================================ - - BYTE ORDER FUNCTIONS - - ============================================================================ - */ - -#if GDEF_ARCH_ENDIAN_BIG - -short LittleShort( short l ){ - byte b1,b2; - - b1 = l & 255; - b2 = ( l >> 8 ) & 255; - - return ( b1 << 8 ) + b2; -} - -short BigShort( short l ){ - return l; -} - - -int LittleLong( int l ){ - byte b1,b2,b3,b4; - - b1 = l & 255; - b2 = ( l >> 8 ) & 255; - b3 = ( l >> 16 ) & 255; - b4 = ( l >> 24 ) & 255; - - return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4; -} - -int BigLong( int l ){ - return l; -} - - -float LittleFloat( float l ){ - union {byte b[4]; float f; } in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float BigFloat( float l ){ - return l; -} - - -#else // !GDEF_ARCH_ENDIAN_BIG - - -short BigShort( short l ){ - byte b1,b2; - - b1 = l & 255; - b2 = ( l >> 8 ) & 255; - - return ( b1 << 8 ) + b2; -} - -short LittleShort( short l ){ - return l; -} - - -int BigLong( int l ){ - byte b1,b2,b3,b4; - - b1 = l & 255; - b2 = ( l >> 8 ) & 255; - b3 = ( l >> 16 ) & 255; - b4 = ( l >> 24 ) & 255; - - return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4; -} - -int LittleLong( int l ){ - return l; -} - -float BigFloat( float l ){ - union {byte b[4]; float f; } in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float LittleFloat( float l ){ - return l; -} - -#endif // ! GDEF_ARCH_ENDIAN_BIG - - -//======================================================= - - -// FIXME: byte swap? - -// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 -// and the initial and final xor values shown below... in other words, the -// CCITT standard CRC used by XMODEM - -#define CRC_INIT_VALUE 0xffff -#define CRC_XOR_VALUE 0x0000 - -static unsigned short crctable[256] = -{ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -void CRC_Init( unsigned short *crcvalue ){ - *crcvalue = CRC_INIT_VALUE; -} - -void CRC_ProcessByte( unsigned short *crcvalue, byte data ){ - *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data]; -} - -unsigned short CRC_Value( unsigned short crcvalue ){ - return crcvalue ^ CRC_XOR_VALUE; -} -//============================================================================= - -/* - ============ - CreatePath - ============ - */ -void CreatePath( const char *path ){ - const char *ofs; - char c; - char dir[1024]; - -#if GDEF_OS_WINDOWS - int olddrive = -1; - - if ( path[1] == ':' ) { - olddrive = _getdrive(); - _chdrive( toupper( path[0] ) - 'A' + 1 ); - } -#endif // !GDEF_OS_WINDOWS - - if ( path[1] == ':' ) { - path += 2; - } - - for ( ofs = path + 1 ; *ofs ; ofs++ ) - { - c = *ofs; - if ( c == '/' || c == '\\' ) { // create the directory - memcpy( dir, path, ofs - path ); - dir[ ofs - path ] = 0; - Q_mkdir( dir ); - } - } - -#if GDEF_OS_WINDOWS - if ( olddrive != -1 ) { - _chdrive( olddrive ); - } -#endif // !GDEF_OS_WINDOWS -} - - -/* - ============ - QCopyFile - - Used to archive source files - ============ - */ -void QCopyFile( const char *from, const char *to ){ - void *buffer; - int length; - - length = LoadFile( from, &buffer ); - CreatePath( to ); - SaveFile( to, buffer, length ); - free( buffer ); -} - -void Sys_Sleep( int n ){ -#if GDEF_OS_WINDOWS - Sleep( n ); -#else // !GDEF_OS_WINDOWS - usleep( n * 1000 ); -#endif // !GDEF_OS_WINDOWS -} diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.h b/tools/quake2/qdata_heretic2/common/cmdlib.h deleted file mode 100644 index b8b1aa3d..00000000 --- a/tools/quake2/qdata_heretic2/common/cmdlib.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - Copyright (C) 1999-2007 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__ - -#if GDEF_COMPILER_MSVC -#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 -#include -#include -#include -#include -#include -#include - -#if GDEF_COMPILER_MSVC - -#pragma intrinsic( memset, memcpy ) - -#endif - -#ifndef __BYTEBOOL__ - #define __BYTEBOOL__ -//typedef enum {false, true} qboolean; -//typedef unsigned char byte; - #include "q_typedef.h" -#endif - -#ifdef PATH_MAX -#define MAX_OS_PATH PATH_MAX -#else -#define MAX_OS_PATH 1024 -#endif -#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 diff --git a/tools/quake2/qdata_heretic2/common/her2_threads.h b/tools/quake2/qdata_heretic2/common/her2_threads.h deleted file mode 100644 index 6027a695..00000000 --- a/tools/quake2/qdata_heretic2/common/her2_threads.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/common/inout.c b/tools/quake2/qdata_heretic2/common/inout.c deleted file mode 100644 index e0c14841..00000000 --- a/tools/quake2/qdata_heretic2/common/inout.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "globaldefs.h" -#include "cmdlib.h" -#include "mathlib.h" -#include "polylib.h" -#include "inout.h" -#include -#include - -#if GDEF_OS_WINDOWS -#include -#include -#endif - -// network broadcasting -#include "l_net/l_net.h" -#include "libxml/tree.h" - -#if GDEF_OS_WINDOWS -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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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" ); - xmlNodeAddContent( 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, "" ); - 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 string - .. various nodes to describe corresponding geometry .. - - */ - if ( !bGotXML ) { - // initialize - doc = xmlNewDoc( "1.0" ); - doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL ); - bGotXML = true; - } - node = xmlNewNode( NULL, "message" ); - xmlNodeAddContent( 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 ); -} diff --git a/tools/quake2/qdata_heretic2/common/inout.h b/tools/quake2/qdata_heretic2/common/inout.h deleted file mode 100644 index 934189f2..00000000 --- a/tools/quake2/qdata_heretic2/common/inout.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 1999-2007 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__ - -#include "globaldefs.h" -// 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, ... ); - -#if GDEF_DEBUG -#define DBG_XML 1 -#endif - -#ifdef DBG_XML -void DumpXML(); -#endif - -#endif diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.c b/tools/quake2/qdata_heretic2/common/l3dslib.c deleted file mode 100644 index 708577a1..00000000 --- a/tools/quake2/qdata_heretic2/common/l3dslib.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#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 ); -} diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.h b/tools/quake2/qdata_heretic2/common/l3dslib.h deleted file mode 100644 index 0b1b5379..00000000 --- a/tools/quake2/qdata_heretic2/common/l3dslib.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.c b/tools/quake2/qdata_heretic2/common/lbmlib.c deleted file mode 100644 index 7eabd19c..00000000 --- a/tools/quake2/qdata_heretic2/common/lbmlib.c +++ /dev/null @@ -1,1043 +0,0 @@ -/* - Copyright (C) 1999-2007 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" - -// Ups the palette values so no pixels except 0 appear transparent -// Need a value of 8 to cater for 16bit renderers - -typedef struct -{ - byte r; - byte g; - byte b; -} paletteRGB_t; - - -void CorrectPalette( byte *pal ){ - paletteRGB_t *p; - - p = (paletteRGB_t *)pal; - // Color 0 always transparent - p->r = 0; - p->g = 0; - p->b = 0; -} - -/* - ============================================================================ - - 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 ); - CorrectPalette( cmapbuffer ); - 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 ); - CorrectPalette( *palette ); - } - - 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 StuffPackedByte( int curRepCount, byte curByte, byte** packPtr ){ - byte* pack; - - pack = *packPtr; - - while ( curRepCount > 0 ) - { - if ( curRepCount == 1 ) { - if ( ( curByte & 0xc0 ) != 0xc0 ) { - *pack++ = curByte; - } - else - { - *pack++ = 0xc1; - *pack++ = curByte; - } - break; - } - if ( curRepCount < 0x0040 ) { - *pack++ = ( 0x00c0 | curRepCount ); - curRepCount = 0; - } - else - { - *pack++ = 0xff; - curRepCount -= 0x003f; - } - *pack++ = curByte; - } - *packPtr = pack; -} - -void WritePCXfile( char *filename, byte *data, - int width, int height, byte *palette ){ - int i, j, length; - pcx_t *pcx; - byte *pack; - byte curByte; - int curRepCount; - - pcx = malloc( width * height * 2 + 1000 ); - memset( pcx, 0, sizeof( *pcx ) ); - - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // RLE - 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( 1 ); // not a grey scale - - // pack the image - pack = &pcx->data; - -/* for (i=0 ; i= rows ) { - goto breakOut; - } - pixbuf += rowOffset; - rowBuf = pixbuf; - } - } - } - 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 ); - rowBuf[0] = red; - rowBuf[1] = green; - rowBuf[2] = blue; - rowBuf[3] = 255; - rowBuf += pixDirection; - break; - case 32: - blue = getc( fin ); - green = getc( fin ); - red = getc( fin ); - alphabyte = getc( fin ); - rowBuf[0] = red; - rowBuf[1] = green; - rowBuf[2] = blue; - rowBuf[3] = alphabyte; - rowBuf += pixDirection; - break; - } - column++; - if ( column == columns ) { // pixel packet run spans across rows - column = 0; - row++; - if ( row >= rows ) { - goto breakOut; - } - pixbuf += rowOffset; - rowBuf = pixbuf; - } - } - } - } -breakOut:; - pixbuf += rowOffset; - } - } - fclose( fin ); -} - -void MergeAlpha( byte *pix, byte *alpha, byte *pal, byte **out, int width, int height ){ - int size, i; - byte *data, *src, *srca; - - size = width * height; - data = malloc( size * 4 ); - if ( !data ) { - Error( "Could not allocate memory for true color image" ); - } - - *out = data; - src = pix; - srca = alpha; - - for ( i = 0; i < size; i++, src++, srca++ ) - { - *data++ = pal[*src * 3 + 0]; // r - *data++ = pal[*src * 3 + 1]; // g - *data++ = pal[*src * 3 + 2]; // b - *data++ = *srca; // a - } - free( pix ); - free( alpha ); - free( pal ); -} - -/* - ============== - LoadAnyImage - - Return Value: - false: paletted texture - true: true color RGBA image (no palette) - ============== - */ -qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height ){ - char ext[128]; - int len; - int alpha_width, alpha_height; - char alpha_name[128]; - byte *alpha_pixels; - - ExtractFileExtension( name, ext ); - - if ( palette ) { - *palette = NULL; - } - - if ( !Q_strcasecmp( ext, "lbm" ) ) { - LoadLBM( name, pixels, palette ); - if ( width ) { - *width = bmhd.w; - } - if ( height ) { - *height = bmhd.h; - } - return false; - } - else if ( !Q_strcasecmp( ext, "pcx" ) ) { - len = strlen( name ); - strcpy( alpha_name, name ); - strcpy( &alpha_name[len - 4], "_a.pcx" ); // Alpha map name (may not exist) - - if ( FileExists( alpha_name ) ) { - LoadPCX( name, pixels, palette, width, height ); // Load in image - LoadPCX( alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height ); // Load in alpha map - if ( ( *width != alpha_width ) || ( *height != alpha_height ) ) { - Error( "Alpha image dimensions not equal to graphic image dimensions" ); - } - MergeAlpha( *pixels, alpha_pixels, *palette, pixels, *width, *height ); - *palette = NULL; //Merge Frees pal - return true; - } - else - { - LoadPCX( name, pixels, palette, width, height ); // Load in image - return false; - } - } - else if ( !Q_strcasecmp( ext, "tga" ) ) { - LoadTGA( name, pixels, width, height ); - if ( palette ) { - *palette = NULL; - } - - return true; - } - else{ - Error( "%s doesn't have a known image extension", name ); - } - - return false; -} diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.h b/tools/quake2/qdata_heretic2/common/lbmlib.h deleted file mode 100644 index 5ee2909f..00000000 --- a/tools/quake2/qdata_heretic2/common/lbmlib.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); diff --git a/tools/quake2/qdata_heretic2/common/mathlib.c b/tools/quake2/qdata_heretic2/common/mathlib.c deleted file mode 100644 index 8243d86d..00000000 --- a/tools/quake2/qdata_heretic2/common/mathlib.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - Copyright (C) 1999-2007 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; -} - -#if GDEF_COMPILER_MSVC -#pragma optimize("g", off) // went back to turning optimization off, - // the bug_fix thing stopped working -#endif - -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; -} - -#if GDEF_COMPILER_MSVC -#pragma optimize("", on) -#endif - -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; - } - } -} diff --git a/tools/quake2/qdata_heretic2/common/mathlib.h b/tools/quake2/qdata_heretic2/common/mathlib.h deleted file mode 100644 index cd989ea3..00000000 --- a/tools/quake2/qdata_heretic2/common/mathlib.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -/* - #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 diff --git a/tools/quake2/qdata_heretic2/common/md4.c b/tools/quake2/qdata_heretic2/common/md4.c deleted file mode 100644 index f5034220..00000000 --- a/tools/quake2/qdata_heretic2/common/md4.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - mdfour.c - - An implementation of MD4 designed for use in the samba SMB - authentication protocol - - Copyright (C) 1997-1998 Andrew Tridgell - - This program 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. - - This program 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 this program; if not, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id: mdfour.c 7689 2007-11-12 14:28:40Z divverent $ - */ - -#include /* XoXus: needed for memset call */ -#include "md4.h" - -/* NOTE: This code makes no attempt to be fast! - - It assumes that a int is at least 32 bits long - */ - -static struct mdfour *m; - -#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 ) ) -#ifdef LARGE_INT32 -#define lshift( x,s ) ( ( ( ( x ) << ( s ) ) & 0xFFFFFFFF ) | ( ( ( x ) >> ( 32 - ( s ) ) ) & 0xFFFFFFFF ) ) -#else -#define lshift( x,s ) ( ( ( x ) << ( s ) ) | ( ( x ) >> ( 32 - ( s ) ) ) ) -#endif - -#define ROUND1( a,b,c,d,k,s ) a = lshift( a + F( b,c,d ) + X[k], s ) -#define ROUND2( a,b,c,d,k,s ) a = lshift( a + G( b,c,d ) + X[k] + 0x5A827999,s ) -#define ROUND3( a,b,c,d,k,s ) a = lshift( a + H( b,c,d ) + X[k] + 0x6ED9EBA1,s ) - -/* this applies md4 to 64 byte chunks */ -static void mdfour64( uint32 *M ){ - int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; - uint32 A,B,C,D; - - for ( j = 0; j < 16; j++ ) - X[j] = M[j]; - - A = m->A; B = m->B; C = m->C; D = m->D; - AA = A; BB = B; CC = C; DD = D; - - ROUND1( A,B,C,D, 0, 3 ); ROUND1( D,A,B,C, 1, 7 ); - ROUND1( C,D,A,B, 2, 11 ); ROUND1( B,C,D,A, 3, 19 ); - ROUND1( A,B,C,D, 4, 3 ); ROUND1( D,A,B,C, 5, 7 ); - ROUND1( C,D,A,B, 6, 11 ); ROUND1( B,C,D,A, 7, 19 ); - ROUND1( A,B,C,D, 8, 3 ); ROUND1( D,A,B,C, 9, 7 ); - ROUND1( C,D,A,B, 10, 11 ); ROUND1( B,C,D,A, 11, 19 ); - ROUND1( A,B,C,D, 12, 3 ); ROUND1( D,A,B,C, 13, 7 ); - ROUND1( C,D,A,B, 14, 11 ); ROUND1( B,C,D,A, 15, 19 ); - - ROUND2( A,B,C,D, 0, 3 ); ROUND2( D,A,B,C, 4, 5 ); - ROUND2( C,D,A,B, 8, 9 ); ROUND2( B,C,D,A, 12, 13 ); - ROUND2( A,B,C,D, 1, 3 ); ROUND2( D,A,B,C, 5, 5 ); - ROUND2( C,D,A,B, 9, 9 ); ROUND2( B,C,D,A, 13, 13 ); - ROUND2( A,B,C,D, 2, 3 ); ROUND2( D,A,B,C, 6, 5 ); - ROUND2( C,D,A,B, 10, 9 ); ROUND2( B,C,D,A, 14, 13 ); - ROUND2( A,B,C,D, 3, 3 ); ROUND2( D,A,B,C, 7, 5 ); - ROUND2( C,D,A,B, 11, 9 ); ROUND2( B,C,D,A, 15, 13 ); - - ROUND3( A,B,C,D, 0, 3 ); ROUND3( D,A,B,C, 8, 9 ); - ROUND3( C,D,A,B, 4, 11 ); ROUND3( B,C,D,A, 12, 15 ); - ROUND3( A,B,C,D, 2, 3 ); ROUND3( D,A,B,C, 10, 9 ); - ROUND3( C,D,A,B, 6, 11 ); ROUND3( B,C,D,A, 14, 15 ); - ROUND3( A,B,C,D, 1, 3 ); ROUND3( D,A,B,C, 9, 9 ); - ROUND3( C,D,A,B, 5, 11 ); ROUND3( B,C,D,A, 13, 15 ); - ROUND3( A,B,C,D, 3, 3 ); ROUND3( D,A,B,C, 11, 9 ); - ROUND3( C,D,A,B, 7, 11 ); ROUND3( B,C,D,A, 15, 15 ); - - A += AA; B += BB; C += CC; D += DD; - -#ifdef LARGE_INT32 - A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; - C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; -#endif - - for ( j = 0; j < 16; j++ ) - X[j] = 0; - - m->A = A; m->B = B; m->C = C; m->D = D; -} - -static void copy64( uint32 *M, unsigned char *in ){ - int i; - - for ( i = 0; i < 16; i++ ) - M[i] = ( in[i * 4 + 3] << 24 ) | ( in[i * 4 + 2] << 16 ) | - ( in[i * 4 + 1] << 8 ) | ( in[i * 4 + 0] << 0 ); -} - -static void copy4( unsigned char *out,uint32 x ){ - out[0] = x & 0xFF; - out[1] = ( x >> 8 ) & 0xFF; - out[2] = ( x >> 16 ) & 0xFF; - out[3] = ( x >> 24 ) & 0xFF; -} - -void mdfour_begin( struct mdfour *md ){ - md->A = 0x67452301; - md->B = 0xefcdab89; - md->C = 0x98badcfe; - md->D = 0x10325476; - md->totalN = 0; -} - - -static void mdfour_tail( unsigned char *in, int n ){ - unsigned char buf[128]; - uint32 M[16]; - uint32 b; - - m->totalN += n; - - b = m->totalN * 8; - - memset( buf, 0, 128 ); - if ( n ) { - memcpy( buf, in, n ); - } - buf[n] = 0x80; - - if ( n <= 55 ) { - copy4( buf + 56, b ); - copy64( M, buf ); - mdfour64( M ); - } - else { - copy4( buf + 120, b ); - copy64( M, buf ); - mdfour64( M ); - copy64( M, buf + 64 ); - mdfour64( M ); - } -} - -void mdfour_update( struct mdfour *md, unsigned char *in, int n ){ - uint32 M[16]; - -// start of edit by Forest 'LordHavoc' Hale -// commented out to prevent crashing when length is 0 -// if (n == 0) mdfour_tail(in, n); -// end of edit by Forest 'LordHavoc' Hale - - m = md; - - while ( n >= 64 ) { - copy64( M, in ); - mdfour64( M ); - in += 64; - n -= 64; - m->totalN += 64; - } - - mdfour_tail( in, n ); -} - - -void mdfour_result( struct mdfour *md, unsigned char *out ){ - m = md; - - copy4( out, m->A ); - copy4( out + 4, m->B ); - copy4( out + 8, m->C ); - copy4( out + 12, m->D ); -} - - -void mdfour( unsigned char *out, unsigned char *in, int n ){ - struct mdfour md; - mdfour_begin( &md ); - mdfour_update( &md, in, n ); - mdfour_result( &md, out ); -} - -/////////////////////////////////////////////////////////////// -// MD4-based checksum utility functions -// -// Copyright (C) 2000 Jeff Teunissen -// -// Author: Jeff Teunissen -// Date: 01 Jan 2000 - -unsigned Com_BlockChecksum( void *buffer, int length ){ - int digest[4]; - unsigned val; - - mdfour( (unsigned char *) digest, (unsigned char *) buffer, length ); - - val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; - - return val; -} - -void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ){ - mdfour( outbuf, (unsigned char *) buffer, len ); -} diff --git a/tools/quake2/qdata_heretic2/common/md4.h b/tools/quake2/qdata_heretic2/common/md4.h deleted file mode 100644 index 6f64c289..00000000 --- a/tools/quake2/qdata_heretic2/common/md4.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - mdfour.h - - an implementation of MD4 designed for use in the SMB authentication - protocol - - Copyright (C) Andrew Tridgell 1997-1998 - - This program 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. - - This program 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 this program; if not, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - */ - -#ifndef _MDFOUR_H -#define _MDFOUR_H - -#ifndef int32 -#define int32 int -#endif - -#if SIZEOF_INT > 4 -#define LARGE_INT32 -#endif - -#ifndef uint32 -#define uint32 unsigned int32 -#endif - -struct mdfour { - uint32 A, B, C, D; - uint32 totalN; -}; - -void mdfour_begin( struct mdfour *md ); // old: MD4Init -void mdfour_update( struct mdfour *md, unsigned char *in, int n ); //old: MD4Update -void mdfour_result( struct mdfour *md, unsigned char *out ); // old: MD4Final -void mdfour( unsigned char *out, unsigned char *in, int n ); - -unsigned Com_BlockChecksum( void *buffer, int length ); -void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ); - -#endif // _MDFOUR_H diff --git a/tools/quake2/qdata_heretic2/common/path_init.c b/tools/quake2/qdata_heretic2/common/path_init.c deleted file mode 100644 index 254977bc..00000000 --- a/tools/quake2/qdata_heretic2/common/path_init.c +++ /dev/null @@ -1,391 +0,0 @@ -/* ------------------------------------------------------------------------------- - - Copyright (C) 1999-2007 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 - */ - -#include "globaldefs.h" - -#if !GDEF_OS_WINDOWS - #include - #include - #include -#endif // !GDEF_OS_WINDOWS - -/* 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 ){ - #if GDEF_OS_WINDOWS - return NULL; - #else // !GDEF_OS_WINDOWS - 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 // !GDEF_OS_WINDOWS -} - - - -/* - PathLokiInitPaths() - initializes some paths on linux/os x - */ - -void LokiInitPaths( char *argv0 ){ - #if GDEF_OS_WINDOWS - /* this is kinda crap, but hey */ - strcpy( installPath, "../" ); - #else // !GDEF_OS_WINDOWS - 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 // !GDEF_OS_WINDOWS -} - - - -/* - 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 ){ - #if !GDEF_OS_WINDOWS - 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 // !GDEF_OS_WINDOWS -} - - - -/* - 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" ); -} diff --git a/tools/quake2/qdata_heretic2/common/polylib.c b/tools/quake2/qdata_heretic2/common/polylib.c deleted file mode 100644 index af5df499..00000000 --- a/tools/quake2/qdata_heretic2/common/polylib.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - Copyright (C) 1999-2007 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; -} diff --git a/tools/quake2/qdata_heretic2/common/polylib.h b/tools/quake2/qdata_heretic2/common/polylib.h deleted file mode 100644 index 00b7b394..00000000 --- a/tools/quake2/qdata_heretic2/common/polylib.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); diff --git a/tools/quake2/qdata_heretic2/common/qfiles.c b/tools/quake2/qdata_heretic2/common/qfiles.c deleted file mode 100644 index 53452f36..00000000 --- a/tools/quake2/qdata_heretic2/common/qfiles.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - -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; -} diff --git a/tools/quake2/qdata_heretic2/common/qfiles.h b/tools/quake2/qdata_heretic2/common/qfiles.h deleted file mode 100644 index bee4b4fc..00000000 --- a/tools/quake2/qdata_heretic2/common/qfiles.h +++ /dev/null @@ -1,619 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/common/scriplib.c b/tools/quake2/qdata_heretic2/common/scriplib.c deleted file mode 100644 index af5e5716..00000000 --- a/tools/quake2/qdata_heretic2/common/scriplib.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - Copyright (C) 1999-2007 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; -} diff --git a/tools/quake2/qdata_heretic2/common/scriplib.h b/tools/quake2/qdata_heretic2/common/scriplib.h deleted file mode 100644 index 8c441c8b..00000000 --- a/tools/quake2/qdata_heretic2/common/scriplib.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); diff --git a/tools/quake2/qdata_heretic2/common/threads.c b/tools/quake2/qdata_heretic2/common/threads.c deleted file mode 100644 index 239226b7..00000000 --- a/tools/quake2/qdata_heretic2/common/threads.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "globaldefs.h" - -#if !GDEF_OS_WINDOWS -// The below define is necessary to use -// pthreads extensions like pthread_mutexattr_settype -#define _GNU_SOURCE -#endif // !GDEF_OS_WINDOWS - -#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 ); -} - - -#if GDEF_OS_WINDOWS - -/* - =================================================================== - - WIN32 - - =================================================================== - */ - -#include - -// 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 ); - } -} - - -#elif GDEF_OS_OSF1 - -/* - =================================================================== - - OSF1 - - =================================================================== - */ - -int numthreads = 4; - -void ThreadSetDefault( void ){ - if ( numthreads == -1 ) { // not set manually - numthreads = 4; - } -} - - -#include - -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 ); - } -} - - -#elif GDEF_OS_IRIX - -/* - =================================================================== - - IRIX - - =================================================================== - */ - -#include -#include -#include -#include - -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 ); - } -} - - -#elif GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS - -/* - ======================================================================= - - Linux pthreads - - ======================================================================= - */ - -// 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 - -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 ( pthread_mutexattr_settype( &mattrib, PTHREAD_MUTEX_ERRORCHECK ) != 0 ) { - 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 ); - } -} - - -#else // UNKNOWN OS - -/* - ======================================================================= - - SINGLE THREAD - - ======================================================================= - */ - -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 // UNKNOWN OS diff --git a/tools/quake2/qdata_heretic2/common/token.c b/tools/quake2/qdata_heretic2/common/token.c deleted file mode 100644 index 632cfe40..00000000 --- a/tools/quake2/qdata_heretic2/common/token.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - Copyright (C) 1999-2007 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[] = -{ - "", - "", - "", - "", - "", - "", - "", - "(", - ")", - "{", - "}", - "[", - "]", - ":", - "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 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; - } -} diff --git a/tools/quake2/qdata_heretic2/common/token.h b/tools/quake2/qdata_heretic2/common/token.h deleted file mode 100644 index 6dca1a1a..00000000 --- a/tools/quake2/qdata_heretic2/common/token.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/common/trilib.c b/tools/quake2/qdata_heretic2/common/trilib.c deleted file mode 100644 index 29acab6f..00000000 --- a/tools/quake2/qdata_heretic2/common/trilib.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include "cmdlib.h" -#include "inout.h" -#include "mathlib.h" -#include "trilib.h" -#include "token.h" -#include "l3dslib.h" -#include "fmodel.h" -#if 1 -#include "qd_skeletons.h" -#endif - -// on disk representation of a face -#define FLOAT_START 99999.0 -#define FLOAT_END -FLOAT_START -#define MAGIC 123322 -#ifndef M_PI - #define M_PI 3.14159265 -#endif - -float FixHTRRotateX = 0.0; -float FixHTRRotateY = 0.0; -float FixHTRRotateZ = 0.0; -float FixHTRTranslateX = 0.0; -float FixHTRTranslateY = 0.0; -float FixHTRTranslateZ = 0.0; - -//#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 LoadTRI( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){ - 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; - - if ( nodesList ) { - *num_mesh_nodes = 0; - *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); - } - - 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 ); - - DefaultNodesList( nodesList,num_mesh_nodes,numtriangles ); -} - - -//========================================================================== -// -// LoadHRC -// -//========================================================================== - -float scaling[3]; -float rotation[3]; -float translation[3]; -static char *hrc_name; - -struct -{ - float v[3]; -} vList[8192]; - -void HandleHRCModel( triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes, - int ActiveNode, int Depth, int numVerts ){ - void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ); - - int i, j; - int vertexCount; - int triCount; - triangle_t *tList; - mesh_node_t *meshNode; - float x, y, z; - float x2, y2, z2; - float rx, ry, rz; - tokenType_t nextToken; - float orig_scaling[3]; - float orig_rotation[3]; - float orig_translation[3]; - int start_tri; - int pos,bit; - int vertIndexBase; - - // Update Node Info - if ( nodesList ) { - TK_BeyondRequire( TK_NAME, TK_STRING ); - - if ( Depth == 0 || tk_String[0] == '_' ) { // Root - ActiveNode = *num_mesh_nodes; - ( *num_mesh_nodes )++; - if ( ( *num_mesh_nodes ) > MAX_FM_MESH_NODES ) { - Error( "Too many mesh nodes in file %s\n", hrc_name ); - } - meshNode = &( *nodesList )[ActiveNode]; - -// memset(meshNode, 0, sizeof(mesh_node_t)); - strcpy( meshNode->name, tk_String ); - - memset( meshNode->tris, 0, sizeof( meshNode->tris ) ); - memset( meshNode->verts, 0, sizeof( meshNode->verts ) ); - - meshNode->start_glcmds = 0; - meshNode->num_glcmds = 0; - vertIndexBase = 0; - } - else - { // Childs under the children - meshNode = &( *nodesList )[ActiveNode]; - vertIndexBase = numVerts; - } - } - else - { - meshNode = NULL; - } - - - // Get the scaling, rotation, and translation values - TK_Beyond( TK_SCALING ); - for ( i = 0; i < 3; i++ ) - { - orig_scaling[i] = scaling[i]; - - TK_Require( TK_FLOATNUMBER ); - scaling[i] *= tk_FloatNumber; - - TK_Fetch(); - } - TK_Beyond( TK_ROTATION ); - for ( i = 0; i < 3; i++ ) - { - orig_rotation[i] = rotation[i]; - - TK_Require( TK_FLOATNUMBER ); - rotation[i] = tk_FloatNumber; - - TK_Fetch(); - } - TK_Beyond( TK_TRANSLATION ); - for ( i = 0; i < 3; i++ ) - { - orig_translation[i] = translation[i]; - - TK_Require( TK_FLOATNUMBER ); - translation[i] += tk_FloatNumber; - - TK_Fetch(); - } - - rx = ( ( rotation[0] - 90.0 ) / 360.0 ) * 2.0 * M_PI; - ry = ( rotation[2] / 360.0 ) * 2.0 * M_PI; - rz = ( rotation[1] / 360.0 ) * 2.0 * M_PI; - - // rjr - might not work if there an item doesn't have a mesh - nextToken = tk_Token; - if ( nextToken == TK_ACTOR_DATA ) { - while ( nextToken != TK_MODEL && nextToken != TK_RBRACE ) - { - nextToken = TK_Fetch(); - } - } - - while ( nextToken == TK_SPLINE ) - { // spline node has two right braces - nextToken = TK_Beyond( TK_RBRACE ); - nextToken = TK_Beyond( TK_RBRACE ); - } - - while ( nextToken == TK_MATERIAL ) - { - nextToken = TK_Beyond( TK_RBRACE ); - } - - while ( nextToken == TK_MODEL ) - { - HandleHRCModel( triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth + 1, 0 ); - - nextToken = TK_Fetch(); - } - - if ( nextToken == TK_MESH ) { - // Get all the tri and vertex info - TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER ); - vertexCount = tk_IntNumber; - for ( i = 0; i < vertexCount; i++ ) - { - TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); - if ( tk_IntNumber != i ) { - Error( "File '%s', line %d:\nVertex index mismatch.\n", - tk_SourceName, tk_Line ); - } - TK_Beyond( TK_POSITION ); - // Apply the scaling, rotation, and translation in the order - // specified in the HRC file. This could be wrong. - TK_Require( TK_FLOATNUMBER ); - x = tk_FloatNumber * scaling[0]; - TK_FetchRequire( TK_FLOATNUMBER ); - y = tk_FloatNumber * scaling[1]; - TK_FetchRequire( TK_FLOATNUMBER ); - z = tk_FloatNumber * scaling[2]; - - 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; - - x2 = x * cos( rz ) + y*sin( rz ); - y2 = -x*sin( rz ) + y*cos( rz ); - x = x2; - y = y2; - - vList[i].v[0] = x + translation[0]; - vList[i].v[1] = y - translation[2]; - vList[i].v[2] = z + translation[1]; - } - TK_BeyondRequire( TK_POLYGONS, TK_INTNUMBER ); - triCount = tk_IntNumber; - if ( triCount >= MAXTRIANGLES ) { - Error( "Too many triangles in file %s\n", hrc_name ); - } - - start_tri = *triangleCount; - *triangleCount += triCount; - - tList = *triList; - - for ( i = 0; i < triCount; i++ ) - { - if ( meshNode ) { // Update the node - pos = ( i + start_tri ) >> 3; - bit = 1 << ( ( i + start_tri ) & 7 ); - meshNode->tris[pos] |= bit; - } - - TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); - if ( tk_IntNumber != i ) { - Error( "File '%s', line %d:\nTriangle index mismatch.\n", - tk_SourceName, tk_Line ); - } - TK_BeyondRequire( TK_NODES, TK_INTNUMBER ); - if ( tk_IntNumber != 3 ) { - Error( "File '%s', line %d:\nBad polygon vertex count: %d.", - tk_SourceName, tk_Line, tk_IntNumber ); - } - tList[i + start_tri].HasUV = true; - for ( j = 0; j < 3; j++ ) - { - TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER ); - if ( tk_IntNumber != j ) { - Error( "File '%s', line %d:\nTriangle vertex index" - " mismatch. %d should be %d\n", tk_SourceName, tk_Line, - tk_IntNumber, j ); - } - TK_BeyondRequire( TK_VERTEX, TK_INTNUMBER ); - - tList[i + start_tri].verts[2 - j][0] = vList[tk_IntNumber].v[0]; - tList[i + start_tri].verts[2 - j][1] = vList[tk_IntNumber].v[1]; - tList[i + start_tri].verts[2 - j][2] = vList[tk_IntNumber].v[2]; -#if 1 - tList[i + start_tri].indicies[2 - j] = tk_IntNumber + vertIndexBase; -#endif - TK_BeyondRequire( TK_UVTEXTURE, TK_FLOATNUMBER ); - tList[i + start_tri].uv[2 - j][0] = tk_FloatNumber; - TK_Fetch(); - TK_Require( TK_FLOATNUMBER ); - tList[i + start_tri].uv[2 - j][1] = tk_FloatNumber; - } - - /* 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]); - */ - } - - TK_Beyond( TK_RBRACE ); - TK_Beyond( TK_RBRACE ); - - if ( tk_Token == TK_EDGES ) { - // TK_Beyond(TK_EDGES); - TK_Beyond( TK_RBRACE ); - } - - scaling[0] = scaling[1] = scaling[2] = 1.0; - // rotation[0] = rotation[1] = rotation[2] = 0.0; - // translation[0] = translation[1] = translation[2] = 0.0; - - // See if there are any other models belonging to this node - -#if 1 - TK_Fetch(); - - nextToken = tk_Token; - if ( nextToken == TK_CLUSTERS ) { - if ( g_skelModel.clustered == -1 ) { - ReadHRCClusterList( meshNode, vertIndexBase ); - } - else - { - nextToken = TK_Get( TK_CLUSTER_NAME ); - - while ( nextToken == TK_CLUSTER_NAME ) - { - TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER ); - nextToken = TK_Fetch(); - } - } - - // one right brace follow the list of clusters - nextToken = TK_Beyond( TK_RBRACE ); - } - else - { - if ( g_skelModel.clustered == -1 && !vertIndexBase ) { - meshNode->clustered = false; - } - } -#endif - - nextToken = tk_Token; - if ( nextToken == TK_SPLINE ) { - while ( nextToken == TK_SPLINE ) - { // spline node has two right braces - nextToken = TK_Beyond( TK_RBRACE ); - nextToken = TK_Beyond( TK_RBRACE ); - } - - nextToken = TK_Beyond( TK_RBRACE ); - } - - while ( nextToken == TK_MATERIAL ) - { - nextToken = TK_Beyond( TK_RBRACE ); - } - - while ( nextToken == TK_MODEL ) - { - HandleHRCModel( triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth + 1, vertexCount + vertIndexBase ); - - nextToken = TK_Fetch(); - } - } - - for ( i = 0; i < 3; i++ ) - { - scaling[i] = orig_scaling[i]; - rotation[i] = orig_rotation[i]; - translation[i] = orig_translation[i]; - } -} - -static void LoadHRC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){ - if ( nodesList ) { - *num_mesh_nodes = 0; - - if ( !*nodesList ) { - *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); - } - } - - hrc_name = fileName; - - scaling[0] = scaling[1] = scaling[2] = 1.0; - rotation[0] = rotation[1] = rotation[2] = 0.0; - translation[0] = translation[1] = translation[2] = 0.0; - - *triangleCount = 0; - *triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" ); - memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) ); - - TK_OpenSource( fileName ); - TK_FetchRequire( TK_HRCH ); - TK_FetchRequire( TK_COLON ); - TK_FetchRequire( TK_SOFTIMAGE ); - - // prime it - TK_Beyond( TK_MODEL ); - - HandleHRCModel( triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0 ); - TK_CloseSource(); -} - -//========================================================================== -// -// LoadHTR -// -//========================================================================== -/* - static int Version2; - - void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes, - int ActiveNode, int Depth, int numVerts) - { - int i, j; - int vertexCount; - int vertexNum; - int triCount; - float origin[3]; - triangle_t *tList; - float x, y, z; - float x2, y2, z2; - float rx, ry, rz; - mesh_node_t *meshNode; - int pos,bit; - int vertIndexBase; - int start_tri; - - if (nodesList) - { - TK_BeyondRequire(TK_NAME, TK_STRING); - - if (Depth == 0 || tk_String[0] == '_') - { // Root - ActiveNode = *num_mesh_nodes; - (*num_mesh_nodes)++; - if ((*num_mesh_nodes) > MAX_FM_MESH_NODES) - { - Error("Too many mesh nodes in file %s\n", hrc_name); - } - meshNode = &(*nodesList)[ActiveNode]; - - // memset(meshNode, 0, sizeof(mesh_node_t)); - strcpy(meshNode->name, tk_String); - - memset(meshNode->tris, 0, sizeof(meshNode->tris)); - memset(meshNode->verts, 0, sizeof(meshNode->verts)); - - meshNode->start_glcmds = 0; - meshNode->num_glcmds = 0; - vertIndexBase = 0; - } - else - { // Childs under the children - meshNode = &(*nodesList)[ActiveNode]; - vertIndexBase = numVerts; - } - } - else - { - meshNode = NULL; - } - - // Get vertex count - TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER); - vertexCount = tk_IntNumber; - - // Get triangle count - TK_BeyondRequire(TK_FACES, TK_INTNUMBER); - triCount = tk_IntNumber; - if(triCount >= MAXTRIANGLES) - { - Error("Too many triangles in file %s\n", hrc_name); - } - - // Get origin - TK_Beyond(TK_ORIGIN); - TK_Require(TK_FLOATNUMBER); - origin[0] = tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - origin[1] = tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - origin[2] = tk_FloatNumber; - - //rx = 90.0/360.0*2.0*M_PI; - rx = FixHTRRotateX/360.0*2.0*M_PI; - ry = FixHTRRotateY/360.0*2.0*M_PI; - rz = FixHTRRotateZ/360.0*2.0*M_PI; - - // Get vertex list - for(i = 0; i < vertexCount; i++) - { - TK_FetchRequire(TK_VERTEX); - TK_FetchRequire(TK_FLOATNUMBER); - x = tk_FloatNumber-origin[0]; - TK_FetchRequire(TK_FLOATNUMBER); - y = tk_FloatNumber-origin[1]; - TK_FetchRequire(TK_FLOATNUMBER); - z = tk_FloatNumber-origin[2]; - - x += FixHTRTranslateX; - y += FixHTRTranslateY; - z += FixHTRTranslateZ; - - 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; - x2 = x*cos(rz)-y*sin(rz); - y2 = x*sin(rz)+y*cos(rz); - x = x2; - y = y2; - - vList[i].v[0] = x; - vList[i].v[1] = y; - vList[i].v[2] = z; - } - - start_tri = *triangleCount; - *triangleCount += triCount; - - tList = *triList; - - // Get face list - for(i = 0; i < triCount; i++) - { - if (meshNode) - { // Update the node - pos = (i + start_tri) >> 3; - bit = 1 << ((i + start_tri) & 7 ); - meshNode->tris[pos] |= bit; - } - - TK_FetchRequire(TK_FACE); - TK_FetchRequire(TK_LPAREN); - for(j = 0; j < 3; j++) - { - TK_FetchRequire(TK_INTNUMBER); - vertexNum = tk_IntNumber-1; - if(vertexNum >= vertexCount) - { - Error("File '%s', line %d:\nVertex number" - " >= vertexCount: %d\n", tk_SourceName, tk_Line, - tk_IntNumber); - } - tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0]; - tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1]; - tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2]; - } - TK_FetchRequire(TK_RPAREN); - #ifdef _QDATA - if (Version2) - { - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[0][0]=tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[0][1]=tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[1][0]=tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[1][1]=tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[2][0]=tk_FloatNumber; - TK_FetchRequire(TK_FLOATNUMBER); - tList[i+start_tri].uv[2][1]=tk_FloatNumber; - tList[i+start_tri].HasUV=1; - } - else - tList[i+start_tri].HasUV=0; - #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]); - - } - - TK_Fetch(); - - if (tk_Token == TK_VERTICES) - { - HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase); - } - } - - static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes) - { - if (nodesList) - { - *num_mesh_nodes = 0; - - if(!*nodesList) - { - *nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List"); - } - } - - hrc_name = fileName; - - scaling[0] = scaling[1] = scaling[2] = 1.0; - rotation[0] = rotation[1] = rotation[2] = 0.0; - translation[0] = translation[1] = translation[2] = 0.0; - - *triangleCount = 0; - *triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list"); - memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t)); - - TK_OpenSource(fileName); - - TK_Beyond(TK_C_HEXEN); - TK_Beyond(TK_C_TRIANGLES); - TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER); - if(tk_IntNumber != 1&&tk_IntNumber != 2) - { - Error("Unsupported version (%d) in file %s\n", tk_IntNumber, - fileName); - } - Version2=(tk_IntNumber==2); - - - HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0); - } - - */ - -static void LoadHTR( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){ - int Version2 = 0; - int i, j; - int vertexCount; - int vertexNum; - struct - { - float v[3]; - } *vList; - int triCount; - float origin[3]; - triangle_t *tList; - float x, y, z; - float x2, y2, z2; - float rx, ry, rz; - - 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 ); - - TK_Beyond( TK_C_HEXEN ); - TK_Beyond( TK_C_TRIANGLES ); - TK_BeyondRequire( TK_C_VERSION, TK_INTNUMBER ); - if ( tk_IntNumber != 1 && tk_IntNumber != 2 ) { - Error( "Unsupported version (%d) in file %s\n", tk_IntNumber, - fileName ); - } - Version2 = ( tk_IntNumber == 2 ); - - - // Get vertex count - TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER ); - vertexCount = tk_IntNumber; - vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" ); - - // Get triangle count - TK_BeyondRequire( TK_FACES, 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 ) ); - - // Get origin - TK_Beyond( TK_ORIGIN ); - TK_Require( TK_FLOATNUMBER ); - origin[0] = tk_FloatNumber; - TK_FetchRequire( TK_FLOATNUMBER ); - origin[1] = tk_FloatNumber; - TK_FetchRequire( TK_FLOATNUMBER ); - origin[2] = tk_FloatNumber; - - //rx = 90.0/360.0*2.0*M_PI; - rx = FixHTRRotateX / 360.0 * 2.0 * M_PI; - ry = FixHTRRotateY / 360.0 * 2.0 * M_PI; - rz = FixHTRRotateZ / 360.0 * 2.0 * M_PI; - - // Get vertex list - for ( i = 0; i < vertexCount; i++ ) - { - TK_FetchRequire( TK_VERTEX ); - TK_FetchRequire( TK_FLOATNUMBER ); - x = tk_FloatNumber - origin[0]; - TK_FetchRequire( TK_FLOATNUMBER ); - y = tk_FloatNumber - origin[1]; - TK_FetchRequire( TK_FLOATNUMBER ); - z = tk_FloatNumber - origin[2]; - - x += FixHTRTranslateX; - y += FixHTRTranslateY; - z += FixHTRTranslateZ; - - 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; - x2 = x * cos( rz ) - y*sin( rz ); - y2 = x * sin( rz ) + y*cos( rz ); - x = x2; - y = y2; - - vList[i].v[0] = x; - vList[i].v[1] = y; - vList[i].v[2] = z; - } - - // Get face list - for ( i = 0; i < triCount; i++ ) - { - TK_FetchRequire( TK_FACE ); - TK_FetchRequire( TK_LPAREN ); - for ( j = 0; j < 3; j++ ) - { - TK_FetchRequire( TK_INTNUMBER ); - vertexNum = tk_IntNumber - 1; - if ( vertexNum >= vertexCount ) { - Error( "File '%s', line %d:\nVertex number" - " >= vertexCount: %d\n", tk_SourceName, tk_Line, - tk_IntNumber ); - } - tList[i].verts[2 - j][0] = vList[vertexNum].v[0]; - tList[i].verts[2 - j][1] = vList[vertexNum].v[1]; - tList[i].verts[2 - j][2] = vList[vertexNum].v[2]; - } - TK_FetchRequire( TK_RPAREN ); -#if 1 - if ( Version2 ) { - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[2][0] = fmod( 1000 + tk_FloatNumber,1 ); - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[2][1] = fmod( 1000 + tk_FloatNumber,1 ); - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[1][0] = fmod( 1000 + tk_FloatNumber,1 ); - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[1][1] = fmod( 1000 + tk_FloatNumber,1 ); - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[0][0] = fmod( 1000 + tk_FloatNumber,1 ); - TK_FetchRequire( TK_FLOATNUMBER ); - tList[i].uv[0][1] = fmod( 1000 + tk_FloatNumber,1 ); - tList[i].HasUV = 1; - } - else{ - tList[i].HasUV = 0; - } -#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]); - */ - } - - free( vList ); - TK_CloseSource(); - DefaultNodesList( nodesList,num_mesh_nodes,triangleCount ); -} - -//========================================================================== -// -// LoadTriangleList -// -//========================================================================== - -void LoadTriangleList( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes ){ - 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 ); - LoadHRC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - printf( " - assuming .HRC\n" ); - return; - } - - strcpy( InputFileName, fileName ); - strcat( InputFileName, ".asc" ); - if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { - fclose( file1 ); - LoadASC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - printf( " - assuming .ASC\n" ); - return; - } - - strcpy( InputFileName, fileName ); - strcat( InputFileName, ".tri" ); - if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { - fclose( file1 ); - LoadTRI( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - printf( " - assuming .TRI\n" ); - return; - } - - strcpy( InputFileName, fileName ); - strcat( InputFileName, ".3ds" ); - if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { - fclose( file1 ); - Load3DSTriangleList( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - printf( " - assuming .3DS\n" ); - return; - } - - strcpy( InputFileName, fileName ); - strcat( InputFileName, ".htr" ); - if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) { - fclose( file1 ); - LoadHTR( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - printf( " - assuming .HTR\n" ); - return; - } - Error( "\n Could not open file '%s':\n" - "No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName ); - } - else - { - if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) { - printf( "\n" ); - fclose( file1 ); - if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) { - LoadHRC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - } - else if ( strcmp( dotstart,".asc" ) == 0 || strcmp( dotstart,".ASC" ) == 0 ) { - LoadASC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - } - else if ( strcmp( dotstart,".tri" ) == 0 || strcmp( dotstart,".TRI" ) == 0 ) { - LoadTRI( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - } - else if ( strcmp( dotstart,".3ds" ) == 0 || strcmp( dotstart,".3DS" ) == 0 ) { - Load3DSTriangleList( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - } - else if ( strcmp( dotstart,".htr" ) == 0 || strcmp( dotstart,".HTR" ) == 0 ) { - LoadHTR( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes ); - } - else - { - Error( "Could not open file '%s':\n",fileName ); - return; - } - } - else //failed to load file - { - Error( "Could not open file '%s':\n",fileName ); - } - - } -} diff --git a/tools/quake2/qdata_heretic2/common/trilib.h b/tools/quake2/qdata_heretic2/common/trilib.h deleted file mode 100644 index 8dfd6d28..00000000 --- a/tools/quake2/qdata_heretic2/common/trilib.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); diff --git a/tools/quake2/qdata_heretic2/fmodels.c b/tools/quake2/qdata_heretic2/fmodels.c deleted file mode 100644 index 7d8df18a..00000000 --- a/tools/quake2/qdata_heretic2/fmodels.c +++ /dev/null @@ -1,3311 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "qd_fmodel.h" -#include "animcomp.h" -#include "qd_skeletons.h" -#include "skeletons.h" -#include "qdata.h" -#include "flex.h" -#include "reference.h" - -#include - -/* - ======================================================================== - - .FM triangle flexible model file format - - ======================================================================== - */ - -//================================================================= - -#define NUMVERTEXNORMALS 162 - -extern float avertexnormals[NUMVERTEXNORMALS][3]; - -#define MAX_GROUPS 128 - -typedef struct -{ - triangle_t triangle; - int group; -} trigroup_t; - -#define TRIVERT_DIST .1 - -typedef struct -{ - int start_frame; - int num_frames; - int degrees; - char *mat; - char *ccomp; - char *cbase; - float *cscale; - float *coffset; - float trans[3]; - float scale[3]; - float bmin[3]; - float bmax[3]; -} fmgroup_t; - -//================================================================ - -// Initial -fmheader_t fmheader; - -// Skin -extern char g_skins[MAX_FM_SKINS][64]; - -// ST Coord -extern fmstvert_t base_st[MAX_FM_VERTS]; - -// Triangles -extern fmtriangle_t triangles[MAX_FM_TRIANGLES]; - -// Frames -fmframe_t g_frames[MAX_FM_FRAMES]; -//fmframe_t *g_FMframes; - -// GL Commands -extern int commands[16384]; -extern int numcommands; - - -// -// varibles set by commands -// -extern float scale_up; // set by $scale -extern vec3_t adjust; // set by $origin -extern int g_fixedwidth, g_fixedheight; // set by $skinsize -extern char modelname[64]; // set by $modelname - - -extern char *g_outputDir; - - -// Mesh Nodes -mesh_node_t *pmnodes = NULL; -fmmeshnode_t mesh_nodes[MAX_FM_MESH_NODES]; - -fmgroup_t groups[MAX_GROUPS]; -int num_groups; -int frame_to_group[MAX_FM_FRAMES]; - -// -// variables set by command line arguments -// -qboolean g_no_opimizations = false; - - -// -// base frame info -// -static int triangle_st[MAX_FM_TRIANGLES][3][2]; - - -// number of gl vertices -extern int numglverts; -// indicates if a triangle has already been used in a glcmd -extern int used[MAX_FM_TRIANGLES]; -// indicates if a triangle has translucency in it or not -static qboolean translucent[MAX_FM_TRIANGLES]; - -// main output file handle -extern FILE *headerouthandle; -// output sizes of buildst() -static int skin_width, skin_height; - - -// statistics -static int total_skin_pixels; -static int skin_pixels_used; - -int ShareVertex( trigroup_t trione, trigroup_t tritwo ); -float DistBetween( vec3_t point1, vec3_t point2 ); -int GetNumTris( trigroup_t *tris, int group ); -void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ); -void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ); -void NewDrawLine( int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height ); - -#if !GDEF_OS_WINDOWS - -void strupr( char *string ){ - int i; - - for ( i = 0 ; i < strlen( string ); i++ ) - toupper( string[i] ); - - return; -} - -#endif -//============================================================== - -/* - =============== - ClearModel - =============== - */ -static void ClearModel( void ){ - memset( &fmheader, 0, sizeof( fmheader ) ); - - modelname[0] = 0; - scale_up = 1.0; - VectorCopy( vec3_origin, adjust ); - g_fixedwidth = g_fixedheight = 0; - g_skipmodel = false; - num_groups = 0; - - if ( pmnodes ) { - free( pmnodes ); - pmnodes = NULL; - } - - ClearSkeletalModel(); -} - - -extern void H_printf( char *fmt, ... ); - - -void WriteHeader( FILE *FH, char *Ident, int Version, int Size, void *Data ){ - header_t header; - static long pos = -1; - long CurrentPos; - - if ( Size == 0 ) { // Don't write out empty packets - return; - } - - if ( pos != -1 ) { - CurrentPos = ftell( FH ); - Size = CurrentPos - pos + sizeof( header_t ); - fseek( FH, pos, SEEK_SET ); - pos = -2; - } - else if ( Size == -1 ) { - pos = ftell( FH ); - } - - memset( &header,0,sizeof( header ) ); - strcpy( header.ident,Ident ); - header.version = Version; - header.size = Size; - - SafeWrite( FH, &header, sizeof( header ) ); - - if ( Data ) { - SafeWrite( FH, Data, Size ); - } - - if ( pos == -2 ) { - pos = -1; - fseek( FH, 0, SEEK_END ); - } -} - -/* - ============ - WriteModelFile - ============ - */ -static void WriteModelFile( FILE *modelouthandle ){ - int i; - int j, k; - fmframe_t *in; - fmaliasframe_t *out; - byte buffer[MAX_FM_VERTS * 4 + 128]; - float v; - int c_on, c_off; - IntListNode_t *current, *toFree; - qboolean framesWritten = false; - size_t temp,size = 0; - - // probably should do this dynamically one of these days - struct - { - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this - } outFrames[MAX_FM_FRAMES]; - -#define DATA_SIZE 0x60000 // 384K had better be enough, particularly for the reference points - byte data[DATA_SIZE]; - byte data2[DATA_SIZE]; - - fmheader.num_glcmds = numcommands; - fmheader.framesize = (int)&( (fmaliasframe_t *)0 )->verts[fmheader.num_xyz]; - - WriteHeader( modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof( fmheader ), &fmheader ); - - // - // write out the skin names - // - - WriteHeader( modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins ); - - // - // write out the texture coordinates - // - c_on = c_off = 0; - for ( i = 0 ; i < fmheader.num_st ; i++ ) - { - base_st[i].s = LittleShort( base_st[i].s ); - base_st[i].t = LittleShort( base_st[i].t ); - } - - WriteHeader( modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof( base_st[0] ), base_st ); - - // - // write out the triangles - // - WriteHeader( modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof( fmtriangle_t ), NULL ); - - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - int j; - fmtriangle_t tri; - - for ( j = 0 ; j < 3 ; j++ ) - { - tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); - tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); - } - - SafeWrite( modelouthandle, &tri, sizeof( tri ) ); - } - - if ( !num_groups ) { - // - // write out the frames - // - WriteHeader( modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL ); - // WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL); - - for ( i = 0 ; i < fmheader.num_frames ; i++ ) - { - in = &g_frames[i]; - out = (fmaliasframe_t *)buffer; - - strcpy( out->name, in->name ); - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; - out->translate[j] = in->mins[j]; - - outFrames[i].scale[j] = out->scale[j]; - outFrames[i].translate[j] = out->translate[j]; - } - - for ( j = 0 ; j < fmheader.num_xyz ; j++ ) - { - // all of these are byte values, so no need to deal with endianness - out->verts[j].lightnormalindex = in->v[j].lightnormalindex; - - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - if ( v < 0 ) { - v = 0; - } - out->verts[j].v[k] = v; - } - } - - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = LittleFloat( out->scale[j] ); - out->translate[j] = LittleFloat( out->translate[j] ); - } - - SafeWrite( modelouthandle, out, fmheader.framesize ); - } - - // Go back and finish the header - // WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL); - } - else - { - WriteHeader( modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN * fmheader.num_frames, NULL ); - for ( i = 0 ; i < fmheader.num_frames ; i++ ) - { - in = &g_frames[i]; - SafeWrite( modelouthandle,in->name,FRAME_NAME_LEN ); - } - WriteHeader( modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL ); - in = &g_frames[0]; - for ( j = 0 ; j < fmheader.num_xyz ; j++ ) - SafeWrite( modelouthandle,&in->v[j].lightnormalindex,1 ); - } - - // - // write out glcmds - // - WriteHeader( modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands * 4, commands ); - - // - // write out mesh nodes - // - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { - memcpy( mesh_nodes[i].tris, pmnodes[i].tris, sizeof( mesh_nodes[i].tris ) ); - memcpy( mesh_nodes[i].verts, pmnodes[i].verts, sizeof( mesh_nodes[i].verts ) ); - mesh_nodes[i].start_glcmds = LittleShort( (short)pmnodes[i].start_glcmds ); - mesh_nodes[i].num_glcmds = LittleShort( (short)pmnodes[i].num_glcmds ); - } - - WriteHeader( modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof( fmmeshnode_t ) * fmheader.num_mesh_nodes, mesh_nodes ); - - if ( num_groups ) { - -/* - typedef struct - { - int start_frame; - int num_frames; - int degrees; - char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char) - char *ccomp; g->num_frames*g->degrees*sizeof(char) - char *cbase; fmheader.num_xyz*3*sizeof(unsigned char) - float *cscale; g->degrees*sizeof(float) - float *coffset; g->degrees*sizeof(float) - float trans[3]; 3*sizeof(float) - float scale[3]; 3*sizeof(float) - } fmgroup_t; - */ - int tmp,k; - fmgroup_t *g; - size = sizeof( int ) + fmheader.num_frames * sizeof( int ); - for ( k = 0; k < num_groups; k++ ) - { - g = &groups[k]; - size += sizeof( int ) * 3; - size += fmheader.num_xyz * 3 * g->degrees * sizeof( char ); - size += g->num_frames * g->degrees * sizeof( char ); - size += fmheader.num_xyz * 3 * sizeof( unsigned char ); - size += g->degrees * sizeof( float ); - size += g->degrees * sizeof( float ); - size += 12 * sizeof( float ); - } - WriteHeader( modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL ); - SafeWrite( modelouthandle,&num_groups,sizeof( int ) ); - SafeWrite( modelouthandle,frame_to_group,sizeof( int ) * fmheader.num_frames ); - - for ( k = 0; k < num_groups; k++ ) - { - g = &groups[k]; - tmp = LittleLong( g->start_frame ); - SafeWrite( modelouthandle,&tmp,sizeof( int ) ); - tmp = LittleLong( g->num_frames ); - SafeWrite( modelouthandle,&tmp,sizeof( int ) ); - tmp = LittleLong( g->degrees ); - SafeWrite( modelouthandle,&tmp,sizeof( int ) ); - - SafeWrite( modelouthandle,g->mat,fmheader.num_xyz * 3 * g->degrees * sizeof( char ) ); - SafeWrite( modelouthandle,g->ccomp,g->num_frames * g->degrees * sizeof( char ) ); - SafeWrite( modelouthandle,g->cbase,fmheader.num_xyz * 3 * sizeof( unsigned char ) ); - SafeWrite( modelouthandle,g->cscale,g->degrees * sizeof( float ) ); - SafeWrite( modelouthandle,g->coffset,g->degrees * sizeof( float ) ); - SafeWrite( modelouthandle,g->trans,3 * sizeof( float ) ); - SafeWrite( modelouthandle,g->scale,3 * sizeof( float ) ); - SafeWrite( modelouthandle,g->bmin,3 * sizeof( float ) ); - SafeWrite( modelouthandle,g->bmax,3 * sizeof( float ) ); - free( g->mat ); - free( g->ccomp ); - free( g->cbase ); - free( g->cscale ); - free( g->coffset ); - } - } - - // write the skeletal info - if ( g_skelModel.type != SKEL_NULL ) { - size = 0; - - temp = sizeof( int ); // change this to a byte - memcpy( data + size, &g_skelModel.type, temp ); - size += temp; - - // number of joints - temp = sizeof( int ); // change this to a byte - memcpy( data + size, &numJointsInSkeleton[g_skelModel.type], temp ); - size += temp; - - // number of verts in each joint cluster - temp = sizeof( int ) * numJointsInSkeleton[g_skelModel.type]; // change this to shorts - memcpy( data + size, &g_skelModel.new_num_verts[1], temp ); - size += temp; - - // cluster verts - for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) - { - current = g_skelModel.vertLists[i]; - while ( current ) - { - temp = sizeof( int ); // change this to a short - memcpy( data + size, ¤t->data, temp ); - size += temp; - toFree = current; - current = current->next; - free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base - } - } - - if ( !num_groups ) { // joints are stored with regular verts for compressed models - framesWritten = true; - - temp = sizeof( int ); // change this to a byte - memcpy( data + size, &framesWritten, temp ); - size += temp; - - for ( i = 0; i < fmheader.num_frames; ++i ) - { - in = &g_frames[i]; - - for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j ) - { - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data + size, &v, temp ); - size += temp; - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data + size, &v, temp ); - size += temp; - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data + size, &v, temp ); - size += temp; - } - } - } - - } - else - { - temp = sizeof( int ); // change this to a byte - memcpy( data + size, &framesWritten, temp ); - size += temp; - } - - WriteHeader( modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data ); - } - - if ( g_skelModel.references != REF_NULL ) { - int refnum; - - size = 0; - if ( RefPointNum <= 0 ) { // Hard-coded labels - refnum = numReferences[g_skelModel.references]; - } - else - { // Labels indicated in QDT - refnum = RefPointNum; - } - - temp = sizeof( int ); // change this to a byte - memcpy( data2 + size, &g_skelModel.references, temp ); - size += temp; - - if ( !num_groups ) { - framesWritten = true; - - temp = sizeof( int ); // change this to a byte - memcpy( data2 + size, &framesWritten, temp ); - size += temp; - - for ( i = 0; i < fmheader.num_frames; ++i ) - { - in = &g_frames[i]; - - for ( j = 0 ; j < refnum; ++j ) - { - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->references[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data2 + size, &v, temp ); - size += temp; - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->references[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data2 + size, &v, temp ); - size += temp; - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->references[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // write out origin as a float since they arn't clamped - temp = sizeof( float ); // change this to a short - assert( size + temp < DATA_SIZE ); - memcpy( data2 + size, &v, temp ); - size += temp; - } - } - } - } - else // FINISH ME: references need to be stored with regular verts for compressed models - { - framesWritten = false; - - temp = sizeof( int ); // change this to a byte - memcpy( data2 + size, &framesWritten, temp ); - size += temp; - } - - WriteHeader( modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2 ); - } -} - -static void CompressFrames(){ - fmgroup_t *g; - int i,j,k; - fmframe_t *in; - - j = 0; - for ( i = 0; i < fmheader.num_frames; i++ ) - { - while ( i >= groups[j].start_frame + groups[j].num_frames && j < num_groups - 1 ) - j++; - frame_to_group[i] = j; - } - - for ( k = 0; k < num_groups; k++ ) - { - g = &groups[k]; - - printf( "\nCompressing Frames for group %i...\n", k ); - AnimCompressInit( g->num_frames,fmheader.num_xyz,g->degrees ); - for ( i = 0; i < g->num_frames; i++ ) - { - in = &g_frames[i + g->start_frame]; - for ( j = 0; j < fmheader.num_xyz; j++ ) - AnimSetFrame( i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2] ); - } - AnimCompressDoit(); - g->mat = (char *) SafeMalloc( fmheader.num_xyz * 3 * g->degrees * sizeof( char ), "CompressFrames" ); - g->ccomp = (char *) SafeMalloc( g->num_frames * g->degrees * sizeof( char ), "CompressFrames" ); - g->cbase = (char *) SafeMalloc( fmheader.num_xyz * 3 * sizeof( unsigned char ), "CompressFrames" ); - g->cscale = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" ); - g->coffset = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" ); - AnimCompressToBytes( g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax ); - AnimCompressEnd(); - } -} - -static void OptimizeVertices( void ){ - qboolean vert_used[MAX_FM_VERTS]; - short vert_replacement[MAX_FM_VERTS]; - int i,j,k,l,pos,bit,set_pos,set_bit; - fmframe_t *in; - qboolean Found; - int num_unique; - static IntListNode_t *newVertLists[NUM_CLUSTERS]; - static int newNum_verts[NUM_CLUSTERS]; - IntListNode_t *current, *next; - - printf( "Optimizing vertices..." ); - - memset( vert_used, 0, sizeof( vert_used ) ); - - if ( g_skelModel.clustered == true ) { - memset( newNum_verts, 0, sizeof( newNum_verts ) ); - memset( newVertLists, 0, sizeof( newVertLists ) ); - } - - num_unique = 0; - - // search for common points among all the frames - for ( i = 0 ; i < fmheader.num_frames ; i++ ) - { - in = &g_frames[i]; - - for ( j = 0; j < fmheader.num_xyz; j++ ) - { - for ( k = 0,Found = false; k < j; k++ ) - { // starting from the beginning always ensures vert_replacement points to the first point in the array - if ( in->v[j].v[0] == in->v[k].v[0] && - in->v[j].v[1] == in->v[k].v[1] && - in->v[j].v[2] == in->v[k].v[2] ) { - Found = true; - vert_replacement[j] = k; - break; - } - - } - - if ( !Found ) { - if ( !vert_used[j] ) { - num_unique++; - } - vert_used[j] = true; - } - } - } - - // recompute the light normals - for ( i = 0 ; i < fmheader.num_frames ; i++ ) - { - in = &g_frames[i]; - - for ( j = 0; j < fmheader.num_xyz; j++ ) - { - if ( !vert_used[j] ) { - k = vert_replacement[j]; - - VectorAdd( in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum ); - in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++; - } - } - - for ( j = 0 ; j < fmheader.num_xyz ; j++ ) - { - vec3_t v; - float maxdot; - int maxdotindex; - int c; - - c = in->v[j].vnorm.numnormals; - if ( !c ) { - Error( "Vertex with no triangles attached" ); - } - - VectorScale( in->v[j].vnorm.normalsum, 1.0 / c, v ); - VectorNormalize( v, v ); - - maxdot = -999999.0; - maxdotindex = -1; - - for ( k = 0 ; k < NUMVERTEXNORMALS ; k++ ) - { - float dot; - - dot = DotProduct( v, avertexnormals[k] ); - if ( dot > maxdot ) { - maxdot = dot; - maxdotindex = k; - } - } - - in->v[j].lightnormalindex = maxdotindex; - } - } - - // create substitution list - num_unique = 0; - for ( i = 0; i < fmheader.num_xyz; i++ ) - { - if ( vert_used[i] ) { - vert_replacement[i] = num_unique; - num_unique++; - } - else - { - vert_replacement[i] = vert_replacement[vert_replacement[i]]; - } - - // vert_replacement[i] is the new index, i is the old index - // need to add the new index to the cluster list if old index was in it - if ( g_skelModel.clustered == true ) { - for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k ) - { - for ( l = 0, current = g_skelModel.vertLists[k]; - l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next ) - { - if ( current->data == i ) { - IntListNode_t *current2; - int m; - qboolean added = false; - - for ( m = 0, current2 = newVertLists[k]; m < newNum_verts[k + 1]; - ++m, current2 = current2->next ) - { - if ( current2->data == vert_replacement[i] ) { - added = true; - break; - } - } - - if ( !added ) { - ++newNum_verts[k + 1]; - - next = newVertLists[k]; - - newVertLists[k] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "OptimizeVertices" ); - // freed after model write out - - newVertLists[k]->data = vert_replacement[i]; - newVertLists[k]->next = next; - } - break; - } - } - } - } - } - - // substitute - for ( i = 0 ; i < fmheader.num_frames ; i++ ) - { - in = &g_frames[i]; - - for ( j = 0; j < fmheader.num_xyz; j++ ) - { - in->v[vert_replacement[j]] = in->v[j]; - } - - } - - for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) - { - IntListNode_t *toFree; - current = g_skelModel.vertLists[i]; - - while ( current ) - { - toFree = current; - current = current->next; - free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base - } - - g_skelModel.vertLists[i] = newVertLists[i]; - g_skelModel.new_num_verts[i + 1] = newNum_verts[i + 1]; - } - -#ifndef NDEBUG - for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k ) - { - for ( l = 0, current = g_skelModel.vertLists[k]; - l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next ) - { - IntListNode_t *current2; - int m; - - for ( m = l + 1, current2 = current->next; m < newNum_verts[k + 1]; - ++m, current2 = current2->next ) - { - if ( current->data == current2->data ) { - printf( "Warning duplicate vertex: %d\n", current->data ); - break; - } - } - } - } -#endif - - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { // reset the vert bits - memset( pmnodes[i].verts,0,sizeof( pmnodes[i].verts ) ); - } - - // repleace the master triangle list vertex indexes and update the vert bits for each mesh node - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - pos = i >> 3; - bit = 1 << ( i & 7 ); - - for ( j = 0 ; j < 3 ; j++ ) - { - set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]]; - - set_pos >>= 3; - set_bit = 1 << ( set_bit & 7 ); - - for ( k = 0; k < fmheader.num_mesh_nodes; k++ ) - { - if ( !( pmnodes[k].tris[pos] & bit ) ) { - continue; - } - pmnodes[k].verts[set_pos] |= set_bit; - } - } - } - - for ( i = 0; i < numcommands; i++ ) - { - j = commands[i]; - if ( !j ) { - continue; - } - - j = abs( j ); - for ( i++; j; j--,i += 3 ) - { - commands[i + 2] = vert_replacement[commands[i + 2]]; - } - i--; - } - - printf( "Reduced by %d\n",fmheader.num_xyz - num_unique ); - - fmheader.num_xyz = num_unique; - if ( num_groups ) { - // tack on the reference verts to the regular verts - if ( g_skelModel.references != REF_NULL ) { - fmframe_t *in; - int index; - int refnum; - - if ( RefPointNum <= 0 ) { // Hard-coded labels - refnum = numReferences[g_skelModel.references]; - } - else - { // Labels indicated in QDT - refnum = RefPointNum; - } - - - for ( i = 0; i < fmheader.num_frames; ++i ) - { - in = &g_frames[i]; - index = fmheader.num_xyz; - - for ( j = 0 ; j < refnum; ++j ) - { - VectorCopy( in->references[j].placement.origin, in->v[index].v ); - index++; - - VectorCopy( in->references[j].placement.direction, in->v[index].v ); - index++; - - VectorCopy( in->references[j].placement.up, in->v[index].v ); - index++; - } - } - - fmheader.num_xyz += refnum * 3; - } - - // tack on the skeletal joint verts to the regular verts - if ( g_skelModel.type != SKEL_NULL ) { - fmframe_t *in; - int index; - - for ( i = 0; i < fmheader.num_frames; ++i ) - { - in = &g_frames[i]; - index = fmheader.num_xyz; - - for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j ) - { - VectorCopy( in->joints[j].placement.origin, in->v[index].v ); - index++; - - VectorCopy( in->joints[j].placement.direction, in->v[index].v ); - index++; - - VectorCopy( in->joints[j].placement.up, in->v[index].v ); - index++; - } - } - - fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type] * 3; - } - - CompressFrames(); - } -} - - -/* - =============== - FinishModel - =============== - */ -void FMFinishModel( void ){ - FILE *modelouthandle; - int i,j,length,tris,verts,bit,pos,total_tris,total_verts; - char name[1024]; - int trans_count; - - if ( !fmheader.num_frames ) { - return; - } - -// -// copy to release directory tree if doing a release build -// - if ( g_release ) { - if ( modelname[0] ) { - sprintf( name, "%s", modelname ); - } - else{ - sprintf( name, "%s/tris.fm", cdpartial ); - } - ReleaseFile( name ); - - for ( i = 0 ; i < fmheader.num_skins ; i++ ) - { - ReleaseFile( g_skins[i] ); - } - fmheader.num_frames = 0; - return; - } - - printf( "\n" ); - - trans_count = 0; - for ( i = 0; i < fmheader.num_tris; i++ ) - if ( translucent[i] ) { - trans_count++; - } - - if ( !g_no_opimizations ) { - OptimizeVertices(); - } - -// -// write the model output file -// - if ( modelname[0] ) { - sprintf( name, "%s%s", g_outputDir, modelname ); - } - else{ - sprintf( name, "%s/tris.fm", g_outputDir ); - } - printf( "saving to %s\n", name ); - CreatePath( name ); - modelouthandle = SafeOpenWrite( name ); - - WriteModelFile( modelouthandle ); - - printf( "%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight ); - printf( "First frame boundaries:\n" ); - printf( " minimum x: %3f\n", g_frames[0].mins[0] ); - printf( " maximum x: %3f\n", g_frames[0].maxs[0] ); - printf( " minimum y: %3f\n", g_frames[0].mins[1] ); - printf( " maximum y: %3f\n", g_frames[0].maxs[1] ); - printf( " minimum z: %3f\n", g_frames[0].mins[2] ); - printf( " maximum z: %3f\n", g_frames[0].maxs[2] ); - printf( "%4d vertices\n", fmheader.num_xyz ); - printf( "%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count ); - printf( "%4d frame\n", fmheader.num_frames ); - printf( "%4d glverts\n", numglverts ); - printf( "%4d glcmd\n", fmheader.num_glcmds ); - printf( "%4d skins\n", fmheader.num_skins ); - printf( "%4d mesh nodes\n", fmheader.num_mesh_nodes ); - printf( "wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used, - total_skin_pixels, (double)( total_skin_pixels - skin_pixels_used ) / (double)total_skin_pixels * 100.0 ); - - printf( "file size: %d\n", (int)ftell( modelouthandle ) ); - printf( "---------------------\n" ); - - if ( g_verbose ) { - if ( fmheader.num_mesh_nodes ) { - total_tris = total_verts = 0; - printf( "Node Name Tris Verts\n" ); - printf( "--------------------------------- ---- -----\n" ); - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { - tris = 0; - verts = 0; - for ( j = 0; j < MAXTRIANGLES; j++ ) - { - pos = ( j ) >> 3; - bit = 1 << ( ( j ) & 7 ); - if ( pmnodes[i].tris[pos] & bit ) { - tris++; - } - } - for ( j = 0; j < MAX_FM_VERTS; j++ ) - { - pos = ( j ) >> 3; - bit = 1 << ( ( j ) & 7 ); - if ( pmnodes[i].verts[pos] & bit ) { - verts++; - } - } - - printf( "%-33s %4d %5d\n",pmnodes[i].name,tris,verts ); - - total_tris += tris; - total_verts += verts; - } - printf( "--------------------------------- ---- -----\n" ); - printf( "%-33s %4d %5d\n","TOTALS",total_tris,total_verts ); - } - } - fclose( modelouthandle ); - - // finish writing header file - H_printf( "\n" ); - - // scale_up is usefull to allow step distances to be adjusted - H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up ); - - // mesh nodes - if ( fmheader.num_mesh_nodes ) { - H_printf( "\n" ); - H_printf( "#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes ); - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { - strcpy( name, pmnodes[i].name ); - strupr( name ); - length = strlen( name ); - for ( j = 0; j < length; j++ ) - { - if ( name[j] == ' ' ) { - name[j] = '_'; - } - } - H_printf( "#define MESH_%s\t\t%d\n", name, i ); - } - } - - fclose( headerouthandle ); - headerouthandle = NULL; - free( pmnodes ); -} - - -/* - ================================================================= - - ALIAS MODEL DISPLAY LIST GENERATION - - ================================================================= - */ - -extern int strip_xyz[128]; -extern int strip_st[128]; -extern int strip_tris[128]; -extern int stripcount; - -/* - ================ - StripLength - ================ - */ -static int StripLength( int starttri, int startv, int num_tris, int node ){ - int m1, m2; - int st1, st2; - int j; - fmtriangle_t *last, *check; - int k; - int pos, bit; - - used[starttri] = 2; - - last = &triangles[starttri]; - - strip_xyz[0] = last->index_xyz[( startv ) % 3]; - strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; - strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; - strip_st[0] = last->index_st[( startv ) % 3]; - strip_st[1] = last->index_st[( startv + 1 ) % 3]; - strip_st[2] = last->index_st[( startv + 2 ) % 3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[( startv + 2 ) % 3]; - st1 = last->index_st[( startv + 2 ) % 3]; - m2 = last->index_xyz[( startv + 1 ) % 3]; - st2 = last->index_st[( startv + 1 ) % 3]; - - // look for a matching triangle -nexttri: - for ( j = starttri + 1, check = &triangles[starttri + 1] - ; j < num_tris ; j++, check++ ) - { - pos = j >> 3; - bit = 1 << ( j & 7 ); - if ( !( pmnodes[node].tris[pos] & bit ) ) { - continue; - } - for ( k = 0 ; k < 3 ; k++ ) - { - if ( check->index_xyz[k] != m1 ) { - continue; - } - if ( check->index_st[k] != st1 ) { - continue; - } - if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { - continue; - } - if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { - continue; - } - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if ( used[j] || translucent[j] != translucent[starttri] ) { - goto done; - } - - // the new edge - if ( stripcount & 1 ) { - m2 = check->index_xyz[ ( k + 2 ) % 3 ]; - st2 = check->index_st[ ( k + 2 ) % 3 ]; - } - else - { - m1 = check->index_xyz[ ( k + 2 ) % 3 ]; - st1 = check->index_st[ ( k + 2 ) % 3 ]; - } - - strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ]; - strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ]; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for ( j = starttri + 1 ; j < num_tris ; j++ ) - if ( used[j] == 2 ) { - used[j] = 0; - } - - return stripcount; -} - - -/* - =========== - FanLength - =========== - */ -static int FanLength( int starttri, int startv, int num_tris, int node ){ - int m1, m2; - int st1, st2; - int j; - fmtriangle_t *last, *check; - int k; - int pos, bit; - - used[starttri] = 2; - - last = &triangles[starttri]; - - strip_xyz[0] = last->index_xyz[( startv ) % 3]; - strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; - strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; - strip_st[0] = last->index_st[( startv ) % 3]; - strip_st[1] = last->index_st[( startv + 1 ) % 3]; - strip_st[2] = last->index_st[( startv + 2 ) % 3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[( startv + 0 ) % 3]; - st1 = last->index_st[( startv + 0 ) % 3]; - m2 = last->index_xyz[( startv + 2 ) % 3]; - st2 = last->index_st[( startv + 2 ) % 3]; - - - // look for a matching triangle -nexttri: - for ( j = starttri + 1, check = &triangles[starttri + 1] - ; j < num_tris ; j++, check++ ) - { - pos = j >> 3; - bit = 1 << ( j & 7 ); - if ( !( pmnodes[node].tris[pos] & bit ) ) { - continue; - } - for ( k = 0 ; k < 3 ; k++ ) - { - if ( check->index_xyz[k] != m1 ) { - continue; - } - if ( check->index_st[k] != st1 ) { - continue; - } - if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { - continue; - } - if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { - continue; - } - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if ( used[j] || translucent[j] != translucent[starttri] ) { - goto done; - } - - // the new edge - m2 = check->index_xyz[ ( k + 2 ) % 3 ]; - st2 = check->index_st[ ( k + 2 ) % 3 ]; - - strip_xyz[stripcount + 2] = m2; - strip_st[stripcount + 2] = st2; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for ( j = starttri + 1 ; j < num_tris ; j++ ) - if ( used[j] == 2 ) { - used[j] = 0; - } - - return stripcount; -} - - - -/* - ================ - BuildGlCmds - - Generate a list of trifans or strips - for the model, which holds for all frames - ================ - */ -static void BuildGlCmds( void ){ - int i, j, k, l; - int startv; - float s, t; - int len, bestlen, besttype; - int best_xyz[1024]; - int best_st[1024]; - int best_tris[1024]; - int type; - int trans_check; - int bit,pos; - - // - // build tristrips - // - numcommands = 0; - numglverts = 0; - - - for ( l = 0; l < fmheader.num_mesh_nodes; l++ ) - { - memset( used, 0, sizeof( used ) ); - - pmnodes[l].start_glcmds = numcommands; - - for ( trans_check = 0; trans_check < 2; trans_check++ ) - { - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - pos = i >> 3; - bit = 1 << ( i & 7 ); - if ( !( pmnodes[l].tris[pos] & bit ) ) { - continue; - } - - // pick an unused triangle and start the trifan - if ( used[i] || trans_check != translucent[i] ) { - continue; - } - - bestlen = 0; - for ( type = 0 ; type < 2 ; type++ ) - // type = 1; - { - for ( startv = 0 ; startv < 3 ; startv++ ) - { - if ( type == 1 ) { - len = StripLength( i, startv, fmheader.num_tris, l ); - } - else{ - len = FanLength( i, startv, fmheader.num_tris, l ); - } - if ( len > bestlen ) { - besttype = type; - bestlen = len; - for ( j = 0 ; j < bestlen + 2 ; j++ ) - { - best_st[j] = strip_st[j]; - best_xyz[j] = strip_xyz[j]; - } - for ( j = 0 ; j < bestlen ; j++ ) - best_tris[j] = strip_tris[j]; - } - } - } - - // mark the tris on the best strip/fan as used - for ( j = 0 ; j < bestlen ; j++ ) - used[best_tris[j]] = 1; - - if ( besttype == 1 ) { - commands[numcommands++] = ( bestlen + 2 ); - } - else{ - commands[numcommands++] = -( bestlen + 2 ); - } - - numglverts += bestlen + 2; - - for ( j = 0 ; j < bestlen + 2 ; j++ ) - { - // emit a vertex into the reorder buffer - k = best_st[j]; - - // emit s/t coords into the commands stream - s = base_st[k].s; - t = base_st[k].t; - - s = ( s ) / fmheader.skinwidth; - t = ( t ) / fmheader.skinheight; - - *(float *)&commands[numcommands++] = s; - *(float *)&commands[numcommands++] = t; - *(int *)&commands[numcommands++] = best_xyz[j]; - } - } - } - commands[numcommands++] = 0; // end of list marker - pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds; - } -} - - -/* - =============================================================== - - BASE FRAME SETUP - - =============================================================== - */ - - -#define LINE_NORMAL 1 -#define LINE_FAT 2 -#define LINE_DOTTED 3 - - -#define ASCII_SPACE 32 - -int LineType = LINE_NORMAL; -extern unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768]; -unsigned char LineColor = 255; -int ScaleWidth, ScaleHeight; - - -static char *CharDefs[] = -{ - "-------------------------", - "-------------------------", // ! - "-------------------------", // " - "-------------------------", // # - "-------------------------", // $ - "-------------------------", // % - "-------------------------", // & - "--*----*-----------------", // ' - "-*---*----*----*-----*---", // ( - "*-----*----*----*---*----", // ) - "-----*--*--**---**--*--*-", // * - "-------------------------", // + - "----------------**--**---", // , - "-------------------------", // - - "----------------**---**--", // . - "-------------------------", // / - " *** * *** * *** * *** ", // 0 - " * ** * * * ", - "**** * *** * *****", - "**** * *** ***** ", - " ** * * * * ***** * ", - "**** * **** ***** ", - " *** * **** * * *** ", - "***** * * * * ", - " *** * * *** * * *** ", - " *** * * **** * *** ", // 9 - "-**---**--------**---**--", // : - "-------------------------", // ; - "-------------------------", // < - "-------------------------", // = - "-------------------------", // > - "-------------------------", // ? - "-------------------------", // @ - "-***-*---*******---**---*", // A - "****-*---*****-*---*****-", - "-*****----*----*-----****", - "****-*---**---**---*****-", - "******----****-*----*****", - "******----****-*----*----", - "-*****----*--***---*-****", - "*---**---*******---**---*", - "-***---*----*----*---***-", - "----*----*----**---*-***-", - "-*--*-*-*--**---*-*--*--*", - "-*----*----*----*----****", - "*---***-***-*-**---**---*", - "*---***--**-*-**--***---*", - "-***-*---**---**---*-***-", - "****-*---*****-*----*----", - "-***-*---**---*-***----**", - "****-*---*****-*-*--*--**", - "-*****-----***-----*****-", - "*****--*----*----*----*--", - "*---**---**---**---******", - "*---**---**---*-*-*---*--", - "*---**---**-*-***-***---*", - "*---*-*-*---*---*-*-*---*", - "*---**---*-*-*---*----*--", - "*****---*---*---*---*****" // Z -}; - -void DrawLine( int x1, int y1, int x2, int y2 ){ - int dx, dy; - int adx, ady; - int count; - float xfrac, yfrac, xstep, ystep; - unsigned sx, sy; - float u, v; - - dx = x2 - x1; - dy = y2 - y1; - adx = abs( dx ); - ady = abs( dy ); - - count = adx > ady ? adx : ady; - count++; - - if ( count > 300 ) { - printf( "Bad count\n" ); - return; // don't ever hang up on bad data - } - - xfrac = x1; - yfrac = y1; - - xstep = (float)dx / count; - ystep = (float)dy / count; - - switch ( LineType ) - { - case LINE_NORMAL: - do - { - if ( xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT ) { - pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor; - } - xfrac += xstep; - yfrac += ystep; - count--; - } while ( count > 0 ); - break; - case LINE_FAT: - do - { - for ( u = -0.1 ; u <= 0.9 ; u += 0.999 ) - { - for ( v = -0.1 ; v <= 0.9 ; v += 0.999 ) - { - sx = xfrac + u; - sy = yfrac + v; - if ( sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT ) { - pic[sy * SKINPAGE_WIDTH + sx] = LineColor; - } - } - } - xfrac += xstep; - yfrac += ystep; - count--; - } while ( count > 0 ); - break; - case LINE_DOTTED: - do - { - if ( count & 1 && xfrac < SKINPAGE_WIDTH && - yfrac < SKINPAGE_HEIGHT ) { - pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor; - } - xfrac += xstep; - yfrac += ystep; - count--; - } while ( count > 0 ); - break; - default: - Error( "Unknown %d.\n", LineType ); - } -} - -//========================================================================== -// -// DrawCharacter -// -//========================================================================== - -static void DrawCharacter( int x, int y, int character ){ - int r, c; - char *def; - - character = toupper( character ); - if ( character < ASCII_SPACE || character > 'Z' ) { - character = ASCII_SPACE; - } - character -= ASCII_SPACE; - for ( def = CharDefs[character], r = 0; r < 5; r++ ) - { - for ( c = 0; c < 5; c++ ) - { - pic[( y + r ) * SKINPAGE_WIDTH + x + c] = *def++ == '*' ? 255 : 0; - } - } -} - -//========================================================================== -// -// DrawTextChar -// -//========================================================================== - -void DrawTextChar( int x, int y, char *text ){ - int c; - - while ( ( c = *text++ ) != '\0' ) - { - DrawCharacter( x, y, c ); - x += 6; - } -} - - -extern void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ); - -//========================================================================== -// ExtractDigit - -static int ExtractDigit( byte *pic, int x, int y ){ - int i; - int r, c; - char digString[32]; - char *buffer; - byte backColor; - char **DigitDefs; - - backColor = pic[( SKINPAGE_HEIGHT - 1 ) * SKINPAGE_WIDTH]; - DigitDefs = &CharDefs['0' - ASCII_SPACE]; - - buffer = digString; - for ( r = 0; r < 5; r++ ) - { - for ( c = 0; c < 5; c++ ) - { - *buffer++ = ( pic[( y + r ) * SKINPAGE_WIDTH + x + c] == backColor ) ? ' ' : '*'; - } - } - *buffer = '\0'; - for ( i = 0; i < 10; i++ ) - { - if ( strcmp( DigitDefs[i], digString ) == 0 ) { - return i; - } - } - - Error( "Unable to extract scaling info from skin PCX." ); - return 0; -} - -//========================================================================== -// ExtractNumber - -int ExtractNumber( byte *pic, int x, int y ){ - return ExtractDigit( pic, x, y ) * 100 + ExtractDigit( pic, x + 6, y ) * 10 + ExtractDigit( pic, x + 12, y ); -} - - - - - -/* - ============ - BuildST - - Builds the triangle_st array for the base frame and - fmheader.skinwidth / fmheader.skinheight - - FIXME: allow this to be loaded from a file for - arbitrary mappings - ============ - */ -static void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ - int backface_flag; - int i, j; - int width, height, iwidth, iheight, swidth; - float basex, basey; - float scale; - vec3_t mins, maxs; - float *pbasevert; - vec3_t vtemp1, vtemp2, normal; - float s_scale, t_scale; - float scWidth; - float scHeight; - int skinwidth; - int skinheight; - - // - // find bounds of all the verts on the base frame - // - ClearBounds( mins, maxs ); - backface_flag = false; - - if ( ptri[0].HasUV ) { // if we have the uv already, we don't want to double up or scale - iwidth = ScaleWidth; - iheight = ScaleHeight; - - t_scale = s_scale = 1.0; - } - else - { - for ( i = 0 ; i < numtri ; i++ ) - for ( j = 0 ; j < 3 ; j++ ) - AddPointToBounds( ptri[i].verts[j], mins, maxs ); - - for ( i = 0 ; i < 3 ; i++ ) - { - mins[i] = floor( mins[i] ); - maxs[i] = ceil( maxs[i] ); - } - - width = maxs[0] - mins[0]; - height = maxs[2] - mins[2]; - - for ( i = 0 ; i < numtri ; i++ ) - { - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - if ( normal[1] > 0 ) { - backface_flag = true; - break; - } - } - scWidth = ScaleWidth * SCALE_ADJUST_FACTOR; - if ( backface_flag ) { //we are doubling - scWidth /= 2; - } - - scHeight = ScaleHeight * SCALE_ADJUST_FACTOR; - - scale = scWidth / width; - - if ( height * scale >= scHeight ) { - scale = scHeight / height; - } - - iwidth = ceil( width * scale ) + 4; - iheight = ceil( height * scale ) + 4; - - s_scale = (float)( iwidth - 4 ) / width; - t_scale = (float)( iheight - 4 ) / height; - t_scale = s_scale; - } - if ( DrawSkin ) { - if ( backface_flag ) { - DrawScreen( s_scale, t_scale, iwidth * 2, iheight ); - } - else{ - DrawScreen( s_scale, t_scale, iwidth, iheight ); - } - } - if ( backface_flag ) { - skinwidth = iwidth * 2; - } - else{ - skinwidth = iwidth; - } - skinheight = iheight; - - -/* if (!g_fixedwidth) - { // old style - scale = 8; - if (width*scale >= 150) - scale = 150.0 / width; - if (height*scale >= 190) - scale = 190.0 / height; - - s_scale = t_scale = scale; - - iwidth = ceil(width*s_scale); - iheight = ceil(height*t_scale); - - iwidth += 4; - iheight += 4; - } - else - { // new style - iwidth = g_fixedwidth / 2; - iheight = g_fixedheight; - - s_scale = (float)(iwidth-4) / width; - t_scale = (float)(iheight-4) / height; - }*/ - -// -// determine which side of each triangle to map the texture to -// - basey = 2; - for ( i = 0 ; i < numtri ; i++ ) - { - if ( ptri[i].HasUV ) { - for ( j = 0 ; j < 3 ; j++ ) - { - triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * skinwidth ); - triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * skinheight ); - } - } - else - { - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - if ( normal[1] > 0 ) { - basex = iwidth + 2; - } - else - { - basex = 2; - } - - for ( j = 0 ; j < 3 ; j++ ) - { - pbasevert = ptri[i].verts[j]; - - triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); - triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); - } - } - - if ( DrawSkin ) { - DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], - triangle_st[i][1][0], triangle_st[i][1][1] ); - DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], - triangle_st[i][2][0], triangle_st[i][2][1] ); - DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], - triangle_st[i][0][0], triangle_st[i][0][1] ); - } - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - - swidth = iwidth; - if ( backface_flag ) { - swidth *= 2; - } - fmheader.skinwidth = ( swidth + 3 ) & ~3; - fmheader.skinheight = iheight; - - skin_width = iwidth; - skin_height = iheight; -} - - -static void BuildNewST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ - int i, j; - - for ( i = 0 ; i < numtri ; i++ ) - { - if ( ptri[i].HasUV ) { - for ( j = 0 ; j < 3 ; j++ ) - { - triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * ( ScaleWidth - 1 ) ); - triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * ( ScaleHeight - 1 ) ); - } - } - - if ( DrawSkin ) { - DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], - triangle_st[i][1][0], triangle_st[i][1][1] ); - DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], - triangle_st[i][2][0], triangle_st[i][2][1] ); - DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], - triangle_st[i][0][0], triangle_st[i][0][1] ); - } - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - - fmheader.skinwidth = ( ScaleWidth + 3 ) & ~3; - fmheader.skinheight = ScaleHeight; - - skin_width = ScaleWidth; - skin_height = ScaleHeight; -} - - - - -byte *BasePalette; -byte *BasePixels,*TransPixels; -int BaseWidth, BaseHeight, TransWidth, TransHeight; -qboolean BaseTrueColor; -static qboolean SetPixel = false; - -int CheckTransRecursiveTri( int *lp1, int *lp2, int *lp3 ){ - int *temp; - int d; - int new[2]; - - d = lp2[0] - lp1[0]; - if ( d < -1 || d > 1 ) { - goto split; - } - d = lp2[1] - lp1[1]; - if ( d < -1 || d > 1 ) { - goto split; - } - - d = lp3[0] - lp2[0]; - if ( d < -1 || d > 1 ) { - goto split2; - } - d = lp3[1] - lp2[1]; - if ( d < -1 || d > 1 ) { - goto split2; - } - - d = lp1[0] - lp3[0]; - if ( d < -1 || d > 1 ) { - goto split3; - } - d = lp1[1] - lp3[1]; - if ( d < -1 || d > 1 ) { -split3: - temp = lp1; - lp1 = lp3; - lp3 = lp2; - lp2 = temp; - - goto split; - } - - return 0; // entire tri is filled - -split2: - temp = lp1; - lp1 = lp2; - lp2 = lp3; - lp3 = temp; - -split: -// split this edge - new[0] = ( lp1[0] + lp2[0] ) >> 1; - new[1] = ( lp1[1] + lp2[1] ) >> 1; - -// draw the point if splitting a leading edge - if ( lp2[1] > lp1[1] ) { - goto nodraw; - } - if ( ( lp2[1] == lp1[1] ) && ( lp2[0] < lp1[0] ) ) { - goto nodraw; - } - - if ( SetPixel ) { - assert( ( new[1] * BaseWidth ) + new[0] < BaseWidth * BaseHeight ); - - if ( BaseTrueColor ) { - BasePixels[( ( new[1] * BaseWidth ) + new[0] ) * 4] = 1; - } - else - { - BasePixels[( new[1] * BaseWidth ) + new[0]] = 1; - } - } - else - { - if ( TransPixels ) { - if ( TransPixels[( new[1] * TransWidth ) + new[0]] != 255 ) { - return 1; - } - } - else if ( BaseTrueColor ) { - if ( BasePixels[( ( ( new[1] * BaseWidth ) + new[0] ) * 4 ) + 3] != 255 ) { - return 1; - } - } - else - { -// pixel = BasePixels[(new[1]*BaseWidth) + new[0]]; - } - } - -nodraw: -// recursively continue - if ( CheckTransRecursiveTri( lp3, lp1, new ) ) { - return 1; - } - - return CheckTransRecursiveTri( lp3, new, lp2 ); -} - -static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters, - IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){ - int i, j; - IntListNode_t *next; - - for ( j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j ) - { - if ( !clusters[j] ) { - continue; - } - - for ( i = 0; i < num_verts[j + 1]; ++i ) - { - if ( clusters[j][i] == oldindex ) { - ++new_num_verts[j + 1]; - - next = vertLists[j]; - - vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" ); - // Currently freed in WriteJointedModelFile only - - vertLists[j]->data = newIndex; - vertLists[j]->next = next; - } - } - } -} - -#define FUDGE_EPSILON 0.002 - -qboolean VectorFudgeCompare( vec3_t v1, vec3_t v2 ){ - int i; - - for ( i = 0 ; i < 3 ; i++ ) - if ( fabs( v1[i] - v2[i] ) > FUDGE_EPSILON ) { - return false; - } - - return true; -} - -/* - ================= - Cmd_Base - ================= - */ -void Cmd_FMBase( qboolean GetST ){ - triangle_t *ptri, *st_tri; - int num_st_tris; - int i, j, k, l; - int x,y,z; -// int time1; - char file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256]; - vec3_t base_xyz[MAX_FM_VERTS]; - FILE *FH; - int pos,bit; - qboolean NewSkin; - - GetScriptToken( false ); - - if ( g_skipmodel || g_release || g_archive ) { - return; - } - - printf( "---------------------\n" ); - sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext ); - printf( "%s ", file1 ); - - ExpandPathAndArchive( file1 ); - - // Use the input filepath for this one. - sprintf( file1, "%s/%s", cddir, token ); - -// time1 = FileTime (file1); -// if (time1 == -1) -// Error ("%s doesn't exist", file1); - -// -// load the base triangles -// - if ( do3ds ) { - Load3DSTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); - } - else{ - LoadTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); - } - - if ( g_ignoreTriUV ) { - for ( i = 0; i < fmheader.num_tris; i++ ) - { - ptri[i].HasUV = 0; - } - } - - GetScriptToken( false ); - sprintf( file2, "%s/%s", cddir, token ); - sprintf( trans_file, "%s/!%s_a.pcx", cddir, token ); - - ExtractFileExtension( file2, extension ); - if ( extension[0] == 0 ) { - strcat( file2, ".pcx" ); - } - printf( "skin: %s\n", file2 ); - - BaseTrueColor = LoadAnyImage( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight ); - - NewSkin = false; - if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) { - if ( g_allow_newskin ) { - ScaleWidth = BaseWidth; - ScaleHeight = BaseHeight; - NewSkin = true; - } - else - { - Error( "Invalid skin page size: (%d,%d) should be (%d,%d)", - BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT ); - } - } - else if ( !BaseTrueColor ) { - ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X, - ENCODED_WIDTH_Y ); - ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X, - ENCODED_HEIGHT_Y ); - } - else - { - Error( "Texture coordinates not supported on true color image" ); - } - - if ( GetST ) { - GetScriptToken( false ); - - sprintf( stfile, "%s/%s.%s", cdarchive, token, trifileext ); - printf( "ST: %s ", stfile ); - - sprintf( stfile, "%s/%s", cddir, token ); - - if ( do3ds ) { - Load3DSTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL ); - } - else{ - LoadTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL ); - } - - if ( num_st_tris != fmheader.num_tris ) { - Error( "num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris ); - } - - printf( " matching triangles...\n" ); - for ( i = 0; i < fmheader.num_tris; i++ ) - { - k = -1; - for ( j = 0; j < num_st_tris; j++ ) - { - for ( x = 0; x < 3; x++ ) - { - for ( y = 0; y < 3; y++ ) - { - if ( x == y ) { - continue; - } - for ( z = 0; z < 3; z++ ) - { - if ( z == x || z == y ) { - continue; - } - - if ( VectorFudgeCompare( ptri[i].verts[0], st_tri[j].verts[x] ) && - VectorFudgeCompare( ptri[i].verts[1], st_tri[j].verts[y] ) && - VectorFudgeCompare( ptri[i].verts[2], st_tri[j].verts[z] ) ) { - if ( k == -1 ) { - k = j; - ptri[i].HasUV = st_tri[k].HasUV; - ptri[i].uv[0][0] = st_tri[k].uv[x][0]; - ptri[i].uv[0][1] = st_tri[k].uv[x][1]; - ptri[i].uv[1][0] = st_tri[k].uv[y][0]; - ptri[i].uv[1][1] = st_tri[k].uv[y][1]; - ptri[i].uv[2][0] = st_tri[k].uv[z][0]; - ptri[i].uv[2][1] = st_tri[k].uv[z][1]; - x = y = z = 999; - } - else if ( k != j ) { - printf( "Duplicate triangle %d found in st file: %d and %d\n",i,k,j ); - printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", - ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2], - ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2], - ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2] ); - printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", - st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2], - st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2], - st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2] ); - printf( " (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n", - st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2], - st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2], - st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2] ); - } - } - } - } - } - } - if ( k == -1 ) { - printf( "No matching triangle %d\n",i ); - } - } - free( st_tri ); - } - -// -// get the ST values -// - if ( ptri && ptri[0].HasUV ) { - if ( !NewSkin ) { - Error( "Base has UVs with old style skin page\nMaybe you want to use -ignoreUV" ); - } - else - { - BuildNewST( ptri, fmheader.num_tris, false ); - } - } - else - { - if ( NewSkin ) { - Error( "Base has new style skin without UVs" ); - } - else - { - BuildST( ptri, fmheader.num_tris, false ); - } - } - - TransPixels = NULL; - if ( !BaseTrueColor ) { - FH = fopen( trans_file,"rb" ); - if ( FH ) { - fclose( FH ); - Load256Image( trans_file, &TransPixels, NULL, &TransWidth, &TransHeight ); - if ( TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight ) { - Error( "source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight ); - } - } - } - -// -// run through all the base triangles, storing each unique vertex in the -// base vertex list and setting the indirect triangles to point to the base -// vertices -// - for ( l = 0; l < fmheader.num_mesh_nodes; l++ ) - { - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - pos = i >> 3; - bit = 1 << ( i & 7 ); - if ( !( pmnodes[l].tris[pos] & bit ) ) { - continue; - } - - for ( j = 0 ; j < 3 ; j++ ) - { - // get the xyz index - for ( k = 0 ; k < fmheader.num_xyz ; k++ ) - { - if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) { - break; // this vertex is already in the base vertex list - } - } - - if ( k == fmheader.num_xyz ) { // new index - VectorCopy( ptri[i].verts[j], base_xyz[fmheader.num_xyz] ); - - if ( pmnodes[l].clustered == true ) { - ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts ); - } - - fmheader.num_xyz++; - } - - pos = k >> 3; - bit = 1 << ( k & 7 ); - pmnodes[l].verts[pos] |= bit; - - triangles[i].index_xyz[j] = k; - - // get the st index - for ( k = 0 ; k < fmheader.num_st ; k++ ) - { - if ( triangle_st[i][j][0] == base_st[k].s - && triangle_st[i][j][1] == base_st[k].t ) { - break; // this vertex is already in the base vertex list - } - } - - if ( k == fmheader.num_st ) { // new index - base_st[fmheader.num_st].s = triangle_st[i][j][0]; - base_st[fmheader.num_st].t = triangle_st[i][j][1]; - fmheader.num_st++; - } - - triangles[i].index_st[j] = k; - } - - if ( TransPixels || BaseTrueColor ) { - translucent[i] = CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); - } - else - { - translucent[i] = false; - } - } - } - - if ( !BaseTrueColor ) { - SetPixel = true; - memset( BasePixels,0,BaseWidth * BaseHeight ); - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); - } - SetPixel = false; - - skin_pixels_used = 0; - for ( i = 0; i < fmheader.skinheight; i++ ) - { - for ( j = 0; j < fmheader.skinwidth; j++ ) - { - skin_pixels_used += BasePixels[( i * BaseWidth ) + j]; - } - } - total_skin_pixels = fmheader.skinheight * fmheader.skinwidth; - } - else - { - SetPixel = true; - memset( BasePixels,0,BaseWidth * BaseHeight * 4 ); - for ( i = 0 ; i < fmheader.num_tris ; i++ ) - { - CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] ); - } - SetPixel = false; - - skin_pixels_used = 0; - for ( i = 0; i < fmheader.skinheight; i++ ) - { - for ( j = 0; j < fmheader.skinwidth; j++ ) - { - skin_pixels_used += BasePixels[( ( i * BaseWidth ) + j ) * 4]; - } - } - total_skin_pixels = fmheader.skinheight * fmheader.skinwidth; - } - - // build triangle strips / fans - BuildGlCmds(); - - if ( TransPixels ) { - free( TransPixels ); - } - free( BasePixels ); - if ( BasePalette ) { - free( BasePalette ); - } - free( ptri ); -} - -void Cmd_FMNodeOrder( void ){ - mesh_node_t *newnodes, *pos; - int i,j; - - if ( !pmnodes ) { - Error( "Base has not been established yet" ); - } - - pos = newnodes = malloc( sizeof( mesh_node_t ) * fmheader.num_mesh_nodes ); - - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { - GetScriptToken( false ); - - for ( j = 0; j < fmheader.num_mesh_nodes; j++ ) - { - if ( strcmpi( pmnodes[j].name, token ) == 0 ) { - *pos = pmnodes[j]; - pos++; - break; - } - } - if ( j >= fmheader.num_mesh_nodes ) { - Error( "Node '%s' not in base list!\n", token ); - } - } - - free( pmnodes ); - pmnodes = newnodes; -} - -//=============================================================== - -extern char *FindFrameFile( char *frame ); - - -/* - =============== - GrabFrame - =============== - */ -void GrabFrame( char *frame ){ - triangle_t *ptri; - int i, j; - fmtrivert_t *ptrivert; - int num_tris; - char file1[1024]; - fmframe_t *fr; - int index_xyz; - char *framefile; - - // the frame 'run1' will be looked for as either - // run.1 or run1.tri, so the new alias sequence save - // feature an be used - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "grabbing %s ", file1 ); - - if ( fmheader.num_frames >= MAX_FM_FRAMES ) { - Error( "fmheader.num_frames >= MAX_FM_FRAMES" ); - } - fr = &g_frames[fmheader.num_frames]; - fmheader.num_frames++; - - strcpy( fr->name, frame ); - -// -// load the frame -// - if ( do3ds ) { - Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL ); - } - else{ - LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL ); - } - - if ( num_tris != fmheader.num_tris ) { - Error( "%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris ); - } - -// -// allocate storage for the frame's vertices -// - ptrivert = fr->v; - - for ( i = 0 ; i < fmheader.num_xyz ; i++ ) - { - ptrivert[i].vnorm.numnormals = 0; - VectorClear( ptrivert[i].vnorm.normalsum ); - } - ClearBounds( fr->mins, fr->maxs ); - -// -// store the frame's vertices in the same order as the base. This assumes the -// triangles and vertices in this frame are in exactly the same order as in the -// base -// - for ( i = 0 ; i < num_tris ; i++ ) - { - vec3_t vtemp1, vtemp2, normal; - float ftemp; - - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - VectorNormalize( normal, normal ); - - // rotate the normal so the model faces down the positive x axis - ftemp = normal[0]; - normal[0] = -normal[1]; - normal[1] = ftemp; - - for ( j = 0 ; j < 3 ; j++ ) - { - index_xyz = triangles[i].index_xyz[j]; - - // rotate the vertices so the model faces down the positive x axis - // also adjust the vertices to the desired origin - ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) + - adjust[0]; - ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) + - adjust[1]; - ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) + - adjust[2]; - - AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs ); - - VectorAdd( ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum ); - ptrivert[index_xyz].vnorm.numnormals++; - } - } - -// -// calculate the vertex normals, match them to the template list, and store the -// index of the best match -// - for ( i = 0 ; i < fmheader.num_xyz ; i++ ) - { - int j; - vec3_t v; - float maxdot; - int maxdotindex; - int c; - - c = ptrivert[i].vnorm.numnormals; - if ( !c ) { - Error( "Vertex with no triangles attached" ); - } - - VectorScale( ptrivert[i].vnorm.normalsum, 1.0 / c, v ); - VectorNormalize( v, v ); - - maxdot = -999999.0; - maxdotindex = -1; - - for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ ) - { - float dot; - - dot = DotProduct( v, avertexnormals[j] ); - if ( dot > maxdot ) { - maxdot = dot; - maxdotindex = j; - } - } - - ptrivert[i].lightnormalindex = maxdotindex; - } - - free( ptri ); -} - -/* - =============== - Cmd_Frame - =============== - */ -void Cmd_FMFrame( void ){ - while ( ScriptTokenAvailable() ) - { - GetScriptToken( false ); - if ( g_skipmodel ) { - continue; - } - if ( g_release || g_archive ) { - fmheader.num_frames = 1; // don't skip the writeout - continue; - } - - H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames ); - - if ( ( g_skelModel.type != SKEL_NULL ) || ( g_skelModel.references != REF_NULL ) ) { - GrabModelTransform( token ); - } - - GrabFrame( token ); - - if ( g_skelModel.type != SKEL_NULL ) { - GrabSkeletalFrame( token ); - } - - if ( g_skelModel.references != REF_NULL ) { - GrabReferencedFrame( token ); - } - - // need to add the up and dir points to the frame bounds here - // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs); - // then remove fudge in determining scale on frame write out - } -} - -/* - =============== - Cmd_Skin - - Skins aren't actually stored in the file, only a reference - is saved out to the header file. - =============== - */ -void Cmd_FMSkin( void ){ - byte *palette; - byte *pixels; - int width, height; - byte *cropped; - int y; - char name[1024], savename[1024], transname[1024], extension[256]; - miptex32_t *qtex32; - int size; - FILE *FH; - qboolean TrueColor; - - GetScriptToken( false ); - - if ( fmheader.num_skins == MAX_FM_SKINS ) { - Error( "fmheader.num_skins == MAX_FM_SKINS" ); - } - - if ( g_skipmodel ) { - return; - } - - sprintf( name, "%s/%s", cdarchive, token ); - strcpy( name, ExpandPathAndArchive( name ) ); -// sprintf (name, "%s/%s.lbm", cddir, token); - - if ( ScriptTokenAvailable() ) { - GetScriptToken( false ); - sprintf( g_skins[fmheader.num_skins], "!%s", token ); - sprintf( savename, "%s!%s", g_outputDir, token ); - sprintf( transname, "%s!%s_a.pcx", gamedir, token ); - } - else - { - sprintf( g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token ); - sprintf( savename, "%s/!%s", g_outputDir, token ); - sprintf( transname, "%s/!%s_a.pcx", cddir, token ); - } - - fmheader.num_skins++; - - if ( g_skipmodel || g_release || g_archive ) { - return; - } - - // load the image - printf( "loading %s\n", name ); - ExtractFileExtension( name, extension ); - if ( extension[0] == 0 ) { - strcat( name, ".pcx" ); - } - - - TrueColor = LoadAnyImage( name, &pixels, &palette, &width, &height ); -// RemapZero (pixels, palette, width, height); - - // crop it to the proper size - - if ( !TrueColor ) { - cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight, "Cmd_FMSkin" ); - for ( y = 0 ; y < fmheader.skinheight ; y++ ) - { - memcpy( cropped + y * fmheader.skinwidth, - pixels + y * width, fmheader.skinwidth ); - } - - TransPixels = NULL; - FH = fopen( transname,"rb" ); - if ( FH ) { - fclose( FH ); - - strcat( g_skins[fmheader.num_skins - 1],".pcx" ); - strcat( savename,".pcx" ); - - // save off the new image - printf( "saving %s\n", savename ); - CreatePath( savename ); - WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette ); - } - else - { - #if 1 - miptex_t *qtex; - qtex = CreateMip( cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true ); - - strcat( g_skins[fmheader.num_skins - 1],".m8" ); - strcat( savename,".m8" ); - - printf( "saving %s\n", savename ); - CreatePath( savename ); - SaveFile( savename, (byte *)qtex, size ); - free( qtex ); - #else - strcat( g_skins[fmheader.num_skins - 1],".pcx" ); - strcat( savename,".pcx" ); - - // save off the new image - printf( "saving %s\n", savename ); - CreatePath( savename ); - WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette ); - #endif - } - } - else - { - cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight * 4, "Cmd_FMSkin" ); - for ( y = 0 ; y < fmheader.skinheight ; y++ ) - { - memcpy( cropped + ( ( y * fmheader.skinwidth ) * 4 ), pixels + ( y * width * 4 ), fmheader.skinwidth * 4 ); - } - - qtex32 = CreateMip32( (unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true ); - - StripExtension( g_skins[fmheader.num_skins - 1] ); - strcat( g_skins[fmheader.num_skins - 1],".m32" ); - StripExtension( savename ); - strcat( savename,".m32" ); - - printf( "saving %s\n", savename ); - CreatePath( savename ); - SaveFile( savename, (byte *)qtex32, size ); - } - - free( pixels ); - if ( palette ) { - free( palette ); - } - free( cropped ); -} - - -/* - =============== - Cmd_Cd - =============== - */ -void Cmd_FMCd( void ){ - char temp[256]; - - FinishModel(); - ClearModel(); - - GetScriptToken( false ); - - // this is a silly mess... - sprintf( cdpartial, "models/%s", token ); - sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token ); - sprintf( cddir, "%s%s", gamedir, cdpartial ); - - // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too. - sprintf( temp, "%s%s", g_outputDir, cdpartial ); - strcpy( g_outputDir, temp ); - - // if -only was specified and this cd doesn't match, - // skip the model (you only need to match leading chars, - // so you could regrab all monsters with -only monsters) - if ( !g_only[0] ) { - return; - } - if ( strncmp( token, g_only, strlen( g_only ) ) ) { - g_skipmodel = true; - printf( "skipping %s\n", cdpartial ); - } -} - - -/* - - //======================= - // NEW GEN - //======================= - - void NewGen (char *ModelFile, char *OutputName, int width, int height) - { - trigroup_t *triangles; - triangle_t *ptri; - triangle_t *grouptris; - mesh_node_t *pmnodes; - - vec3_t *vertices; - vec3_t *uvs; - vec3_t aveNorm, crossvect; - vec3_t diffvect1, diffvect2; - vec3_t v0, v1, v2; - vec3_t n, u, v; - vec3_t base, zaxis, yaxis; - vec3_t uvwMin, uvwMax; - vec3_t groupMin, groupMax; - vec3_t uvw; - - float *uFinal, *vFinal; - unsigned char *newpic; - - int finalstart = 0, finalcount = 0; - int xbase = 0, xwidth = 0, ywidth = 0; - int *todo, *done, finished; - int i, j, k, l; //counters - int groupnum, numtris, numverts, num; - int count; - FILE *grpfile; - long datasize; - - for ( i = 0; i<3; i++) - { - aveNorm[i] = 0; - uvwMin[i] = 1e30f; - uvwMax[i] = -1e30f; - } - - pmnodes = NULL; - ptri = NULL; - triangles = NULL; - - zaxis[0] = 0; - zaxis[1] = 0; - zaxis[2] = 1; - - yaxis[0] = 0; - yaxis[1] = 1; - yaxis[2] = 0; - - LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes); - - todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen"); - done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen"); - triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen"); - - for ( i=0; i < fmheader.num_tris; i++) - { - todo[i] = false; - done[i] = false; - triangles[i].triangle = ptri[i]; - triangles[i].group = 0; - } - - groupnum = 0; - - // transitive closure algorithm follows - // put all triangles who transitively share vertices into separate groups - - while (1) - { - for ( i = 0; i < fmheader.num_tris; i++) - { - if (!done[i]) - { - break; - } - } - if ( i == fmheader.num_tris) - { - break; - } - finished = false; - todo[i] = true; - while (!finished) - { - finished = true; - for ( i = 0; i < fmheader.num_tris; i++) - { - if (todo[i]) - { - done[i] = true; - triangles[i].group = groupnum; - todo[i] = false; - for ( j = 0; j < fmheader.num_tris; j++) - { - if ((!done[j]) && (ShareVertex(triangles[i],triangles[j]))) - { - todo[j] = true; - finished = false; - } - } - } - } - } - groupnum++; - } - uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen"); - vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen"); - - grpfile = fopen("grpdebug.txt","w"); - - - for (i = 0; i < groupnum; i++) - { - - fprintf(grpfile,"Group Number: %d\n", i); - - numtris = GetNumTris(triangles, i); // number of triangles in group i - numverts = numtris * 3; - - fprintf(grpfile,"%d triangles.\n", numtris); - - vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen"); - uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen"); - grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen"); - - for (count = 0; count < fmheader.num_tris; count++) - { - if (triangles[count].group == i) - { - fprintf(grpfile,"Triangle %d\n", count); - } - } - fprintf(grpfile,"\n"); - - - - - GetOneGroup(triangles, i, grouptris); - - num = 0; - for (j = 0; j < numtris; j++) - { - VectorCopy(grouptris[j].verts[0], v0); - VectorCopy(grouptris[j].verts[1], v1); - VectorCopy(grouptris[j].verts[2], v2); - VectorSubtract(v1, v0, diffvect1); - VectorSubtract(v2, v1, diffvect2); - CrossProduct( diffvect1, diffvect2, crossvect); - VectorAdd(aveNorm, crossvect, aveNorm); - VectorCopy(v0,vertices[num]); - num++; // FIXME - VectorCopy(v1,vertices[num]); - num++; // add routine to add only verts that - VectorCopy(v2,vertices[num]); - num++; // have not already been added - } - - assert (num >= 3); - // figure out the best plane projections - DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base); - - if (DotProduct(aveNorm,n) < 0.0f) - { - VectorScale(n, -1.0f, n); - } - VectorNormalize(n,n); - if (fabs(n[2]) < .57) - { - CrossProduct( zaxis, n, crossvect); - VectorCopy(crossvect, u); - } - else - { - CrossProduct( yaxis, n, crossvect); - VectorCopy(crossvect, u); - } - VectorNormalize(u,u); - CrossProduct( n, u, crossvect); - VectorCopy(crossvect, v); - VectorNormalize(v,v); - - num = 0; - - for ( j = 0; j < 3; j++) - { - groupMin[j] = 1e30f; - groupMax[j] = -1e30f; - } - - for ( j = 0; j < numtris; j++) - { - for ( k = 0; k < 3; k++) - { - VectorCopy(grouptris[j].verts[k],v0); - VectorSubtract(v0, base, v0); - uvw[0] = DotProduct(v0, u); - uvw[1] = DotProduct(v0, v); - uvw[2] = DotProduct(v0, n); - VectorCopy(uvw,uvs[num]); - num++; - for ( l = 0; l < 3; l++) - { - if (uvw[l] < groupMin[l]) - { - groupMin[l] = uvw[l]; - } - if (uvw[l] > groupMax[l]) - { - groupMax[l] = uvw[l]; - } - } - } - } - - xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap - ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin - - for ( j=0; j < numverts; j++) - { - uFinal[finalcount] = uvs[j][0] + xwidth + xbase; - vFinal[finalcount] = uvs[j][1] + ywidth; - if (uFinal[finalcount] < uvwMin[0]) - { - uvwMin[0] = uFinal[finalcount]; - } - if (uFinal[finalcount] > uvwMax[0]) - { - uvwMax[0] = uFinal[finalcount]; - } - if (vFinal[finalcount] < uvwMin[1]) - { - uvwMin[1] = vFinal[finalcount]; - } - if (vFinal[finalcount] > uvwMax[1]) - { - uvwMax[1] = vFinal[finalcount]; - } - finalcount++; - } - - fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth); - fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth); - - finalcount = finalstart; - - for ( count = 0; count < numverts; count++) - { - fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]); - fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]); - } - - finalstart = finalcount; - - fprintf(grpfile,"\n"); - - free(vertices); - free(uvs); - free(grouptris); - - xbase += ceil(groupMax[0] - groupMin[0]) + 2; - - } - - fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]); - fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]); - - - ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount); - - for (k = 0; k < finalcount; k++) - { - fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]); - } - - // i've got the array of vertices in uFinal and vFinal. Now I need to write them and draw lines - - datasize = width * height*sizeof(unsigned char); - newpic = (unsigned char*)SafeMalloc(datasize, "NewGen"); - memset(newpic,0,datasize); - memset(pic_palette,0,sizeof(pic_palette)); - pic_palette[767] = pic_palette[766] = pic_palette[765] = 255; - - k = 0; - while (k < finalcount) - { - NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height); - k++; - NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height); - k++; - NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height); - k++; - fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k); - } - - WritePCXfile (OutputName, newpic, width, height, pic_palette); - - fclose(grpfile); - - free(todo); - free(done); - free(triangles); - free(newpic); - return; - } - void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height) - { - long dx, dy; - long adx, ady; - long count; - float xfrac, yfrac, xstep, ystep; - unsigned long sx, sy; - float u, v; - - dx = x2 - x1; - dy = y2 - y1; - adx = abs(dx); - ady = abs(dy); - - count = adx > ady ? adx : ady; - count++; - - if(count > 300) - { - printf("Bad count\n"); - return; // don't ever hang up on bad data - } - - xfrac = x1; - yfrac = y1; - - xstep = (float)dx/count; - ystep = (float)dy/count; - - switch(LineType) - { - case LINE_NORMAL: - do - { - if(xfrac < width && yfrac < height) - { - picture[(long)yfrac*width+(long)xfrac] = LineColor; - } - xfrac += xstep; - yfrac += ystep; - count--; - } while (count > 0); - break; - case LINE_FAT: - do - { - for (u=-0.1 ; u<=0.9 ; u+=0.999) - { - for (v=-0.1 ; v<=0.9 ; v+=0.999) - { - sx = xfrac+u; - sy = yfrac+v; - if(sx < width && sy < height) - { - picture[sy*width+sx] = LineColor; - } - } - } - xfrac += xstep; - yfrac += ystep; - count--; - } while (count > 0); - break; - case LINE_DOTTED: - do - { - if(count&1 && xfrac < width && - yfrac < height) - { - picture[(long)yfrac*width+(long)xfrac] = LineColor; - } - xfrac += xstep; - yfrac += ystep; - count--; - } while (count > 0); - break; - default: - Error("Unknown %d.\n", LineType); - } - } - */ -void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ){ - - int i; - float hscale, vscale; - float scale; - - hscale = max[0]; - vscale = max[1]; - - hscale = ( Width - 2 ) / max[0]; - vscale = ( Height - 2 ) / max[1]; - - scale = hscale; - if ( scale > vscale ) { - scale = vscale; - } - for ( i = 0; i < verts; i++ ) - { - u[i] *= scale; - v[i] *= scale; - } - return; -} - - -void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ){ - int i; - int j; - - j = 0; - for ( i = 0; i < fmheader.num_tris; i++ ) - { - if ( tris[i].group == grp ) { - triangles[j++] = tris[i].triangle; - } - } - return; -} - - -int GetNumTris( trigroup_t *tris, int grp ){ - int i; - int verts; - - verts = 0; - for ( i = 0; i < fmheader.num_tris; i++ ) - { - if ( tris[i].group == grp ) { - verts++; - } - } - return verts; -} - - -int ShareVertex( trigroup_t trione, trigroup_t tritwo ){ - int i; - int j; - - i = 1; - j = 1; - for ( i = 0; i < 3; i++ ) - { - for ( j = 0; j < 3; j++ ) - { - if ( DistBetween( trione.triangle.verts[i],tritwo.triangle.verts[j] ) < TRIVERT_DIST ) { - return true; - } - } - } - return false; -} - - -float DistBetween( vec3_t point1, vec3_t point2 ){ - float dist; - - dist = ( point1[0] - point2[0] ); - dist *= dist; - dist += ( point1[1] - point2[1] ) * ( point1[1] - point2[1] ); - dist += ( point1[2] - point2[2] ) * ( point1[2] - point2[2] ); - dist = sqrt( dist ); - return dist; -} - - -void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ){ - triangle_t *ptri; - mesh_node_t *pmnodes; - int i; - - pmnodes = NULL; - ptri = NULL; - - LoadTriangleList( ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes ); - if ( g_ignoreTriUV ) { - for ( i = 0; i < fmheader.num_tris; i++ ) - { - ptri[i].HasUV = 0; - } - } - - memset( pic,0,sizeof( pic ) ); - memset( pic_palette,0,sizeof( pic_palette ) ); - pic_palette[767] = pic_palette[766] = pic_palette[765] = 255; - - ScaleWidth = Width; - ScaleHeight = Height; - - BuildST( ptri, fmheader.num_tris, true ); - - WritePCXfile( OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette ); - - printf( "Gen Skin Stats:\n" ); - printf( " Input Base: %s\n",ModelFile ); - printf( " Input Dimensions: %d,%d\n",Width,Height ); - printf( "\n" ); - printf( " Output File: %s\n",OutputName ); - printf( " Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight ); - - if ( fmheader.num_mesh_nodes ) { - printf( "\nNodes:\n" ); - for ( i = 0; i < fmheader.num_mesh_nodes; i++ ) - { - printf( " %s\n",pmnodes[i].name ); - } - } - - free( ptri ); - free( pmnodes ); -} - - -void Cmd_FMBeginGroup( void ){ - GetScriptToken( false ); - - g_no_opimizations = false; - - groups[num_groups].start_frame = fmheader.num_frames; - groups[num_groups].num_frames = 0; - - groups[num_groups].degrees = atol( token ); - if ( groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32 ) { - Error( "Degrees of freedom out of range: %d",groups[num_groups].degrees ); - } -} - -void Cmd_FMEndGroup( void ){ - groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame; - - if ( num_groups < MAX_GROUPS - 1 ) { - num_groups++; - } - else - { - Error( "Number of compression groups exceded: %i\n", MAX_GROUPS ); - } -} diff --git a/tools/quake2/qdata_heretic2/h2data.rc b/tools/quake2/qdata_heretic2/h2data.rc deleted file mode 100644 index 21540bc2..00000000 --- a/tools/quake2/qdata_heretic2/h2data.rc +++ /dev/null @@ -1,115 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON DISCARDABLE "..\\..\\..\\icons\\h2data.ico" - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "Heavily modified from original ID tool\0" - VALUE "CompanyName", "Raven Software\0" - VALUE "FileDescription", "qdata\0" - VALUE "FileVersion", "2.0\0" - VALUE "InternalName", "qdata\0" - VALUE "LegalCopyright", "Copyright © 1998\0" - VALUE "OriginalFilename", "qdata.exe\0" - VALUE "ProductName", "Raven Software qdata\0" - VALUE "ProductVersion", "2.0\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/tools/quake2/qdata_heretic2/images.c b/tools/quake2/qdata_heretic2/images.c deleted file mode 100644 index 555303bc..00000000 --- a/tools/quake2/qdata_heretic2/images.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - Copyright (C) 1999-2007 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" - -#if GDEF_OS_WINDOWS - #include -#endif - -#if GDEF_OS_MACOS && !defined( XWINDOWS ) -#include -#else -#include -#endif - -#if 1 -extern char *g_outputDir; -#endif // _QDATA - -char mip_prefix[1024]; // directory to dump the textures in - -qboolean colormap_issued; -byte colormap_palette[768]; - -unsigned total_x = 0; -unsigned total_y = 0; -unsigned total_textures = 0; - -#define MAX_IMAGE_SIZE 512 - -#if 0 -/* - ============== - 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; - } -} - -#endif - - -// ******************************************************************** -// ** Mip Map Pre-Processing Routines -// ******************************************************************** - -#define intensity_value 1 - -static unsigned image_pal[256]; - -#define MAX_LAST 25 - -long palette_r[256], palette_g[256], palette_b[256]; -long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place; - -long cached; - -void PrepareConvert( unsigned *palette ){ - int i; - - for ( i = 0; i < 256; i++ ) - { - palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16; - palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8; - palette_b[i] = ( palette[i] & 0x000000ff ); - } - - for ( i = 0; i < MAX_LAST; i++ ) - last_r[i] = -1; - - last_place = -1; -} - -int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){ - int i; - long min_dist; - int min_index; - long dist; - long dr, dg, db, biggest_delta; - - for ( i = 0; i < MAX_LAST; i++ ) - if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) { - cached++; - return last_i[i]; - } - - min_dist = 256 * 256 + 256 * 256 + 256 * 256; - biggest_delta = 256 * 256; - min_index = 0; - - for ( i = 0; i < 256; i++ ) - { - dr = abs( palette_r[i] - r ); - if ( dr > biggest_delta ) { - continue; - } - dg = abs( palette_g[i] - g ); - if ( dg > biggest_delta ) { - continue; - } - db = abs( palette_b[i] - b ); - if ( db > biggest_delta ) { - continue; - } - - dist = dr * dr + dg * dg + db * db; - if ( dist < min_dist ) { - min_dist = dist; - min_index = i; - if ( min_dist == 0 ) { - break; - } - - dist = dr; - if ( dg > dist ) { - dist = dg; - } - if ( db > dist ) { - dist = db; - } - if ( dist < biggest_delta ) { - biggest_delta = dist; - } - } - } - - last_place++; - if ( last_place >= MAX_LAST ) { - last_place = 0; - } - - last_r[last_place] = r; - last_g[last_place] = g; - last_b[last_place] = b; - last_i[last_place] = min_index; - - return min_index; -} - - -void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out, - int outwidth, int outheight, palette_t *palette ){ - int i, j; - byte *inrow, *inrow2; - unsigned frac, fracstep; - unsigned p1[1024], p2[1024], *p1p, *p2p; - palette_t *c1,*c2,*c3,*c4; - unsigned r,g,b; - - fracstep = inwidth * 0x10000 / outwidth; - - frac = fracstep >> 2; - for ( i = 0 ; i < outwidth ; i++ ) - { - p1[i] = frac >> 16; - frac += fracstep; - } - frac = 3 * ( fracstep >> 2 ); - for ( i = 0 ; i < outwidth ; i++ ) - { - p2[i] = frac >> 16; - frac += fracstep; - } - - cached = 0; - - for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth) - { - inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight ); - inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight ); - - p1p = p1; - p2p = p2; - for ( j = 0 ; j < outwidth ; j++ ) - { - c1 = &palette[*( (byte *)inrow + ( *p1p ) )]; - c2 = &palette[*( (byte *)inrow + ( *p2p ) )]; - c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )]; - c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )]; - - r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2; - g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2; - b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2; - - *out++ = ConvertTrueColorToPal( r,g,b ); - } - } -} - -void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){ - int i, j; - palette_t *c1,*c2,*c3,*c4; - unsigned r,g,b; - - cached = 0; - memset( out, 0, 256 * 256 ); - width <<= 1; - height <<= 1; - - for ( i = 0; i < height; i += 2, in += width ) - { - for ( j = 0; j < width; j += 2 ) - { - c1 = &palette[in[0]]; - c3 = &palette[in[width]]; - in++; - c2 = &palette[in[0]]; - c4 = &palette[in[width]]; - in++; - - r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2; - g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2; - b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2; - - *out++ = ConvertTrueColorToPal( r, g, b ); - } - } -} - - -miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){ - int scaled_width, scaled_height; - int i,j,r,g,b; - byte intensitytable[256]; - byte scaled[256 * 256]; - byte out[256 * 256]; - int miplevel; - miptex_t *mp; - byte *pos; - int size; - - for ( i = 0 ; i < 256 ; i++ ) - { - j = i * intensity_value; - if ( j > 255 ) { - j = 255; - } - intensitytable[i] = j; - } - - for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 ) - ; - if ( 1 && scaled_width > width && 1 ) { - scaled_width >>= 1; - } - for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 ) - ; - if ( 1 && scaled_height > height && 1 ) { - scaled_height >>= 1; - } - - // don't ever bother with >256 textures - if ( scaled_width > 256 ) { - scaled_width = 256; - } - if ( scaled_height > 256 ) { - scaled_height = 256; - } - - if ( scaled_width < 1 ) { - scaled_width = 1; - } - if ( scaled_height < 1 ) { - scaled_height = 1; - } - - size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 ); - mp = (miptex_t *)SafeMalloc( size, "CreateMip" ); - memset( mp,0,size ); - - mp->version = MIP_VERSION; - - for ( i = j = 0; i < 256; i++,j += 3 ) - { - mp->palette[i].r = r = intensitytable[palette[j]]; - mp->palette[i].g = g = intensitytable[palette[j + 1]]; - mp->palette[i].b = b = intensitytable[palette[j + 2]]; - image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b ); - } - - PrepareConvert( image_pal ); - - if ( scaled_width == width && scaled_height == height ) { - memcpy( scaled, data, width * height ); - } - else{ - GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette ); - } - - pos = (byte *)( mp + 1 ); - miplevel = 0; - - while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) ) - { - if ( scaled_width < 1 ) { - scaled_width = 1; - } - if ( scaled_height < 1 ) { - scaled_height = 1; - } - - if ( miplevel > 0 ) { - GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette ); - } - else{ - memcpy( out, scaled, 256 * 256 ); - } - - mp->width[miplevel] = scaled_width; - mp->height[miplevel] = scaled_height; - mp->offsets[miplevel] = pos - ( (byte *)( mp ) ); - memcpy( pos, out, scaled_width * scaled_height ); - memcpy( scaled, out, 256 * 256 ); - pos += scaled_width * scaled_height; - - scaled_width >>= 1; - scaled_height >>= 1; - - miplevel++; - } - - *FinalSize = pos - ( (byte *)( mp ) ); - - return mp; -} - - -void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){ - int i, j; - unsigned *inrow, *inrow2; - unsigned frac, fracstep; - unsigned p1[1024], p2[1024]; - byte *pix1, *pix2, *pix3, *pix4; - - fracstep = inwidth * 0x10000 / outwidth; - - frac = fracstep >> 2; - for ( i = 0 ; i < outwidth ; i++ ) - { - p1[i] = 4 * ( frac >> 16 ); - frac += fracstep; - } - frac = 3 * ( fracstep >> 2 ); - for ( i = 0 ; i < outwidth ; i++ ) - { - p2[i] = 4 * ( frac >> 16 ); - frac += fracstep; - } - - for ( i = 0 ; i < outheight ; i++, out += outwidth ) - { - inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight ); - inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight ); - frac = fracstep >> 1; - for ( j = 0 ; j < outwidth ; j++ ) - { - pix1 = (byte *)inrow + p1[j]; - pix2 = (byte *)inrow + p2[j]; - pix3 = (byte *)inrow2 + p1[j]; - pix4 = (byte *)inrow2 + p2[j]; - ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2; - ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2; - ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2; - ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2; - } - } -} - -void GL_MipMap( byte *out, byte *in, int width, int height ){ - int i, j; - - width <<= 3; - height <<= 1; - for ( i = 0 ; i < height ; i++, in += width ) - { - for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 ) - { - out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2; - out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2; - out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2; - out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2; - } - } -} - -miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){ - int scaled_width, scaled_height; - unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; - unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; - int miplevel; - miptex32_t *mp; - byte *pos; - int size; - paletteRGBA_t *test; - - for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 ) - ; - if ( 1 && scaled_width > width && 1 ) { - scaled_width >>= 1; - } - for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 ) - ; - if ( 1 && scaled_height > height && 1 ) { - scaled_height >>= 1; - } - - // don't ever bother with >256 textures - if ( scaled_width > MAX_IMAGE_SIZE ) { - scaled_width = MAX_IMAGE_SIZE; - } - if ( scaled_height > MAX_IMAGE_SIZE ) { - scaled_height = MAX_IMAGE_SIZE; - } - - if ( scaled_width < 1 ) { - scaled_width = 1; - } - if ( scaled_height < 1 ) { - scaled_height = 1; - } - - size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 ); - mp = (miptex32_t *)SafeMalloc( size, "CreateMip" ); - memset( mp,0,size ); - - mp->version = MIP32_VERSION; - - size = width * height; - test = (paletteRGBA_t *)data; - while ( size ) - { - if ( test->a != 255 ) { - mp->flags |= LittleLong( SURF_ALPHA_TEXTURE ); - break; - } - - size--; - test++; - } - - if ( scaled_width == width && scaled_height == height ) { - memcpy( scaled, data, width * height * 4 ); - } - else{ - GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height ); - } - - pos = (byte *)( mp + 1 ); - miplevel = 0; - - while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) ) - { - if ( scaled_width < 1 ) { - scaled_width = 1; - } - if ( scaled_height < 1 ) { - scaled_height = 1; - } - - if ( miplevel > 0 ) { - GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height ); - } - else - { - memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 ); - } - - mp->width[miplevel] = scaled_width; - mp->height[miplevel] = scaled_height; - mp->offsets[miplevel] = pos - ( (byte *)( mp ) ); - memcpy( pos, out, scaled_width * scaled_height * 4 ); - memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 ); - pos += scaled_width * scaled_height * 4; - - scaled_width >>= 1; - scaled_height >>= 1; - - miplevel++; - } - - *FinalSize = pos - ( (byte *)( mp ) ); - - return mp; -} - -/* - ============== - 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]; - - GetScriptToken( 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; - } - - GetScriptToken( false ); - xl = atoi( token ); - GetScriptToken( false ); - yl = atoi( token ); - GetScriptToken( false ); - w = atoi( token ); - GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Grab" ); - 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]; - - GetScriptToken( false ); - - sprintf( savename, "%s%s.lmp", gamedir, token ); - - if ( g_release ) { - sprintf( dest, "%s.lmp", token ); - ReleaseFile( dest ); - return; - } - - GetScriptToken( false ); - xl = atoi( token ); - GetScriptToken( false ); - yl = atoi( token ); - GetScriptToken( false ); - w = atoi( token ); - GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Raw" ); - 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 ( !ScriptTokenAvailable() ) { // just setting colormap_issued - return; - } - - GetScriptToken( 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 = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" ); - 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_altnamevalue, - pt_damagenamevalue, - pt_flagvalue, - pt_materialvalue, - pt_scale, - pt_mip, - pt_detail, - pt_gl, - pt_nomip, - pt_detailer, -} parmtype_t; - -typedef struct -{ - char *name; - int flags; - parmtype_t type; -} mipparm_t; - -mipparm_t mipparms[] = -{ - // utility content attributes - {"pushpull",CONTENTS_PUSHPULL, pt_contents}, - {"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 - - {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps - - // texture chaining - {"anim", 0, pt_animvalue}, // animname is the next animation - {"alt", 0, pt_altnamevalue}, // altname is the alternate texture - {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture - {"scale", 0, pt_scale}, // next two values are for scale - {"mip", 0, pt_mip}, - {"detail", 0, pt_detail}, - - {"GL_ZERO", GL_ZERO, pt_gl}, - {"GL_ONE", GL_ONE, pt_gl}, - {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl}, - {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl}, - {"GL_DST_COLOR", GL_DST_COLOR, pt_gl}, - {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl}, - {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl}, - {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl}, - {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl}, - {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl}, - {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl}, - - // 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 - {"alpha", SURF_ALPHA_TEXTURE, pt_flags}, - {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down... - {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished.... - - {"material", SURF_MATERIAL, pt_materialvalue}, - {"metal", SURF_TYPE_METAL, pt_flags}, - {"stone", SURF_TYPE_STONE, pt_flags}, - {"wood", SURF_TYPE_WOOD, pt_flags}, - - {"m_nomip", 0, pt_nomip}, - {"m_detail", 0, pt_detailer}, - - {NULL, 0, pt_contents} -}; - -/* - ============== - Cmd_Mip - - $mip filename x y width height - must be multiples of sixteen - SURF_WINDOW - ============== - */ - -void Cmd_Mip( void ){ - int xl,yl,xh,yh,w,h; - byte *dest, *source; - int flags, value, contents; - mipparm_t *mp; - char lumpname[128]; - char altname[128]; - char animname[128]; - char damagename[128]; - byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; - unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE]; - materialtype_t *mat; - char filename[1024]; - unsigned *destl, *sourcel; - int linedelta, x, y; - int size; - miptex_t *qtex; - miptex32_t *qtex32; - float scale_x, scale_y; - int mip_scale; - // detail texturing - char dt_name[128]; - 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; - - - 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 & 15 ) || ( h & 15 ) ) { - Error( "line %i: miptex sizes must be multiples of 16", scriptline ); - } - - flags = 0; - flags2 = 0; - contents = 0; - value = 0; - mip_scale = 0; - - altname[0] = animname[0] = damagename[0] = 0; - - scale_x = scale_y = 0.5; - - // detail texturing - dt_name[0] = 0; - dt_scale_x = dt_scale_y = 0.0; - dt_u = dt_v = 0.0; - dt_alpha = 0.0; - dt_src_blend_mode = dt_dst_blend_mode = 0; - - // get optional flags and values - while ( ScriptTokenAvailable() ) - { - GetScriptToken( false ); - - for ( mp = mipparms ; mp->name ; mp++ ) - { - if ( !strcmp( mp->name, token ) ) { - switch ( mp->type ) - { - case pt_animvalue: - GetScriptToken( false ); // specify the next animation frame - strcpy( animname, token ); - break; - case pt_altnamevalue: - GetScriptToken( false ); // specify the alternate texture - strcpy( altname, token ); - break; - case pt_damagenamevalue: - GetScriptToken( false ); // specify the damage texture - strcpy( damagename, token ); - break; - case pt_flags: - flags |= mp->flags; - break; - case pt_contents: - contents |= mp->flags; - break; - case pt_flagvalue: - flags |= mp->flags; - GetScriptToken( false ); // specify the light value - value = atoi( token ); - break; - case pt_materialvalue: - GetScriptToken( false ); - for ( mat = materialtypes ; mat->name ; mat++ ) - { - if ( !strcmp( mat->name, token ) ) { - // assumes SURF_MATERIAL is in top 8 bits - flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 ); - break; - } - } - break; - case pt_scale: - GetScriptToken( false ); // specify the x scale - scale_x = atof( token ); - GetScriptToken( false ); // specify the y scale - scale_y = atof( token ); - break; - - case pt_mip: - mip_scale = 1; - break; - - case pt_detailer: - flags2 |= MIP32_DETAILER_FLAG2; - break; - - case pt_nomip: - flags2 |= MIP32_NOMIP_FLAG2; - break; - - case pt_detail: - GetScriptToken( false ); - strcpy( dt_name, token ); - GetScriptToken( false ); - dt_scale_x = atof( token ); - GetScriptToken( false ); - dt_scale_y = atof( token ); - GetScriptToken( false ); - dt_u = atof( token ); - GetScriptToken( false ); - dt_v = atof( token ); - GetScriptToken( false ); - dt_alpha = atof( token ); - GetScriptToken( false ); - for ( mp = mipparms ; mp->name ; mp++ ) - { - if ( !strcmp( mp->name, token ) ) { - if ( mp->type == pt_gl ) { - dt_src_blend_mode = mp->flags; - break; - } - } - } - if ( !mp->name ) { - Error( "line %i: invalid gl blend mode %s", scriptline, token ); - } - GetScriptToken( false ); - for ( mp = mipparms ; mp->name ; mp++ ) - { - if ( !strcmp( mp->name, token ) ) { - if ( mp->type == pt_gl ) { - dt_dst_blend_mode = mp->flags; - break; - } - } - } - if ( !mp->name ) { - Error( "line %i: invalid gl blend mode %s", scriptline, token ); - } - break; - } - break; - } - } - if ( !mp->name ) { - Error( "line %i: unknown parm %s", scriptline, token ); - } - } - - if ( g_release ) { - return; // textures are only released by $maps - - } - xh = xl + w; - yh = yl + h; - if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) { - Error( "line %i image %s: image is too big!", scriptline, lumpname ); - } - - if ( TrueColorImage ) { - if ( xl >= longimagewidth || xh > longimagewidth || - yl >= longimageheight || yh > longimageheight ) { - Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, 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, true ); - - qtex32->flags |= LittleLong( flags ); - qtex32->flags2 |= LittleLong( flags2 ); - qtex32->contents = LittleLong( contents ); - qtex32->value = LittleLong( value ); - qtex32->scale_x = scale_x; - qtex32->scale_y = scale_y; - qtex32->mip_scale = mip_scale; - sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname ); - if ( animname[0] ) { - sprintf( qtex32->animname, "%s/%s", mip_prefix, animname ); - } - if ( altname[0] ) { - sprintf( qtex32->altname, "%s/%s", mip_prefix, altname ); - } - if ( damagename[0] ) { - sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename ); - } - if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) { - sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name ); - qtex32->dt_scale_x = dt_scale_x; - qtex32->dt_scale_y = dt_scale_y; - qtex32->dt_u = dt_u; - qtex32->dt_v = dt_v; - qtex32->dt_alpha = dt_alpha; - qtex32->dt_src_blend_mode = dt_src_blend_mode; - qtex32->dt_dst_blend_mode = dt_dst_blend_mode; - } - - // - // write it out - // - sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname ); - if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) { - printf( "writing %s with ALPHA\n", filename ); - } - else{ - printf( "writing %s\n", filename ); - } - SaveFile( filename, (byte *)qtex32, size ); - - free( qtex32 ); - } - else - { - 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, true ); - - 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 ); - } - - // - // write it out - // - sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname ); - printf( "writing %s\n", filename ); - SaveFile( filename, (byte *)qtex, size ); - - 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]; - - GetScriptToken( false ); - strcpy( mip_prefix, token ); - // create the directory if needed - sprintf( filename, "%stextures", g_outputDir ); - Q_mkdir( filename ); - sprintf( filename, "%stextures/%s", g_outputDir, 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; - - GetScriptToken( 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 ); - } - } -} diff --git a/tools/quake2/qdata_heretic2/jointed.c b/tools/quake2/qdata_heretic2/jointed.c deleted file mode 100644 index de8b802a..00000000 --- a/tools/quake2/qdata_heretic2/jointed.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include -#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 ); - } -} diff --git a/tools/quake2/qdata_heretic2/jointed.h b/tools/quake2/qdata_heretic2/jointed.h deleted file mode 100644 index 264d3175..00000000 --- a/tools/quake2/qdata_heretic2/jointed.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 1999-2007 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 diff --git a/tools/quake2/qdata_heretic2/joints.h b/tools/quake2/qdata_heretic2/joints.h deleted file mode 100644 index f8e64bf5..00000000 --- a/tools/quake2/qdata_heretic2/joints.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - -#include "globaldefs.h" - -#ifdef _HERETIC2_ -#include "angles.h" -#endif - -//typedef float vec3_t[3]; -//typedef unsigned char byte; - -#if !GDEF_OS_WINDOWS -#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 diff --git a/tools/quake2/qdata_heretic2/models.c b/tools/quake2/qdata_heretic2/models.c deleted file mode 100644 index 244f24ac..00000000 --- a/tools/quake2/qdata_heretic2/models.c +++ /dev/null @@ -1,2041 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include "jointed.h" -#include "fmodel.h" - -//================================================================= - -typedef struct -{ - int numnormals; - vec3_t normalsum; -} vertexnormals_t; - -typedef struct -{ - vec3_t v; - int lightnormalindex; -} trivert_t; - -typedef struct -{ - vec3_t mins, maxs; - char name[16]; - trivert_t v[MAX_VERTS]; - QDataJoint_t joints[NUM_CLUSTERS]; // ,this -} frame_t; - -// ,and all of this should get out of here, need to use new stuff in fmodels instead - -typedef struct IntListNode_s -{ - int data; - struct IntListNode_s *next; -} IntListNode_t; // gaak - -typedef struct -{ - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this -} PartialAliasFrame_t; - -int jointed; -int clustered; - -int *clusters[NUM_CLUSTERS]; -IntListNode_t *vertLists[NUM_CLUSTERS]; -int num_verts[NUM_CLUSTERS + 1]; -int new_num_verts[NUM_CLUSTERS + 1]; - -// end that - -//================================================================ - -frame_t g_frames[MAX_FRAMES]; -//frame_t *g_frames; - -static dmdl_t model; - - -float scale_up; // set by $scale -vec3_t adjust; // set by $origin -int g_fixedwidth, g_fixedheight; // set by $skinsize - - -// -// base frame info -// -dstvert_t base_st[MAX_VERTS]; -dtriangle_t triangles[MAX_TRIANGLES]; - -static int triangle_st[MAX_TRIANGLES][3][2]; - -// the command list holds counts, s/t values, and xyz indexes -// that are valid for every frame -int commands[16384]; -int numcommands; -int numglverts; -int used[MAX_TRIANGLES]; - -char g_skins[MAX_MD2SKINS][64]; - -char cdarchive[1024]; -char cdpartial[1024]; -char cddir[1024]; - -char modelname[64]; // empty unless $modelname issued (players) - -extern char *g_outputDir; - -#define NUMVERTEXNORMALS 162 - -float avertexnormals[NUMVERTEXNORMALS][3] = -{ - #include "anorms.h" -}; - -unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768]; - -FILE *headerouthandle = NULL; - -//============================================================== - -/* - =============== - ClearModel - =============== - */ -static void ClearModel( void ){ - memset( &model, 0, sizeof( model ) ); - - modelname[0] = 0; - jointed = NOT_JOINTED; - clustered = 0; - scale_up = 1.0; - VectorCopy( vec3_origin, adjust ); - g_fixedwidth = g_fixedheight = 0; - g_skipmodel = false; -} - - -void H_printf( char *fmt, ... ){ - va_list argptr; - char name[1024]; - - if ( !headerouthandle ) { - sprintf( name, "%s/tris.h", cddir ); - headerouthandle = SafeOpenWrite( name ); - fprintf( headerouthandle, "// %s\n\n", cddir ); - fprintf( headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n" ); - } - - va_start( argptr, fmt ); - vfprintf( headerouthandle, fmt, argptr ); - va_end( argptr ); -} - -#if 1 -/* - ============ - WriteModelFile - ============ - */ -void WriteCommonModelFile( FILE *modelouthandle, PartialAliasFrame_t *outFrames ){ - int i; - dmdl_t modeltemp; - int j, k; - frame_t *in; - daliasframe_t *out; - byte buffer[MAX_VERTS * 4 + 128]; - float v; - int c_on, c_off; - - model.version = ALIAS_VERSION; - model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz]; - model.num_glcmds = numcommands; - model.ofs_skins = sizeof( dmdl_t ); - model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; - model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t ); - model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t ); - model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize; - model.ofs_end = model.ofs_glcmds + model.num_glcmds * sizeof( int ); - // - // write out the model header - // - for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ ) - ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] ); - - SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) ); - - // - // write out the skin names - // - SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME ); - - // - // write out the texture coordinates - // - c_on = c_off = 0; - for ( i = 0 ; i < model.num_st ; i++ ) - { - base_st[i].s = LittleShort( base_st[i].s ); - base_st[i].t = LittleShort( base_st[i].t ); - } - - SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) ); - - // - // write out the triangles - // - for ( i = 0 ; i < model.num_tris ; i++ ) - { - int j; - dtriangle_t tri; - - for ( j = 0 ; j < 3 ; j++ ) - { - tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); - tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); - } - - SafeWrite( modelouthandle, &tri, sizeof( tri ) ); - } - - // - // write out the frames - // - for ( i = 0 ; i < model.num_frames ; i++ ) - { - in = &g_frames[i]; - out = (daliasframe_t *)buffer; - - strcpy( out->name, in->name ); - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; - out->translate[j] = in->mins[j]; - - if ( outFrames ) { - outFrames[i].scale[j] = out->scale[j]; - outFrames[i].translate[j] = out->translate[j]; - } - } - - for ( j = 0 ; j < model.num_xyz ; j++ ) - { - // all of these are byte values, so no need to deal with endianness - out->verts[j].lightnormalindex = in->v[j].lightnormalindex; - - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - if ( v < 0 ) { - v = 0; - } - out->verts[j].v[k] = v; - } - } - - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = LittleFloat( out->scale[j] ); - out->translate[j] = LittleFloat( out->translate[j] ); - } - - SafeWrite( modelouthandle, out, model.framesize ); - } - - // - // write out glcmds - // - SafeWrite( modelouthandle, commands, numcommands * 4 ); -} - -/* - ============ - WriteModelFile - ============ - */ -void WriteModelFile( FILE *modelouthandle ){ - model.ident = IDALIASHEADER; - - WriteCommonModelFile( modelouthandle, NULL ); -} - -/* - ============ - WriteJointedModelFile - ============ - */ -void WriteJointedModelFile( FILE *modelouthandle ){ - int i; - int j, k; - frame_t *in; - float v; - IntListNode_t *current, *toFree; - PartialAliasFrame_t outFrames[MAX_FRAMES]; - - model.ident = IDJOINTEDALIASHEADER; - - WriteCommonModelFile( modelouthandle, outFrames ); - - // Skeletal Type - SafeWrite( modelouthandle, &jointed, sizeof( int ) ); - - // number of joints - SafeWrite( modelouthandle, &numJointsForSkeleton[jointed], sizeof( int ) ); - - // number of verts in each cluster - SafeWrite( modelouthandle, &new_num_verts[1], sizeof( int ) * numJointsForSkeleton[jointed] ); - - // cluster verts - for ( i = 0; i < new_num_verts[0]; ++i ) - { - current = vertLists[i]; - while ( current ) - { - SafeWrite( modelouthandle, ¤t->data, sizeof( int ) ); - toFree = current; - current = current->next; - free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base - } - } - - for ( i = 0 ; i < model.num_frames ; i++ ) - { - in = &g_frames[i]; - - for ( j = 0 ; j < new_num_verts[0]; ++j ) - { - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - - if ( v < 0 ) { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite( modelouthandle, &v, sizeof( float ) ); - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - - if ( v < 0 ) { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite( modelouthandle, &v, sizeof( float ) ); - } - - for ( k = 0 ; k < 3 ; k++ ) - { - v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - - if ( v < 0 ) { - v = 0; - } - - // write out origin as a float (there's only a few per model, so it's not really - // a size issue) - SafeWrite( modelouthandle, &v, sizeof( float ) ); - } - } - } -} -#else -/* - ============ - WriteModelFile - ============ - */ -static void WriteModelFile( FILE *modelouthandle ){ - int i; - dmdl_t modeltemp; - int j, k; - frame_t *in; - daliasframe_t *out; - byte buffer[MAX_VERTS * 4 + 128]; - float v; - int c_on, c_off; - - model.ident = IDALIASHEADER; - model.version = ALIAS_VERSION; - model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz]; - model.num_glcmds = numcommands; - model.ofs_skins = sizeof( dmdl_t ); - model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; - model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t ); - model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t ); - model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize; - model.ofs_end = model.ofs_glcmds + model.num_glcmds * 4; - - // - // write out the model header - // - for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ ) - ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] ); - - SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) ); - - // - // write out the skin names - // - SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME ); - - // - // write out the texture coordinates - // - c_on = c_off = 0; - for ( i = 0 ; i < model.num_st ; i++ ) - { - base_st[i].s = LittleShort( base_st[i].s ); - base_st[i].t = LittleShort( base_st[i].t ); - } - - SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) ); - - // - // write out the triangles - // - for ( i = 0 ; i < model.num_tris ; i++ ) - { - int j; - dtriangle_t tri; - - for ( j = 0 ; j < 3 ; j++ ) - { - tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] ); - tri.index_st[j] = LittleShort( triangles[i].index_st[j] ); - } - - SafeWrite( modelouthandle, &tri, sizeof( tri ) ); - } - - // - // write out the frames - // - for ( i = 0 ; i < model.num_frames ; i++ ) - { - in = &g_frames[i]; - out = (daliasframe_t *)buffer; - - strcpy( out->name, in->name ); - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255; - out->translate[j] = in->mins[j]; - } - - for ( j = 0 ; j < model.num_xyz ; j++ ) - { - // all of these are byte values, so no need to deal with endianness - out->verts[j].lightnormalindex = in->v[j].lightnormalindex; - - for ( k = 0 ; k < 3 ; k++ ) - { - // scale to byte values & min/max check - v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] ); - - // clamp, so rounding doesn't wrap from 255.6 to 0 - if ( v > 255.0 ) { - v = 255.0; - } - if ( v < 0 ) { - v = 0; - } - out->verts[j].v[k] = v; - } - } - - for ( j = 0 ; j < 3 ; j++ ) - { - out->scale[j] = LittleFloat( out->scale[j] ); - out->translate[j] = LittleFloat( out->translate[j] ); - } - - SafeWrite( modelouthandle, out, model.framesize ); - } - - // - // write out glcmds - // - SafeWrite( modelouthandle, commands, numcommands * 4 ); -} -#endif - -/* - =============== - FinishModel - =============== - */ -void FinishModel( void ){ - FILE *modelouthandle; - int i; - char name[1024]; - - if ( !model.num_frames ) { - return; - } - -// -// copy to release directory tree if doing a release build -// - if ( g_release ) { - if ( modelname[0] ) { - sprintf( name, "%s", modelname ); - } - else{ - sprintf( name, "%s/tris.md2", cdpartial ); - } - ReleaseFile( name ); - - for ( i = 0 ; i < model.num_skins ; i++ ) - { - ReleaseFile( g_skins[i] ); - } - model.num_frames = 0; - return; - } - -// -// write the model output file -// - if ( modelname[0] ) { - sprintf( name, "%s%s", g_outputDir, modelname ); - } - else{ - sprintf( name, "%s/tris.md2", g_outputDir ); - } - printf( "saving to %s\n", name ); - CreatePath( name ); - modelouthandle = SafeOpenWrite( name ); - -#if 1 - if ( jointed != NOT_JOINTED ) { - WriteJointedModelFile( modelouthandle ); - } - else -#endif - WriteModelFile( modelouthandle ); - - printf( "%3dx%3d skin\n", model.skinwidth, model.skinheight ); - printf( "First frame boundaries:\n" ); - printf( " minimum x: %3f\n", g_frames[0].mins[0] ); - printf( " maximum x: %3f\n", g_frames[0].maxs[0] ); - printf( " minimum y: %3f\n", g_frames[0].mins[1] ); - printf( " maximum y: %3f\n", g_frames[0].maxs[1] ); - printf( " minimum z: %3f\n", g_frames[0].mins[2] ); - printf( " maximum z: %3f\n", g_frames[0].maxs[2] ); - printf( "%4d vertices\n", model.num_xyz ); - printf( "%4d triangles\n", model.num_tris ); - printf( "%4d frame\n", model.num_frames ); - printf( "%4d glverts\n", numglverts ); - printf( "%4d glcmd\n", model.num_glcmds ); - printf( "%4d skins\n", model.num_skins ); - printf( "file size: %d\n", (int)ftell( modelouthandle ) ); - printf( "---------------------\n" ); - - fclose( modelouthandle ); - - // finish writing header file - H_printf( "\n" ); - - // scale_up is usefull to allow step distances to be adjusted - H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up ); - - fclose( headerouthandle ); - headerouthandle = NULL; -} - - -/* - ================================================================= - - ALIAS MODEL DISPLAY LIST GENERATION - - ================================================================= - */ - -int strip_xyz[128]; -int strip_st[128]; -int strip_tris[128]; -int stripcount; - -/* - ================ - StripLength - ================ - */ -static int StripLength( int starttri, int startv ){ - int m1, m2; - int st1, st2; - int j; - dtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - strip_xyz[0] = last->index_xyz[( startv ) % 3]; - strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; - strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; - strip_st[0] = last->index_st[( startv ) % 3]; - strip_st[1] = last->index_st[( startv + 1 ) % 3]; - strip_st[2] = last->index_st[( startv + 2 ) % 3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[( startv + 2 ) % 3]; - st1 = last->index_st[( startv + 2 ) % 3]; - m2 = last->index_xyz[( startv + 1 ) % 3]; - st2 = last->index_st[( startv + 1 ) % 3]; - - // look for a matching triangle -nexttri: - for ( j = starttri + 1, check = &triangles[starttri + 1] - ; j < model.num_tris ; j++, check++ ) - { - for ( k = 0 ; k < 3 ; k++ ) - { - if ( check->index_xyz[k] != m1 ) { - continue; - } - if ( check->index_st[k] != st1 ) { - continue; - } - if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { - continue; - } - if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { - continue; - } - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if ( used[j] ) { - goto done; - } - - // the new edge - if ( stripcount & 1 ) { - m2 = check->index_xyz[ ( k + 2 ) % 3 ]; - st2 = check->index_st[ ( k + 2 ) % 3 ]; - } - else - { - m1 = check->index_xyz[ ( k + 2 ) % 3 ]; - st1 = check->index_st[ ( k + 2 ) % 3 ]; - } - - strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ]; - strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ]; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for ( j = starttri + 1 ; j < model.num_tris ; j++ ) - if ( used[j] == 2 ) { - used[j] = 0; - } - - return stripcount; -} - - -/* - =========== - FanLength - =========== - */ -static int FanLength( int starttri, int startv ){ - int m1, m2; - int st1, st2; - int j; - dtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - strip_xyz[0] = last->index_xyz[( startv ) % 3]; - strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3]; - strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3]; - strip_st[0] = last->index_st[( startv ) % 3]; - strip_st[1] = last->index_st[( startv + 1 ) % 3]; - strip_st[2] = last->index_st[( startv + 2 ) % 3]; - - strip_tris[0] = starttri; - stripcount = 1; - - m1 = last->index_xyz[( startv + 0 ) % 3]; - st1 = last->index_st[( startv + 0 ) % 3]; - m2 = last->index_xyz[( startv + 2 ) % 3]; - st2 = last->index_st[( startv + 2 ) % 3]; - - - // look for a matching triangle -nexttri: - for ( j = starttri + 1, check = &triangles[starttri + 1] - ; j < model.num_tris ; j++, check++ ) - { - for ( k = 0 ; k < 3 ; k++ ) - { - if ( check->index_xyz[k] != m1 ) { - continue; - } - if ( check->index_st[k] != st1 ) { - continue; - } - if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) { - continue; - } - if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) { - continue; - } - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if ( used[j] ) { - goto done; - } - - // the new edge - m2 = check->index_xyz[ ( k + 2 ) % 3 ]; - st2 = check->index_st[ ( k + 2 ) % 3 ]; - - strip_xyz[stripcount + 2] = m2; - strip_st[stripcount + 2] = st2; - strip_tris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for ( j = starttri + 1 ; j < model.num_tris ; j++ ) - if ( used[j] == 2 ) { - used[j] = 0; - } - - return stripcount; -} - - - -/* - ================ - BuildGlCmds - - Generate a list of trifans or strips - for the model, which holds for all frames - ================ - */ -static void BuildGlCmds( void ){ - int i, j, k; - int startv; - float s, t; - int len, bestlen, besttype; - int best_xyz[1024]; - int best_st[1024]; - int best_tris[1024]; - int type; - - // - // build tristrips - // - numcommands = 0; - numglverts = 0; - memset( used, 0, sizeof( used ) ); - for ( i = 0 ; i < model.num_tris ; i++ ) - { - // pick an unused triangle and start the trifan - if ( used[i] ) { - continue; - } - - bestlen = 0; - for ( type = 0 ; type < 2 ; type++ ) -// type = 1; - { - for ( startv = 0 ; startv < 3 ; startv++ ) - { - if ( type == 1 ) { - len = StripLength( i, startv ); - } - else{ - len = FanLength( i, startv ); - } - if ( len > bestlen ) { - besttype = type; - bestlen = len; - for ( j = 0 ; j < bestlen + 2 ; j++ ) - { - best_st[j] = strip_st[j]; - best_xyz[j] = strip_xyz[j]; - } - for ( j = 0 ; j < bestlen ; j++ ) - best_tris[j] = strip_tris[j]; - } - } - } - - // mark the tris on the best strip/fan as used - for ( j = 0 ; j < bestlen ; j++ ) - used[best_tris[j]] = 1; - - if ( besttype == 1 ) { - commands[numcommands++] = ( bestlen + 2 ); - } - else{ - commands[numcommands++] = -( bestlen + 2 ); - } - - numglverts += bestlen + 2; - - for ( j = 0 ; j < bestlen + 2 ; j++ ) - { - // emit a vertex into the reorder buffer - k = best_st[j]; - - // emit s/t coords into the commands stream - s = base_st[k].s; - t = base_st[k].t; - - s = ( s + 0.5 ) / model.skinwidth; - t = ( t + 0.5 ) / model.skinheight; - - *(float *)&commands[numcommands++] = s; - *(float *)&commands[numcommands++] = t; - *(int *)&commands[numcommands++] = best_xyz[j]; - } - } - - commands[numcommands++] = 0; // end of list marker -} - - -/* - =============================================================== - - BASE FRAME SETUP - - =============================================================== - */ - -/* - ============ - BuildST - - Builds the triangle_st array for the base frame and - model.skinwidth / model.skinheight - - FIXME: allow this to be loaded from a file for - arbitrary mappings - ============ - */ -#if 0 -static void OldBuildST( triangle_t *ptri, int numtri ){ - int i, j; - int width, height, iwidth, iheight, swidth; - float basex, basey; - float s_scale, t_scale; - float scale; - vec3_t mins, maxs; - float *pbasevert; - vec3_t vtemp1, vtemp2, normal; - - // - // find bounds of all the verts on the base frame - // - ClearBounds( mins, maxs ); - - for ( i = 0 ; i < numtri ; i++ ) - for ( j = 0 ; j < 3 ; j++ ) - AddPointToBounds( ptri[i].verts[j], mins, maxs ); - - for ( i = 0 ; i < 3 ; i++ ) - { - mins[i] = floor( mins[i] ); - maxs[i] = ceil( maxs[i] ); - } - - width = maxs[0] - mins[0]; - height = maxs[2] - mins[2]; - - if ( !g_fixedwidth ) { // old style - scale = 8; - if ( width * scale >= 150 ) { - scale = 150.0 / width; - } - if ( height * scale >= 190 ) { - scale = 190.0 / height; - } - - s_scale = t_scale = scale; - - iwidth = ceil( width * s_scale ); - iheight = ceil( height * t_scale ); - - iwidth += 4; - iheight += 4; - } - else - { // new style - iwidth = g_fixedwidth / 2; - iheight = g_fixedheight; - - s_scale = (float)( iwidth - 4 ) / width; - t_scale = (float)( iheight - 4 ) / height; - } - -// -// determine which side of each triangle to map the texture to -// - for ( i = 0 ; i < numtri ; i++ ) - { - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - if ( normal[1] > 0 ) { - basex = iwidth + 2; - } - else - { - basex = 2; - } - basey = 2; - - for ( j = 0 ; j < 3 ; j++ ) - { - pbasevert = ptri[i].verts[j]; - - triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); - triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); - } - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - swidth = iwidth * 2; - model.skinwidth = ( swidth + 3 ) & ~3; - model.skinheight = iheight; -} -#endif - -//========================================================================== -// -// DrawScreen -// -//========================================================================== - -void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ){ - int i; - byte *scrpos; - char buffer[256]; - - // Divider - scrpos = &pic[( INFO_Y - 2 ) * SKINPAGE_WIDTH]; - for ( i = 0; i < SKINPAGE_WIDTH; i++ ) - { - *scrpos++ = 255; - } - - sprintf( buffer, "GENSKIN: " ); - DrawTextChar( 16, INFO_Y, buffer ); - - sprintf( buffer, "( %03d * %03d ) SCALE %f %f, SKINWIDTH %d," - " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth * 2, (int)iheight ); - DrawTextChar( 80, INFO_Y, buffer ); -} - -/* - ============ - BuildST - - Builds the triangle_st array for the base frame and - model.skinwidth / model.skinheight - - FIXME: allow this to be loaded from a file for - arbitrary mappings - ============ - */ -void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){ - int i, j; - int width, height, iwidth, iheight, swidth; - float basex, basey; - float scale; - vec3_t mins, maxs; - float *pbasevert; - vec3_t vtemp1, vtemp2, normal; - float s_scale, t_scale; - float scWidth; - float scHeight; - - // - // find bounds of all the verts on the base frame - // - ClearBounds( mins, maxs ); - - for ( i = 0 ; i < numtri ; i++ ) - for ( j = 0 ; j < 3 ; j++ ) - AddPointToBounds( ptri[i].verts[j], mins, maxs ); - - for ( i = 0 ; i < 3 ; i++ ) - { - mins[i] = floor( mins[i] ); - maxs[i] = ceil( maxs[i] ); - } - - width = maxs[0] - mins[0]; - height = maxs[2] - mins[2]; - - - scWidth = ( ScaleWidth / 2 ) * SCALE_ADJUST_FACTOR; - scHeight = ScaleHeight * SCALE_ADJUST_FACTOR; - - scale = scWidth / width; - - if ( height * scale >= scHeight ) { - scale = scHeight / height; - } - - iwidth = ceil( width * scale ) + 4; - iheight = ceil( height * scale ) + 4; - - s_scale = (float)( iwidth - 4 ) / width; - t_scale = (float)( iheight - 4 ) / height; - t_scale = s_scale; - - if ( DrawSkin ) { - DrawScreen( s_scale, t_scale, iwidth, iheight ); - } - - -/* if (!g_fixedwidth) - { // old style - scale = 8; - if (width*scale >= 150) - scale = 150.0 / width; - if (height*scale >= 190) - scale = 190.0 / height; - - s_scale = t_scale = scale; - - iwidth = ceil(width*s_scale); - iheight = ceil(height*t_scale); - - iwidth += 4; - iheight += 4; - } - else - { // new style - iwidth = g_fixedwidth / 2; - iheight = g_fixedheight; - - s_scale = (float)(iwidth-4) / width; - t_scale = (float)(iheight-4) / height; - }*/ - -// -// determine which side of each triangle to map the texture to -// - for ( i = 0 ; i < numtri ; i++ ) - { - if ( ptri[i].HasUV ) { - for ( j = 0 ; j < 3 ; j++ ) - { - triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * iwidth ); - triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * iheight ); - } - } - else - { - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - if ( normal[1] > 0 ) { - basex = iwidth + 2; - } - else - { - basex = 2; - } - basey = 2; - - for ( j = 0 ; j < 3 ; j++ ) - { - pbasevert = ptri[i].verts[j]; - - triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex ); - triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey ); - } - } - - DrawLine( triangle_st[i][0][0], triangle_st[i][0][1], - triangle_st[i][1][0], triangle_st[i][1][1] ); - DrawLine( triangle_st[i][1][0], triangle_st[i][1][1], - triangle_st[i][2][0], triangle_st[i][2][1] ); - DrawLine( triangle_st[i][2][0], triangle_st[i][2][1], - triangle_st[i][0][0], triangle_st[i][0][1] ); - } - -// make the width a multiple of 4; some hardware requires this, and it ensures -// dword alignment for each scan - - swidth = iwidth * 2; - model.skinwidth = ( swidth + 3 ) & ~3; - model.skinheight = iheight; -} - - -static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters, - IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){ - int i, j; - IntListNode_t *next; - - for ( j = 0; j < num_verts[0]; ++j ) - { - for ( i = 0; i < num_verts[j + 1]; ++i ) - { - if ( clusters[j][i] == oldindex ) { - ++new_num_verts[j + 1]; - - next = vertLists[j]; - - vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" ); - // Currently freed in WriteJointedModelFile only - - vertLists[j]->data = newIndex; - vertLists[j]->next = next; - } - } - } -} - -/* - ================= - Cmd_Base - ================= - */ -void Cmd_Base( void ){ - vec3_t base_xyz[MAX_VERTS]; - triangle_t *ptri; - int i, j, k; -#if 1 -#else - int time1; -#endif - char file1[1024]; - char file2[1024]; - - GetScriptToken( false ); - - if ( g_skipmodel || g_release || g_archive ) { - return; - } - - printf( "---------------------\n" ); -#if 1 - sprintf( file1, "%s/%s", cdpartial, token ); - printf( "%s ", file1 ); - - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s", cddir, token ); -#else - sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext ); - printf( "%s\n", file1 ); - - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s.%s", cddir, token, trifileext ); - - time1 = FileTime( file1 ); - if ( time1 == -1 ) { - Error( "%s doesn't exist", file1 ); - } -#endif -// -// load the base triangles -// - if ( do3ds ) { - Load3DSTriangleList( file1, &ptri, &model.num_tris, NULL, NULL ); - } - else{ - LoadTriangleList( file1, &ptri, &model.num_tris, NULL, NULL ); - } - - - GetScriptToken( false ); - sprintf( file2, "%s/%s.pcx", cddir, token ); -// sprintf (trans_file, "%s/!%s_a.pcx", cddir, token); - - printf( "skin: %s\n", file2 ); - Load256Image( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight ); - - if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) { - if ( g_allow_newskin ) { - ScaleWidth = BaseWidth; - ScaleHeight = BaseHeight; - } - else - { - Error( "Invalid skin page size: (%d,%d) should be (%d,%d)", - BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT ); - } - } - else - { - ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X, - ENCODED_WIDTH_Y ); - ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X, - ENCODED_HEIGHT_Y ); - } - -// -// get the ST values -// - BuildST( ptri, model.num_tris,false ); - -// -// run through all the base triangles, storing each unique vertex in the -// base vertex list and setting the indirect triangles to point to the base -// vertices -// - for ( i = 0 ; i < model.num_tris ; i++ ) - { - for ( j = 0 ; j < 3 ; j++ ) - { - // get the xyz index - for ( k = 0 ; k < model.num_xyz ; k++ ) - if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) { - break; - } // this vertex is already in the base vertex list - - if ( k == model.num_xyz ) { // new index - VectorCopy( ptri[i].verts[j], base_xyz[model.num_xyz] ); - - if ( clustered ) { - ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts ); - } - - model.num_xyz++; - } - - triangles[i].index_xyz[j] = k; - - // get the st index - for ( k = 0 ; k < model.num_st ; k++ ) - if ( triangle_st[i][j][0] == base_st[k].s - && triangle_st[i][j][1] == base_st[k].t ) { - break; - } // this vertex is already in the base vertex list - - if ( k == model.num_st ) { // new index - base_st[model.num_st].s = triangle_st[i][j][0]; - base_st[model.num_st].t = triangle_st[i][j][1]; - model.num_st++; - } - - triangles[i].index_st[j] = k; - } - } - - // build triangle strips / fans - BuildGlCmds(); -} - -//=============================================================== - -char *FindFrameFile( char *frame ){ - int time1; - char file1[1024]; - static char retname[1024]; - char base[32]; - char suffix[32]; - char *s; - - if ( strstr( frame, "." ) ) { - return frame; // allready in dot format - - } - // split 'run1' into 'run' and '1' - s = frame + strlen( frame ) - 1; - - while ( s != frame && *s >= '0' && *s <= '9' ) - s--; - - strcpy( suffix, s + 1 ); - strcpy( base, frame ); - base[s - frame + 1] = 0; - - sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "hrc" ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s%s.%s", base, suffix, "hrc" ); - return retname; - } - - sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "asc" ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s%s.%s", base, suffix, "asc" ); - return retname; - } - - sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "tri" ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s%s.%s", base, suffix, "tri" ); - return retname; - } - - sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "3ds" ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s%s.%s", base, suffix, "3ds" ); - return retname; - } - - sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "htr" ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s%s.%s", base, suffix, "htr" ); - return retname; - } - - // check for 'run.1' - sprintf( file1, "%s/%s.%s",cddir, base, suffix ); - time1 = FileTime( file1 ); - if ( time1 != -1 ) { - sprintf( retname, "%s.%s", base, suffix ); - return retname; - } - - Error( "frame %s could not be found",frame ); - return NULL; -} - -/* - =============== - GrabFrame - =============== - */ -static void GrabFrame( char *frame ){ - triangle_t *ptri; - int i, j; - trivert_t *ptrivert; - int num_tris; - char file1[1024]; - frame_t *fr; - vertexnormals_t vnorms[MAX_VERTS]; - int index_xyz; - char *framefile; - - // the frame 'run1' will be looked for as either - // run.1 or run1.tri, so the new alias sequence save - // feature an be used - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "grabbing %s ", file1 ); - - if ( model.num_frames >= MAX_FRAMES ) { - Error( "model.num_frames >= MAX_FRAMES" ); - } - fr = &g_frames[model.num_frames]; - model.num_frames++; - - strcpy( fr->name, frame ); - -// -// load the frame -// - if ( do3ds ) { - Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL ); - } - else{ - LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL ); - } - - if ( num_tris != model.num_tris ) { - Error( "%s: number of triangles doesn't match base frame\n", file1 ); - } - -// -// allocate storage for the frame's vertices -// - ptrivert = fr->v; - - for ( i = 0 ; i < model.num_xyz ; i++ ) - { - vnorms[i].numnormals = 0; - VectorClear( vnorms[i].normalsum ); - } - ClearBounds( fr->mins, fr->maxs ); - -// -// store the frame's vertices in the same order as the base. This assumes the -// triangles and vertices in this frame are in exactly the same order as in the -// base -// - for ( i = 0 ; i < num_tris ; i++ ) - { - vec3_t vtemp1, vtemp2, normal; - float ftemp; - - VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 ); - VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 ); - CrossProduct( vtemp1, vtemp2, normal ); - - VectorNormalize( normal, normal ); - - // rotate the normal so the model faces down the positive x axis - ftemp = normal[0]; - normal[0] = -normal[1]; - normal[1] = ftemp; - - for ( j = 0 ; j < 3 ; j++ ) - { - index_xyz = triangles[i].index_xyz[j]; - - // rotate the vertices so the model faces down the positive x axis - // also adjust the vertices to the desired origin - ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) + - adjust[0]; - ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) + - adjust[1]; - ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) + - adjust[2]; - - AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs ); - - VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum ); - vnorms[index_xyz].numnormals++; - } - } - -// -// calculate the vertex normals, match them to the template list, and store the -// index of the best match -// - for ( i = 0 ; i < model.num_xyz ; i++ ) - { - int j; - vec3_t v; - float maxdot; - int maxdotindex; - int c; - - c = vnorms[i].numnormals; - if ( !c ) { - Error( "Vertex with no triangles attached" ); - } - - VectorScale( vnorms[i].normalsum, 1.0 / c, v ); - VectorNormalize( v, v ); - - maxdot = -999999.0; - maxdotindex = -1; - - for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ ) - { - float dot; - - dot = DotProduct( v, avertexnormals[j] ); - if ( dot > maxdot ) { - maxdot = dot; - maxdotindex = j; - } - } - - ptrivert[i].lightnormalindex = maxdotindex; - } - - free( ptri ); -} - -/* - =============== - GrabJointedFrame - =============== - */ -void GrabJointedFrame( char *frame ){ - char file1[1024]; - char *framefile; - frame_t *fr; - - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "grabbing %s\n", file1 ); - - fr = &g_frames[model.num_frames - 1]; // last frame read in - - LoadJointList( file1, fr->joints, jointed ); -} - -/* - =============== - GrabGlobals - =============== - */ -void GrabGlobals( char *frame ){ - char file1[1024]; - char *framefile; - frame_t *fr; - - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "grabbing %s\n", file1 ); - - fr = &g_frames[model.num_frames - 1]; // last frame read in - - LoadGlobals( file1 ); -} - -/* - =============== - Cmd_Frame - =============== - */ -void Cmd_Frame( void ){ - while ( ScriptTokenAvailable() ) - { - GetScriptToken( false ); - if ( g_skipmodel ) { - continue; - } - if ( g_release || g_archive ) { - model.num_frames = 1; // don't skip the writeout - continue; - } - - H_printf( "#define FRAME_%-16s\t%i\n", token, model.num_frames ); - - GrabFrame( token ); - } -} - -/* - =============== - Cmd_Skin - - Skins aren't actually stored in the file, only a reference - is saved out to the header file. - =============== - */ -void Cmd_Skin( void ){ - byte *palette; - byte *pixels; - int width, height; - byte *cropped; - int y; - char name[1024], savename[1024]; - - GetScriptToken( false ); - - if ( model.num_skins == MAX_MD2SKINS ) { - Error( "model.num_skins == MAX_MD2SKINS" ); - } - - if ( g_skipmodel ) { - return; - } - -#if 1 - sprintf( name, "%s/%s.pcx", cddir, token ); - sprintf( savename, "%s/!%s.pcx", g_outputDir, token ); - sprintf( g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token ); -#else - sprintf( name, "%s/%s.lbm", cdarchive, token ); - strcpy( name, ExpandPathAndArchive( name ) ); -// sprintf (name, "%s/%s.lbm", cddir, token); - - if ( ScriptTokenAvailable() ) { - GetScriptToken( false ); - sprintf( g_skins[model.num_skins], "%s.pcx", token ); - sprintf( savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins] ); - } - else - { - sprintf( savename, "%s/%s.pcx", g_outputDir, token ); - sprintf( g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token ); - } -#endif - - model.num_skins++; - - if ( g_skipmodel || g_release || g_archive ) { - return; - } - - // load the image - printf( "loading %s\n", name ); - Load256Image( name, &pixels, &palette, &width, &height ); -// RemapZero (pixels, palette, width, height); - - // crop it to the proper size - cropped = (byte *) SafeMalloc( model.skinwidth * model.skinheight, "Cmd_Skin" ); - for ( y = 0 ; y < model.skinheight ; y++ ) - { - memcpy( cropped + y * model.skinwidth, - pixels + y * width, model.skinwidth ); - } - - // save off the new image - printf( "saving %s\n", savename ); - CreatePath( savename ); - WritePCXfile( savename, cropped, model.skinwidth, - model.skinheight, palette ); - - free( pixels ); - free( palette ); - free( cropped ); -} - - -/* - ================= - Cmd_Origin - ================= - */ -void Cmd_Origin( void ){ - // rotate points into frame of reference so model points down the - // positive x axis - GetScriptToken( false ); - adjust[1] = -atof( token ); - - GetScriptToken( false ); - adjust[0] = atof( token ); - - GetScriptToken( false ); - adjust[2] = -atof( token ); -} - - -/* - ================= - Cmd_ScaleUp - ================= - */ -void Cmd_ScaleUp( void ){ - GetScriptToken( false ); - scale_up = atof( token ); - if ( g_skipmodel || g_release || g_archive ) { - return; - } - - printf( "Scale up: %f\n", scale_up ); -} - - -/* - ================= - Cmd_Skinsize - - Set a skin size other than the default - ================= - */ -void Cmd_Skinsize( void ){ - GetScriptToken( false ); - g_fixedwidth = atoi( token ); - GetScriptToken( false ); - g_fixedheight = atoi( token ); -} - -/* - ================= - Cmd_Modelname - - Gives a different name/location for the file, instead of the cddir - ================= - */ -void Cmd_Modelname( void ){ - GetScriptToken( false ); - strcpy( modelname, token ); -} - -/* - =============== - Cmd_Cd - =============== - */ -void Cmd_Cd( void ){ - char temp[256]; - - FinishModel(); - ClearModel(); - - GetScriptToken( false ); - - // this is a silly mess... - sprintf( cdpartial, "models/%s", token ); - sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token ); - sprintf( cddir, "%s%s", gamedir, cdpartial ); - - // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too. - sprintf( temp, "%s%s", g_outputDir, cdpartial ); - strcpy( g_outputDir, temp ); - - // if -only was specified and this cd doesn't match, - // skip the model (you only need to match leading chars, - // so you could regrab all monsters with -only monsters) - if ( !g_only[0] ) { - return; - } - if ( strncmp( token, g_only, strlen( g_only ) ) ) { - g_skipmodel = true; - printf( "skipping %s\n", cdpartial ); - } -} - -/* - ================= - Cmd_Cluster - ================= - */ -void Cmd_Cluster(){ - char file1[1024]; - - GetScriptToken( false ); - - printf( "---------------------\n" ); - sprintf( file1, "%s/%s", cdpartial, token ); - printf( "%s\n", file1 ); - - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s", cddir, token ); - - LoadClusters( file1, (int **)&clusters, (int *)&num_verts, jointed ); - - new_num_verts[0] = num_verts[0]; - - clustered = 1; -} - -// Model construction cover functions. -void MODELCMD_Modelname( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - Cmd_Modelname(); -/* - switch(modeltype) - { - case MODEL_MD2: - Cmd_Modelname (); - break; - case MODEL_FM: - Cmd_FMModelname (); - break; - } - */ -} - -void MODELCMD_Cd( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Cd(); - break; - case MODEL_FM: - Cmd_FMCd(); - break; - } -} - -void MODELCMD_Origin( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - Cmd_Origin(); -/* switch(modeltype) - { - case MODEL_MD2: - Cmd_Origin (); - break; - case MODEL_FM: - Cmd_FMOrigin (); - break; - } - */ -} - -void MODELCMD_Cluster( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Cluster(); - break; - case MODEL_FM: - Cmd_FMCluster(); - break; - } -} - -void MODELCMD_Base( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Base(); - break; - case MODEL_FM: - Cmd_FMBase( false ); - break; - } -} - -void MODELCMD_BaseST( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Base(); - break; - case MODEL_FM: - Cmd_FMBase( true ); - break; - } -} - -void MODELCMD_ScaleUp( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - Cmd_ScaleUp(); -/* switch(modeltype) - { - case MODEL_MD2: - Cmd_ScaleUp (); - break; - case MODEL_FM: - Cmd_FMScaleUp (); - break; - } - */ -} - -void MODELCMD_Frame( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Frame(); - break; - case MODEL_FM: - Cmd_FMFrame(); - break; - } -} - -void MODELCMD_Skin( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - Cmd_Skin(); - break; - case MODEL_FM: - Cmd_FMSkin(); - break; - } -} - -void MODELCMD_Skinsize( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - Cmd_Skinsize(); -/* - switch(modeltype) - { - case MODEL_MD2: - Cmd_Skinsize (); - break; - case MODEL_FM: - Cmd_FMSkinsize (); - break; - } - */ -} - -void MODELCMD_Skeleton( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - break; - case MODEL_FM: - Cmd_FMSkeleton(); - break; - } -} - -void MODELCMD_BeginGroup( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - break; - case MODEL_FM: - Cmd_FMBeginGroup(); - break; - } -} - -void MODELCMD_EndGroup( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - break; - case MODEL_FM: - Cmd_FMEndGroup(); - break; - } -} - -void MODELCMD_Referenced( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - break; - case MODEL_FM: - Cmd_FMReferenced(); - break; - } -} - -void MODELCMD_NodeOrder( int modeltype ){ - if ( g_forcemodel ) { - modeltype = g_forcemodel; - } - - switch ( modeltype ) - { - case MODEL_MD2: - break; - case MODEL_FM: - Cmd_FMNodeOrder(); - break; - } -} diff --git a/tools/quake2/qdata_heretic2/pics.c b/tools/quake2/qdata_heretic2/pics.c deleted file mode 100644 index e9e91c27..00000000 --- a/tools/quake2/qdata_heretic2/pics.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright (C) 1999-2007 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 ); -} diff --git a/tools/quake2/qdata_heretic2/qcommon/angles.h b/tools/quake2/qdata_heretic2/qcommon/angles.h deleted file mode 100644 index b0baf314..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/angles.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// Angles in radians - -#define ANGLE_0 0.0F -#define ANGLE_1 0.017453292F -#define ANGLE_5 0.087266462F -#define ANGLE_10 0.174532925F -#define ANGLE_15 0.261799387F -#define ANGLE_20 0.392699081F -#define ANGLE_30 0.523598775F -#define ANGLE_45 0.785398163F -#define ANGLE_60 1.047197551F -#define ANGLE_72 1.256637061F -#define ANGLE_90 1.570796327F -#define ANGLE_120 2.094395102F -#define ANGLE_135 2.35619449F -#define ANGLE_144 2.513274123F -#define ANGLE_180 3.141592653F -#define ANGLE_225 3.926990817F -#define ANGLE_270 4.71238898F -#define ANGLE_315 5.497787144F -#define ANGLE_360 6.283185307F - -// Angles in degrees - -#define DEGREE_0 0.0F -#define DEGREE_180 180.0F -#define DEGREE_45 ( DEGREE_180 / 4.0F ) -#define DEGREE_90 ( DEGREE_180 / 2.0F ) -#define DEGREE_135 ( DEGREE_90 + DEGREE_45 ) -#define DEGREE_270 ( DEGREE_180 + DEGREE_90 ) -#define DEGREE_360 ( DEGREE_180 * 2.0F ) - -#define DEGREE_225 ( DEGREE_180 + DEGREE_45 ) -#define DEGREE_315 ( DEGREE_270 + DEGREE_45 ) - -#define DEGREE_30 ( DEGREE_180 / 6.0F ) -#define DEGREE_60 ( DEGREE_180 / 3.0F ) -#define DEGREE_120 ( DEGREE_360 / 3.0F ) - -#define DEGREE_1 ( DEGREE_180 / 180.0F ) -#define DEGREE_5 ( DEGREE_180 / 36.0F ) -#define DEGREE_10 ( DEGREE_180 / 18.0F ) -#define DEGREE_15 ( DEGREE_180 / 12.0F ) -#define DEGREE_20 ( DEGREE_180 / 8.0F ) - -// Conversion routines - -#define ANGLE_TO_RAD ANGLE_1 -#define RAD_TO_ANGLE ( 180.0F / ANGLE_180 ) - -#define SHORT_TO_ANGLE ( 360.0 / 65536 ) - -#if GDEF_COMPILER_MSVC -#pragma warning(disable : 4305) // 'initializing' : truncation from 'const double ' to 'float ' -#endif diff --git a/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h b/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h deleted file mode 100644 index 46663dd5..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 1999-2007 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 _ARRAYEDLIST_H -#define _ARRAYEDLIST_H - -#include -#include - -typedef struct ArrayedListNode_s -{ - int data; - int next; - int inUse; -} ArrayedListNode_t; - -#define ARRAYEDLISTNODE_NULL -1 - -static GDEF_ATTRIBUTE_INLINE int GetFreeNode( ArrayedListNode_t *nodeArray, int max ){ - int i; - - for ( i = 0; i < max; ++i ) - { - if ( !nodeArray[i].inUse ) { - nodeArray[i].inUse = 1; - return i; - } - } - - assert( 0 ); - return -1; -} - -static GDEF_ATTRIBUTE_INLINE void FreeNode( ArrayedListNode_t *nodeArray, int index ){ - nodeArray[index].inUse = 0; -} - -#endif //_ARRAYEDLIST_H diff --git a/tools/quake2/qdata_heretic2/qcommon/flex.h b/tools/quake2/qdata_heretic2/qcommon/flex.h deleted file mode 100644 index 98184e87..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/flex.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// Generic flexible format - -typedef struct -{ - char ident[32]; - int version; - int size; -} header_t; - -void WriteHeader( FILE *, char *, int, int, void * ); - -// end diff --git a/tools/quake2/qdata_heretic2/qcommon/fmodel.h b/tools/quake2/qdata_heretic2/qcommon/fmodel.h deleted file mode 100644 index e2ebfa8d..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/fmodel.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - - -/* - ======================================================================== - - .FM triangle flexible model file format - - ======================================================================== - */ - -#ifndef __FMODEL_HEADER -#define __FMODEL_HEADER - -#include "bspfile.h" - -//typedef unsigned char byte; -//typedef int qboolean; -//typedef float vec3_t[3]; - -#define MAX_FM_TRIANGLES 2048 -#define MAX_FM_VERTS 2048 -#define MAX_FM_FRAMES 2048 -#define MAX_FM_SKINS 64 -#define MAX_FM_SKINNAME 64 -#define MAX_FM_MESH_NODES 16 // also defined in game/qshared.h - - -#define DTRIVERTX_V0 0 -#define DTRIVERTX_V1 1 -#define DTRIVERTX_V2 2 -#define DTRIVERTX_LNI 3 -#define DTRIVERTX_SIZE 4 - -#define SKINPAGE_WIDTH 640 -#define SKINPAGE_HEIGHT 480 - -#define ENCODED_WIDTH_X 92 -#define ENCODED_WIDTH_Y 475 -#define ENCODED_HEIGHT_X 128 -#define ENCODED_HEIGHT_Y 475 - -#define SCALE_ADJUST_FACTOR 0.96 - -#define INFO_HEIGHT 5 -#define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT ) - -extern byte *BasePalette; -extern byte *BasePixels,*TransPixels; -extern int BaseWidth, BaseHeight, TransWidth, TransHeight; -extern int ScaleWidth, ScaleHeight; - -int ExtractNumber( byte *pic, int x, int y ); -void DrawTextChar( int x, int y, char *text ); -void DrawLine( int x1, int y1, int x2, int y2 ); - -// 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. - - -// Initial Header -#define FM_HEADER_NAME "header" -#define FM_HEADER_VER 2 - -typedef struct -{ - 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 num_mesh_nodes; -} fmheader_t; - - -// Skin Header -#define FM_SKIN_NAME "skin" -#define FM_SKIN_VER 1 - - -// ST Coord Header -#define FM_ST_NAME "st coord" -#define FM_ST_VER 1 - -typedef struct -{ - short s; - short t; -} fmstvert_t; - - -// Tri Header -#define FM_TRI_NAME "tris" -#define FM_TRI_VER 1 - -typedef struct -{ - short index_xyz[3]; - short index_st[3]; -} fmtriangle_t; - - -// Frame Header -#define FM_FRAME_NAME "frames" -#define FM_FRAME_VER 1 - -// Frame for compression, just the names -#define FM_SHORT_FRAME_NAME "short frames" -#define FM_SHORT_FRAME_VER 1 - -// Normals for compressed frames -#define FM_NORMAL_NAME "normals" -#define FM_NORMAL_VER 1 - -// Compressed Frame Data -#define FM_COMP_NAME "comp data" -#define FM_COMP_VER 1 - -// GL Cmds Header -#define FM_GLCMDS_NAME "glcmds" -#define FM_GLCMDS_VER 1 - - -// Mesh Nodes Header -#define FM_MESH_NAME "mesh nodes" -#define FM_MESH_VER 3 - -// Skeleton Header -#define FM_SKELETON_NAME "skeleton" -#define FM_SKELETON_VER 1 - -// References Header -#define FM_REFERENCES_NAME "references" -#define FM_REFERENCES_VER 1 - -typedef struct -{ - - union - { - - byte tris[MAX_FM_TRIANGLES >> 3]; - - struct { - short *triIndicies; - int num_tris; - }; - - }; - - byte verts[MAX_FM_VERTS >> 3]; - short start_glcmds, num_glcmds; -} fmmeshnode_t; - -//================================================================= - -// Frame info -typedef struct -{ - byte v[3]; // scaled byte to fit in frame mins/maxs - byte lightnormalindex; -} fmtrivertx_t; - -typedef struct -{ - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this - char name[16]; // frame name from grabbing - fmtrivertx_t verts[1]; // variable sized -} fmaliasframe_t; - - -#endif // #define __FMODEL_HEADER diff --git a/tools/quake2/qdata_heretic2/qcommon/h2common.h b/tools/quake2/qdata_heretic2/qcommon/h2common.h deleted file mode 100644 index e1f25591..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/h2common.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 1999-2007 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 H2COMMON_H -#define H2COMMON_H - #define H2COMMON_API -#endif diff --git a/tools/quake2/qdata_heretic2/qcommon/placement.h b/tools/quake2/qdata_heretic2/qcommon/placement.h deleted file mode 100644 index 9151183f..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/placement.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 1999-2007 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 PLACEMENT_H -#define PLACEMENT_H - -#include "q_typedef.h" - -//typedef float vec3_t[3]; - -typedef struct Placement_s -{ - vec3_t origin; - vec3_t direction; - vec3_t up; -} Placement_t; - -#endif diff --git a/tools/quake2/qdata_heretic2/qcommon/q_typedef.h b/tools/quake2/qdata_heretic2/qcommon/q_typedef.h deleted file mode 100644 index cbe69dd1..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/q_typedef.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 1999-2007 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 Q_TYPEDEF_H -#define Q_TYPEDEF_H - -typedef float vec_t; -typedef vec_t vec2_t[2]; -typedef vec_t vec3_t[3]; -typedef double vec3d_t[3]; -typedef vec_t vec5_t[5]; - -typedef float matrix3_t[3][3]; -typedef float matrix3d_t[3][3]; - -typedef int fixed4_t; -typedef int fixed8_t; -typedef int fixed16_t; - -typedef unsigned char byte; - -#ifndef __cplusplus -typedef enum {false, true} qboolean; -#else -typedef int qboolean; -#endif - -typedef struct edict_s edict_t; - -typedef struct paletteRGBA_s -{ - union - { - struct - { - byte r,g,b,a; - }; - unsigned c; - byte c_array[4]; - }; -} paletteRGBA_t; - -#endif diff --git a/tools/quake2/qdata_heretic2/qcommon/qfiles.h b/tools/quake2/qdata_heretic2/qcommon/qfiles.h deleted file mode 100644 index 4d0648c1..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/qfiles.h +++ /dev/null @@ -1,603 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - - ======================================================================== - */ - -#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 6144 - - -/* - ======================================================================== - - 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 IDCOMPRESSEDALIASHEADER ( ( '2' << 24 ) + ( 'C' << 16 ) + ( 'D' << 8 ) + 'I' ) - -/* - ======================================================================== - - .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 4096 -#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 -{ - union - { - struct - { - byte v[3]; // scaled byte to fit in frame mins/maxs - byte lightnormalindex; - }; - - int vert; - }; -} 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; - -// compressed model -typedef struct dcompmdl_s -{ - dmdl_t header; - short CompressedFrameSize; - short UniqueVerts; - short *remap; - float *translate; // then add this - float *scale; // multiply byte verts by this - char *mat; - char *frames; - char *base; - float *ctranslate; - float *cscale; - char data[1]; -} dcompmdl_t; - -typedef struct -{ - dcompmdl_t compModInfo; - int rootCluster; - int skeletalType; - struct ModelSkeleton_s *skeletons; -} JointedModel_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 - -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 unused[20]; // 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 // Quake 2 original -#define MAX_MAP_BRUSHES 10240 -#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! - -// ************************************************************************************************ -// CONTENTS_XXX -// ------------ -// Contents flags. -// ************************************************************************************************ - -// 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_AUX 0x00000004 -#define CONTENTS_LAVA 0x00000008 -#define CONTENTS_SLIME 0x00000010 -#define CONTENTS_WATER 0x00000020 -#define CONTENTS_MIST 0x00000040 -#define LAST_VISIBLE_CONTENTS CONTENTS_MIST - -// 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 leaves. -#define CONTENTS_TRANSLUCENT 0x10000000 // Auto set if any surface has transparency. -#define CONTENTS_LADDER 0x20000000 -#define CONTENTS_CAMERANOBLOCK 0x40000000 // Camera LOS ignores any brushes with this flag. - -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; diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.c b/tools/quake2/qdata_heretic2/qcommon/reference.c deleted file mode 100644 index 7be9740d..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/reference.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include "reference.h" -#include "arrayedlist.h" -#include "resourcemanager.h" -#include "skeletons.h" - -char *referenceRootNames[] = -{ - "elf_Lhandroot", //0 - "elf_Rhandroot", - "elf_Rfootroot", - "elf_Lfootroot", - "elf_Bstaffroot", - "elf_bladeroot", - "elf_hellroot", - "StaffBone", //7 - "SwordBone", - "SpearBone", - "RFootBone", - "LFootBone", - "hp_backroot", //12 - "hp_staffroot", - "hp_lhandroot", - "hp_rhandroot", - "hp_rfootroot", - "hp_lfootroot", - "staffroot", //18 - "rfootroot", - "lfootroot", - "rhandroot", - "lhandroot", - "leyeroot", - "reyeroot" -}; - -int referenceRootNameOffsets[NUM_REFERENCED] = -{ - 0, // CORVUS - 7, // INSECT - 12, // HIGH PRIESTESS - 18, // MORCALAVIN -}; - -int numReferences[NUM_REFERENCED] = -{ - NUM_REFERENCES_CORVUS, - NUM_REFERENCES_INSECT, - NUM_REFERENCES_PRIESTESS, - NUM_REFERENCES_MORK, -}; - -int corvusJointIDs[NUM_REFERENCES_CORVUS] = -{ - CORVUS_UPPERBACK, - CORVUS_UPPERBACK, - -1, - -1, - CORVUS_UPPERBACK, - CORVUS_UPPERBACK, - CORVUS_UPPERBACK, -}; - -int *jointIDs[NUM_REFERENCED] = -{ - corvusJointIDs, -}; - -static ResourceManager_t ReferenceMngr; - -void InitReferenceMngr(){ -#define REFERENCE_BLOCK_SIZE 8 - char *dummystr = NULL; - - ResMngr_Con( &ReferenceMngr, sizeof( LERPedReferences_t ), REFERENCE_BLOCK_SIZE, dummystr ); -} - -void ReleaseReferenceMngr(){ - ResMngr_Des( &ReferenceMngr ); -} - -LERPedReferences_t *LERPedReferences_new( int init_refType ){ - LERPedReferences_t *newRefs; - - newRefs = ResMngr_AllocateResource( &ReferenceMngr, sizeof( *newRefs ) ); - newRefs->refType = init_refType; - newRefs->jointIDs = jointIDs[init_refType]; - newRefs->lastUpdate = -( REF_MINCULLTIME * 2.0 ); - - memset( newRefs->references, 0, MAX_REFPOINTS * sizeof( Reference_t ) ); - memset( newRefs->oldReferences, 0, MAX_REFPOINTS * sizeof( Reference_t ) ); - - return newRefs; -} - -void LERPedReferences_delete( LERPedReferences_t *toDelete ){ - ResMngr_DeallocateResource( &ReferenceMngr, toDelete, sizeof( *toDelete ) ); -} - -// end diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.h b/tools/quake2/qdata_heretic2/qcommon/reference.h deleted file mode 100644 index 747c4d43..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/reference.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 1999-2007 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 REFERENCE_H -#define REFERENCE_H - -#include "placement.h" - -#define MAX_REFPOINTS 16 -#define REF_MINCULLTIME 1.0 - -typedef struct Reference_s -{ - int activecount; - Placement_t placement; -} Reference_t; - -typedef struct LERPedReferences_s -{ - int refType; - int *jointIDs; - float lastUpdate; - Reference_t references[MAX_REFPOINTS]; - Reference_t oldReferences[MAX_REFPOINTS]; -} LERPedReferences_t; - -// Reference Types -enum { - REF_NULL = -1, - REF_CORVUS, //0 - REF_INSECT, //1 - REF_PRIESTESS, //2 - REF_MORK, //3 - NUM_REFERENCED //4 -}; - -// Corvus Reference Points -enum { - CORVUS_LEFTHAND, //0 - CORVUS_RIGHTHAND, - CORVUS_LEFTFOOT, - CORVUS_RIGHTFOOT, - CORVUS_STAFF, - CORVUS_BLADE, - CORVUS_HELL_HEAD, - NUM_REFERENCES_CORVUS //7 -}; - -// Tchekrik Reference Points -enum { - INSECT_STAFF, //0 - INSECT_SWORD, - INSECT_SPEAR, - INSECT_RIGHTFOOT, - INSECT_LEFTFOOT, - NUM_REFERENCES_INSECT //5 -}; - -// High Priestess Reference Points -enum { - PRIESTESS_BACK, //0 - PRIESTESS_STAFF, - PRIESTESS_LHAND, - PRIESTESS_RHAND, - PRIESTESS_RFOOT, - PRIESTESS_LFOOT, - NUM_REFERENCES_PRIESTESS //6 -}; - -// Morcalavin Reference Points -enum -{ - MORK_STAFFREF, //0 - MORK_RFOOTREF, //1 - MORK_LFOOTREF, //2 - MORK_RHANDREF, //3 - MORK_LHANDREF, //4 - MORK_LEYEREF, //5 - MORK_REYEREF, //6 - NUM_REFERENCES_MORK //7 -}; - -#define CORVUS_LIMBS_MASK ( ( 1 << CORVUS_LEFTHAND ) | ( 1 << CORVUS_RIGHTHAND ) | ( 1 << CORVUS_LEFTFOOT ) | ( 1 << CORVUS_RIGHTFOOT ) ) -#define CORVUS_WEAPON_MASK ( ( 1 << CORVUS_STAFF ) | ( 1 << CORVUS_BLADE ) | ( 1 << CORVUS_HELL_HEAD ) ) -#define CORVUS_MASK ( CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK ) - -#define INSECT_MASK ( ( 1 << INSECT_STAFF ) | ( 1 << INSECT_SWORD ) | ( 1 << INSECT_SPEAR ) | ( 1 << INSECT_RIGHTFOOT ) | ( 1 << INSECT_LEFTFOOT ) ) - -#define PRIESTESS_MASK ( ( 1 << PRIESTESS_BACK ) | ( 1 << PRIESTESS_STAFF ) | ( 1 << PRIESTESS_LHAND ) | ( 1 << PRIESTESS_RHAND ) | ( 1 << PRIESTESS_RFOOT ) | ( 1 << PRIESTESS_LFOOT ) ) - -#define MORK_MASK ( ( 1 << MORK_STAFFREF ) | ( 1 << MORK_RFOOTREF ) | ( 1 << MORK_LFOOTREF ) | ( 1 << MORK_RHANDREF ) | ( 1 << MORK_LHANDREF ) | ( 1 << MORK_LEYEREF ) | ( 1 << MORK_REYEREF ) ) - -extern char *referenceRootNames[]; -extern int referenceRootNameOffsets[]; -extern int numReferences[]; - -void EnableRefPoints( LERPedReferences_t *refInfo, int mask ); -void DisableRefPoints( LERPedReferences_t *refInfo, int mask ); - -void InitReferenceMngr(); -void ReleaseReferenceMngr(); - -LERPedReferences_t *LERPedReferences_new( int init_refType ); -void LERPedReferences_delete( LERPedReferences_t *toDelete ); - -#endif diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c deleted file mode 100644 index 2eb01409..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - - -// -// ResourceManager.c -// - -#include -#include "resourcemanager.h" -#include - -typedef struct ResMngr_Block_s -{ - char *start; - unsigned int size; - struct ResMngr_Block_s *next; -} ResMngr_Block_t; - -static void ResMngr_CreateBlock( ResourceManager_t *resource ){ - unsigned int _blockSize; - char *block; - char **current; - ResMngr_Block_t *temp; - unsigned int i; - - _blockSize = resource->nodeSize * resource->resPerBlock; - - block = malloc( _blockSize ); - - assert( block ); - - temp = malloc( sizeof( *temp ) ); - - temp->start = block; - temp->size = _blockSize; - temp->next = resource->blockList; - - resource->blockList = temp; - - resource->free = (char **)( block ); - - current = resource->free; - - for ( i = 1; i < resource->resPerBlock; ++i ) - { - // set current->next to point to next node - *current = (char *)( current ) + resource->nodeSize; - - // set current node to current->next - current = (char **)( *current ); - } - - *current = NULL; -} - -H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ){ - resource->resSize = init_resSize; - - resource->resPerBlock = init_resPerBlock; - - resource->nodeSize = resource->resSize + sizeof( *resource->free ); - - resource->blockList = NULL; - - resource->numResourcesAllocated = 0; - - ResMngr_CreateBlock( resource ); -} - -H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ){ - ResMngr_Block_t *toDelete; - -#if 0 - if ( resource->numResourcesAllocated ) { - char mess[100]; - sprintf( mess,"Potential memory leak %d bytes unfreed\n",resource->resSize * resource->numResourcesAllocated ); - OutputDebugString( mess ); - } -#endif - - while ( resource->blockList ) - { - toDelete = resource->blockList; - resource->blockList = resource->blockList->next; - free( toDelete->start ); - free( toDelete ); - } -} - -H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ){ - char **toPop; - - assert( size == resource->resSize ); - - ++resource->numResourcesAllocated; - - assert( resource->free ); // constructor not called; possibly due to a static object - // containing a static ResourceManagerFastLarge member being - // constructed before its own static members - - toPop = resource->free; - - // set unallocated to the next node and check for NULL (end of list) - if ( !( resource->free = (char **)( *resource->free ) ) ) { // if at end create new block - ResMngr_CreateBlock( resource ); - } - - // set next to NULL - *toPop = NULL; - - // return the resource for the node - return (void *)( toPop + 1 ); -} - -H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ){ - char **toPush; - - assert( size == resource->resSize ); - - --resource->numResourcesAllocated; - - toPush = (char **)( toDeallocate ) - 1; - - assert( resource->free ); // see same assert at top of AllocateResource - - // set toPop->next to current unallocated front - *toPush = (char *)( resource->free ); - - // set unallocated to the node removed from allocated - resource->free = toPush; -} - -// end diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h deleted file mode 100644 index be82d786..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// -// ResourceManager.h -// - -#include "h2common.h" -#include // needed here for size_t - -typedef struct ResourceManager_s -{ - size_t resSize; - unsigned int resPerBlock; - unsigned int nodeSize; - struct ResMngr_Block_s *blockList; - char **free; - char *ResMan_Name; - - unsigned numResourcesAllocated; - -} ResourceManager_t; - -extern H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ); -extern H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ); -extern H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ); -extern H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ); diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.c b/tools/quake2/qdata_heretic2/qcommon/skeletons.c deleted file mode 100644 index 453cb77a..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/skeletons.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// -// Skeletons.c -// - -#include "skeletons.h" - -char *skeletonRootNames[] = -{ - "RAVEN_ROOT", - "BOX_ROOT", - "BEETLE_ROOT", - "ELFLORD_ROOT", - "PLAGUELF_ROOT", - "ELF_BACKROOT", -}; - -int skeletonRNameOffsets[] = -{ - 0, // RAVEN - 1, // BOX - 2, // BEETLE - 3, // ELFLORD - 4, // PLAGUE ELF - 5, // CORVUS -}; - -char *skeletonJointNames[] = -{ - "RAVEN_LOWERBACK", // 0 - "RAVEN_UPPERBACK", - "RAVEN_NECK", - "BOX_CENTER", // 3 - "BEETLE_NECK", // 4 - "BEETLE_HEAD", - "PLAGUELF_BACKB", // 6 - "PLAGUELF_BACKC", - "PLAGUELF_NECK", - "ELF_BACKB", // 9 - "ELF_BACKC", - "ELF_NECKB", -}; - -int skeletonNameOffsets[] = -{ - 0, // RAVEN - 3, // BOX - 4, // BEETLE - -1, // ELFLORD - 6, // PLAGUE ELF - 9, // CORVUS -}; - -char *skeletonEffectorNames[] = -{ - "BEETLE_EYES", // 0 - "CORVUS_EYES", // 1 -}; - -int skeletonENameOffsets[] = -{ - -1, // RAVEN - -1, // BOX - 0, // BEETLE - -1, // ELFLORD - 1, // PLAGUE ELF -}; - -int numJointsInSkeleton[] = -{ - NUM_JOINTS_RAVEN, - NUM_JOINTS_BOX, - NUM_JOINTS_BEETLE, - NUM_JOINTS_ELFLORD, - NUM_JOINTS_PLAGUE_ELF, - NUM_JOINTS_CORVUS, -}; - -int numNodesInSkeleton[] = -{ - 2, // RAVEN - 0, // BOX - 1, // BEETLE - -1, // ELFLORD - 2, // PLAGUE ELF - 2, // CORVUS -}; - -void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root ); -void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root ); -void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); -void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); -void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ); - -CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] = -{ - CreateRavenSkel, - CreateBoxSkel, - CreateBeetleSkel, - CreateElfLordSkel, - CreatePlagueElfSkel, - CreatePlagueElfSkel, // Corvus has the same structure as the Plague Elf -}; - -void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ - char *root; - int *children; - int nodeIndex; - - root = (char *)g_skeletalJoints + rootIndex * jointSize; - - children = (int *)( root + RAVEN_HEAD * jointSize ); - *children = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + RAVEN_UPPERBACK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + RAVEN_LOWERBACK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; -} - -void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ - char *root; - int *children; - - root = (char *)g_skeletalJoints + rootIndex * jointSize; - - children = (int *)( root + RAVEN_HEAD * jointSize ); - *children = ARRAYEDLISTNODE_NULL; -} - -void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ - char *root; - int *children; - int nodeIndex; - - root = (char *)g_skeletalJoints + rootIndex * jointSize; - - children = (int *)( root + BEETLE_HEAD * jointSize ); - *children = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + BEETLE_NECK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; -} - -void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ - char *root; - int *children; - int nodeIndex; - - root = (char *)g_skeletalJoints + rootIndex * jointSize; - - children = (int *)( root + BEETLE_HEAD * jointSize ); - *children = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + BEETLE_NECK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; -} - -void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){ - char *root; - int *children; - int nodeIndex; - - root = (char *)g_skeletalJoints + rootIndex * jointSize; - - children = (int *)( root + PLAGUE_ELF_HEAD * jointSize ); - *children = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + PLAGUE_ELF_UPPERBACK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; - - nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES ); - - children = (int *)( root + PLAGUE_ELF_LOWERBACK * jointSize ); - *children = nodeIndex; - - g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK; - g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL; -} diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.h b/tools/quake2/qdata_heretic2/qcommon/skeletons.h deleted file mode 100644 index 9d7fe961..00000000 --- a/tools/quake2/qdata_heretic2/qcommon/skeletons.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 1999-2007 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 // for size_t -#include "arrayedlist.h" - -#define JN_YAW_CHANGED 0x00000001 -#define JN_PITCH_CHANGED 0x00000002 -#define JN_ROLL_CHANGED 0x00000004 - -// Skeleton types -enum { - SKEL_NULL = -1, - SKEL_RAVEN = 0, - SKEL_BOX, - SKEL_BEETLE, - SKEL_ELFLORD, - SKEL_PLAGUE_ELF, - SKEL_CORVUS, - NUM_SKELETONS -}; - -// Raven Skeletal joints -enum { - RAVEN_LOWERBACK = 0, - RAVEN_UPPERBACK, - RAVEN_HEAD, - NUM_JOINTS_RAVEN -}; - -// Box Skeletal joints -enum { - BOX_CENTER = 0, - NUM_JOINTS_BOX -}; - -// Beetle Skeletal joints -enum { - BEETLE_NECK = 0, - BEETLE_HEAD, - NUM_JOINTS_BEETLE -}; - -// Elflord Skeletal joints -enum { - ELFLORD_, - ELFLORD__, - NUM_JOINTS_ELFLORD -}; - -// Plague Elf Skeletal joints -enum { - PLAGUE_ELF_LOWERBACK, - PLAGUE_ELF_UPPERBACK, - PLAGUE_ELF_HEAD, - NUM_JOINTS_PLAGUE_ELF -}; - -// Corvus Skeletal joints -enum { - CORVUS_LOWERBACK, - CORVUS_UPPERBACK, - CORVUS_HEAD, - NUM_JOINTS_CORVUS -}; - -#define NO_SWAP_FRAME -1 -#define NULL_ROOT_JOINT -1 - -#define MAX_ARRAYED_SKELETAL_JOINTS 255 // has max of 65,535 (if this remains at 255, net code can be changed to reflect) -#define MAX_ARRAYED_JOINT_NODES ( MAX_ARRAYED_SKELETAL_JOINTS - 1 ) - -#define MAX_JOINTS_PER_SKELETON 8 // arbitrary small number -#define MAX_JOINT_NODES_PER_SKELETON ( MAX_JOINTS_PER_SKELETON - 1 ) - -extern char *skeletonRootNames[]; -extern int skeletonRNameOffsets[]; -extern char *skeletonJointNames[]; -extern int skeletonNameOffsets[]; -extern int numJointsInSkeleton[]; -extern char *skeletonEffectorNames[]; -extern int skeletonENameOffsets[]; -extern int numNodesInSkeleton[]; - -typedef void ( *CreateSkeleton_t )( void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex ); - -extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS]; diff --git a/tools/quake2/qdata_heretic2/qd_fmodel.h b/tools/quake2/qdata_heretic2/qd_fmodel.h deleted file mode 100644 index 286fb071..00000000 --- a/tools/quake2/qdata_heretic2/qd_fmodel.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 1999-2007 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 FMODEL_H -#define FMODEL_H -#include "fmodel.h" -#endif -#include "qd_skeletons.h" - -typedef struct -{ - int numnormals; - vec3_t normalsum; -} fmvertexnormals_t; - -typedef struct -{ - vec3_t v; - int lightnormalindex; - fmvertexnormals_t vnorm; -} fmtrivert_t; - -#define FRAME_NAME_LEN ( 16 ) - -typedef struct -{ - vec3_t mins, maxs; - char name[FRAME_NAME_LEN]; - fmtrivert_t v[MAX_FM_VERTS]; - struct QD_SkeletalJoint_s joints[NUM_CLUSTERS]; - struct QD_SkeletalJoint_s references[NUM_REFERENCES]; -} fmframe_t; - -extern fmframe_t g_frames[MAX_FM_FRAMES]; - -extern fmheader_t fmheader; -extern char cdarchive[1024]; // set by $fmcd -extern char cdpartial[1024]; // set by $fmcd -extern char cddir[1024]; // set by $fmcd - -void GrabFrame( char *frame ); -void H_printf( char *fmt, ... ); -char *FindFrameFile( char *frame ); diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.c b/tools/quake2/qdata_heretic2/qd_skeletons.c deleted file mode 100644 index 97e2a1f8..00000000 --- a/tools/quake2/qdata_heretic2/qd_skeletons.c +++ /dev/null @@ -1,1231 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "qd_skeletons.h" -#include "skeletons.h" -#include "qd_fmodel.h" -#include "angles.h" -#include "token.h" -#include "qdata.h" -#include "reference.h" - -#include -#include -#include - - -// We're assuming no more than 16 reference points, with no more than 32 characters in the name -char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN]; -int RefPointNum = 0; - -Skeletalfmheader_t g_skelModel; - -void ClearSkeletalModel(){ - g_skelModel.type = SKEL_NULL; - g_skelModel.clustered = false; - g_skelModel.references = REF_NULL; -} - -//========================================================================== -// -// LoadHRCClustered -// -//========================================================================== - -// Places the null terminated src string into the dest string less any trailing digits or underscores -void StripTrailingDigits( char *src, char *dest ){ -#ifndef NDEBUG - int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files -#endif - int i = 0; - - while ( src[i] != '\0' ) - { - ++i; -#ifndef NDEBUG - assert( i < max ); -#endif - } - - while ( ( src[--i] >= '0' && src[i] <= '9' ) || src[i] == '_' ) - { - - } - - memcpy( dest, src, ++i ); - - dest[i] = '\0'; -} - -static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){ - extern void HandleHRCModel( triangle_t **triList, int *triangleCount, - mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth ); - - extern mesh_node_t *pmnodes; - - triangle_t *triList; -// mesh_node_t *nodesList; - int num_mesh_nodes = 0, triangleCount = 0; - -#if 0 - int i; - int j, numVerts; - char stripped[SKELETAL_NAME_MAX]; - - for ( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i ) - { - num_verts[i] = 0; - } - - 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 ); - - StripTrailingDigits( tk_String, stripped ); - - for ( i = 0; i < numJointsInSkeleton[skelType]; ++i ) - { - if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) { - i = -i + numJointsInSkeleton[skelType] - 1; - - TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER ); - - numVerts = tk_IntNumber; - - if ( !num_verts[i + 1] ) { // first set of verts for cluster - clusterList[i] = SafeMalloc( numVerts * sizeof( int ), "LoadHRCClustered" ); - assert( clusterList[i] ); - } - else // any later sets of verts need to copy current - { - int *temp; - - temp = SafeMalloc( ( num_verts[i + 1] + numVerts ) * sizeof( int ), "LoadHRCClustered" ); - assert( temp ); - - memcpy( temp + numVerts, clusterList[i], num_verts[i + 1] * sizeof( int ) ); - - free( clusterList[i] ); - - clusterList[i] = temp; - } - - // currently this function is only called by LoadModelClusters. - // Apparently the matching free has disappeared, - // should probably be free at the end of FMCmd_Base - - TK_Beyond( TK_LBRACE ); - - for ( j = 0; j < numVerts; ++j ) - { - TK_Require( TK_INTNUMBER ); - clusterList[i][j] = tk_IntNumber; - TK_Fetch(); - } - - num_verts[i + 1] += numVerts; - - break; - } - } - } - - num_verts[0] = numJointsInSkeleton[skelType]; -#endif - -#if 1 // get the index number localized to the root -// for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i) -// { -// g_skelModel.num_verts[i] = 0; -// } - - TK_OpenSource( fileName ); - TK_FetchRequire( TK_HRCH ); - TK_FetchRequire( TK_COLON ); - TK_FetchRequire( TK_SOFTIMAGE ); - - // prime it - TK_Beyond( TK_MODEL ); - - triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" ); - memset( triList,0,MAXTRIANGLES * sizeof( triangle_t ) ); -// nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List"); - pmnodes = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" ); - - memset( pmnodes, 0, MAX_FM_MESH_NODES * sizeof( mesh_node_t ) ); - - // this should eventually use a stripped down version of this - HandleHRCModel( &triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0 ); - -// free(nodesList); - free( triList ); - - num_verts[0] = numJointsInSkeleton[skelType]; -#endif -} - -void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ){ - int i, j, numVerts; - tokenType_t nextToken; - char stripped[SKELETAL_NAME_MAX]; - - meshNode->clustered = true; - - nextToken = TK_Get( TK_CLUSTER_NAME ); - - while ( nextToken == TK_CLUSTER_NAME ) - { - TK_FetchRequire( TK_STRING ); - - StripTrailingDigits( tk_String, stripped ); - - for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i ) - { - if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type] + i] ) == 0 ) { - i = -i + numJointsInSkeleton[g_skelModel.type] - 1; - - TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER ); - - numVerts = tk_IntNumber; - - if ( !baseIndex ) { - meshNode->clusters[i] = (int *) SafeMalloc( numVerts * sizeof( int ), "ReadHRCClusterList" ); - assert( meshNode->clusters[i] ); - } - else - { - int *temp; - - temp = meshNode->clusters[i]; - meshNode->clusters[i] = (int *) SafeMalloc( ( meshNode->num_verts[i + 1] + numVerts ) * sizeof( int ), "ReadHRCClusterList" ); - assert( meshNode->clusters[i] ); - - memcpy( meshNode->clusters[i], temp, meshNode->num_verts[i + 1] * sizeof( int ) ); - free( temp ); - } - - // currently this function is only called by LoadModelClusters. - // Apparently the matching free has disappeared, - // should probably be free at the end of FMCmd_Base - - TK_Beyond( TK_LBRACE ); - - for ( j = 0; j < numVerts; ++j ) - { - TK_Require( TK_INTNUMBER ); - meshNode->clusters[i][baseIndex + j] = tk_IntNumber + baseIndex; - TK_Fetch(); - } - - if ( baseIndex ) { - meshNode->num_verts[i + 1] += numVerts; - } - else - { - meshNode->num_verts[i + 1] = numVerts; - } - - break; - } - } - - TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER ); - nextToken = TK_Fetch(); - } -} - -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_skelModel.scaling[i] = tk_FloatNumber; - TK_Fetch(); - } - - TK_Beyond( TK_ROTATION ); - for ( i = 0; i < 3; i++ ) - { - TK_Require( TK_FLOATNUMBER ); - g_skelModel.rotation[i] = tk_FloatNumber; - TK_Fetch(); - } - - TK_Beyond( TK_TRANSLATION ); - for ( i = 0; i < 3; i++ ) - { - TK_Require( TK_FLOATNUMBER ); - g_skelModel.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 ParseVec3d( vec3d_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 ParseRotation3d( vec3d_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 ParseTranslation3d( vec3d_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, QD_SkeletalJoint_t *jointList, int skelType ){ -#define MAX_STACK 64 - int i, j; - vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK]; - int curCorrespondingJoint[MAX_STACK]; - int currentStack = 0, stackSize; - double cx, sx, cy, sy, cz, sz; - double rx, ry, rz; - double x2, y2, z2; - char stripped[SKELETAL_NAME_MAX]; - Placement_d_t *placement; - - TK_OpenSource( fileName ); - TK_FetchRequire( TK_HRCH ); - TK_FetchRequire( TK_COLON ); - TK_FetchRequire( TK_SOFTIMAGE ); - - TK_Beyond( TK_MODEL ); - - while ( TK_Search( TK_NAME ) != TK_EOF ) - { - TK_Require( TK_STRING ); - - StripTrailingDigits( tk_String, stripped ); - - if ( stricmp( stripped, skeletonRootNames[skeletonRNameOffsets[skelType]] ) == 0 ) { - break; - } - } - - if ( tk_Token == TK_EOF ) { - Error( "Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]] ); - return; - } - - TK_Beyond( TK_SCALING ); - - ParseVec3d( curScale[currentStack] ); - - TK_Beyond( TK_ROTATION ); - - ParseRotation3d( curRotation[currentStack] ); - - TK_Beyond( TK_TRANSLATION ); - - ParseVec3d( curTranslation[currentStack] ); - - // account for global model translation - curTranslation[currentStack][1] += g_skelModel.translation[0]; - curTranslation[currentStack][2] += g_skelModel.translation[1]; - curTranslation[currentStack][0] += g_skelModel.translation[2]; - - curCorrespondingJoint[currentStack] = -1; - - ++currentStack; - - for ( i = 0; i < numJointsInSkeleton[skelType]; ++i ) - { - while ( 1 ) - { - TK_Beyond( TK_MODEL ); - - TK_BeyondRequire( TK_NAME, TK_STRING ); - - StripTrailingDigits( tk_String, stripped ); - - if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) { - break; - } - - TK_Beyond( TK_SCALING ); - - ParseVec3d( curScale[currentStack] ); - - TK_Beyond( TK_ROTATION ); - - ParseRotation3d( curRotation[currentStack] ); - - TK_Beyond( TK_TRANSLATION ); - - ParseVec3d( curTranslation[currentStack] ); - - curCorrespondingJoint[currentStack] = -1; - - ++currentStack; - } - - TK_Beyond( TK_SCALING ); - - ParseVec3d( curScale[currentStack] ); - - TK_Beyond( TK_ROTATION ); - - ParseRotation3d( 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 ); - - ParseVec3d( 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.origin[1] = 0.0; - jointList[i].placement.origin[2] = 0.0; - jointList[i].placement.origin[0] = 0.0; - - jointList[i].placement.direction[1] = 20.0; - 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] = 20.0; - jointList[i].placement.up[0] = 0.0; - - curCorrespondingJoint[currentStack] = i; - - ++currentStack; - } - - stackSize = currentStack; - -#if 0 - // rotate the direction and up vectors to correspond to the rotation - for ( i = 0; i < numJointsInSkeleton[skelType]; ++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 direction to a point in the 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 up to a point in the 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]; - } -#endif - - for ( i = stackSize - 1; i >= 0; --i ) - { - rx = curRotation[i][0] * ANGLE_TO_RAD; - ry = curRotation[i][1] * ANGLE_TO_RAD; - rz = curRotation[i][2] * ANGLE_TO_RAD; - - cx = cos( rx ); - sx = sin( rx ); - - cy = cos( ry ); - sy = sin( ry ); - - cz = cos( rz ); - sz = sin( rz ); - -#if 1 - for ( j = i; j < stackSize; ++j ) - { - if ( curCorrespondingJoint[j] != -1 ) { - placement = &jointList[curCorrespondingJoint[j]].placement; - - // y-axis rotation for origin - x2 = placement->origin[0] * cy + placement->origin[2] * sy; - z2 = -placement->origin[0] * sy + placement->origin[2] * cy; - placement->origin[0] = x2; - placement->origin[2] = z2; - - // y-axis rotation for direction - x2 = placement->direction[0] * cy + placement->direction[2] * sy; - z2 = -placement->direction[0] * sy + placement->direction[2] * cy; - placement->direction[0] = x2; - placement->direction[2] = z2; - - // y-axis rotation for up - x2 = placement->up[0] * cy + placement->up[2] * sy; - z2 = -placement->up[0] * sy + placement->up[2] * cy; - placement->up[0] = x2; - placement->up[2] = z2; - - // z-axis rotation for origin - x2 = placement->origin[0] * cz - placement->origin[1] * sz; - y2 = placement->origin[0] * sz + placement->origin[1] * cz; - placement->origin[0] = x2; - placement->origin[1] = y2; - - // z-axis rotation for direction - x2 = placement->direction[0] * cz - placement->direction[1] * sz; - y2 = placement->direction[0] * sz + placement->direction[1] * cz; - placement->direction[0] = x2; - placement->direction[1] = y2; - - // z-axis rotation for up - x2 = placement->up[0] * cz - placement->up[1] * sz; - y2 = placement->up[0] * sz + placement->up[1] * cz; - placement->up[0] = x2; - placement->up[1] = y2; - - // x-axis rotation for origin - y2 = placement->origin[1] * cx - placement->origin[2] * sx; - z2 = placement->origin[1] * sx + placement->origin[2] * cx; - placement->origin[1] = y2; - placement->origin[2] = z2; - - // x-axis rotation for direction vector - y2 = placement->direction[1] * cx - placement->direction[2] * sx; - z2 = placement->direction[1] * sx + placement->direction[2] * cx; - placement->direction[1] = y2; - placement->direction[2] = z2; - - // x-axis rotation for up vector - y2 = placement->up[1] * cx - placement->up[2] * sx; - z2 = placement->up[1] * sx + placement->up[2] * cx; - placement->up[1] = y2; - placement->up[2] = z2; - - // translate origin - placement->origin[0] += curTranslation[i][0]; - placement->origin[1] += curTranslation[i][1]; - placement->origin[2] += curTranslation[i][2]; - - // translate back to local coord - placement->direction[0] += curTranslation[i][0]; - placement->direction[1] += curTranslation[i][1]; - placement->direction[2] += curTranslation[i][2]; - - // translate back to local coord - placement->up[0] += curTranslation[i][0]; - placement->up[1] += curTranslation[i][1]; - placement->up[2] += curTranslation[i][2]; - } - } -#else - // This screwed up and needs to be sorted out!!! - // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton - 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]; - } - } -#endif - } -} - -void LoadModelTransform( 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 LoadModelClusters( 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 LoadSkeleton( char *fileName, QD_SkeletalJoint_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 ); - } -} - -/* - =============== - GrabSkeletalFrame - =============== - */ -void GrabSkeletalFrame( char *frame ){ - char file1[1024]; - char *framefile; - fmframe_t *fr; - - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "Grabbing Skeletal Frame %s\n", file1 ); - - fr = &g_frames[fmheader.num_frames - 1]; // last frame read in - - LoadSkeleton( file1, fr->joints, g_skelModel.type ); -} - -/* - =============== - GrabModelTransform - =============== - */ -void GrabModelTransform( char *frame ){ - char file1[1024]; - char *framefile; - fmframe_t *fr; - - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - -// printf ("grabbing %s\n", file1); - - fr = &g_frames[fmheader.num_frames - 1]; // last frame read in - - LoadModelTransform( file1 ); -} - -void Cmd_FMCluster(){ - char file1[1024]; - - GetScriptToken( false ); - - printf( "---------------------\n" ); - sprintf( file1, "%s/%s", cdpartial, token ); - printf( "%s\n", file1 ); - - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s", cddir, token ); - - g_skelModel.clustered = -1; - - LoadModelClusters( file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type ); - - g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0]; - - g_skelModel.clustered = true; -} - -void Cmd_FMSkeleton(){ - GetScriptToken( false ); - g_skelModel.type = atoi( token ); -} - -void Cmd_FMSkeletalFrame(){ - while ( ScriptTokenAvailable() ) - { - GetScriptToken( false ); - if ( g_skipmodel ) { - GetScriptToken( false ); - continue; - } - if ( g_release || g_archive ) { - fmheader.num_frames = 1; // don't skip the writeout - GetScriptToken( false ); - continue; - } - - H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames ); - - GrabModelTransform( token ); - GrabFrame( token ); - GrabSkeletalFrame( token ); - - // need to add the up and dir points to the frame bounds here - // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs); - // then remove fudge in determining scale on frame write out - } -} - -static void LoadHRCReferences( char *fileName, fmframe_t *fr ){ -#define MAX_STACK 64 - int i, j, k; - vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK]; - int curCorrespondingJoint[MAX_STACK]; - int currentStack, stackSize; - double cx, sx, cy, sy, cz, sz; - double rx, ry, rz; - double x2, y2, z2; - char stripped[SKELETAL_NAME_MAX]; - Placement_d_t *placement; - int refnum; - - TK_OpenSource( fileName ); - TK_FetchRequire( TK_HRCH ); - TK_FetchRequire( TK_COLON ); - TK_FetchRequire( TK_SOFTIMAGE ); - - if ( RefPointNum <= 0 ) { // There were no labels indicated in the QDT, so use the hard-coded stuff. - refnum = numReferences[g_skelModel.references]; - } - else - { - refnum = RefPointNum; - } - - for ( k = 0; k < refnum; ++k ) - { - currentStack = 0; - - // Load the root to get translation and initial rotation -// TK_Beyond(TK_MODEL); - - while ( TK_Search( TK_NAME ) != TK_EOF ) - { - TK_Require( TK_STRING ); - - StripTrailingDigits( tk_String, stripped ); - - if ( RefPointNum == 0 ) { // Hard coded refpoint labels - if ( stricmp( stripped, - referenceRootNames[referenceRootNameOffsets[g_skelModel.references] + k] ) == 0 ) { - break; - } - } - else - { // labels indicated by the QDT - if ( stricmp( stripped, RefPointNameList[k] ) == 0 ) { - break; - } - } - } - - if ( tk_Token == TK_EOF ) { - if ( RefPointNum == 0 ) { // Hard coded refpoint labels - Error( "Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]] ); - } - else - { // labels indicated by the QDT - Error( "Bone Chain Root: %s not found\n", RefPointNameList[k] ); - } - return; - } - -// TK_Beyond(TK_SCALING); - -// ParseVec3d(curScale[currentStack]); - - TK_Beyond( TK_ROTATION ); - - ParseRotation3d( curRotation[currentStack] ); - - TK_Beyond( TK_TRANSLATION ); - - ParseVec3d( curTranslation[currentStack] ); - - // account for global model translation - curTranslation[currentStack][1] += g_skelModel.translation[0]; - curTranslation[currentStack][2] += g_skelModel.translation[1]; - curTranslation[currentStack][0] += g_skelModel.translation[2]; - - curCorrespondingJoint[currentStack] = -1; - -// rjr - this one not needed, as there is also a stack increment 20 lines below??? -// ++currentStack; - - // Load the joint to get orientation - TK_Beyond( TK_MODEL ); - -// TK_Beyond(TK_SCALING); - -// ParseVec3d(curScale[currentStack]); - - TK_Beyond( TK_ROTATION ); - - ParseRotation3d( curRotation[currentStack] ); - -// TK_Beyond(TK_TRANSLATION); - -// ParseVec3d(curTranslation[currentStack]); - - fr->references[k].placement.origin[1] = 0.0; - fr->references[k].placement.origin[2] = 0.0; - fr->references[k].placement.origin[0] = 0.0; - - fr->references[k].placement.direction[1] = 20.0; - fr->references[k].placement.direction[2] = 0.0; - fr->references[k].placement.direction[0] = 0.0; - - fr->references[k].placement.up[1] = 0.0; - fr->references[k].placement.up[2] = 20.0; - fr->references[k].placement.up[0] = 0.0; - - curCorrespondingJoint[currentStack] = k; - - ++currentStack; - - stackSize = currentStack; - - for ( i = stackSize - 1; i >= 0; --i ) - { - rx = curRotation[i][0] * ANGLE_TO_RAD; - ry = curRotation[i][1] * ANGLE_TO_RAD; - rz = curRotation[i][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; j < stackSize; ++j ) - { - if ( curCorrespondingJoint[j] != -1 ) { - placement = &fr->references[curCorrespondingJoint[j]].placement; - - // y-axis rotation for origin - x2 = placement->origin[0] * cy + placement->origin[2] * sy; - z2 = -placement->origin[0] * sy + placement->origin[2] * cy; - placement->origin[0] = x2; - placement->origin[2] = z2; - - // y-axis rotation for direction - x2 = placement->direction[0] * cy + placement->direction[2] * sy; - z2 = -placement->direction[0] * sy + placement->direction[2] * cy; - placement->direction[0] = x2; - placement->direction[2] = z2; - - // y-axis rotation for up - x2 = placement->up[0] * cy + placement->up[2] * sy; - z2 = -placement->up[0] * sy + placement->up[2] * cy; - placement->up[0] = x2; - placement->up[2] = z2; - - // z-axis rotation for origin - x2 = placement->origin[0] * cz - placement->origin[1] * sz; - y2 = placement->origin[0] * sz + placement->origin[1] * cz; - placement->origin[0] = x2; - placement->origin[1] = y2; - - // z-axis rotation for direction - x2 = placement->direction[0] * cz - placement->direction[1] * sz; - y2 = placement->direction[0] * sz + placement->direction[1] * cz; - placement->direction[0] = x2; - placement->direction[1] = y2; - - // z-axis rotation for up - x2 = placement->up[0] * cz - placement->up[1] * sz; - y2 = placement->up[0] * sz + placement->up[1] * cz; - placement->up[0] = x2; - placement->up[1] = y2; - - // x-axis rotation for origin - y2 = placement->origin[1] * cx - placement->origin[2] * sx; - z2 = placement->origin[1] * sx + placement->origin[2] * cx; - placement->origin[1] = y2; - placement->origin[2] = z2; - - // x-axis rotation for direction vector - y2 = placement->direction[1] * cx - placement->direction[2] * sx; - z2 = placement->direction[1] * sx + placement->direction[2] * cx; - placement->direction[1] = y2; - placement->direction[2] = z2; - - // x-axis rotation for up vector - y2 = placement->up[1] * cx - placement->up[2] * sx; - z2 = placement->up[1] * sx + placement->up[2] * cx; - placement->up[1] = y2; - placement->up[2] = z2; - - // translate origin - placement->origin[0] += curTranslation[i][0]; - placement->origin[1] += curTranslation[i][1]; - placement->origin[2] += curTranslation[i][2]; - - // translate back to local coord - placement->direction[0] += curTranslation[i][0]; - placement->direction[1] += curTranslation[i][1]; - placement->direction[2] += curTranslation[i][2]; - - // translate back to local coord - placement->up[0] += curTranslation[i][0]; - placement->up[1] += curTranslation[i][1]; - placement->up[2] += curTranslation[i][2]; - - } - } - } - printf( "%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2] ); - } - printf( "\n" ); -} - -void Cmd_FMReferenced(){ - int i; - - GetScriptToken( false ); - g_skelModel.references = atoi( token ); - - // Guess what? Now, we now want a list of strings to look for here instead of a hard-coded list - for ( i = 0; i < REF_MAX_POINTS; i++ ) - { - if ( ScriptTokenAvailable() ) { // There is yet another reference point waiting. - GetScriptToken( false ); - strcpy( RefPointNameList[i], token ); - } - else - { - break; - } - } - - RefPointNum = i; - - if ( RefPointNum > 0 ) { - printf( "Searching for %d different reference points.\n", RefPointNum ); - } - else - { - printf( "Using built-in reference points.\n" ); - } - -} - -void LoadReferences( char *fileName, fmframe_t *fr ){ - 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 ); - - LoadHRCReferences( InputFileName, fr ); - - 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 ) { - LoadHRCReferences( fileName, fr ); - - return; - } - } - - Error( "Could not open file '%s':\n",fileName ); - } -} - -void GrabReferencedFrame( char *frame ){ - char file1[1024]; - char *framefile; - fmframe_t *fr; - - framefile = FindFrameFile( frame ); - - sprintf( file1, "%s/%s", cdarchive, framefile ); - ExpandPathAndArchive( file1 ); - - sprintf( file1, "%s/%s",cddir, framefile ); - - printf( "Grabbing Referenced %s\n", file1 ); - - fr = &g_frames[fmheader.num_frames - 1]; // last frame read in - - LoadReferences( file1, fr ); -} diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.h b/tools/quake2/qdata_heretic2/qd_skeletons.h deleted file mode 100644 index 7765c579..00000000 --- a/tools/quake2/qdata_heretic2/qd_skeletons.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (C) 1999-2007 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 QD_SKELETONS_H -#define QD_SKELETONS_H - -#include "placement.h" - - -typedef struct Placement_d_s -{ - vec3d_t origin; - vec3d_t direction; - vec3d_t up; -} Placement_d_t; - -typedef struct QD_SkeletalJoint_s -{ - Placement_d_t placement; - vec3d_t rotation; -} QD_SkeletalJoint_t; - -#define NUM_CLUSTERS 8 - -typedef struct IntListNode_s -{ - int data; - struct IntListNode_s *next; -} IntListNode_t; // gaak - -typedef struct Skeletalfmheader_s -{ - int type; - int clustered; - int references; - - int *clusters[NUM_CLUSTERS]; - IntListNode_t *vertLists[NUM_CLUSTERS]; - int num_verts[NUM_CLUSTERS + 1]; - int new_num_verts[NUM_CLUSTERS + 1]; - - float scaling[3]; - float rotation[3]; - float translation[3]; -} Skeletalfmheader_t; - -#define SKELETAL_NAME_MAX 32 - -extern Skeletalfmheader_t g_skelModel; - -void ClearSkeletalModel(); -void GrabModelTransform( char *frame ); -void GrabSkeletalFrame( char *frame ); -void GrabReferencedFrame( char *frame ); - -// Reference Stuff -#define NUM_REFERENCES 8 - -#define REF_MAX_POINTS 16 -#define REF_MAX_STRLEN 32 - -// We're assuming no more than 16 reference points, with no more than 32 characters in the name -extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN]; -extern int RefPointNum; - -#endif diff --git a/tools/quake2/qdata_heretic2/qdata.c b/tools/quake2/qdata_heretic2/qdata.c deleted file mode 100644 index 5ec53a9e..00000000 --- a/tools/quake2/qdata_heretic2/qdata.c +++ /dev/null @@ -1,764 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "globaldefs.h" -#include "md4.h" - -void TK_Init(); - -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 -int g_forcemodel = MODEL_AUTO; -qboolean g_verbose = false; -qboolean g_allow_newskin = true; -qboolean g_ignoreTriUV = false; -qboolean g_publishOutput = false; - -char *ext_3ds = "3ds"; -char *ext_tri = "tri"; -char *trifileext; - -char g_materialFile[256] = "none"; // default for Heretic2 -char *g_outputDir; -extern char *g_publishDir; - -extern qboolean g_nomkdir; - -/* - ======================================================= - - PAK FILES - - ======================================================= - */ - -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 ); - - // segment moved to old.c - - 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 ){ - GetScriptToken( false ); - ReleaseFile( token ); -} - -/* - =============== - PackDirectory_r - - =============== - */ -#if GDEF_OS_WINDOWS -#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 -#ifdef NeXT -#include -#else -#include -#endif - -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 ){ - GetScriptToken( 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_strcasecmp( name, rtex[i] ) ) { - 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 ( ScriptTokenAvailable() ) - { - GetScriptToken( 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 - GetScriptToken( true ); - if ( endofscript ) { - return; - } - if ( token[0] == '$' ) { - break; - } - while ( ScriptTokenAvailable() ) - GetScriptToken( false ); - } while ( 1 ); - - // - // model commands - // - if ( !strcmp( token, "$modelname" ) ) { - MODELCMD_Modelname( MODEL_MD2 ); - } - else if ( !strcmp( token, "$cd" ) ) { - MODELCMD_Cd( MODEL_MD2 ); - } - else if ( !strcmp( token, "$origin" ) ) { - MODELCMD_Origin( MODEL_MD2 ); - } - else if ( !strcmp( token, "$cluster" ) ) { - MODELCMD_Cluster( MODEL_MD2 ); - } - else if ( !strcmp( token, "$base" ) ) { - MODELCMD_Base( MODEL_MD2 ); - } - else if ( !strcmp( token, "$scale" ) ) { - MODELCMD_ScaleUp( MODEL_MD2 ); - } - else if ( !strcmp( token, "$frame" ) ) { - MODELCMD_Frame( MODEL_MD2 ); - } - else if ( !strcmp( token, "$skin" ) ) { - MODELCMD_Skin( MODEL_MD2 ); - } - else if ( !strcmp( token, "$skinsize" ) ) { - MODELCMD_Skinsize( MODEL_MD2 ); - } - // - // flexible model commands - // - else if ( !strcmp( token, "$fm_modelname" ) ) { - MODELCMD_Modelname( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_base" ) ) { - MODELCMD_Base( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_basest" ) ) { - MODELCMD_BaseST( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_cd" ) ) { - MODELCMD_Cd( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_origin" ) ) { - MODELCMD_Origin( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_cluster" ) ) { - MODELCMD_Cluster( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_skeleton" ) ) { - MODELCMD_Skeleton( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_scale" ) ) { - MODELCMD_ScaleUp( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_frame" ) ) { - MODELCMD_Frame( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_skeletal_frame" ) ) { // left in for compadibility with qdt already using fm_skeletal_frame - MODELCMD_Frame( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_skin" ) ) { - MODELCMD_Skin( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_skinsize" ) ) { - MODELCMD_Skinsize( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_begin_group" ) ) { - MODELCMD_BeginGroup( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_end_group" ) ) { - MODELCMD_EndGroup( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_referenced" ) ) { - MODELCMD_Referenced( MODEL_FM ); - } - else if ( !strcmp( token, "$fm_node_order" ) ) { - MODELCMD_NodeOrder( MODEL_FM ); - } - - // - // sprite commands - // - else if ( !strcmp( token, "$spritename" ) ) { - Cmd_SpriteName(); - } - else if ( !strcmp( token, "$sprdir" ) ) { - Cmd_Sprdir(); - } - else if ( !strcmp( token, "$load" ) ) { - Cmd_Load(); - } - else if ( !strcmp( token, "$spriteframe" ) ) { - Cmd_SpriteFrame(); - } - // - // image commands - // - else if ( !strcmpi( token, "$grab" ) ) { - Cmd_Grab(); - } - else if ( !strcmpi( token, "$raw" ) ) { - Cmd_Raw(); - } - else if ( !strcmpi( token, "$colormap" ) ) { - Cmd_Colormap(); - } - else if ( !strcmpi( token, "$mippal" ) ) { - Cmd_Mippal(); - } - else if ( !strcmpi( token, "$mipdir" ) ) { - Cmd_Mipdir(); - } - else if ( !strcmpi( token, "$mip" ) ) { - Cmd_Mip(); - } - else if ( !strcmp( token, "$environment" ) ) { - Cmd_Environment(); - } - // - // pics - // - else if ( !strcmp( token, "$picdir" ) ) { - Cmd_Picdir(); - } - else if ( !strcmp( token, "$pic" ) ) { - Cmd_Pic(); - } - // - // book - // - else if ( !strcmp( token, "$bookdir" ) ) { - Cmd_Bookdir(); - } - else if ( !strcmp( token, "$book" ) ) { - Cmd_Book(); - } - // - // tmix - // - else if ( !strcmp( token, "$texturemix" ) ) { - Cmd_TextureMix(); - } - // - // 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 ){ - int i; - char path[1024]; - char *basedir; - double starttime, endtime; - - printf( "Qdata Plus : "__TIME__ " "__DATE__ "\n" ); - - starttime = I_FloatTime(); - basedir = NULL; - - TK_Init(); - ExpandWildcards( &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], "-base" ) ) { - i++; - basedir = argv[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 ( !strcmpi( argv[i], "-keypress" ) ) { - g_dokeypress = true; - } - else if ( !strcmp( argv[i], "-3ds" ) ) { - do3ds = true; - printf( "loading .3ds files\n" ); - } - else if ( !strcmp( argv[i], "-materialfile" ) ) { - strcpy( g_materialFile, argv[i + 1] ); - printf( "Setting material file to %s\n", g_materialFile ); - i++; - } -/* else if (!strcmpi(argv[i], "-newgen")) - { - if (i < argc-4) - { - printf("run new triangle grouping routine here\n"); - NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4])); - } - else - { - printf("qdata -newskin width height\n"); - } - return 0; - } - */ else if ( !strcmpi( argv[i], "-genskin" ) ) { - i++; - if ( i < argc - 3 ) { - GenSkin( argv[i],argv[i + 1],atol( argv[i + 2] ),atol( argv[i + 3] ) ); - } - else - { - printf( "qdata -genskin \n" ); - } - return 0; - - } - else if ( !strcmpi( argv[i], "-noopts" ) ) { - g_no_opimizations = true; - printf( "not performing optimizations\n" ); - } - else if ( !strcmpi( argv[i], "-md2" ) ) { - g_forcemodel = MODEL_MD2; - } - else if ( !strcmpi( argv[i], "-fm" ) ) { - g_forcemodel = MODEL_FM; - } - else if ( !strcmpi( argv[i], "-verbose" ) ) { - g_verbose = true; - } - else if ( !strcmpi( argv[i], "-oldskin" ) ) { - g_allow_newskin = false; - } - else if ( !strcmpi( argv[i], "-ignoreUV" ) ) { - g_ignoreTriUV = true; - } - else if ( !strcmpi( argv[i], "-publish" ) ) { - g_publishOutput = true; - } - else if ( !strcmpi( argv[i], "-nomkdir" ) ) { - g_nomkdir = true; - } - else if ( argv[i][0] == '-' ) { - Error( "Unknown option \"%s\"", argv[i] ); - } - else{ - break; - } - } - - if ( i >= argc ) { - Error( "usage: qdata [-archive ]\n" - " [-release ]\n" - " [-base ]\n" - " [-compress]\n" - " [-pak ]\n" - " [-only ]\n" - " [-keypress]\n" - " [-3ds]\n" - " [-materialfile ]\n" - " [-noopts]\n" - " [-md2]\n" - " [-fm]\n" - " [-verbose]\n" - " [-ignoreUV]\n" - " [-oldskin]\n" - " [-publish]\n" - " [-nomkdir]\n" - " file.qdt\n" - "or\n" - " qdata -genskin " ); - } - - 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" ); - DefaultExtension( g_materialFile, ".mat" ); - SetQdirFromPath( path ); - - printf( "workingdir='%s'\n", gamedir ); - if ( basedir ) { - qdir[0] = 0; - g_outputDir = basedir; - } - - printf( "outputdir='%s'\n", g_outputDir ); - - QFile_ReadMaterialTypes( g_materialFile ); - LoadScriptFile( ExpandArg( path ) ); - - // - // parse it - // - ParseScript(); - - // write out the last model - FinishModel(); - FMFinishModel(); - FinishSprite(); - } - - if ( total_textures ) { - printf( "\n" ); - printf( "Total textures processed: %d\n",total_textures ); - printf( "Average size: %d x %d\n",total_x / total_textures, total_y / total_textures ); - } - - if ( g_pak ) { - FinishPak(); - } - - endtime = I_FloatTime(); - printf( "Time elapsed: %f\n", endtime - starttime ); - - if ( g_dokeypress ) { - printf( "Success! ... Hit a key: " ); - getchar(); - } - - return 0; -} diff --git a/tools/quake2/qdata_heretic2/qdata.h b/tools/quake2/qdata_heretic2/qdata.h deleted file mode 100644 index 0cfa6067..00000000 --- a/tools/quake2/qdata_heretic2/qdata.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// qdata.h - -#include "globaldefs.h" -#include -#include -#include -#include -#include - -#include "cmdlib.h" -#include "inout.h" -#include "scriplib.h" -#include "mathlib.h" -#include "trilib.h" -#include "lbmlib.h" -#include "her2_threads.h" -#include "l3dslib.h" -#include "bspfile.h" - -#if !GDEF_OS_WINDOWS -#define stricmp strcasecmp -#define strcmpi strcasecmp -#endif - - -#define MODEL_AUTO 0 -#define MODEL_MD2 1 -#define MODEL_FM 2 - -// Model cover functions (to allow the forcing of a model type) -void MODELCMD_Modelname( int modeltype ); -void MODELCMD_Cd( int modeltype ); -void MODELCMD_Origin( int modeltype ); -void MODELCMD_Jointed( int modeltype ); -void MODELCMD_Cluster( int modeltype ); -void MODELCMD_Base( int modeltype ); -void MODELCMD_BaseST( int modeltype ); -void MODELCMD_ScaleUp( int modeltype ); -void MODELCMD_Frame( int modeltype ); -void MODELCMD_Skin( int modeltype ); -void MODELCMD_Skinsize( int modeltype ); -void MODELCMD_Skeleton( int modeltype ); -void MODELCMD_SkeletalFrame( int modeltype ); -void MODELCMD_BeginGroup( int modeltype ); -void MODELCMD_EndGroup( int modeltype ); -void MODELCMD_Referenced( int modeltype ); -void MODELCMD_NodeOrder( int modeltype ); - -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_Skin( void ); -void Cmd_Skinsize( void ); -void FinishModel( void ); -void Cmd_Cluster( void ); - -// Flexible Models -//void Cmd_FMModelname (void); -void Cmd_FMBase( qboolean GetST ); -void Cmd_FMCd( void ); -//void Cmd_FMOrigin (void); -void Cmd_FMCluster(); -void Cmd_FMSkeleton(); -//void Cmd_FMScaleUp (void); -void Cmd_FMFrame( void ); -void Cmd_FMSkeletalFrame(); -void Cmd_FMSkin( void ); -//void Cmd_FMSkinsize (void); -void Cmd_FMBeginGroup( void ); -void Cmd_FMEndGroup( void ); -void Cmd_FMReferenced(); -void Cmd_FMNodeOrder( void ); -void FMFinishModel( void ); -void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ); -void NewGen( char *ModelFile, char *OutputName, int width, int height ); - - -void Cmd_Inverse16Table( void ); - -void Cmd_SpriteName( void ); -void Cmd_Load( void ); -void Cmd_SpriteFrame( void ); -void Cmd_Sprdir( 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_Picdir( void ); -void Cmd_Pic( void ); - -void Cmd_Bookdir( void ); -void Cmd_Book( void ); - -void Cmd_TextureMix( 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 TrueColorImage; -extern unsigned *longimage; -extern int longimagewidth, longimageheight; - -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 qboolean g_no_opimizations; -extern int g_forcemodel; -extern qboolean g_verbose; -extern qboolean g_allow_newskin; -extern qboolean g_ignoreTriUV; //from qdata.c -extern qboolean g_dokeypress; - -extern char *trifileext; - -extern char g_materialFile[256]; - -extern unsigned total_x; -extern unsigned total_y; -extern unsigned total_textures; - -miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ); -miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ); diff --git a/tools/quake2/qdata_heretic2/resource.h b/tools/quake2/qdata_heretic2/resource.h deleted file mode 100644 index 3d6343e5..00000000 --- a/tools/quake2/qdata_heretic2/resource.h +++ /dev/null @@ -1,18 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by Script1.rc -// -#define IDI_ICON1 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/tools/quake2/qdata_heretic2/sprites.c b/tools/quake2/qdata_heretic2/sprites.c deleted file mode 100644 index ecb9d096..00000000 --- a/tools/quake2/qdata_heretic2/sprites.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - Copyright (C) 1999-2007 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" - -#define MAX_SPRFRAMES MAX_MD2SKINS - -dsprite_t sprite; -dsprframe_t frames[MAX_SPRFRAMES]; - -byte *byteimage, *lbmpalette; -int byteimagewidth, byteimageheight; - -qboolean TrueColorImage; -unsigned *longimage; -int longimagewidth, longimageheight; - -char spritename[1024]; - - -void FinishSprite( void ); -void Cmd_Spritename( void ); - -char spr_prefix[1024]; -char pic_prefix[1024]; - -extern char *g_outputDir; - - -/* - ============== - 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, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, 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; - - GetScriptToken( false ); - - if ( g_release ) { - return; - } - - name = ExpandPathAndArchive( token ); - - // load the image - printf( "loading %s\n", name ); - TrueColorImage = LoadAnyImage( name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight ); - - if ( !TrueColorImage ) { -// RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight); - } - else - { - if ( longimage ) { - free( longimage ); - } - longimage = (unsigned *)byteimage; - longimagewidth = byteimagewidth; - longimageheight = byteimageheight; - - byteimage = NULL; - byteimagewidth = 0; - byteimageheight = 0; - } -} - - -/* - =============== - Cmd_SpriteFrame - =============== - */ - -void Cmd_SpriteFrame( void ){ - int x,y,xl,yl,xh,yh,w,h; - dsprframe_t *pframe; - int ox, oy, linedelta, size; -// byte *cropped; - char filename[1024]; - miptex_t *qtex; - miptex32_t *qtex32; - unsigned *destl, *sourcel; - unsigned bufferl[256 * 256]; - byte *dest, *source; - byte buffer[256 * 256]; - - GetScriptToken( false ); - xl = atoi( token ); - GetScriptToken( false ); - yl = atoi( token ); - GetScriptToken( false ); - w = atoi( token ); - GetScriptToken( false ); - h = atoi( token ); - - // origin offset is optional - if ( ScriptTokenAvailable() ) { - GetScriptToken( false ); - ox = atoi( token ); - GetScriptToken( false ); - oy = atoi( token ); - } - else - { - ox = w / 2; - oy = h / 2; - } - - if ( ( xl & 0x0f ) || ( yl & 0x0f ) || ( w & 0x0f ) || ( h & 0x0f ) ) { - Error( "Sprite dimensions not multiples of 16\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; - - if ( g_release ) { - ReleaseFile( pframe->name ); - return; - } - - if ( TrueColorImage ) { - sprintf( filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes ); - sprintf( pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes ); - - 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, true ); - - qtex32->contents = 0; - qtex32->value = 0; - strcpy( qtex32->name, pframe->name ); - // - // write it out - // - printf( "writing %s\n", filename ); - SaveFile( filename, (byte *)qtex32, size ); - - free( qtex32 ); - } - else - { - sprintf( filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes ); - sprintf( pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes ); - - 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, true ); - - qtex->flags = 0; - qtex->contents = 0; - qtex->value = 0; - strcpy( qtex->name, pframe->name ); - // - // write it out - // - printf( "writing %s\n", filename ); - SaveFile( filename, (byte *)qtex, size ); - - free( qtex ); - } - - sprite.numframes++; -} - - -/* - ============== - Cmd_SpriteName - ============== - */ -void Cmd_SpriteName( void ){ - if ( sprite.numframes ) { - FinishSprite(); - } - - GetScriptToken( false ); - strcpy( spritename, token ); - memset( &sprite, 0, sizeof( sprite ) ); - memset( &frames, 0, sizeof( frames ) ); -} - - -/* - =============== - Cmd_Sprdir - =============== - */ -void Cmd_Sprdir( void ){ - char filename[1024]; - - GetScriptToken( false ); - strcpy( spr_prefix, token ); - // create the directory if needed - sprintf( filename, "%sSprites", g_outputDir ); - Q_mkdir( filename ); - sprintf( filename, "%sSprites/%s", g_outputDir, spr_prefix ); - Q_mkdir( filename ); -} diff --git a/tools/quake2/qdata_heretic2/svdcmp.c b/tools/quake2/qdata_heretic2/svdcmp.c deleted file mode 100644 index 14865af3..00000000 --- a/tools/quake2/qdata_heretic2/svdcmp.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - Copyright (C) 1999-2007 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 -#include -#include -#include -#include - -static double at,bt,ct; -#define PYTHAG( a,b ) ( ( at = fabs( a ) ) > ( bt = fabs( b ) ) ? \ - ( ct = bt / at,at * sqrt( 1.0 + ct * ct ) ) : ( bt ? ( ct = at / bt,bt * sqrt( 1.0 + ct * ct ) ) : 0.0 ) ) - -static double maxarg1,maxarg2; -#define MAX( a,b ) ( maxarg1 = ( a ),maxarg2 = ( b ),( maxarg1 ) > ( maxarg2 ) ? \ - ( maxarg1 ) : ( maxarg2 ) ) -#define SIGN( a,b ) ( ( b ) >= 0.0 ? fabs( a ) : -fabs( a ) ) - -void ntrerror( char *s ){ - printf( "%s\n",s ); - exit( 1 ); -} - -double *allocVect( int sz ){ - double *ret; - - ret = calloc( sizeof( double ), (size_t)sz ); - return ret; -} - -void freeVect( double *ret ){ - free( ret ); -} - -double **allocMatrix( int r,int c ){ - double **ret; - - ret = calloc( sizeof( double ), (size_t)( r * c ) ); - return ret; -} - -void freeMatrix( double **ret,int r ){ - free( ret ); -} - -void svdcmp( double** a, int m, int n, double* w, double** v ){ - int flag,i,its,j,jj,k,l,nm; - double c,f,h,s,x,y,z; - double anorm = 0.0,g = 0.0,scale = 0.0; - double *rv1; - void nrerror(); - - if ( m < n ) { - ntrerror( "SVDCMP: You must augment A with extra zero rows" ); - } - rv1 = allocVect( n ); - for ( i = 1; i <= n; i++ ) { - l = i + 1; - rv1[i] = scale * g; - g = s = scale = 0.0; - if ( i <= m ) { - for ( k = i; k <= m; k++ ) scale += fabs( a[k][i] ); - if ( scale ) { - for ( k = i; k <= m; k++ ) { - a[k][i] /= scale; - s += a[k][i] * a[k][i]; - } - f = a[i][i]; - g = -SIGN( sqrt( s ),f ); - h = f * g - s; - a[i][i] = f - g; - if ( i != n ) { - for ( j = l; j <= n; j++ ) { - for ( s = 0.0,k = i; k <= m; k++ ) s += a[k][i] * a[k][j]; - f = s / h; - for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i]; - } - } - for ( k = i; k <= m; k++ ) a[k][i] *= scale; - } - } - w[i] = scale * g; - g = s = scale = 0.0; - if ( i <= m && i != n ) { - for ( k = l; k <= n; k++ ) scale += fabs( a[i][k] ); - if ( scale ) { - for ( k = l; k <= n; k++ ) { - a[i][k] /= scale; - s += a[i][k] * a[i][k]; - } - f = a[i][l]; - g = -SIGN( sqrt( s ),f ); - h = f * g - s; - a[i][l] = f - g; - for ( k = l; k <= n; k++ ) rv1[k] = a[i][k] / h; - if ( i != m ) { - for ( j = l; j <= m; j++ ) { - for ( s = 0.0,k = l; k <= n; k++ ) s += a[j][k] * a[i][k]; - for ( k = l; k <= n; k++ ) a[j][k] += s * rv1[k]; - } - } - for ( k = l; k <= n; k++ ) a[i][k] *= scale; - } - } - anorm = MAX( anorm,( fabs( w[i] ) + fabs( rv1[i] ) ) ); - } - for ( i = n; i >= 1; i-- ) { - if ( i < n ) { - if ( g ) { - for ( j = l; j <= n; j++ ) - v[j][i] = ( a[i][j] / a[i][l] ) / g; - for ( j = l; j <= n; j++ ) { - for ( s = 0.0,k = l; k <= n; k++ ) s += a[i][k] * v[k][j]; - for ( k = l; k <= n; k++ ) v[k][j] += s * v[k][i]; - } - } - for ( j = l; j <= n; j++ ) v[i][j] = v[j][i] = 0.0; - } - v[i][i] = 1.0; - g = rv1[i]; - l = i; - } - for ( i = n; i >= 1; i-- ) { - l = i + 1; - g = w[i]; - if ( i < n ) { - for ( j = l; j <= n; j++ ) a[i][j] = 0.0; - } - if ( g ) { - g = 1.0 / g; - if ( i != n ) { - for ( j = l; j <= n; j++ ) { - for ( s = 0.0,k = l; k <= m; k++ ) s += a[k][i] * a[k][j]; - f = ( s / a[i][i] ) * g; - for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i]; - } - } - for ( j = i; j <= m; j++ ) a[j][i] *= g; - } - else { - for ( j = i; j <= m; j++ ) a[j][i] = 0.0; - } - ++a[i][i]; - } - for ( k = n; k >= 1; k-- ) { - for ( its = 1; its <= 30; its++ ) { - flag = 1; - for ( l = k; l >= 1; l-- ) { - nm = l - 1; - if ( fabs( rv1[l] ) + anorm == anorm ) { - flag = 0; - break; - } - if ( fabs( w[nm] ) + anorm == anorm ) { - break; - } - } - if ( flag ) { - c = 0.0; - s = 1.0; - for ( i = l; i <= k; i++ ) { - f = s * rv1[i]; - if ( fabs( f ) + anorm != anorm ) { - g = w[i]; - h = PYTHAG( f,g ); - w[i] = h; - h = 1.0 / h; - c = g * h; - s = ( -f * h ); - for ( j = 1; j <= m; j++ ) { - y = a[j][nm]; - z = a[j][i]; - a[j][nm] = y * c + z * s; - a[j][i] = z * c - y * s; - } - } - } - } - z = w[k]; - if ( l == k ) { - if ( z < 0.0 ) { - w[k] = -z; - for ( j = 1; j <= n; j++ ) v[j][k] = ( -v[j][k] ); - } - break; - } - if ( its == 30 ) { - ntrerror( "No convergence in 30 SVDCMP iterations" ); - } - x = w[l]; - nm = k - 1; - y = w[nm]; - g = rv1[nm]; - h = rv1[k]; - f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0 * h * y ); - g = PYTHAG( f,1.0 ); - f = ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + SIGN( g,f ) ) ) - h ) ) / x; - c = s = 1.0; - for ( j = l; j <= nm; j++ ) { - i = j + 1; - g = rv1[i]; - y = w[i]; - h = s * g; - g = c * g; - z = PYTHAG( f,h ); - rv1[j] = z; - c = f / z; - s = h / z; - f = x * c + g * s; - g = g * c - x * s; - h = y * s; - y = y * c; - for ( jj = 1; jj <= n; jj++ ) { - x = v[jj][j]; - z = v[jj][i]; - v[jj][j] = x * c + z * s; - v[jj][i] = z * c - x * s; - } - z = PYTHAG( f,h ); - w[j] = z; - if ( z ) { - z = 1.0 / z; - c = f * z; - s = h * z; - } - f = ( c * g ) + ( s * y ); - x = ( c * y ) - ( s * g ); - for ( jj = 1; jj <= m; jj++ ) { - y = a[jj][j]; - z = a[jj][i]; - a[jj][j] = y * c + z * s; - a[jj][i] = z * c - y * s; - } - } - rv1[l] = 0.0; - rv1[k] = f; - w[k] = x; - } - } - freeVect( rv1 ); -} - - - -void svbksb( double** u, double* w, double** v,int m, int n, double* b, double* x ){ - int jj,j,i; - double s,*tmp; - tmp = allocVect( n ); - for ( j = 1; j <= n; j++ ) - { - s = 0.0; - if ( w[j] ) { - for ( i = 1; i <= m; i++ ) - s += u[i][j] * b[i]; - s /= w[j]; - } - tmp[j] = s; - } - for ( j = 1; j <= n; j++ ) - { - s = 0.0; - for ( jj = 1; jj <= n; jj++ ) - s += v[j][jj] * tmp[jj]; - x[j] = s; - } - freeVect( tmp ); -} - -#undef SIGN -#undef MAX -#undef PYTHAG - - -#if 1 -void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){ - int usedfs; - int *remap; - int i,j; - double **da; - double **v; - double *w; - int DOFerr; - float mx; - int bestat; - - if ( nframes > framesize ) { - usedfs = nframes; - } - else{ - usedfs = framesize; - } - - da = allocMatrix( usedfs,nframes ); - v = allocMatrix( nframes,nframes ); - w = allocVect( nframes ); - - DOFerr = 0; //false - for ( i = 0; i < nframes; i++ ) - { - for ( j = 0; j < framesize; j++ ) - da[j + 1][i + 1] = a[i * framesize + j]; - for (; j < usedfs; j++ ) - da[j + 1][i + 1] = 0.0; - } - - svdcmp( da,usedfs,nframes,w,v ); - - remap = calloc( sizeof( int ), (size_t)nframes ); - - - for ( i = 0; i < nframes; i++ ) - remap[i] = -1; - for ( j = 0; j < compressedsize; j++ ) - { - mx = -1.0f; - for ( i = 0; i < nframes; i++ ) - { - if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) { - mx = (float) fabs( w[i + 1] ); - bestat = i; - } - } - - if ( mx > 0 ) { - remap[bestat] = j; - } - else - { - DOFerr = 1; //true - } - } - - if ( DOFerr ) { - printf( "Warning: To many degrees of freedom! File size may increase\n" ); - - for ( i = 0; i < compressedsize; i++ ) - { - values[i] = 0; - for ( j = 0; j < framesize; j++ ) - res[i * framesize + j] = 0; - } - } - - for ( i = 0; i < nframes; i++ ) - { - if ( remap[i] < 0 ) { - w[i + 1] = 0.0; - } - else - { - values[remap[i]] = (float) w[i + 1]; - for ( j = 0; j < framesize; j++ ) - res[remap[i] * framesize + j] = (float) da[j + 1][i + 1]; - } - } - freeVect( w ); - freeMatrix( v,nframes ); - freeMatrix( da,framesize ); - free( remap ); -} - -#else - -void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){ - int *remap; - int i,j; - int nrows; - nrows = nframes; - if ( nrows < framesize ) { - nrows = framesize; - } - double **da = allocMatrix( nrows,framesize ); - double **v = allocMatrix( framesize,framesize ); - double *w = allocVect( framesize ); - float mx; - int bestat; - - for ( j = 0; j < framesize; j++ ) - { - for ( i = 0; i < nframes; i++ ) - da[j + 1][i + 1] = a[i * framesize + j]; - for (; i < nrows; i++ ) - da[j + 1][i + 1] = 0.0; - } - - svdcmp( da,nrows,framesize,w,v ); - - remap = new int[framesize]; - - - for ( i = 0; i < framesize; i++ ) - remap[i] = -1; - for ( j = 0; j < compressedsize; j++ ) - { - mx = -1.0f; - for ( i = 0; i < framesize; i++ ) - { - if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) { - mx = fabs( w[i + 1] ); - bestat = i; - } - } - assert( mx > -.5f ); - remap[bestat] = j; - } - // josh **DO NOT** put your dof>nframes mod here - for ( i = 0; i < framesize; i++ ) - { - if ( remap[i] < 0 ) { - w[i + 1] = 0.0; - } - else - { - values[remap[i]] = w[i + 1]; - for ( j = 0; j < framesize; j++ ) - res[remap[i] * framesize + j] = v[j + 1][i + 1]; - } - } - freeVect( w ); - freeMatrix( v,framesize ); - freeMatrix( da,nrows ); - delete[] remap; -} - -#endif - -void DOsvdPlane( float *pnts,int npnts,float *n,float *base ){ - int i,j; - double **da = allocMatrix( npnts,3 ); - double **v = allocMatrix( 3,3 ); - double *w = allocVect( 3 ); - float mn = 1E30f; - int bestat; - - - assert( npnts >= 3 ); - base[0] = pnts[0]; - base[1] = pnts[1]; - base[2] = pnts[2]; - for ( i = 1; i < npnts; i++ ) - { - for ( j = 0; j < 3; j++ ) - base[j] += pnts[i * 3 + j]; - } - base[0] /= (float)( npnts ); - base[1] /= (float)( npnts ); - base[2] /= (float)( npnts ); - - for ( i = 0; i < 3; i++ ) - { - for ( j = 0; j < npnts; j++ ) - da[j + 1][i + 1] = pnts[j * 3 + i] - base[i]; - } - - svdcmp( da,npnts,3,w,v ); - for ( i = 0; i < 3; i++ ) - { - if ( fabs( w[i + 1] ) < mn ) { - mn = (float) fabs( w[i + 1] ); - bestat = i; - } - } - n[0] = (float) v[1][bestat + 1]; - n[1] = (float) v[2][bestat + 1]; - n[2] = (float) v[3][bestat + 1]; - freeVect( w ); - freeMatrix( v,3 ); - freeMatrix( da,npnts ); -} diff --git a/tools/quake2/qdata_heretic2/tables.c b/tools/quake2/qdata_heretic2/tables.c deleted file mode 100644 index ad86c1ee..00000000 --- a/tools/quake2/qdata_heretic2/tables.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - Copyright (C) 1999-2007 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]; - - GetScriptToken( 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 ) ); -} diff --git a/tools/quake2/qdata_heretic2/tmix.c b/tools/quake2/qdata_heretic2/tmix.c deleted file mode 100644 index 936cd6e5..00000000 --- a/tools/quake2/qdata_heretic2/tmix.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - Copyright (C) 1999-2007 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 "flex.h" - -#define MAXFILES 2048 - -#if !GDEF_OS_WINDOWS -#define strlwr strlower -#endif // !GDEF_OS_WINDOWS - -typedef struct -{ - int x; - int y; - int w; - int h; - int cw; - int ch; - int rw; - int index; - int depth; - int col; - int baseline; - char name[128]; -} Coords; - -int filenum; -int valid; -Coords in[MAXFILES]; -Coords out; -char outscript[256]; -char sourcedir[256]; -char outusage[256]; -char root[32]; - -int destsize = 0; -byte *pixels = NULL; // Buffer to load image -long *outpixels = NULL; // Buffer to store combined textures -long *usagemap = NULL; // Buffer of usage map -void *bmptemp = NULL; // Buffer of usage map -byte *map = NULL; - -int xcharsize; -int ycharsize; -int dosort = 0; -int missed = 0; -int overlap = 0; -int nobaseline = 0; -int percent; - -////////////////////////////////////////////////// -// Setting the char based usage map // -////////////////////////////////////////////////// - -byte TryPlace( Coords *coord ){ - int x, y; - byte entry = 0; - byte *mapitem; - - mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw ); - - for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw ) - { - for ( x = 0; x < coord->cw; x++ ) - { - if ( entry |= *mapitem++ & 8 ) { - return( entry ); - } - } - } - return( entry ); -} - -void SetMap( Coords *coord ){ - int x, y; - byte *mapitem; - - mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw ); - - for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw ) - for ( x = 0; x < coord->cw; x++ ) - *mapitem++ |= 8; -} - -////////////////////////////////////////////////// -// Setting the pixel based usage map // -////////////////////////////////////////////////// - -void CheckOverlap( Coords *coord ){ - int x; - int y; - long *dest; - - x = coord->x; - y = coord->y; - - dest = (long *)( usagemap + x + ( y * out.w ) ); - - for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) - { - for ( x = 0; x < coord->w; x++ ) - { - if ( *dest++ ) { - overlap++; - return; - } - } - } -} - -void SetUsageMap( Coords *coord ){ - int x; - int y; - long *dest; - - x = coord->x; - y = coord->y; - - dest = (long *)( usagemap + x + ( y * out.w ) ); - - for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) - { - for ( x = 0; x < coord->w; x++ ) - { - *dest++ = coord->col; - } - } -} - -////////////////////////////////////////////////// -// Flips the BMP image to the correct way up // -////////////////////////////////////////////////// - -void CopyLine( byte *dest, byte *src, int size ){ - int x; - - for ( x = 0; x < size; x++ ) - *dest++ = *src++; -} - -/****************************************************/ -/* Printing headers etc */ -/****************************************************/ - -void RemoveLeading( char *name ){ - int i; - char temp[128]; - - for ( i = strlen( name ) - 1; i > 0; i-- ) - { - if ( ( name[i] == '\\' ) || ( name[i] == '/' ) ) { - strcpy( temp, name + i + 1 ); - strcpy( name, temp ); - return; - } - } -} - -void RemoveExt( char *name ){ - while ( ( *name != '.' ) && *name ) - name++; - *name = 0; -} - -/****************************************************/ -/* Misc calcualtions */ -/****************************************************/ - -int TotalArea(){ - int i; - int total = 0; - - for ( i = 0; i < ( filenum + 2 ); i++ ) - total += in[i].w * in[i].h; - - return( total ); -} - -/****************************************************/ -/* Setup and checking of all info */ -/****************************************************/ - -void InitVars(){ - filenum = 0; - valid = 0; - dosort = 0; - missed = 0; - overlap = 0; - nobaseline = 0; - - memset( outscript, 0, sizeof( outscript ) ); - memset( outscript, 0, sizeof( sourcedir ) ); - memset( outscript, 0, sizeof( outusage ) ); - memset( outscript, 0, sizeof( root ) ); - - memset( in, 0, sizeof( in ) ); - memset( &out, 0, sizeof( out ) ); -} -void Cleanup(){ - if ( pixels ) { - free( pixels ); - } - if ( usagemap ) { - free( usagemap ); - } - if ( outpixels ) { - free( outpixels ); - } - if ( bmptemp ) { - free( bmptemp ); - } - if ( map ) { - free( map ); - } -} - -typedef struct glxy_s -{ - float xl, yt, xr, yb; - int w, h, baseline; -} glxy_t; - -int SaveScript( char *name ){ - FILE *fp; - int i, j; - glxy_t buff; - - if ( fp = fopen( name, "wb" ) ) { - for ( j = 0; j < filenum; j++ ) - { - for ( i = 0; i < filenum; i++ ) - { - if ( in[i].index == j ) { - if ( in[i].depth ) { - buff.xl = (float)in[i].x / (float)out.w; - buff.yt = (float)in[i].y / (float)out.h; - buff.xr = ( (float)in[i].w + (float)in[i].x ) / (float)out.w; - buff.yb = ( (float)in[i].h + (float)in[i].y ) / (float)out.h; - buff.w = in[i].w; - buff.h = in[i].h; - buff.baseline = in[i].baseline; - } - else - { - memset( &buff, 0, sizeof( glxy_t ) ); - } - fwrite( &buff, 1, sizeof( glxy_t ), fp ); - i = filenum; - } - } - } - fclose( fp ); - return( true ); - } - else{ - return( false ); - } -} - -int GetScriptInfo( char *name ){ - FILE *fp; - char buffer[256]; - char tempbuff[256]; - char delims[] = {" \t,\n"}; - - printf( "Opening script file %s.\n", name ); - - if ( fp = fopen( name, "r" ) ) { - while ( fgets( buffer, 256, fp ) ) - { - if ( strncmp( buffer, "//", 2 ) && strncmp( buffer, "\n", 1 ) ) { - strupr( buffer ); - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "OUTPUT" ) == 0 ) { - strcpy( out.name, strtok( NULL, delims ) ); - strlwr( out.name ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "SOURCEDIR" ) == 0 ) { - strcpy( tempbuff, strtok( NULL, delims ) ); - strcpy( sourcedir, ExpandPathAndArchive( tempbuff ) ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "DOSORT" ) == 0 ) { - dosort = 1; - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "XCHARSIZE" ) == 0 ) { - xcharsize = strtol( strtok( NULL, delims ), NULL, 0 ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "YCHARSIZE" ) == 0 ) { - ycharsize = strtol( strtok( NULL, delims ), NULL, 0 ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "OUTSCRIPT" ) == 0 ) { - strcpy( outscript, strtok( NULL, delims ) ); - strlwr( outscript ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "OUTUSAGE" ) == 0 ) { - strcpy( outusage, strtok( NULL, delims ) ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "POS" ) == 0 ) { - out.w = strtol( strtok( NULL, delims ), NULL, 0 ); - out.h = strtol( strtok( NULL, delims ), NULL, 0 ); - } - - strcpy( tempbuff, buffer ); - if ( strcmp( strtok( tempbuff, delims ), "FILE" ) == 0 ) { - strcpy( in[filenum].name, strtok( NULL, delims ) ); - in[filenum].x = strtol( strtok( NULL, delims ), NULL, 0 ); - in[filenum].y = strtol( strtok( NULL, delims ), NULL, 0 ); - in[filenum].col = strtol( strtok( NULL, delims ), NULL, 0 ); - filenum++; - } - } - } - fclose( fp ); - return( true ); - } - else - { - printf( "ERROR : Could not open script file.\n" ); - return( false ); - } -} - -int CheckVars(){ - int i; - - if ( out.name[0] == 0 ) { - printf( "ERROR : No output name specified.\n" ); - return( false ); - } - if ( ( out.w <= 0 ) || ( out.h <= 0 ) ) { - printf( "ERROR : Invalid VRAM coordinates.\n" ); - return( false ); - } - if ( filenum == 0 ) { - printf( "ERROR : No input files specified.\n" ); - return( false ); - } - for ( i = 0; i < filenum; i++ ) - if ( in[i].name[0] == 0 ) { - printf( "ERROR : Input filename invalid.\n" ); - return( false ); - } - return( true ); -} - -// Makes sure texture is totally within the output area - -int CheckCoords( Coords *coord ){ - if ( ( coord->x + coord->w ) > out.w ) { - return( false ); - } - if ( ( coord->y + coord->h ) > out.h ) { - return( false ); - } - - return( true ); -} -// Gets the width, height, palette width and palette height of each BMP file - -int GetFileDimensions(){ - int i; - int width, height; - char name[128]; - - for ( i = 0; i < filenum; i++ ) - { - in[i].index = i; - - strcpy( name, sourcedir ); - strcat( name, in[i].name ); - printf( "Getting file dimensions, file : %s \r", in[i].name ); - if ( FileExists( name ) ) { - LoadAnyImage( name, NULL, NULL, &width, &height ); - in[i].depth = 32; - in[i].rw = width; - in[i].w = width; // makes it width in - in[i].h = height; - in[i].cw = ( in[i].w + ( xcharsize - 1 ) ) / xcharsize; - in[i].ch = ( in[i].h + ( ycharsize - 1 ) ) / ycharsize; - - if ( !CheckCoords( &in[i] ) && ( in[i].x >= 0 ) ) { - printf( "Error : texture %s out of bounds.\n", in[i].name ); - return( false ); - } - valid++; - } - else - { - in[i].depth = 0; - in[i].x = -1; - in[i].y = -1; - in[i].w = 0; - in[i].h = 0; - } - } - printf( "\n\n" ); - return( true ); -} - -// Sorts files into order for optimal space finding -// Fixed position ones first, followed by the others in descending size -// The theory being that it is easier to find space for smaller textures. -// size = (width + height) -// For space finding it is easier to place a 32x32 than a 128x2 - -#define WEIGHT 0x8000 - -void Swap( Coords *a, Coords *b ){ - Coords c; - - c = *a; - *a = *b; - *b = c; -} - -void SortInNames(){ - int i, j; - int largest, largcount; - int size; - - printf( "Sorting filenames by size.\n\n" ); - - for ( j = 0; j < filenum; j++ ) - { - largest = -1; - largcount = -1; - - for ( i = j; i < filenum; i++ ) - { - if ( in[i].depth ) { - size = in[i].w + in[i].h; - - if ( ( in[i].x < 0 ) && ( size > largest ) ) { - largcount = i; - largest = size; - } - } - } - if ( ( largcount >= 0 ) && ( largcount != j ) ) { - Swap( &in[j], &in[largcount] ); - } - } -} - -int SetVars( char *name ){ - if ( !GetScriptInfo( name ) ) { - return( false ); - } - - if ( !CheckVars() ) { - return( false ); - } - - destsize = out.w * out.h; - - out.cw = out.w / xcharsize; - out.ch = out.h / ycharsize; - - if ( ( usagemap = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { - return( false ); - } - if ( ( outpixels = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { - return( false ); - } - if ( ( bmptemp = (void *)SafeMalloc( destsize * 4, "" ) ) == NULL ) { - return( false ); - } - if ( ( map = (byte *)SafeMalloc( destsize / ( xcharsize * ycharsize ), "" ) ) == NULL ) { - return( false ); - } - - if ( GetFileDimensions() == false ) { - return( false ); - } - - if ( dosort ) { - SortInNames(); - } - - return( true ); -} -/****************************************************/ -/* Actual copying routines */ -/****************************************************/ - -int FindCoords( Coords *coord ){ - int tx, ty; - - if ( coord->x >= 0 ) { - SetMap( coord ); - return( true ); - } - else - { - for ( ty = 0; ty < out.ch; ty++ ) - { - for ( tx = 0; tx < out.cw; tx++ ) - { - coord->x = ( tx * xcharsize ); - coord->y = ( ty * ycharsize ); - - if ( CheckCoords( coord ) && !TryPlace( coord ) ) { - SetMap( coord ); - return( true ); - } - } - } - } - coord->x = -1; - coord->y = -1; - - return( false ); -} - -void CheckBaseline( int i ){ - int y; - long *pix; - - in[i].baseline = -1; - pix = (long *)pixels; - - for ( y = 0; y < in[i].h; y++, pix += in[i].w ) - { - if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) { - in[i].baseline = y; - break; - } - } - pix = (long *)pixels; - for ( y = 0; y < in[i].w * in[i].h; y++, pix++ ) - { - if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) { - *pix = 0; - } - } - - if ( in[i].baseline == -1 ) { - printf( "\nERROR : %s has no baseline\n", in[i].name ); - nobaseline++; - } -} - -void CopyToMain32( Coords *coord ){ - int x; - int y; - long *source; - long *dest; - - x = coord->x; - y = coord->y; - - source = (long *)pixels; - dest = (long *)( outpixels + x + ( y * out.w ) ); - - for ( y = 0; y < coord->h; y++, dest += out.w - coord->w ) - { - for ( x = 0; x < coord->w; x++ ) - { - *dest++ = *source++; - } - } -} - -void CreateMain(){ - int i, count; - int width, height; - char name[128]; - - for ( i = 0, count = 0; i < filenum; i++ ) - { - if ( in[i].depth ) { - printf( "\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline ); - count++; - if ( !FindCoords( &in[i] ) ) { - missed++; - } - else - { - strcpy( name, sourcedir ); - strcat( name, in[i].name ); - LoadAnyImage( name, &pixels, NULL, &width, &height ); - CheckBaseline( i ); - CheckOverlap( &in[i] ); - CopyToMain32( &in[i] ); - SetUsageMap( &in[i] ); - } - } - } -} - -void Cmd_TextureMix(){ - miptex32_t *qtex32; - char filename[1024]; - int size; - - InitVars(); - - GetScriptToken( false ); - - strcpy( root, token ); - RemoveExt( root ); - RemoveLeading( root ); - - strcpy( filename, ExpandPathAndArchive( token ) ); - if ( SetVars( filename ) ) { - // Create combined texture - percent = ( ( TotalArea() * 100 ) / ( out.w * out.h ) ); - printf( "Total area consumed : %d%%\n", percent ); - printf( "Texture resolution : %dx%d pixels.\n", xcharsize, ycharsize ); - CreateMain(); - - // Save image as m32 - sprintf( filename, "%spics/misc/%s.m32", gamedir, out.name ); - qtex32 = CreateMip32( (unsigned *)outpixels, out.w, out.h, &size, false ); - - qtex32->contents = 0; - qtex32->value = 0; - qtex32->scale_x = 1.0; - qtex32->scale_y = 1.0; - sprintf( qtex32->name, "misc/%s", out.name ); - - printf( "\n\nwriting %s\n", filename ); - SaveFile( filename, (byte *)qtex32, size ); - free( qtex32 ); - - // Save out script file - sprintf( filename, "%spics/misc/%s.fnt", gamedir, outscript ); - printf( "Writing %s as script file\n", filename ); - if ( !SaveScript( filename ) ) { - printf( "Unable to save output script.\n" ); - } - } - printf( "Everythings groovy.\n" ); - Cleanup(); -} - -// end diff --git a/tools/quake2/qdata_heretic2/video.c b/tools/quake2/qdata_heretic2/video.c deleted file mode 100644 index 51bf4620..00000000 --- a/tools/quake2/qdata_heretic2/video.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* - Copyright (C) 1999-2007 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 - */ - -// To do - -// Sound error handling (when sound too short) -// rle b4 huffing -// adpcm encoding of sound - -#if 0 -#include "qdata.h" -#include "flex.h" -#include "fc.h" -#include "adpcm.h" - -#define MIN_REPT 15 -#define MAX_REPT 0 -#define HUF_TOKENS ( 256 + MAX_REPT ) - -#define BLOCKSIZE 8 - -#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h -#define SQRT2 1.414213562 - -typedef struct hnode_s -{ - int count; - qboolean used; - int children[2]; -} hnode_t; - -typedef struct -{ - int rate; - int width; - int channels; - int loopstart; - int samples; - int dataofs; // chunk starts this many bytes from file start -} wavinfo_t; - -// These weren`t picked out my ass.... -// They were defined at http://www.rahul.net/jfm/dct.html -// However, I think he plucked them out of his ass..... - -float Quantise[BLOCKSIZE * BLOCKSIZE]; - -float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] = -{ - 16.0F / 16.0F, 11.0F / 16.0F, 10.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 51.0F / 16.0F, 61.0F / 16.0F, - 12.0F / 16.0F, 13.0F / 16.0F, 14.0F / 16.0F, 19.0F / 16.0F, 26.0F / 16.0F, 58.0F / 16.0F, 60.0F / 16.0F, 55.0F / 16.0F, - 14.0F / 16.0F, 13.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 57.0F / 16.0F, 69.0F / 16.0F, 56.0F / 16.0F, - 14.0F / 16.0F, 17.0F / 16.0F, 22.0F / 16.0F, 29.0F / 16.0F, 51.0F / 16.0F, 87.0F / 16.0F, 80.0F / 16.0F, 62.0F / 16.0F, - 18.0F / 16.0F, 22.0F / 16.0F, 37.0F / 16.0F, 56.0F / 16.0F, 68.0F / 16.0F,109.0F / 16.0F,103.0F / 16.0F, 77.0F / 16.0F, - 24.0F / 16.0F, 35.0F / 16.0F, 55.0F / 16.0F, 64.0F / 16.0F, 81.0F / 16.0F,104.0F / 16.0F,113.0F / 16.0F, 92.0F / 16.0F, - 49.0F / 16.0F, 64.0F / 16.0F, 78.0F / 16.0F, 87.0F / 16.0F,103.0F / 16.0F,121.0F / 16.0F,120.0F / 16.0F,101.0F / 16.0F, - 72.0F / 16.0F, 92.0F / 16.0F, 95.0F / 16.0F, 98.0F / 16.0F,112.0F / 16.0F,100.0F / 16.0F,103.0F / 16.0F, 99.0F / 16.0F -}; - -int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] = -{ - 0, - 1, 8, - 16, 9, 2, - 3, 10, 17, 24, - 32, 25, 18, 11, 4, - 5, 12, 19, 26, 33, 40, - 48, 41, 34, 27, 20, 13, 6, - 7, 14, 21, 28, 35, 42, 49, 56, - 57, 50, 43, 36, 29, 22, 15, - 23, 30, 37, 44, 51, 58, - 59, 52, 45, 38, 31, - 39, 46, 53, 60, - 61, 54, 47, - 55, 62, - 63 -}; - -char base[32]; - -byte *soundtrack; - -byte scaled[256][HUF_TOKENS]; -unsigned int charbits1[256][HUF_TOKENS]; -int charbitscount1[256][HUF_TOKENS]; -hnode_t hnodes1[256][HUF_TOKENS * 2]; -int numhnodes1[256]; -int order0counts[256]; -int numhnodes; -hnode_t hnodes[512]; -unsigned charbits[256]; -int charbitscount[256]; - -CineHead_t cinehead; - -byte *data_p; -byte *iff_end; -byte *last_chunk; -byte *iff_data; -int iff_chunk_len; - -float dctbase[BLOCKSIZE][BLOCKSIZE]; -float red[BLOCKSIZE * BLOCKSIZE]; -float green[BLOCKSIZE * BLOCKSIZE]; -float blue[BLOCKSIZE * BLOCKSIZE]; -float temp[BLOCKSIZE * BLOCKSIZE]; - -wavinfo_t wavinfo; -adpcm_t adpcm; - -/* - =============================================================================== - - WAV loading - - =============================================================================== - */ - -/* Intel ADPCM step variation table */ -static int indexTable[16] = -{ - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8, -}; - -static int stepsizeTable[89] = -{ - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 -}; - -#if 0 -static void adpcm_decoder( char *indata, short *outdata, int len, adpcm_state_t *state ){ - signed char *inp; /* Input buffer pointer */ - short *outp; /* output buffer pointer */ - int sign; /* Current adpcm sign bit */ - int delta; /* Current adpcm output value */ - int step; /* Stepsize */ - int valpred; /* Predicted value */ - int vpdiff; /* Current change to valpred */ - int index; /* Current step change index */ - int inputbuffer; /* place to keep next 4-bit value */ - int bufferstep; /* toggle between inputbuffer/input */ - - outp = outdata; - inp = (signed char *)indata; - - valpred = state->valprev; - index = state->index; - step = stepsizeTable[index]; - - bufferstep = 0; - - for (; len > 0; len-- ) - { - /* Step 1 - get the delta value */ - if ( bufferstep ) { - delta = inputbuffer & 0xf; - } - else - { - inputbuffer = *inp++; - delta = ( inputbuffer >> 4 ) & 0xf; - } - bufferstep = !bufferstep; - - /* Step 2 - Find new index value (for later) */ - index += indexTable[delta]; - if ( index < 0 ) { - index = 0; - } - if ( index > 88 ) { - index = 88; - } - - /* Step 3 - Separate sign and magnitude */ - sign = delta & 8; - delta = delta & 7; - - /* Step 4 - Compute difference and new predicted value */ - /* - ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment - ** in adpcm_coder. - */ - vpdiff = step >> 3; - if ( delta & 4 ) { - vpdiff += step; - } - if ( delta & 2 ) { - vpdiff += step >> 1; - } - if ( delta & 1 ) { - vpdiff += step >> 2; - } - - if ( sign ) { - valpred -= vpdiff; - } - else{ - valpred += vpdiff; - } - - /* Step 5 - clamp output value */ - if ( valpred > 32767 ) { - valpred = 32767; - } - else if ( valpred < -32768 ) { - valpred = -32768; - } - - /* Step 6 - Update step value */ - step = stepsizeTable[index]; - - /* Step 7 - Output value */ - *outp++ = valpred; - } - - state->valprev = valpred; - state->index = index; -} -#endif - -void adpcm_coder( short *inp, adpcm_t *adpcm ){ - int val; /* Current input sample value */ - int sign; /* Current adpcm sign bit */ - int delta; /* Current adpcm output value */ - int diff; /* Difference between val and valprev */ - int step; /* Stepsize */ - int valpred; /* Predicted output value */ - int vpdiff; /* Current change to valpred */ - int index; /* Current step change index */ - int outputbuffer; /* place to keep previous 4-bit value */ - int bufferstep; /* toggle between outputbuffer/output */ - adpcm_state_t *state; - char *outp; - int len; - - state = &adpcm->state; - len = state->count; - outp = adpcm->adpcm; - - valpred = state->in_valprev; - index = state->in_index; - step = stepsizeTable[index]; - - bufferstep = 1; - while ( len-- ) - { - val = *inp++; - - /* Step 1 - compute difference with previous value */ - diff = val - valpred; - sign = ( diff < 0 ) ? 8 : 0; - if ( sign ) { - diff = -diff; - } - - /* Step 2 - Divide and clamp */ - /* Note: - ** This code *approximately* computes: - ** delta = diff*4/step; - ** vpdiff = (delta+0.5)*step/4; - ** but in shift step bits are dropped. The net result of this is - ** that even if you have fast mul/div hardware you cannot put it to - ** good use since the fixup would be too expensive. - */ - delta = 0; - vpdiff = ( step >> 3 ); - - if ( diff >= step ) { - delta = 4; - diff -= step; - vpdiff += step; - } - step >>= 1; - if ( diff >= step ) { - delta |= 2; - diff -= step; - vpdiff += step; - } - step >>= 1; - if ( diff >= step ) { - delta |= 1; - vpdiff += step; - } - - /* Step 3 - Update previous value */ - if ( sign ) { - valpred -= vpdiff; - } - else{ - valpred += vpdiff; - } - - /* Step 4 - Clamp previous value to 16 bits */ - if ( valpred > 32767 ) { - valpred = 32767; - } - else if ( valpred < -32768 ) { - valpred = -32768; - } - - /* Step 5 - Assemble value, update index and step values */ - delta |= sign; - - index += indexTable[delta]; - if ( index < 0 ) { - index = 0; - } - if ( index > 88 ) { - index = 88; - } - step = stepsizeTable[index]; - - /* Step 6 - Output value */ - if ( bufferstep ) { - outputbuffer = ( delta << 4 ) & 0xf0; - } - else{ - *outp++ = ( delta & 0x0f ) | outputbuffer; - } - - bufferstep = !bufferstep; - } - - /* Output last step, if needed */ - if ( !bufferstep ) { - *outp++ = outputbuffer; - } - - state->out_valprev = valpred; - state->out_index = index; -} - -void FindNextChunk( char *name ){ - while ( 1 ) - { - data_p = last_chunk; - - if ( data_p >= iff_end ) { // didn't find the chunk - data_p = NULL; - return; - } - - data_p += 4; - iff_chunk_len = *(long *)data_p; - data_p += 4; - if ( iff_chunk_len < 0 ) { - data_p = NULL; - return; - } - - data_p -= 8; - last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 ); - if ( !strncmp( data_p, name, 4 ) ) { - return; - } - } -} - -void FindChunk( char *name ){ - last_chunk = iff_data; - FindNextChunk( name ); -} - -void DumpChunks( void ){ - char str[5]; - - str[4] = 0; - data_p = iff_data; - do - { - memcpy( str, data_p, 4 ); - data_p += 4; - iff_chunk_len = *(long *)data_p; - data_p += 4; - printf( "0x%x : %s (%d)\n", (int)( data_p - 4 ), str, iff_chunk_len ); - data_p += ( iff_chunk_len + 1 ) & ~1; - } - while ( data_p < iff_end ); -} - -/* - ============ - GetWavinfo - ============ - */ -wavinfo_t GetWavinfo( char *name, byte *wav, int wavlength ){ - wavinfo_t info; - int i; - int format; - int samples; - - memset( &info, 0, sizeof( info ) ); - - if ( !wav ) { - return( info ); - } - - iff_data = wav; - iff_end = wav + wavlength; - -// find "RIFF" chunk - FindChunk( "RIFF" ); - if ( !( data_p && !strncmp( data_p + 8, "WAVE", 4 ) ) ) { - printf( "Missing RIFF/WAVE chunks\n" ); - return( info ); - } - -// get "fmt " chunk - iff_data = data_p + 12; - - FindChunk( "fmt " ); - if ( !data_p ) { - printf( "Missing fmt chunk\n" ); - return( info ); - } - data_p += 8; - format = *(short *)data_p; - data_p += 2; - if ( format != 1 ) { - printf( "Microsoft PCM format only\n" ); - return( info ); - } - - info.channels = *(short *)data_p; - data_p += 2; - info.rate = *(long *)data_p; - data_p += 4; - data_p += 6; - info.width = *(short *)data_p / 8; - data_p += 2; - -// get cue chunk - FindChunk( "cue " ); - if ( data_p ) { - data_p += 32; - info.loopstart = *(long *)data_p; - data_p += 4; - -// if the next chunk is a LIST chunk, look for a cue length marker - FindNextChunk( "LIST" ); - if ( data_p ) { -// this is not a proper parse, but it works with cooledit... - if ( !strncmp( data_p + 28, "mark", 4 ) ) { - data_p += 24; - i = *(long *)data_p; // samples in loop - data_p += 4; - info.samples = info.loopstart + i; - } - } - } - else{ - info.loopstart = -1; - } - -// find data chunk - FindChunk( "data" ); - if ( !data_p ) { - printf( "Missing data chunk\n" ); - return( info ); - } - - data_p += 4; - samples = *(long *)data_p; - data_p += 4; - - if ( info.samples ) { - if ( samples < info.samples ) { - Error( "Sound %s has a bad loop length", name ); - } - } - else{ - info.samples = samples; - } - - info.dataofs = data_p - wav; - return( info ); -} - -// ============== -// LoadSoundtrack -// ============== - -void LoadSoundtrack(){ - char name[1024]; - FILE *f; - int len; - - soundtrack = NULL; - sprintf( name, "%svideo/%s/%s.wav", gamedir, base, base ); - printf( "\nLoading sound : %s\n", name ); - f = fopen( name, "rb" ); - if ( !f ) { - printf( "\nNo soundtrack for %s\n", base ); - return; - } - len = Q_filelength( f ); - soundtrack = SafeMalloc( len, "LoadSoundtrack" ); - fread( soundtrack, 1, len, f ); - fclose( f ); - - wavinfo = GetWavinfo( name, soundtrack, len ); - adpcm.state.out_valprev = 0; - adpcm.state.out_index = 0; -} - -// ================== -// WriteSound -// ================== - -int WriteSound( FILE *output, int frame, int numframes ){ - int start, end; - int count; - int empty = 0; - int width; - char *work; - - width = wavinfo.width * wavinfo.channels; - start = ( ( frame * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0; // start sample - end = ( ( ( frame + numframes ) * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0; // end sample - count = end - start; - - work = soundtrack + wavinfo.dataofs + ( start * width ); - adpcm.state.count = count * wavinfo.channels; // Number of samples - adpcm.state.in_valprev = adpcm.state.out_valprev; - adpcm.state.in_index = adpcm.state.out_index; - adpcm_coder( (short *)work, &adpcm ); - WriteHeader( output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, ( adpcm.state.count / 2 ) + sizeof( adpcm_state_t ), (char *)&adpcm ); - return( count / 2 ); -} -// ============================== -// Basic run length encoder -// ============================== - -char *RLEZZ( char *in, char *out ){ - int srun; - char count; - int idx = 0; - - while ( idx < 64 ) - { - srun = idx; // Start of run - - while ( idx < 63 ) - { - if ( in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]] ) { - break; - } - idx++; - } - count = (char)( idx - srun ); // count of repeated bytes - - if ( !count ) { - while ( idx < 63 ) - { - if ( in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]] ) { - break; - } - idx++; - } - if ( idx == 63 ) { - idx++; - } - - count = (char)( idx - srun ); // count of unique bytes - *out++ = count; - while ( count-- ) - *out++ = in[LUT_ZZ[srun++]]; - } - else - { - *out++ = -( count + 1 ); - *out++ = in[LUT_ZZ[idx]]; - idx++; - } - } - return( out ); -} - -// ============================== -// Discrete Cosine Transformation -// ============================== - -void init_base( float quant ){ - int y, x; - - for ( y = 0; y < BLOCKSIZE; y++ ) - for ( x = 0; x < BLOCKSIZE; x++ ) - { - if ( y == 0 ) { - dctbase[y][x] = 1; - } - else{ - dctbase[y][x] = SQRT2 * cos( ( ( x * 2 + 1 ) * y * M_PI ) / ( BLOCKSIZE * 2 ) ); - } - } - - for ( y = 0; y < BLOCKSIZE * BLOCKSIZE; y++ ) - Quantise[y] = LUT_Quantise[y] / quant; -} - -void SplitComponents( byte *src, int width, int height ){ - int i, j; - float *tr = red; - float *tg = green; - float *tb = blue; - - for ( i = 0; i < BLOCKSIZE; i++, src += ( width - BLOCKSIZE ) * 4 ) - for ( j = 0; j < BLOCKSIZE; j++ ) - { - *tr++ = ( (float)*src++ ) - 128.0F; - *tg++ = ( (float)*src++ ) - 128.0F; - *tb++ = ( (float)*src++ ) - 128.0F; - src++; - } -} - -void transferH( float *src, float *dst ){ - int y, dx, dy; - float sum; - float *work; - - for ( y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE ) - { - for ( dy = 0; dy < BLOCKSIZE; dy++ ) - { - sum = 0; - work = src; - for ( dx = 0; dx < BLOCKSIZE; dx++, work++ ) - sum += dctbase[dy][dx] * *work; - - *dst++ = sum / BLOCKSIZE; - } - } -} - -void transferV( float *src, float *dst ){ - int x, dy, fy; - float sum; - float *work; - - for ( x = 0; x < BLOCKSIZE; x++, src++, dst++ ) - { - for ( fy = 0; fy < BLOCKSIZE; fy++ ) - { - sum = 0; - work = src; - for ( dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE ) - sum += dctbase[fy][dy] * *work; - - dst[fy * BLOCKSIZE] = sum / BLOCKSIZE; - } - } -} - -char *Combine( byte *dst, float *p, float *q ){ - int i, j; - byte rlesrc[BLOCKSIZE * BLOCKSIZE]; - int c; - byte *work; - - work = rlesrc; - for ( j = 0; j < BLOCKSIZE; j++ ) - for ( i = 0; i < BLOCKSIZE; i++ ) - { - c = (int)( ( *p++ / *q++ ) + 128.5F ); - c -= 128; - - if ( c < -128 ) { - c = -128; - } - if ( c > 127 ) { - c = 127; - } - - *work++ = (char)c; - } - - dst = RLEZZ( rlesrc, dst ); - return( dst ); -} - -char *CombineComponents( char *dst, int width, int height ){ - dst = Combine( dst, red, Quantise ); - dst = Combine( dst, green, Quantise ); - dst = Combine( dst, blue, Quantise ); - return( dst ); -} - -void DCT( cblock_t *out, cblock_t in, int width, int height ){ - int x, y; - char *cursrc; - char *curdst; - - curdst = out->data; - for ( y = 0; y < height; y += BLOCKSIZE ) - for ( x = 0; x < width; x += BLOCKSIZE ) - { - cursrc = in.data + ( ( y * width ) + x ) * 4; - SplitComponents( cursrc, width, height ); - transferH( red, temp ); - transferV( temp, red ); - transferH( green, temp ); - transferV( temp, green ); - transferH( blue, temp ); - transferV( temp, blue ); - curdst = CombineComponents( curdst, width, height ); - } - out->count = curdst - out->data; -} - -// ================== -// BuildChars1 -// ================== - -void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){ - hnode_t *node; - - if ( nodenum < HUF_TOKENS ) { - if ( bitcount > 32 ) { - Error( "bitcount > 32" ); - } - charbits1[prev][nodenum] = bits; - charbitscount1[prev][nodenum] = bitcount; - return; - } - - node = &hnodes1[prev][nodenum]; - bits <<= 1; - BuildChars1( prev, node->children[0], bits, bitcount + 1 ); - bits |= 1; - BuildChars1( prev, node->children[1], bits, bitcount + 1 ); -} - -// ================== -// SmallestNode1 -// ================== - -int SmallestNode1( hnode_t *hnodes, int numhnodes ){ - int i; - int best, bestnode; - - best = 99999999; - bestnode = -1; - for ( i = 0; i < numhnodes; i++ ) - { - if ( hnodes[i].used ) { - continue; - } - if ( !hnodes[i].count ) { - continue; - } - if ( hnodes[i].count < best ) { - best = hnodes[i].count; - bestnode = i; - } - } - - if ( bestnode == -1 ) { - return( -1 ); - } - - hnodes[bestnode].used = true; - return( bestnode ); -} - -// ================== -// BuildTree1 -// ================== - -void BuildTree1( int prev ){ - hnode_t *node, *nodebase; - int numhnodes; - - // build the nodes - numhnodes = HUF_TOKENS; - nodebase = hnodes1[prev]; - while ( 1 ) - { - node = &nodebase[numhnodes]; - - // pick two lowest counts - node->children[0] = SmallestNode1( nodebase, numhnodes ); - if ( node->children[0] == -1 ) { - break; // no more - - } - node->children[1] = SmallestNode1( nodebase, numhnodes ); - if ( node->children[1] == -1 ) { - break; - } - - node->count = nodebase[node->children[0]].count + - nodebase[node->children[1]].count; - numhnodes++; - } - numhnodes1[prev] = numhnodes - 1; - BuildChars1( prev, numhnodes - 1, 0, 0 ); -} - -// ================== -// Huffman1_Count -// ================== - -void Huffman1_Count( cblock_t in ){ - int i; - int prev; - int v; - int rept; - - prev = 0; - for ( i = 0; i < in.count; i++ ) - { - v = in.data[i]; - order0counts[v]++; - hnodes1[prev][v].count++; - prev = v; - - for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ ) - if ( in.data[i + rept] != v ) { - break; - } - if ( rept > MIN_REPT ) { - hnodes1[prev][255 + rept].count++; - i += rept - 1; - } - } -} - -// ================== -// Huffman1_Build -// ================== - -void Huffman1_Build(){ - int i, j, v; - int max; - int total; - - for ( i = 0; i < 256; i++ ) - { -// normalize and save the counts - max = 0; - for ( j = 0; j < HUF_TOKENS; j++ ) - { - if ( hnodes1[i][j].count > max ) { - max = hnodes1[i][j].count; - } - } - if ( max == 0 ) { - max = 1; - } - total = 0; -// easy to overflow 32 bits here! - for ( j = 0; j < HUF_TOKENS; j++ ) - { - v = ( hnodes1[i][j].count * (double) 255 + max - 1 ) / max; - if ( v > 255 ) { - Error( "v > 255" ); - } - scaled[i][j] = hnodes1[i][j].count = v; - if ( v ) { - total++; - } - } - if ( total == 1 ) { // must have two tokens - if ( !scaled[i][0] ) { - scaled[i][0] = hnodes1[i][0].count = 1; - } - else{ - scaled[i][1] = hnodes1[i][1].count = 1; - } - } - BuildTree1( i ); - } -} - -// ================== -// Huffman1 -// Order 1 compression with pre-built table -// ================== - -cblock_t Huffman1( cblock_t in ){ - int i; - int outbits, c; - unsigned bits; - byte *out_p; - cblock_t out; - int prev; - int v; - int rept; - - out_p = out.data = SafeMalloc( ( in.count * 2 ) + 1024 + 4, "Huffman" ); - memset( out_p, 0, ( in.count * 2 ) + 1024 + 4 ); - - // leave space for compressed count - out_p += 4; - // write count - *(long *)out_p = in.count; - out_p += 4; - - // write bits - outbits = 0; - prev = 0; - for ( i = 0; i < in.count; i++ ) - { - v = in.data[i]; - - c = charbitscount1[prev][v]; - bits = charbits1[prev][v]; - if ( !c ) { - Error( "!bits" ); - } - while ( c ) - { - c--; - if ( bits & ( 1 << c ) ) { - out_p[outbits >> 3] |= 1 << ( outbits & 7 ); - } - outbits++; - } - - prev = v; - // check for repeat encodes - for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ ) - if ( in.data[i + rept] != v ) { - break; - } - if ( rept > MIN_REPT ) { - c = charbitscount1[prev][255 + rept]; - bits = charbits1[prev][255 + rept]; - if ( !c ) { - Error( "!bits" ); - } - while ( c ) - { - c--; - if ( bits & ( 1 << c ) ) { - out_p[outbits >> 3] |= 1 << ( outbits & 7 ); - } - outbits++; - } - i += rept - 1; - } - } - out_p += ( outbits + 7 ) >> 3; - out.count = out_p - out.data; - - out_p = out.data; - *(long *)out_p = out.count; - return( out ); -} -// =================== -// LoadFrame -// =================== - -void LoadFrame( cblock_t *out, char *base, int frame ){ - cblock_t in; - int width, height; - char name[1024]; - FILE *f; - - in.data = NULL; - in.count = -1; - sprintf( name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame ); - - f = fopen( name, "rb" ); - if ( !f ) { - out->data = NULL; - return; - } - fclose( f ); - - LoadTGA( name, &in.data, &width, &height ); - if ( ( width != cinehead.Width ) || ( height != cinehead.Height ) ) { - free( in.data ); - printf( "Invalid picture size\n" ); - out->data = NULL; - return; - } - out->data = SafeMalloc( width * height * 3, "LoadFrame" ); // rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression) - DCT( out, in, width, height ); - free( in.data ); -} - -// ================================== -// Cmd_Video -// -// video -// ================================== - -void Cmd_Video(){ - char savename[256]; - char name[256]; - FILE *output; - int frame; - int width, height; - cblock_t in, huffman; - int size; - float dctconst; - int maxsize, ssize; - int min_rle_size, warnings; - int ave_image, ave_sound; - - GetScriptToken( false ); - strcpy( base, token ); - if ( g_release ) { - return; - } - - GetScriptToken( false ); - dctconst = atof( token ); - GetScriptToken( false ); - maxsize = atoi( token ); - - sprintf( savename, "%svideo/%s.cin", gamedir, base ); - - // clear stuff - memset( charbits1, 0, sizeof( charbits1 ) ); - memset( charbitscount1, 0, sizeof( charbitscount1 ) ); - memset( hnodes1, 0, sizeof( hnodes1 ) ); - memset( numhnodes1, 0, sizeof( numhnodes1 ) ); - memset( order0counts, 0, sizeof( order0counts ) ); - - // load the entire sound wav file if present - LoadSoundtrack(); - - cinehead.SndRate = wavinfo.rate; - cinehead.SndWidth = wavinfo.width; - cinehead.SndChannels = wavinfo.channels; - - sprintf( name, "%svideo/%s/%s0000.tga", gamedir, base, base ); - printf( "Loading sequence : %s\n", name ); - printf( "DCT constant : %f\n", dctconst ); - - LoadTGA( name, NULL, &width, &height ); - - output = fopen( savename, "wb" ); - if ( !output ) { - Error( "Can't open %s", savename ); - } - - if ( ( width % BLOCKSIZE ) || ( height % BLOCKSIZE ) ) { - Error( "Width and height must be a multiple of %d", BLOCKSIZE ); - } - - cinehead.Width = width; - cinehead.Height = height; - init_base( dctconst ); - - // build the dictionary - printf( "Counting : " ); - min_rle_size = 0; - for ( frame = 0; ; frame++ ) - { - printf( "." ); - LoadFrame( &in, base, frame ); - if ( !in.data ) { - break; - } - Huffman1_Count( in ); - if ( in.count > min_rle_size ) { - min_rle_size = in.count; - } - free( in.data ); - } - printf( "\n" ); - cinehead.NumFrames = frame; - printf( "Num Frames : %d\n", frame ); - cinehead.MaxRleSize = ( min_rle_size + 0x1f ) & 0xfffffe0; - cinehead.MaxSndSize = ( ( 4 * wavinfo.rate * wavinfo.channels / 14 ) + 0x1f ) & 0xffffffe0; - - WriteHeader( output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof( CineHead_t ), &cinehead ); - - // build nodes and write counts - Huffman1_Build(); - WriteHeader( output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof( scaled ), scaled ); - WriteHeader( output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof( Quantise ), Quantise ); - - ave_image = 0; - ave_sound = 0; - warnings = 0; - // compress it with the dictionary - if ( soundtrack ) { - ssize = WriteSound( output, frame, 4 ); - ave_sound += ssize; - } - - for ( frame = 0; frame < cinehead.NumFrames; frame++ ) - { - // save some sound samples - printf( "Packing : ", frame ); - LoadFrame( &in, base, frame ); - - // save the image - huffman = Huffman1( in ); - printf( "%d bytes rle, %d bytes huffman", in.count, huffman.count ); - size = ( huffman.count + 3 ) & 0xfffffffc; // round up to longwords - if ( size > maxsize ) { - printf( " ** WARNING **" ); - warnings++; - } - printf( "\n" ); - ave_image += huffman.count; - - WriteHeader( output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data ); - if ( soundtrack ) { - ssize = WriteSound( output, frame + 4, 1 ); - ave_sound += ssize; - } - - free( in.data ); - free( huffman.data ); - } - printf( "\nTotal size: %d (headers + %d image + %d sound)\n", ftell( output ), ave_image, ave_sound ); - printf( "Data rate : %d bytes per sec (image and sound)\n", ( ave_image + ave_sound ) / cinehead.NumFrames ); - printf( "Cin created ok with %d warnings.\n", warnings ); - fclose( output ); - - if ( soundtrack ) { - free( soundtrack ); - } -} -#endif - -void Cmd_Video(){ -} - -// end