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,) \
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)
--- /dev/null
+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 ()
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <sys/types.h>
+#include <sys/stat.h>
+
+#if GDEF_OS_WINDOWS
+#include <direct.h>
+#include <windows.h>
+#elif GDEF_OS_NEXT
+#include <libc.h>
+#else // OTHER OSES
+#include <unistd.h>
+#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
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <sys/types.h>
+#include <sys/stat.h>
+
+#if GDEF_OS_WINDOWS
+#include <direct.h>
+#include <windows.h>
+#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, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">" );
+ NMSG_Clear( &msg );
+ NMSG_WriteString( &msg, sMsg );
+ Net_Send( brdcst_socket, &msg );
+ }
+}
+
+void Broadcast_Shutdown(){
+ if ( brdcst_socket ) {
+ Sys_Printf( "Disconnecting\n" );
+ Net_Disconnect( brdcst_socket );
+ brdcst_socket = NULL;
+ }
+}
+
+// all output ends up through here
+void FPrintf( int flag, char *buf ){
+ xmlNodePtr node;
+ static qboolean bGotXML = false;
+ char level[2];
+
+ printf( buf );
+
+ // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
+ if ( flag == SYS_NOXML ) {
+ return;
+ }
+
+ // ouput an XML file of the run
+ // use the DOM interface to build a tree
+ /*
+ <message level='flag'>
+ message string
+ .. various nodes to describe corresponding geometry ..
+ </message>
+ */
+ if ( !bGotXML ) {
+ // initialize
+ doc = xmlNewDoc( "1.0" );
+ doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
+ bGotXML = true;
+ }
+ node = xmlNewNode( NULL, "message" );
+ 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 );
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "l3dslib.h"
+#include "token.h"
+#include "fmodel.h"
+#include "bspfile.h"
+
+#define MAIN3DS 0x4D4D
+#define EDIT3DS 0x3D3D // this is the start of the editor config
+#define EDIT_OBJECT 0x4000
+#define OBJ_TRIMESH 0x4100
+#define TRI_VERTEXL 0x4110
+#define TRI_FACEL1 0x4120
+
+#define MAXVERTS 2000
+
+typedef struct {
+ int v[4];
+} tri;
+
+float fverts[MAXVERTS][3];
+tri tris[MAXTRIANGLES];
+
+int bytesread, level, numtris, totaltris;
+int vertsfound, trisfound;
+
+triangle_t *ptri;
+
+
+
+void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles ){
+ int pos, bit, i;
+
+ if ( nodesList ) {
+ *num_mesh_nodes = 1;
+ memset( &( *nodesList )[0], 0, sizeof( mesh_node_t ) );
+ strcpy( ( *nodesList )[0].name, "default" );
+
+ // set all of the tris to be used for the top node
+ for ( i = 0; i < ( *numtriangles ); i++ )
+ {
+ pos = ( i ) >> 3;
+ bit = 1 << ( ( i ) & 7 );
+
+ ( *nodesList )[0].tris[pos] |= bit;
+ }
+ }
+}
+
+
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
+// start out with a vertex pool and vertex indices for triangles, we have to convert
+// to raw, explicit triangles
+void StoreAliasTriangles( void ){
+ int i, j, k;
+
+ if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
+ Error( "Error: Too many triangles" );
+ }
+
+ for ( i = 0; i < numtris ; i++ )
+ {
+ for ( j = 0 ; j < 3 ; j++ )
+ {
+ for ( k = 0 ; k < 3 ; k++ )
+ {
+ ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
+ }
+ }
+ }
+
+ totaltris += numtris;
+ numtris = 0;
+ vertsfound = 0;
+ trisfound = 0;
+}
+
+
+int ParseVertexL( FILE *input ){
+ int i, j, startbytesread, numverts;
+ unsigned short tshort;
+
+ if ( vertsfound ) {
+ Error( "Error: Multiple vertex chunks" );
+ }
+
+ vertsfound = 1;
+ startbytesread = bytesread;
+
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &tshort, sizeof( tshort ), 1, input );
+ bytesread += sizeof( tshort );
+ numverts = (int)tshort;
+
+ if ( numverts > MAXVERTS ) {
+ Error( "Error: Too many vertices" );
+ }
+
+ for ( i = 0 ; i < numverts ; i++ )
+ {
+ for ( j = 0 ; j < 3 ; j++ )
+ {
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &fverts[i][j], sizeof( float ), 1, input );
+ bytesread += sizeof( float );
+ }
+ }
+
+ if ( vertsfound && trisfound ) {
+ StoreAliasTriangles();
+ }
+
+ return bytesread - startbytesread;
+}
+
+
+int ParseFaceL1( FILE *input ){
+
+ int i, j, startbytesread;
+ unsigned short tshort;
+
+ if ( trisfound ) {
+ Error( "Error: Multiple face chunks" );
+ }
+
+ trisfound = 1;
+ startbytesread = bytesread;
+
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &tshort, sizeof( tshort ), 1, input );
+ bytesread += sizeof( tshort );
+ numtris = (int)tshort;
+
+ if ( numtris > MAXTRIANGLES ) {
+ Error( "Error: Too many triangles" );
+ }
+
+ for ( i = 0 ; i < numtris ; i++ )
+ {
+ for ( j = 0 ; j < 4 ; j++ )
+ {
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &tshort, sizeof( tshort ), 1, input );
+ bytesread += sizeof( tshort );
+ tris[i].v[j] = (int)tshort;
+ }
+ }
+
+ if ( vertsfound && trisfound ) {
+ StoreAliasTriangles();
+ }
+
+ return bytesread - startbytesread;
+}
+
+
+int ParseChunk( FILE *input ){
+#define BLOCK_SIZE 4096
+ char temp[BLOCK_SIZE];
+ unsigned short type;
+ int i, length, w, t, retval;
+
+ level++;
+ retval = 0;
+
+// chunk type
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &type, sizeof( type ), 1, input );
+ bytesread += sizeof( type );
+
+// chunk length
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &length, sizeof( length ), 1, input );
+ bytesread += sizeof( length );
+ w = length - 6;
+
+// process chunk if we care about it, otherwise skip it
+ switch ( type )
+ {
+ case TRI_VERTEXL:
+ w -= ParseVertexL( input );
+ goto ParseSubchunk;
+
+ case TRI_FACEL1:
+ w -= ParseFaceL1( input );
+ goto ParseSubchunk;
+
+ case EDIT_OBJECT:
+ // read the name
+ i = 0;
+
+ do
+ {
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &temp[i], 1, 1, input );
+ i++;
+ w--;
+ bytesread++;
+ } while ( temp[i - 1] );
+
+ case MAIN3DS:
+ case OBJ_TRIMESH:
+ case EDIT3DS:
+ // parse through subchunks
+ParseSubchunk:
+ while ( w > 0 )
+ {
+ w -= ParseChunk( input );
+ }
+
+ retval = length;
+ goto Done;
+
+ default:
+ // skip other chunks
+ while ( w > 0 )
+ {
+ t = w;
+
+ if ( t > BLOCK_SIZE ) {
+ t = BLOCK_SIZE;
+ }
+
+ if ( feof( input ) ) {
+ Error( "Error: unexpected end of file" );
+ }
+
+ fread( &temp, t, 1, input );
+ bytesread += t;
+
+ w -= t;
+ }
+
+ retval = length;
+ goto Done;
+ }
+
+Done:
+ level--;
+ return retval;
+}
+
+
+void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
+ FILE *input;
+ short int tshort;
+
+ if ( nodesList ) {
+ *num_mesh_nodes = 0;
+ *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+ }
+
+ bytesread = 0;
+ level = 0;
+ numtris = 0;
+ totaltris = 0;
+ vertsfound = 0;
+ trisfound = 0;
+
+ if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
+ fprintf( stderr,"reader: could not open file '%s'\n", filename );
+ exit( 0 );
+ }
+
+ fread( &tshort, sizeof( tshort ), 1, input );
+
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
+// no MAIN3DS
+ if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
+ fprintf( stderr,"File is not a 3DS file.\n" );
+ exit( 0 );
+ }
+
+// back to top of file so we can parse the first chunk descriptor
+ fseek( input, 0, SEEK_SET );
+
+ ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
+
+ *pptri = ptri;
+
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
+ ParseChunk( input );
+
+ if ( vertsfound || trisfound ) {
+ Error( "Incomplete triangle set" );
+ }
+
+ *numtriangles = totaltris;
+
+ fclose( input );
+
+ DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
+}
+
+//==========================================================================
+//
+// LoadASC
+//
+//==========================================================================
+
+void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
+ int i, j;
+ int vertexCount;
+ struct
+ {
+ float v[3];
+ } *vList;
+ int triCount;
+ triangle_t *tList;
+ float x, y, z;
+// float x2, y2, z2;
+// float rx, ry, rz;
+ qboolean goodObject;
+
+ if ( nodesList ) {
+ *num_mesh_nodes = 0;
+ *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+ }
+
+ TK_OpenSource( fileName );
+
+ goodObject = false;
+ while ( goodObject == false )
+ {
+ TK_Beyond( TK_C_NAMED );
+ TK_Beyond( TK_OBJECT );
+ TK_Beyond( TK_C_TRI );
+ TK_Beyond( TK_MESH );
+ TK_BeyondRequire( TK_C_VERTICES, TK_COLON );
+ TK_FetchRequire( TK_INTNUMBER );
+ vertexCount = tk_IntNumber;
+ if ( vertexCount > 0 ) {
+ goodObject = true;
+ }
+ }
+ TK_BeyondRequire( TK_C_FACES, TK_COLON );
+ TK_FetchRequire( TK_INTNUMBER );
+ triCount = tk_IntNumber;
+ if ( triCount >= MAXTRIANGLES ) {
+ Error( "Too many triangles in file %s\n", fileName );
+ }
+ *triangleCount = triCount;
+ tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
+ *triList = tList;
+
+ memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
+ TK_BeyondRequire( TK_C_VERTEX, TK_LIST );
+
+/* rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
+ //rx = (rotation[0]/360.0)*2.0*M_PI;
+ ry = (rotation[1]/360.0)*2.0*M_PI;
+ rz = (rotation[2]/360.0)*2.0*M_PI;
+ */
+ vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
+ for ( i = 0; i < vertexCount; i++ )
+ {
+ TK_BeyondRequire( TK_C_VERTEX, TK_INTNUMBER );
+ if ( tk_IntNumber != i ) {
+ Error( "File '%s', line %d:\nVertex index mismatch.\n",
+ tk_SourceName, tk_Line );
+ }
+ TK_FetchRequireFetch( TK_COLON );
+
+ TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+ x = tk_FloatNumber;
+ TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+ y = tk_FloatNumber;
+ TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+ z = tk_FloatNumber;
+
+/* x2 = x*cos(rz)+y*sin(rz);
+ y2 = -x*sin(rz)+y*cos(rz);
+ x = x2;
+ y = y2;
+ y2 = y*cos(rx)+z*sin(rx);
+ z2 = -y*sin(rx)+z*cos(rx);
+ y = y2;
+ z = z2;
+ x2 = x*cos(ry)-z*sin(ry);
+ z2 = x*sin(ry)+z*cos(ry);
+ x = x2;
+ z = z2;
+ */
+ vList[i].v[0] = x;
+ vList[i].v[1] = y;
+ vList[i].v[2] = z;
+ }
+ TK_BeyondRequire( TK_C_FACE, TK_LIST );
+ for ( i = 0; i < triCount; i++ )
+ {
+ TK_BeyondRequire( TK_C_FACE, TK_INTNUMBER );
+ if ( tk_IntNumber != i ) {
+ Error( "File '%s', line %d:\nTriangle index mismatch.\n",
+ tk_SourceName, tk_Line );
+ }
+ for ( j = 0; j < 3; j++ )
+ {
+ TK_BeyondRequire( TK_IDENTIFIER, TK_COLON );
+ TK_FetchRequire( TK_INTNUMBER );
+ if ( tk_IntNumber >= vertexCount ) {
+ Error( "File '%s', line %d:\nVertex number"
+ " > vertexCount: %d\n", tk_SourceName, tk_Line,
+ tk_IntNumber );
+ }
+ tList[i].verts[2 - j][0] = vList[tk_IntNumber].v[0];
+ tList[i].verts[2 - j][1] = vList[tk_IntNumber].v[1];
+ tList[i].verts[2 - j][2] = vList[tk_IntNumber].v[2];
+#ifdef _QDATA
+ tList[i].indicies[2 - j] = tk_IntNumber;
+#endif
+ }
+
+/* printf("Face %i:\n v0: %f, %f, %f\n v1: %f, %f, %f\n"
+ " v2: %f, %f, %f\n", i,
+ tList[i].verts[0][0],
+ tList[i].verts[0][1],
+ tList[i].verts[0][2],
+ tList[i].verts[1][0],
+ tList[i].verts[1][1],
+ tList[i].verts[1][2],
+ tList[i].verts[2][0],
+ tList[i].verts[2][1],
+ tList[i].verts[2][2]);
+ */
+ }
+
+ DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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<height ; i++)
+ {
+ for (j=0 ; j<width ; j++)
+ {
+ if ( (*data & 0xc0) != 0xc0)
+ *pack++ = *data++;
+ else
+ {
+ *pack++ = 0xc1;
+ *pack++ = *data++;
+ }
+ }
+ }
+ */
+ for ( i = 0 ; i < height ; i++ )
+ {
+ curByte = *data;
+ curRepCount = 0;
+ for ( j = 0 ; j < width ; j++ )
+ {
+ if ( *data == curByte ) {
+ curRepCount++;
+ data++;
+ continue;
+ }
+ StuffPackedByte( curRepCount, curByte, &pack );
+ curByte = *data++;
+ curRepCount = 1;
+ }
+ StuffPackedByte( curRepCount, curByte, &pack );
+ }
+ // write the palette
+ *pack++ = 0x0c; // palette ID byte
+ for ( i = 0 ; i < 768 ; i++ )
+ *pack++ = *palette++;
+
+// write output file
+ length = pack - (byte *)pcx;
+ SaveFile( filename, pcx, length );
+
+ free( pcx );
+}
+
+
+/*
+ ============================================================================
+
+ LOAD IMAGE
+
+ ============================================================================
+ */
+
+/*
+ ==============
+ Load256Image
+
+ Will load either an lbm or pcx, depending on extension.
+ Any of the return pointers can be NULL if you don't want them.
+ ==============
+ */
+void Load256Image( char *name, byte **pixels, byte **palette,
+ int *width, int *height ){
+ char ext[128];
+
+ ExtractFileExtension( name, ext );
+ if ( !Q_strcasecmp( ext, "lbm" ) ) {
+ LoadLBM( name, pixels, palette );
+ if ( width ) {
+ *width = bmhd.w;
+ }
+ if ( height ) {
+ *height = bmhd.h;
+ }
+ }
+ else if ( !Q_strcasecmp( ext, "pcx" ) ) {
+ LoadPCX( name, pixels, palette, width, height );
+ }
+ else{
+ Error( "%s doesn't have a known image extension", name );
+ }
+}
+
+
+/*
+ ==============
+ Save256Image
+
+ Will save either an lbm or pcx, depending on extension.
+ ==============
+ */
+void Save256Image( char *name, byte *pixels, byte *palette,
+ int width, int height ){
+ char ext[128];
+
+ ExtractFileExtension( name, ext );
+ if ( !Q_strcasecmp( ext, "lbm" ) ) {
+ WriteLBMfile( name, pixels, width, height, palette );
+ }
+ else if ( !Q_strcasecmp( ext, "pcx" ) ) {
+ WritePCXfile( name, pixels, width, height, palette );
+ }
+ else{
+ Error( "%s doesn't have a known image extension", name );
+ }
+}
+
+
+
+
+/*
+ ============================================================================
+
+ TARGA IMAGE
+
+ ============================================================================
+ */
+
+typedef struct _TargaHeader
+{
+ unsigned char id_length, colormap_type, image_type;
+ unsigned short colormap_index, colormap_length;
+ unsigned char colormap_size;
+ unsigned short x_origin, y_origin, width, height;
+ unsigned char pixel_size, attributes;
+} TargaHeader;
+
+int fgetLittleShort( FILE *f ){
+ byte b1, b2;
+
+ b1 = fgetc( f );
+ b2 = fgetc( f );
+
+ return( (short)( b1 + ( b2 << 8 ) ) );
+}
+
+int fgetLittleLong( FILE *f ){
+ byte b1, b2, b3, b4;
+
+ b1 = fgetc( f );
+ b2 = fgetc( f );
+ b3 = fgetc( f );
+ b4 = fgetc( f );
+
+ return( b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 ) );
+}
+
+
+/*
+ =============
+ LoadTGA
+ =============
+ */
+void LoadTGA( char *name, byte **pixels, int *width, int *height ){
+ int columns, rows, numPixels;
+ byte *pixbuf;
+ byte *rowBuf;
+ int row, column;
+ FILE *fin;
+ byte *targa_rgba;
+ TargaHeader targa_header;
+ unsigned char red, green, blue, alphabyte;
+ unsigned char packetHeader, packetSize, j;
+ int flip;
+ int mirror;
+ int rowOffset;
+ int pixDirection;
+
+ fin = fopen( name, "rb" );
+ if ( !fin ) {
+ Error( "Couldn't read %s", name );
+ }
+
+ targa_header.id_length = fgetc( fin );
+ targa_header.colormap_type = fgetc( fin );
+ targa_header.image_type = fgetc( fin );
+
+ targa_header.colormap_index = fgetLittleShort( fin );
+ targa_header.colormap_length = fgetLittleShort( fin );
+ targa_header.colormap_size = fgetc( fin );
+ targa_header.x_origin = fgetLittleShort( fin );
+ targa_header.y_origin = fgetLittleShort( fin );
+ targa_header.width = fgetLittleShort( fin );
+ targa_header.height = fgetLittleShort( fin );
+ targa_header.pixel_size = fgetc( fin );
+ targa_header.attributes = fgetc( fin );
+ flip = ( targa_header.attributes & 0x020 ) == 0;
+ mirror = ( targa_header.attributes & 0x010 ) != 0;
+
+ if ( ( targa_header.image_type != 2 ) && ( targa_header.image_type != 10 ) ) {
+ Error( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
+ }
+
+ if ( targa_header.colormap_type || ( ( targa_header.pixel_size != 32 ) && ( targa_header.pixel_size != 24 ) ) ) {
+ Error( "Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
+ }
+
+ columns = targa_header.width;
+ rows = targa_header.height;
+ numPixels = columns * rows;
+
+ if ( width ) {
+ *width = columns;
+ }
+ if ( height ) {
+ *height = rows;
+ }
+
+ if ( !pixels ) {
+ return;
+ }
+
+ targa_rgba = malloc( numPixels * 4 );
+ *pixels = targa_rgba;
+
+ if ( flip ) {
+ pixbuf = targa_rgba + ( ( rows - 1 ) * columns * 4 );
+ rowOffset = -columns * 4;
+ }
+ else
+ {
+ pixbuf = targa_rgba;
+ rowOffset = columns * 4;
+ }
+ if ( mirror ) {
+ pixDirection = -4;
+ pixbuf += ( ( columns - 1 ) * 4 );
+ }
+ else
+ {
+ pixDirection = 4;
+ }
+
+ if ( targa_header.id_length ) {
+ fseek( fin, targa_header.id_length, SEEK_CUR ); // skip TARGA image comment
+
+ }
+ if ( targa_header.image_type == 2 ) { // Uncompressed, RGB images
+ for ( row = 0; row < rows; row++ )
+ {
+ rowBuf = pixbuf;
+ for ( column = 0; column < columns; column++ )
+ {
+ 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;
+ }
+ }
+ pixbuf += rowOffset;
+ }
+ }
+ else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images
+ for ( row = 0; row < rows; row++ )
+ {
+ rowBuf = pixbuf;
+ for ( column = 0; column < columns; )
+ {
+ packetHeader = getc( fin );
+ packetSize = 1 + ( packetHeader & 0x7f );
+ if ( packetHeader & 0x80 ) { // run-length packet
+ switch ( targa_header.pixel_size )
+ {
+ case 24:
+ blue = getc( fin );
+ green = getc( fin );
+ red = getc( fin );
+ alphabyte = 255;
+ break;
+ case 32:
+ blue = getc( fin );
+ green = getc( fin );
+ red = getc( fin );
+ alphabyte = getc( fin );
+ break;
+ }
+
+ for ( j = 0; j < packetSize; j++ )
+ {
+ rowBuf[0] = red;
+ rowBuf[1] = green;
+ rowBuf[2] = blue;
+ rowBuf[3] = alphabyte;
+ rowBuf += pixDirection;
+ column++;
+ if ( column == columns ) { // run spans across rows
+ column = 0;
+ row++;
+ if ( row >= 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;
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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;
+ }
+ }
+}
--- /dev/null
+/*
+ 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 <math.h>
+/*
+ #ifdef DOUBLEVEC_T
+ typedef double vec_t;
+ #else
+ typedef float vec_t;
+ #endif
+ typedef vec_t vec3_t[3];
+ */
+#define SIDE_FRONT 0
+#define SIDE_ON 2
+#define SIDE_BACK 1
+#define SIDE_CROSS -2
+
+#define Q_PI 3.14159265358979323846
+
+extern vec3_t vec3_origin;
+
+#define EQUAL_EPSILON 0.001
+
+qboolean VectorCompare( vec3_t v1, vec3_t v2 );
+
+#define DotProduct( x,y ) ( x[0] * y[0] + x[1] * y[1] + x[2] * y[2] )
+#define VectorSubtract( a,b,c ) {c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; }
+#define VectorAdd( a,b,c ) {c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; }
+#define VectorCopy( a,b ) {b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
+#define VectorScale( a,b,c ) {c[0] = b * a[0]; c[1] = b * a[1]; c[2] = b * a[2]; }
+#define VectorClear( x ) {x[0] = x[1] = x[2] = 0; }
+#define VectorNegate( x ) {x[0] = -x[0]; x[1] = -x[1]; x[2] = -x[2]; }
+
+vec_t Q_rint( vec_t in );
+vec_t _DotProduct( vec3_t v1, vec3_t v2 );
+void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out );
+void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out );
+void _VectorCopy( vec3_t in, vec3_t out );
+void _VectorScale( vec3_t v, vec_t scale, vec3_t out );
+
+double VectorLength( vec3_t v );
+
+void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc );
+
+void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross );
+vec_t VectorNormalize( vec3_t in, vec3_t out );
+vec_t ColorNormalize( vec3_t in, vec3_t out );
+void VectorInverse( vec3_t v );
+
+void ClearBounds( vec3_t mins, vec3_t maxs );
+void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs );
+
+#endif
--- /dev/null
+/*
+ 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 <string.h> /* 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 <d2deek@pmail.net>
+//
+// Author: Jeff Teunissen <d2deek@pmail.net>
+// 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 );
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/* -------------------------------------------------------------------------------
+
+ 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 <unistd.h>
+ #include <pwd.h>
+ #include <limits.h>
+#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" );
+}
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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 <windows.h>
+
+materialtype_t defaultmaterialtypes[] =
+{
+ {"gravel", MATERIAL_GRAVEL},
+ {"metal", MATERIAL_METAL},
+ {"stone", MATERIAL_STONE},
+ {"wood", MATERIAL_WOOD},
+ {NULL, 0}
+};
+
+materialtype_t *materialtypes;
+
+void QFile_ReadMaterialTypes( char* filename ){
+ int i;
+ FILE *f;
+
+ f = fopen( filename, "rb" );
+ if ( !f ) {
+ materialtypes = defaultmaterialtypes;
+ return;
+ }
+ fclose( f );
+
+ free( materialtypes );
+ materialtypes = (materialtype_t*)malloc( 256 * sizeof( materialtype_t ) );
+
+ LoadScriptFile( filename );
+ i = 0;
+
+ while ( i < 255 )
+ {
+ GetScriptToken( true );
+ if ( endofscript ) {
+ break;
+ }
+ if ( strcmp( token, "material" ) != 0 ) {
+ while ( ScriptTokenAvailable() )
+ {
+ GetScriptToken( false );
+ }
+ }
+ else
+ {
+ GetScriptToken( false );
+ materialtypes[i].name = (char*)malloc( strlen( token ) + 1 );
+ strcpy( materialtypes[i].name, token );
+ GetScriptToken( false );
+ materialtypes[i].value = atoi( token );
+ }
+ i++;
+ }
+ materialtypes[i].name = NULL;
+ materialtypes[i].value = 0;
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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 <windows.h>
+
+// Setting default Threads to 1
+int numthreads = 1;
+CRITICAL_SECTION crit;
+static int enter;
+
+void ThreadSetDefault( void ){
+ SYSTEM_INFO info;
+
+ if ( numthreads == -1 ) { // not set manually
+ GetSystemInfo( &info );
+ numthreads = info.dwNumberOfProcessors;
+ if ( numthreads < 1 || numthreads > 32 ) {
+ numthreads = 1;
+ }
+ }
+
+ Sys_Printf( "%i threads\n", numthreads );
+}
+
+
+void ThreadLock( void ){
+ if ( !threaded ) {
+ return;
+ }
+ EnterCriticalSection( &crit );
+ if ( enter ) {
+ Error( "Recursive ThreadLock\n" );
+ }
+ enter = 1;
+}
+
+void ThreadUnlock( void ){
+ if ( !threaded ) {
+ return;
+ }
+ if ( !enter ) {
+ Error( "ThreadUnlock without lock\n" );
+ }
+ enter = 0;
+ LeaveCriticalSection( &crit );
+}
+
+/*
+ =============
+ RunThreadsOn
+ =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+ int threadid[MAX_THREADS];
+ HANDLE threadhandle[MAX_THREADS];
+ int i;
+ int start, end;
+
+ start = I_FloatTime();
+ dispatch = 0;
+ workcount = workcnt;
+ oldf = -1;
+ pacifier = showpacifier;
+ threaded = true;
+
+ //
+ // run threads in parallel
+ //
+ InitializeCriticalSection( &crit );
+
+ if ( numthreads == 1 ) { // use same thread
+ func( 0 );
+ }
+ else
+ {
+ for ( i = 0 ; i < numthreads ; i++ )
+ {
+ threadhandle[i] = CreateThread(
+ NULL, // LPSECURITY_ATTRIBUTES lpsa,
+ //0, // DWORD cbStack,
+
+ /* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
+ ( 4096 * 1024 ),
+
+ (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
+ (LPVOID)i, // LPVOID lpvThreadParm,
+ 0, // DWORD fdwCreate,
+ &threadid[i] );
+ }
+
+ for ( i = 0 ; i < numthreads ; i++ )
+ WaitForSingleObject( threadhandle[i], INFINITE );
+ }
+ DeleteCriticalSection( &crit );
+
+ threaded = false;
+ end = I_FloatTime();
+ if ( pacifier ) {
+ Sys_Printf( " (%i)\n", end - start );
+ }
+}
+
+
+#elif GDEF_OS_OSF1
+
+/*
+ ===================================================================
+
+ OSF1
+
+ ===================================================================
+ */
+
+int numthreads = 4;
+
+void ThreadSetDefault( void ){
+ if ( numthreads == -1 ) { // not set manually
+ numthreads = 4;
+ }
+}
+
+
+#include <pthread.h>
+
+pthread_mutex_t *my_mutex;
+
+void ThreadLock( void ){
+ if ( my_mutex ) {
+ pthread_mutex_lock( my_mutex );
+ }
+}
+
+void ThreadUnlock( void ){
+ if ( my_mutex ) {
+ pthread_mutex_unlock( my_mutex );
+ }
+}
+
+
+/*
+ =============
+ RunThreadsOn
+ =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+ int i;
+ pthread_t work_threads[MAX_THREADS];
+ pthread_addr_t status;
+ pthread_attr_t attrib;
+ pthread_mutexattr_t mattrib;
+ int start, end;
+
+ start = I_FloatTime();
+ dispatch = 0;
+ workcount = workcnt;
+ oldf = -1;
+ pacifier = showpacifier;
+ threaded = true;
+
+ if ( pacifier ) {
+ setbuf( stdout, NULL );
+ }
+
+ if ( !my_mutex ) {
+ my_mutex = safe_malloc( sizeof( *my_mutex ) );
+ if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
+ Error( "pthread_mutex_attr_create failed" );
+ }
+ if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
+ Error( "pthread_mutexattr_setkind_np failed" );
+ }
+ if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
+ Error( "pthread_mutex_init failed" );
+ }
+ }
+
+ if ( pthread_attr_create( &attrib ) == -1 ) {
+ Error( "pthread_attr_create failed" );
+ }
+ if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
+ Error( "pthread_attr_setstacksize failed" );
+ }
+
+ for ( i = 0 ; i < numthreads ; i++ )
+ {
+ if ( pthread_create( &work_threads[i], attrib
+ , (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) {
+ Error( "pthread_create failed" );
+ }
+ }
+
+ for ( i = 0 ; i < numthreads ; i++ )
+ {
+ if ( pthread_join( work_threads[i], &status ) == -1 ) {
+ Error( "pthread_join failed" );
+ }
+ }
+
+ threaded = false;
+
+ end = I_FloatTime();
+ if ( pacifier ) {
+ Sys_Printf( " (%i)\n", end - start );
+ }
+}
+
+
+#elif GDEF_OS_IRIX
+
+/*
+ ===================================================================
+
+ IRIX
+
+ ===================================================================
+ */
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+int numthreads = -1;
+abilock_t lck;
+
+void ThreadSetDefault( void ){
+ if ( numthreads == -1 ) {
+ numthreads = prctl( PR_MAXPPROCS );
+ }
+ Sys_Printf( "%i threads\n", numthreads );
+ usconfig( CONF_INITUSERS, numthreads );
+}
+
+
+void ThreadLock( void ){
+ spin_lock( &lck );
+}
+
+void ThreadUnlock( void ){
+ release_lock( &lck );
+}
+
+
+/*
+ =============
+ RunThreadsOn
+ =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+ int i;
+ int pid[MAX_THREADS];
+ int start, end;
+
+ start = I_FloatTime();
+ dispatch = 0;
+ workcount = workcnt;
+ oldf = -1;
+ pacifier = showpacifier;
+ threaded = true;
+
+ if ( pacifier ) {
+ setbuf( stdout, NULL );
+ }
+
+ init_lock( &lck );
+
+ for ( i = 0 ; i < numthreads - 1 ; i++ )
+ {
+ pid[i] = sprocsp( ( void ( * )( void *, size_t ) )func, PR_SALL, (void *)i
+ , NULL, 0x200000 ); // 2 meg stacks
+ if ( pid[i] == -1 ) {
+ perror( "sproc" );
+ Error( "sproc failed" );
+ }
+ }
+
+ func( i );
+
+ for ( i = 0 ; i < numthreads - 1 ; i++ )
+ wait( NULL );
+
+ threaded = false;
+
+ end = I_FloatTime();
+ if ( pacifier ) {
+ Sys_Printf( " (%i)\n", end - start );
+ }
+}
+
+
+#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 <pthread.h>
+
+typedef struct pt_mutex_s
+{
+ pthread_t *owner;
+ pthread_mutex_t a_mutex;
+ pthread_cond_t cond;
+ unsigned int lock;
+} pt_mutex_t;
+
+pt_mutex_t global_lock;
+
+void ThreadLock( void ){
+ pt_mutex_t *pt_mutex = &global_lock;
+
+ if ( !threaded ) {
+ return;
+ }
+
+ pthread_mutex_lock( &pt_mutex->a_mutex );
+ if ( pthread_equal( pthread_self(), (pthread_t)&pt_mutex->owner ) ) {
+ pt_mutex->lock++;
+ }
+ else
+ {
+ if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
+ pt_mutex->owner = (pthread_t *)pthread_self();
+ pt_mutex->lock = 1;
+ }
+ else
+ {
+ while ( 1 )
+ {
+ pthread_cond_wait( &pt_mutex->cond, &pt_mutex->a_mutex );
+ if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
+ pt_mutex->owner = (pthread_t *)pthread_self();
+ pt_mutex->lock = 1;
+ break;
+ }
+ }
+ }
+ }
+ pthread_mutex_unlock( &pt_mutex->a_mutex );
+}
+
+void ThreadUnlock( void ){
+ pt_mutex_t *pt_mutex = &global_lock;
+
+ if ( !threaded ) {
+ return;
+ }
+
+ pthread_mutex_lock( &pt_mutex->a_mutex );
+ pt_mutex->lock--;
+
+ if ( pt_mutex->lock == 0 ) {
+ pt_mutex->owner = NULL;
+ pthread_cond_signal( &pt_mutex->cond );
+ }
+
+ pthread_mutex_unlock( &pt_mutex->a_mutex );
+}
+
+void recursive_mutex_init( pthread_mutexattr_t attribs ){
+ pt_mutex_t *pt_mutex = &global_lock;
+
+ pt_mutex->owner = NULL;
+ if ( pthread_mutex_init( &pt_mutex->a_mutex, &attribs ) != 0 ) {
+ Error( "pthread_mutex_init failed\n" );
+ }
+ if ( pthread_cond_init( &pt_mutex->cond, NULL ) != 0 ) {
+ Error( "pthread_cond_init failed\n" );
+ }
+
+ pt_mutex->lock = 0;
+}
+
+/*
+ =============
+ RunThreadsOn
+ =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+ pthread_mutexattr_t mattrib;
+ pthread_t work_threads[MAX_THREADS];
+
+ int start, end;
+ int i = 0, status = 0;
+
+ start = I_FloatTime();
+ pacifier = showpacifier;
+
+ dispatch = 0;
+ oldf = -1;
+ workcount = workcnt;
+
+ if ( numthreads == 1 ) {
+ func( 0 );
+ }
+ else
+ {
+ threaded = true;
+
+ if ( pacifier ) {
+ setbuf( stdout, NULL );
+ }
+
+ if ( pthread_mutexattr_init( &mattrib ) != 0 ) {
+ Error( "pthread_mutexattr_init failed" );
+ }
+ if ( 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
--- /dev/null
+/*
+ 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[] =
+{
+ "<nothing>",
+ "<unknown_char>",
+ "<EOF>",
+ "<identifier>",
+ "<string>",
+ "<int_number>",
+ "<float_number>",
+ "(",
+ ")",
+ "{",
+ "}",
+ "[",
+ "]",
+ ":",
+ "mesh",
+ "model",
+ "nodes",
+ "rotation",
+ "scaling",
+ "translation",
+ "polygons",
+ "position",
+ "vertex",
+ "vertices",
+ "HRCH",
+ "Softimage"
+};
+
+// CODE --------------------------------------------------------------------
+
+//==========================================================================
+//
+// TK_Init
+//
+//==========================================================================
+
+void TK_Init( void ){
+ int i;
+
+ for ( i = 0; i < 256; i++ )
+ {
+ ASCIIToChrCode[i] = CHR_SPECIAL;
+ }
+ for ( i = '0'; i <= '9'; i++ )
+ {
+ ASCIIToChrCode[i] = CHR_NUMBER;
+ }
+ for ( i = 'A'; i <= 'Z'; i++ )
+ {
+ ASCIIToChrCode[i] = CHR_LETTER;
+ }
+ for ( i = 'a'; i <= 'z'; i++ )
+ {
+ ASCIIToChrCode[i] = CHR_LETTER;
+ }
+ ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
+ ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
+ ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
+ tk_String = TokenStringBuffer;
+ IncLineNumber = FALSE;
+ SourceOpen = FALSE;
+}
+
+//==========================================================================
+//
+// TK_OpenSource
+//
+//==========================================================================
+
+void TK_OpenSource( char *fileName ){
+ int size;
+
+ TK_CloseSource();
+ size = LoadFile( fileName, (void **)&FileStart );
+ strcpy( tk_SourceName, fileName );
+ SourceOpen = TRUE;
+ FileEnd = FileStart + size;
+ FilePtr = FileStart;
+ tk_Line = 1;
+ tk_Token = TK_NONE;
+ NextChr();
+}
+
+//==========================================================================
+//
+// TK_CloseSource
+//
+//==========================================================================
+
+void TK_CloseSource( void ){
+ if ( SourceOpen ) {
+ free( FileStart );
+ SourceOpen = FALSE;
+ }
+}
+
+//==========================================================================
+//
+// TK_Fetch
+//
+//==========================================================================
+
+tokenType_t TK_Fetch( void ){
+ while ( Chr == ASCII_SPACE )
+ {
+ NextChr();
+ }
+ if ( Chr == '-' ) {
+ ProcessNumberToken();
+ }
+ else{switch ( ASCIIToChrCode[(byte)Chr] )
+ {
+ case CHR_EOF:
+ tk_Token = TK_EOF;
+ break;
+ case CHR_LETTER:
+ ProcessLetterToken();
+ break;
+ case CHR_NUMBER:
+ ProcessNumberToken();
+ break;
+ case CHR_QUOTE:
+ ProcessQuoteToken();
+ break;
+ default:
+ ProcessSpecialToken();
+ break;
+ }}
+ return tk_Token;
+}
+
+//==========================================================================
+//
+// TK_Require
+//
+//==========================================================================
+
+void TK_Require( tokenType_t tokType ){
+ if ( tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER ) {
+ tk_FloatNumber = (float)tk_IntNumber;
+ tk_Token = TK_FLOATNUMBER;
+ return;
+ }
+ if ( tk_Token != tokType ) {
+ Error( "File '%s', line %d:\nExpected '%s', found '%s'.\n",
+ tk_SourceName, tk_Line, TokenNames[tokType],
+ TokenNames[tk_Token] );
+ }
+}
+
+void TK_FetchRequire( tokenType_t tokType ){
+ TK_Fetch();
+ TK_Require( tokType );
+}
+
+tokenType_t TK_RequireFetch( tokenType_t tokType ){
+ TK_Require( tokType );
+ return TK_Fetch();
+}
+
+tokenType_t TK_FetchRequireFetch( tokenType_t tokType ){
+ TK_Fetch();
+ TK_Require( tokType );
+ return TK_Fetch();
+}
+
+tokenType_t TK_Beyond( tokenType_t tokType ){
+ while ( tk_Token != tokType )
+ {
+ if ( TK_Fetch() == TK_EOF ) {
+ Error( "File '%s':\nCould not find token '%s'.\n", // FIXME: TokenNames table not big enuff
+ tk_SourceName, TokenNames[tokType] );
+ }
+ }
+ return TK_Fetch();
+}
+
+void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok ){
+ TK_Beyond( bTok );
+ TK_Require( rTok );
+}
+
+tokenType_t TK_Search( tokenType_t tokType ){
+ while ( tk_Token != tokType )
+ {
+ if ( TK_Fetch() == TK_EOF ) {
+ return TK_EOF;
+ }
+ }
+ return TK_Fetch();
+}
+
+tokenType_t TK_Get( tokenType_t tokType ){
+ while ( tk_Token != tokType )
+ {
+ if ( TK_Fetch() == TK_EOF ) {
+ Error( "File '%s':\nCould not find token '%s'.\n",
+ tk_SourceName, TokenNames[tokType] );
+ }
+ }
+ return tk_Token;
+}
+
+//==========================================================================
+//
+// ProcessLetterToken
+//
+//==========================================================================
+
+static void ProcessLetterToken( void ){
+ int i;
+ char *text;
+
+ i = 0;
+ text = TokenStringBuffer;
+ while ( ASCIIToChrCode[(byte)Chr] == CHR_LETTER
+ || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+ {
+ if ( ++i == MAX_IDENTIFIER_LENGTH ) {
+ Error( "File '%s', line %d:\nIdentifier too long.\n",
+ tk_SourceName, tk_Line );
+ }
+ *text++ = Chr;
+ NextChr();
+ }
+ *text = 0;
+ if ( CheckForKeyword() == FALSE ) {
+ tk_Token = TK_IDENTIFIER;
+ }
+}
+
+//==========================================================================
+//
+// CheckForKeyword
+//
+//==========================================================================
+
+static qboolean CheckForKeyword( void ){
+ int i;
+
+ for ( i = 0; Keywords[i].name != NULL; i++ )
+ {
+ if ( strcmp( tk_String, Keywords[i].name ) == 0 ) {
+ tk_Token = Keywords[i].token;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//==========================================================================
+//
+// ProcessNumberToken
+//
+//==========================================================================
+
+static void ProcessNumberToken( void ){
+ char *buffer;
+
+ buffer = TempBuffer;
+ *buffer++ = Chr;
+ NextChr();
+ while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+ {
+ *buffer++ = Chr;
+ NextChr();
+ }
+ if ( Chr == '.' ) { // Float
+ *buffer++ = Chr;
+ NextChr(); // Skip period
+ while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+ {
+ *buffer++ = Chr;
+ NextChr();
+ }
+ *buffer = 0;
+ tk_FloatNumber = (float)atof( TempBuffer );
+ tk_Token = TK_FLOATNUMBER;
+ return;
+ }
+
+ // Integer
+ *buffer = 0;
+ tk_IntNumber = atoi( TempBuffer );
+ tk_Token = TK_INTNUMBER;
+}
+
+//==========================================================================
+//
+// ProcessQuoteToken
+//
+//==========================================================================
+
+static void ProcessQuoteToken( void ){
+ int i;
+ char *text;
+
+ i = 0;
+ text = TokenStringBuffer;
+ NextChr();
+ while ( Chr != ASCII_QUOTE )
+ {
+ if ( Chr == EOF_CHARACTER ) {
+ Error( "File '%s', line %d:\n<EOF> inside string.\n",
+ tk_SourceName, tk_Line );
+ }
+ if ( ++i > MAX_QUOTED_LENGTH - 1 ) {
+ Error( "File '%s', line %d:\nString literal too long.\n",
+ tk_SourceName, tk_Line );
+ }
+ *text++ = Chr;
+ NextChr();
+ }
+ *text = 0;
+ NextChr();
+ tk_Token = TK_STRING;
+}
+
+//==========================================================================
+//
+// ProcessSpecialToken
+//
+//==========================================================================
+
+static void ProcessSpecialToken( void ){
+ char c;
+
+ c = Chr;
+ NextChr();
+ switch ( c )
+ {
+ case '(':
+ tk_Token = TK_LPAREN;
+ break;
+ case ')':
+ tk_Token = TK_RPAREN;
+ break;
+ case '{':
+ tk_Token = TK_LBRACE;
+ break;
+ case '}':
+ tk_Token = TK_RBRACE;
+ break;
+ case '[':
+ tk_Token = TK_LBRACKET;
+ break;
+ case ']':
+ tk_Token = TK_RBRACKET;
+ break;
+ case ':':
+ tk_Token = TK_COLON;
+ break;
+ default:
+ tk_Token = TK_UNKNOWNCHAR;
+ break;
+ }
+}
+
+//==========================================================================
+//
+// NextChr
+//
+//==========================================================================
+
+static void NextChr( void ){
+ if ( FilePtr >= FileEnd ) {
+ Chr = EOF_CHARACTER;
+ return;
+ }
+ if ( IncLineNumber == TRUE ) {
+ tk_Line++;
+ IncLineNumber = FALSE;
+ }
+ Chr = *FilePtr++;
+ if ( Chr < ASCII_SPACE ) {
+ if ( Chr == '\n' ) {
+ IncLineNumber = TRUE;
+ }
+ Chr = ASCII_SPACE;
+ }
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <stdio.h>
+#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 );
+ }
+
+ }
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+#include "animcomp.h"
+
+
+void *SafeMalloc( size_t n, char *desc );
+
+
+
+float *matrix;
+float *delta;
+float *best;
+float *comp;
+float *tcomp;
+float *bestcomp;
+float *frames;
+float *base;
+
+int MatWidth;
+int MatHeight;
+int CFrameSize;
+int nFrames;
+
+
+void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
+ nFrames = nframes;
+ MatWidth = nVerts * 3;
+ MatHeight = CompressedFrameSize;
+ CFrameSize = CompressedFrameSize;
+ matrix = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+ best = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+ delta = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+ comp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+ tcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+ bestcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+ base = (float *)SafeMalloc( MatWidth * sizeof( float ), "AnimCompressInit" );
+ frames = (float *)SafeMalloc( MatWidth * nFrames * sizeof( float ), "AnimCompressInit" );
+}
+
+void AnimSetFrame( int frame,int index,float x,float y,float z ){
+ frames[frame * MatWidth + index * 3] = x;
+ frames[frame * MatWidth + index * 3 + 1] = y;
+ frames[frame * MatWidth + index * 3 + 2] = z;
+}
+
+typedef struct
+{
+ int index;
+ float val;
+} SORTP;
+
+
+#define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
+
+extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
+
+void AnimCompressDoit(){
+ float compression;
+ float *rescale;
+ float *ans;
+ float maxdev;
+ float avedev;
+ float tmp;
+ int j,k,l,numave;
+
+ for ( k = 0; k < MatWidth; k++ )
+ base[k] = 0.0f;
+ for ( j = 0; j < nFrames; j++ )
+ for ( k = 0; k < MatWidth; k++ )
+ base[k] += frames[j * MatWidth + k];
+ tmp = 1.0f / (float)nFrames;
+ for ( k = 0; k < MatWidth; k++ )
+ base[k] *= tmp;
+ for ( j = 0; j < nFrames; j++ )
+ for ( k = 0; k < MatWidth; k++ )
+ frames[j * MatWidth + k] -= base[k];
+
+ ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressDoit" );
+ rescale = (float *)SafeMalloc( sizeof( float ) * CFrameSize, "AnimCompressDoit" );
+ DOsvd( frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight );
+ avedev = 0.0;
+ for ( l = 0; l < CFrameSize; l++ )
+ avedev += rescale[l];
+ for ( l = 0; l < CFrameSize; l++ )
+ printf( "%3.1f ",100.0f * rescale[l] / avedev );
+ printf( "\n" );
+ for ( j = 0; j < nFrames; j++ )
+ {
+ for ( l = 0; l < CFrameSize; l++ )
+ {
+ bestcomp[j * CFrameSize + l] = 0.0;
+ for ( k = 0; k < MatWidth; k++ )
+ bestcomp[j * CFrameSize + l] += best[l * MatWidth + k] * frames[j * MatWidth + k];
+ }
+ }
+ numave = 0;
+ avedev = 0.0;
+ maxdev = 0.0;
+ for ( j = 0; j < nFrames; j++ )
+ {
+ for ( k = 0; k < MatWidth; k++ )
+ {
+ ans[k] = 0.0;
+ for ( l = 0; l < CFrameSize; l++ )
+ ans[k] += best[l * MatWidth + k] * bestcomp[j * CFrameSize + l];
+ ans[k] -= frames[j * MatWidth + k];
+ tmp = (float)fabs( ans[k] );
+ if ( tmp > maxdev ) {
+ maxdev = tmp;
+ }
+ avedev += tmp;
+ numave++;
+ }
+ }
+ avedev /= (float)numave;
+ printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
+ printf( "%d bytes original size\n",MatWidth * nFrames );
+ printf( "%d bytes of overhead\n",MatWidth * MatHeight );
+ printf( "%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize * nFrames );
+ compression = (float)( MatWidth * MatHeight + CFrameSize * nFrames + MatWidth );
+ compression /= (float)( MatWidth * nFrames );
+ printf( "Overall compression = %f %%\n",100.0f - 100.0f * compression );
+ compression = (float)( CFrameSize );
+ compression /= (float)( MatWidth );
+ printf( "frame size compression = %f %%\n",100.0f - 100.0f * compression );
+ free( rescale );
+ free( ans );
+}
+
+void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
+ int k,l,nv,j;
+ float maxdev;
+ float avedev;
+ float tmp;
+ int numave;
+ float t,mx;
+ float *ans;
+
+
+ nv = MatWidth / 3;
+
+ trans[0] = 1E30f;
+ scale[0] = -1E30f;
+ trans[1] = 1E30f;
+ scale[1] = -1E30f;
+ trans[2] = 1E30f;
+ scale[2] = -1E30f;
+ for ( k = 0; k < MatWidth; k += 3 )
+ {
+ if ( base[k] > scale[0] ) {
+ scale[0] = base[k];
+ }
+ if ( base[k] < trans[0] ) {
+ trans[0] = base[k];
+ }
+
+ if ( base[k + 1] > scale[1] ) {
+ scale[1] = base[k + 1];
+ }
+ if ( base[k + 1] < trans[1] ) {
+ trans[1] = base[k + 1];
+ }
+
+ if ( base[k + 2] > scale[2] ) {
+ scale[2] = base[k + 2];
+ }
+ if ( base[k + 2] < trans[2] ) {
+ trans[2] = base[k + 2];
+ }
+ }
+
+ scale[0] -= trans[0];
+ scale[1] -= trans[1];
+ scale[2] -= trans[2];
+ scale[0] /= 255.0f;
+ scale[1] /= 255.0f;
+ scale[2] /= 255.0f;
+ for ( k = 0; k < MatWidth; k += 3 )
+ {
+ t = ( base[k] - trans[0] ) / scale[0];
+ if ( t < 0.0f ) {
+ t = 0.0f;
+ }
+ if ( t > 255.0f ) {
+ t = 255.0f;
+ }
+ cbase[k] = (unsigned char)t;
+
+ t = ( base[k + 1] - trans[1] ) / scale[1];
+ if ( t < 0.0f ) {
+ t = 0.0f;
+ }
+ if ( t > 255.0f ) {
+ t = 255.0f;
+ }
+ cbase[k + 1] = (unsigned char)t;
+
+ t = ( base[k + 2] - trans[2] ) / scale[2];
+ if ( t < 0.0f ) {
+ t = 0.0f;
+ }
+ if ( t > 255.0f ) {
+ t = 255.0f;
+ }
+ cbase[k + 2] = (unsigned char)t;
+ }
+ for ( l = 0; l < MatHeight; l++ )
+ {
+ mx = 0.0;
+ for ( k = 0; k < MatWidth; k++ )
+ {
+ if ( fabs( best[l * MatWidth + k] ) > mx ) {
+ mx = (float)fabs( best[l * MatWidth + k] );
+ }
+ }
+ if ( mx > 1E-8 ) {
+ mx /= 127.0f;
+ coffset[l] = 1E30f;
+ cscale[l] = -1E30f;
+ for ( j = 0; j < nFrames; j++ )
+ {
+ bestcomp[j * MatHeight + l] *= mx;
+ if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
+ cscale[l] = bestcomp[j * MatHeight + l];
+ }
+ if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
+ coffset[l] = bestcomp[j * MatHeight + l];
+ }
+ }
+ cscale[l] -= coffset[l];
+ if ( cscale[l] > 1E-10 ) {
+ for ( j = 0; j < nFrames; j++ )
+ {
+ tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
+ if ( tmp > 127.0f ) {
+ tmp = 127.0f;
+ }
+ if ( tmp < -127.0f ) {
+ tmp = -127.0f;
+ }
+ ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
+ }
+ coffset[l] += cscale[l] * 127.0f / 254.0f;
+ cscale[l] /= 254.0f;
+ }
+ else
+ {
+ cscale[l] = 1.0f;
+ coffset[l] = 0.0f;
+ for ( j = 0; j < nFrames; j++ )
+ ccomp[j * MatHeight + l] = 0;
+ }
+ mx = 1.0f / mx;
+ for ( k = 0; k < MatWidth; k++ )
+ {
+ tmp = best[l * MatWidth + k] * mx;
+ if ( tmp > 127.0f ) {
+ tmp = 127.0f;
+ }
+ if ( tmp < -127.0f ) {
+ tmp = -127.0f;
+ }
+ mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
+ }
+ }
+ else
+ {
+ cscale[l] = 1.0f;
+ coffset[l] = 0.0f;
+ for ( j = 0; j < nFrames; j++ )
+ ccomp[j * MatHeight + l] = 0;
+ for ( k = 0; k < MatWidth; k++ )
+ mat[k * MatHeight + l] = 0;
+ }
+ }
+ bmin[0] = 1E30f;
+ bmin[1] = 1E30f;
+ bmin[2] = 1E30f;
+ bmax[0] = -1E30f;
+ bmax[1] = -1E30f;
+ bmax[2] = -1E30f;
+ numave = 0;
+ avedev = 0.0;
+ maxdev = 0.0;
+ ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
+ for ( j = 0; j < nFrames; j++ )
+ {
+ for ( k = 0; k < MatWidth; k++ )
+ {
+ ans[k] = 0.0;
+ for ( l = 0; l < CFrameSize; l++ )
+ ans[k] += (float)( mat[l + k * MatHeight] ) * ( (float)( ccomp[j * CFrameSize + l] ) * cscale[l] + coffset[l] );
+ ans[k] += (float)( cbase[k] ) * scale[k % 3] + trans[k % 3];
+ tmp = (float)fabs( ans[k] - frames[j * MatWidth + k] - base[k] );
+ if ( tmp > maxdev ) {
+ maxdev = tmp;
+ }
+ avedev += tmp;
+ numave++;
+
+ if ( bmin[k % 3] > ans[k] ) {
+ bmin[k % 3] = ans[k];
+ }
+ if ( bmax[k % 3] < ans[k] ) {
+ bmax[k % 3] = ans[k];
+ }
+ }
+ }
+ avedev /= (float)numave;
+ printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
+ free( ans );
+}
+
+void AnimCompressGetMatrix( float *mat ){
+ int k,l;
+ for ( k = 0; k < MatWidth; k++ )
+ for ( l = 0; l < MatHeight; l++ )
+ mat[k * MatHeight + l] = best[l * MatWidth + k];
+}
+
+void AnimCompressGetFrames( float *mat ){
+ memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
+}
+
+void AnimCompressGetBase( int i,float *x,float *y,float *z ){
+ *x = base[i * 3];
+ *y = base[i * 3 + 1];
+ *z = base[i * 3 + 2];
+}
+
+void AnimCompressEnd(){
+ free( matrix );
+ free( best );
+ free( delta );
+ free( comp );
+ free( tcomp );
+ free( bestcomp );
+ free( base );
+ free( frames );
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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},
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <assert.h>
+
+/*
+ ========================================================================
+
+ .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 <linetype> %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 <linetype> %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 );
+ }
+}
--- /dev/null
+//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
+
--- /dev/null
+/*
+ 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 <windows.h>
+#endif
+
+#if GDEF_OS_MACOS && !defined( XWINDOWS )
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#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 <OPTIONS>
+ 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 );
+ }
+ }
+}
--- /dev/null
+/*
+ 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 <assert.h>
+#include <math.h>
+#include "token.h"
+#include "joints.h"
+#include "angles.h"
+#include "inout.h"
+
+char *SKEL_ROOT_NAMES[] =
+{
+ "RAVEN_SPINE"
+};
+
+char *SKEL_NAMES[] =
+{
+ "RAVEN_WAIST1",
+ "RAVEN_WAIST2",
+ "RAVEN_NECK"
+};
+
+int NAME_OFFSETS[] =
+{
+ 0
+};
+
+int numJointsForSkeleton[] =
+{
+ NUM_JOINTS_RAVEN,
+ NUM_JOINTS_BOX
+};
+
+float g_scaling[3];
+float g_rotation[3];
+float g_translation[3];
+
+//==========================================================================
+//
+// LoadHRCClustered
+//
+//==========================================================================
+
+static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
+ int i, j;
+
+ TK_OpenSource( fileName );
+ TK_FetchRequire( TK_HRCH );
+ TK_FetchRequire( TK_COLON );
+ TK_FetchRequire( TK_SOFTIMAGE );
+
+ TK_Beyond( TK_CLUSTERS );
+
+ while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
+ {
+ TK_Require( TK_STRING );
+
+ for ( i = 0; i < numJointsForSkeleton[skelType]; ++i )
+ {
+ if ( stricmp( tk_String, SKEL_NAMES[NAME_OFFSETS[skelType] + i] ) == 0 ) {
+ i = -i + numJointsForSkeleton[skelType] - 1;
+
+ TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
+
+ num_verts[i + 1] = tk_IntNumber;
+
+ clusterList[i] = (int *) SafeMalloc( num_verts[i + 1] * sizeof( int ), "LoadHRCClustered" );
+ assert( clusterList[i] );
+ // currently this function is only called by LoadTriangleListClustered, which in turn is only
+ // called by Cmd_Base in qdata. This is where the only call to free for this memory is being made.
+
+ TK_Beyond( TK_LBRACE );
+
+ for ( j = 0; j < num_verts[i + 1]; ++j )
+ {
+ TK_Require( TK_INTNUMBER );
+ clusterList[i][j] = tk_IntNumber;
+ TK_Fetch();
+ }
+
+ break;
+ }
+ }
+ }
+
+ num_verts[0] = numJointsForSkeleton[skelType];
+}
+
+static void LoadHRCGlobals( char *fileName ){
+ int i;
+
+ TK_OpenSource( fileName );
+ TK_FetchRequire( TK_HRCH );
+ TK_FetchRequire( TK_COLON );
+ TK_FetchRequire( TK_SOFTIMAGE );
+ TK_Beyond( TK_MODEL );
+
+ TK_Beyond( TK_SCALING );
+ for ( i = 0; i < 3; i++ )
+ {
+ TK_Require( TK_FLOATNUMBER );
+ g_scaling[i] = tk_FloatNumber;
+ TK_Fetch();
+ }
+
+ TK_Beyond( TK_ROTATION );
+ for ( i = 0; i < 3; i++ )
+ {
+ TK_Require( TK_FLOATNUMBER );
+ g_rotation[i] = tk_FloatNumber;
+ TK_Fetch();
+ }
+
+ TK_Beyond( TK_TRANSLATION );
+ for ( i = 0; i < 3; i++ )
+ {
+ TK_Require( TK_FLOATNUMBER );
+ g_translation[i] = tk_FloatNumber;
+ TK_Fetch();
+ }
+}
+
+static void ParseVec3( vec3_t in ){
+ TK_Require( TK_FLOATNUMBER );
+ in[1] = tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[2] = tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3( vec3_t in ){
+ TK_Require( TK_FLOATNUMBER );
+ in[1] = -tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[2] = tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3( vec3_t in ){
+ TK_Require( TK_FLOATNUMBER );
+ in[1] = tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[2] = tk_FloatNumber;
+ TK_FetchRequire( TK_FLOATNUMBER );
+ in[0] = tk_FloatNumber;
+}
+
+static void LoadHRCJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
+#define MAX_STACK 64
+ int i, j;
+ vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
+ int curCorrespondingJoint[MAX_STACK];
+ int currentStack = 0, stackSize;
+ int baseJoint;
+ float cx, sx, cy, sy, cz, sz;
+ float rx, ry, rz;
+ float x2, y2, z2;
+
+
+ TK_OpenSource( fileName );
+ TK_FetchRequire( TK_HRCH );
+ TK_FetchRequire( TK_COLON );
+ TK_FetchRequire( TK_SOFTIMAGE );
+
+ TK_Beyond( TK_MODEL );
+ TK_Beyond( TK_MODEL );
+
+/* while(1)
+ {
+ TK_Beyond(TK_MODEL);
+ TK_BeyondRequire(TK_NAME, TK_STRING);
+
+ if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
+ break;
+ }*/
+
+ TK_Beyond( TK_SCALING );
+
+ ParseVec3( curScale[currentStack] );
+
+ TK_Beyond( TK_ROTATION );
+
+ ParseRotation3( curRotation[currentStack] );
+
+ TK_Beyond( TK_TRANSLATION );
+
+ ParseVec3( curTranslation[currentStack] );
+
+ // account for global model translation
+ curTranslation[currentStack][1] += g_translation[0];
+ curTranslation[currentStack][2] += g_translation[1];
+ curTranslation[currentStack][0] += g_translation[2];
+
+ ++currentStack;
+
+ for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
+ {
+ while ( 1 )
+ {
+ TK_Beyond( TK_MODEL );
+
+// TK_BeyondRequire(TK_NAME, TK_STRING);
+
+// if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
+ break;
+
+ TK_Beyond( TK_SCALING );
+
+ ParseVec3( curScale[currentStack] );
+
+ TK_Beyond( TK_ROTATION );
+
+ ParseRotation3( curRotation[currentStack] );
+
+ TK_Beyond( TK_TRANSLATION );
+
+ ParseVec3( curTranslation[currentStack] );
+
+ curCorrespondingJoint[currentStack] = -1;
+
+ ++currentStack;
+ }
+
+ TK_Beyond( TK_SCALING );
+
+ ParseVec3( curScale[currentStack] );
+
+ TK_Beyond( TK_ROTATION );
+
+ ParseRotation3( curRotation[currentStack] );
+
+ jointList[i].rotation[1] = curRotation[currentStack][1];
+ jointList[i].rotation[2] = curRotation[currentStack][2];
+ jointList[i].rotation[0] = curRotation[currentStack][0];
+
+ TK_Beyond( TK_TRANSLATION );
+
+ ParseVec3( curTranslation[currentStack] );
+
+ jointList[i].placement.origin[1] = curTranslation[currentStack][1];
+ jointList[i].placement.origin[2] = curTranslation[currentStack][2];
+ jointList[i].placement.origin[0] = curTranslation[currentStack][0];
+
+ jointList[i].placement.direction[1] = 7.5;
+ jointList[i].placement.direction[2] = 0.0;
+ jointList[i].placement.direction[0] = 0.0;
+
+ jointList[i].placement.up[1] = 0.0;
+ jointList[i].placement.up[2] = 7.5;
+ jointList[i].placement.up[0] = 0.0;
+
+ curCorrespondingJoint[currentStack] = i;
+
+ ++currentStack;
+ }
+
+ stackSize = currentStack;
+
+ for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
+ {
+ rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
+ ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
+ rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
+
+ cx = cos( rx );
+ sx = sin( rx );
+
+ cy = cos( ry );
+ sy = sin( ry );
+
+ cz = cos( rz );
+ sz = sin( rz );
+
+ // y-axis rotation for direction
+ x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
+ z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
+ jointList[i].placement.direction[0] = x2;
+ jointList[i].placement.direction[2] = z2;
+
+ // y-axis rotation for up
+ x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
+ z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
+ jointList[i].placement.up[0] = x2;
+ jointList[i].placement.up[2] = z2;
+
+ // z-axis rotation for direction
+ x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
+ y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
+ jointList[i].placement.direction[0] = x2;
+ jointList[i].placement.direction[1] = y2;
+
+ // z-axis rotation for up
+ x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
+ y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
+ jointList[i].placement.up[0] = x2;
+ jointList[i].placement.up[1] = y2;
+
+ // x-axis rotation for direction vector
+ y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
+ z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
+ jointList[i].placement.direction[1] = y2;
+ jointList[i].placement.direction[2] = z2;
+
+ // x-axis rotation for up vector
+ y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
+ z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
+ jointList[i].placement.up[1] = y2;
+ jointList[i].placement.up[2] = z2;
+
+ // translate to position in model
+ jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
+ jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
+ jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
+
+ // translate to position in model
+ jointList[i].placement.up[0] += jointList[i].placement.origin[0];
+ jointList[i].placement.up[1] += jointList[i].placement.origin[1];
+ jointList[i].placement.up[2] += jointList[i].placement.origin[2];
+ }
+
+ baseJoint = NUM_JOINTS_RAVEN;
+
+ for ( i = stackSize /*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i )
+ {
+
+ rx = curRotation[i - 1][0] * ANGLE_TO_RAD;
+ ry = curRotation[i - 1][1] * ANGLE_TO_RAD;
+ rz = curRotation[i - 1][2] * ANGLE_TO_RAD;
+
+ cx = cos( rx );
+ sx = sin( rx );
+
+ cy = cos( ry );
+ sy = sin( ry );
+
+ cz = cos( rz );
+ sz = sin( rz );
+
+ for ( j = i - 1; j < stackSize - 1; ++j )
+ {
+ // y-axis rotation for origin
+ x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
+ z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
+ jointList[j].placement.origin[0] = x2;
+ jointList[j].placement.origin[2] = z2;
+
+ // y-axis rotation for direction
+ x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
+ z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
+ jointList[j].placement.direction[0] = x2;
+ jointList[j].placement.direction[2] = z2;
+
+ // y-axis rotation for up
+ x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
+ z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
+ jointList[j].placement.up[0] = x2;
+ jointList[j].placement.up[2] = z2;
+
+ // z-axis rotation for origin
+ x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
+ y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
+ jointList[j].placement.origin[0] = x2;
+ jointList[j].placement.origin[1] = y2;
+
+ // z-axis rotation for direction
+ x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
+ y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
+ jointList[j].placement.direction[0] = x2;
+ jointList[j].placement.direction[1] = y2;
+
+ // z-axis rotation for up
+ x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
+ y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
+ jointList[j].placement.up[0] = x2;
+ jointList[j].placement.up[1] = y2;
+
+ // x-axis rotation for origin
+ y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
+ z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
+ jointList[j].placement.origin[1] = y2;
+ jointList[j].placement.origin[2] = z2;
+
+ // x-axis rotation for direction vector
+ y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
+ z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
+ jointList[j].placement.direction[1] = y2;
+ jointList[j].placement.direction[2] = z2;
+
+ // x-axis rotation for up vector
+ y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
+ z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
+ jointList[j].placement.up[1] = y2;
+ jointList[j].placement.up[2] = z2;
+
+ if ( curCorrespondingJoint[j + 1] != -1 ) {
+ // translate origin
+ jointList[j].placement.origin[0] += curTranslation[i - 1][0];
+ jointList[j].placement.origin[1] += curTranslation[i - 1][1];
+ jointList[j].placement.origin[2] += curTranslation[i - 1][2];
+
+ // translate back to local coord
+ jointList[j].placement.direction[0] += curTranslation[i - 1][0];
+ jointList[j].placement.direction[1] += curTranslation[i - 1][1];
+ jointList[j].placement.direction[2] += curTranslation[i - 1][2];
+
+ // translate back to local coord
+ jointList[j].placement.up[0] += curTranslation[i - 1][0];
+ jointList[j].placement.up[1] += curTranslation[i - 1][1];
+ jointList[j].placement.up[2] += curTranslation[i - 1][2];
+ }
+ }
+ }
+}
+
+void LoadGlobals( char *fileName ){
+ FILE *file1;
+ int dot = '.';
+ char *dotstart;
+ char InputFileName[256];
+
+ dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+ if ( !dotstart ) {
+ strcpy( InputFileName, fileName );
+ strcat( InputFileName, ".hrc" );
+ if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+ fclose( file1 );
+
+ LoadHRCGlobals( InputFileName );
+
+ printf( " - assuming .HRC\n" );
+ return;
+ }
+
+ Error( "\n Could not open file '%s':\n"
+ "No HRC match.\n", fileName );
+ }
+ else
+ {
+ if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+ printf( "\n" );
+ fclose( file1 );
+ if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+ LoadHRCGlobals( fileName );
+ return;
+ }
+ }
+
+ Error( "Could not open file '%s':\n",fileName );
+ }
+}
+
+void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
+ FILE *file1;
+ int dot = '.';
+ char *dotstart;
+ char InputFileName[256];
+
+ dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+ if ( !dotstart ) {
+ strcpy( InputFileName, fileName );
+ strcat( InputFileName, ".hrc" );
+ if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+ fclose( file1 );
+
+ LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
+
+ printf( " - assuming .HRC\n" );
+ return;
+ }
+
+ Error( "\n Could not open file '%s':\n"
+ "No HRC match.\n", fileName );
+ }
+ else
+ {
+ if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+ printf( "\n" );
+ fclose( file1 );
+ if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+ LoadHRCClustered( fileName, clusterList, num_verts, skelType );
+ return;
+ }
+ }
+
+ Error( "Could not open file '%s':\n",fileName );
+ }
+}
+
+void LoadJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
+ FILE *file1;
+ int dot = '.';
+ char *dotstart;
+ char InputFileName[256];
+
+ dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+ if ( !dotstart ) {
+ strcpy( InputFileName, fileName );
+ strcat( InputFileName, ".hrc" );
+ if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+ fclose( file1 );
+
+ LoadHRCJointList( InputFileName, jointList, skelType );
+
+ printf( " - assuming .HRC\n" );
+ return;
+ }
+
+ Error( "\n Could not open file '%s':\n"
+ "No HRC.\n", fileName );
+ }
+ else
+ {
+ if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+ printf( "\n" );
+ fclose( file1 );
+ if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+ LoadHRCJointList( fileName, jointList, skelType );
+
+ return;
+ }
+ }
+
+ Error( "Could not open file '%s':\n",fileName );
+ }
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <assert.h>
+#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;
+ }
+}
--- /dev/null
+/*
+ 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 );
+}
--- /dev/null
+/*
+ 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 );
--- /dev/null
+/*
+ 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 <assert.h>
+#include <math.h>
+#include <memory.h>
+
+
+// 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 );
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <sys/types.h>
+#ifdef NeXT
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#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 <base.hrc> <skin.pcx> 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 <base.hrc> <skin.pcx> <desired width> <desired height>\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 <directory>]\n"
+ " [-release <directory>]\n"
+ " [-base <directory>]\n"
+ " [-compress]\n"
+ " [-pak <file>]\n"
+ " [-only <model>]\n"
+ " [-keypress]\n"
+ " [-3ds]\n"
+ " [-materialfile <file>]\n"
+ " [-noopts]\n"
+ " [-md2]\n"
+ " [-fm]\n"
+ " [-verbose]\n"
+ " [-ignoreUV]\n"
+ " [-oldskin]\n"
+ " [-publish]\n"
+ " [-nomkdir]\n"
+ " file.qdt\n"
+ "or\n"
+ " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>" );
+ }
+
+ 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;
+}
--- /dev/null
+/*
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#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 );
--- /dev/null
+//{{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
--- /dev/null
+/*
+ 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 );
+}
--- /dev/null
+/*
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+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 );
+}
--- /dev/null
+/*
+ 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 ) );
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <directory> <framedigits>
+// ==================================
+
+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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <assert.h>
+#include <globaldefs.h>
+
+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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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;
--- /dev/null
+/*
+ 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 <string.h>
+#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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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 <stdio.h>
+#include "resourcemanager.h"
+#include <assert.h>
+
+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
--- /dev/null
+/*
+ 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 <stdlib.h> // 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 );
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 <stdlib.h> // 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];
+++ /dev/null
-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 ()
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <memory.h>
-#include "animcomp.h"
-
-
-void *SafeMalloc( size_t n, char *desc );
-
-
-
-float *matrix;
-float *delta;
-float *best;
-float *comp;
-float *tcomp;
-float *bestcomp;
-float *frames;
-float *base;
-
-int MatWidth;
-int MatHeight;
-int CFrameSize;
-int nFrames;
-
-
-void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
- nFrames = nframes;
- MatWidth = nVerts * 3;
- MatHeight = CompressedFrameSize;
- CFrameSize = CompressedFrameSize;
- matrix = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
- best = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
- delta = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
- comp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
- tcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
- bestcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
- base = (float *)SafeMalloc( MatWidth * sizeof( float ), "AnimCompressInit" );
- frames = (float *)SafeMalloc( MatWidth * nFrames * sizeof( float ), "AnimCompressInit" );
-}
-
-void AnimSetFrame( int frame,int index,float x,float y,float z ){
- frames[frame * MatWidth + index * 3] = x;
- frames[frame * MatWidth + index * 3 + 1] = y;
- frames[frame * MatWidth + index * 3 + 2] = z;
-}
-
-typedef struct
-{
- int index;
- float val;
-} SORTP;
-
-
-#define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
-
-extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
-
-void AnimCompressDoit(){
- float compression;
- float *rescale;
- float *ans;
- float maxdev;
- float avedev;
- float tmp;
- int j,k,l,numave;
-
- for ( k = 0; k < MatWidth; k++ )
- base[k] = 0.0f;
- for ( j = 0; j < nFrames; j++ )
- for ( k = 0; k < MatWidth; k++ )
- base[k] += frames[j * MatWidth + k];
- tmp = 1.0f / (float)nFrames;
- for ( k = 0; k < MatWidth; k++ )
- base[k] *= tmp;
- for ( j = 0; j < nFrames; j++ )
- for ( k = 0; k < MatWidth; k++ )
- frames[j * MatWidth + k] -= base[k];
-
- ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressDoit" );
- rescale = (float *)SafeMalloc( sizeof( float ) * CFrameSize, "AnimCompressDoit" );
- DOsvd( frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight );
- avedev = 0.0;
- for ( l = 0; l < CFrameSize; l++ )
- avedev += rescale[l];
- for ( l = 0; l < CFrameSize; l++ )
- printf( "%3.1f ",100.0f * rescale[l] / avedev );
- printf( "\n" );
- for ( j = 0; j < nFrames; j++ )
- {
- for ( l = 0; l < CFrameSize; l++ )
- {
- bestcomp[j * CFrameSize + l] = 0.0;
- for ( k = 0; k < MatWidth; k++ )
- bestcomp[j * CFrameSize + l] += best[l * MatWidth + k] * frames[j * MatWidth + k];
- }
- }
- numave = 0;
- avedev = 0.0;
- maxdev = 0.0;
- for ( j = 0; j < nFrames; j++ )
- {
- for ( k = 0; k < MatWidth; k++ )
- {
- ans[k] = 0.0;
- for ( l = 0; l < CFrameSize; l++ )
- ans[k] += best[l * MatWidth + k] * bestcomp[j * CFrameSize + l];
- ans[k] -= frames[j * MatWidth + k];
- tmp = (float)fabs( ans[k] );
- if ( tmp > maxdev ) {
- maxdev = tmp;
- }
- avedev += tmp;
- numave++;
- }
- }
- avedev /= (float)numave;
- printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
- printf( "%d bytes original size\n",MatWidth * nFrames );
- printf( "%d bytes of overhead\n",MatWidth * MatHeight );
- printf( "%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize * nFrames );
- compression = (float)( MatWidth * MatHeight + CFrameSize * nFrames + MatWidth );
- compression /= (float)( MatWidth * nFrames );
- printf( "Overall compression = %f %%\n",100.0f - 100.0f * compression );
- compression = (float)( CFrameSize );
- compression /= (float)( MatWidth );
- printf( "frame size compression = %f %%\n",100.0f - 100.0f * compression );
- free( rescale );
- free( ans );
-}
-
-void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
- int k,l,nv,j;
- float maxdev;
- float avedev;
- float tmp;
- int numave;
- float t,mx;
- float *ans;
-
-
- nv = MatWidth / 3;
-
- trans[0] = 1E30f;
- scale[0] = -1E30f;
- trans[1] = 1E30f;
- scale[1] = -1E30f;
- trans[2] = 1E30f;
- scale[2] = -1E30f;
- for ( k = 0; k < MatWidth; k += 3 )
- {
- if ( base[k] > scale[0] ) {
- scale[0] = base[k];
- }
- if ( base[k] < trans[0] ) {
- trans[0] = base[k];
- }
-
- if ( base[k + 1] > scale[1] ) {
- scale[1] = base[k + 1];
- }
- if ( base[k + 1] < trans[1] ) {
- trans[1] = base[k + 1];
- }
-
- if ( base[k + 2] > scale[2] ) {
- scale[2] = base[k + 2];
- }
- if ( base[k + 2] < trans[2] ) {
- trans[2] = base[k + 2];
- }
- }
-
- scale[0] -= trans[0];
- scale[1] -= trans[1];
- scale[2] -= trans[2];
- scale[0] /= 255.0f;
- scale[1] /= 255.0f;
- scale[2] /= 255.0f;
- for ( k = 0; k < MatWidth; k += 3 )
- {
- t = ( base[k] - trans[0] ) / scale[0];
- if ( t < 0.0f ) {
- t = 0.0f;
- }
- if ( t > 255.0f ) {
- t = 255.0f;
- }
- cbase[k] = (unsigned char)t;
-
- t = ( base[k + 1] - trans[1] ) / scale[1];
- if ( t < 0.0f ) {
- t = 0.0f;
- }
- if ( t > 255.0f ) {
- t = 255.0f;
- }
- cbase[k + 1] = (unsigned char)t;
-
- t = ( base[k + 2] - trans[2] ) / scale[2];
- if ( t < 0.0f ) {
- t = 0.0f;
- }
- if ( t > 255.0f ) {
- t = 255.0f;
- }
- cbase[k + 2] = (unsigned char)t;
- }
- for ( l = 0; l < MatHeight; l++ )
- {
- mx = 0.0;
- for ( k = 0; k < MatWidth; k++ )
- {
- if ( fabs( best[l * MatWidth + k] ) > mx ) {
- mx = (float)fabs( best[l * MatWidth + k] );
- }
- }
- if ( mx > 1E-8 ) {
- mx /= 127.0f;
- coffset[l] = 1E30f;
- cscale[l] = -1E30f;
- for ( j = 0; j < nFrames; j++ )
- {
- bestcomp[j * MatHeight + l] *= mx;
- if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
- cscale[l] = bestcomp[j * MatHeight + l];
- }
- if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
- coffset[l] = bestcomp[j * MatHeight + l];
- }
- }
- cscale[l] -= coffset[l];
- if ( cscale[l] > 1E-10 ) {
- for ( j = 0; j < nFrames; j++ )
- {
- tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
- if ( tmp > 127.0f ) {
- tmp = 127.0f;
- }
- if ( tmp < -127.0f ) {
- tmp = -127.0f;
- }
- ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
- }
- coffset[l] += cscale[l] * 127.0f / 254.0f;
- cscale[l] /= 254.0f;
- }
- else
- {
- cscale[l] = 1.0f;
- coffset[l] = 0.0f;
- for ( j = 0; j < nFrames; j++ )
- ccomp[j * MatHeight + l] = 0;
- }
- mx = 1.0f / mx;
- for ( k = 0; k < MatWidth; k++ )
- {
- tmp = best[l * MatWidth + k] * mx;
- if ( tmp > 127.0f ) {
- tmp = 127.0f;
- }
- if ( tmp < -127.0f ) {
- tmp = -127.0f;
- }
- mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
- }
- }
- else
- {
- cscale[l] = 1.0f;
- coffset[l] = 0.0f;
- for ( j = 0; j < nFrames; j++ )
- ccomp[j * MatHeight + l] = 0;
- for ( k = 0; k < MatWidth; k++ )
- mat[k * MatHeight + l] = 0;
- }
- }
- bmin[0] = 1E30f;
- bmin[1] = 1E30f;
- bmin[2] = 1E30f;
- bmax[0] = -1E30f;
- bmax[1] = -1E30f;
- bmax[2] = -1E30f;
- numave = 0;
- avedev = 0.0;
- maxdev = 0.0;
- ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
- for ( j = 0; j < nFrames; j++ )
- {
- for ( k = 0; k < MatWidth; k++ )
- {
- ans[k] = 0.0;
- for ( l = 0; l < CFrameSize; l++ )
- ans[k] += (float)( mat[l + k * MatHeight] ) * ( (float)( ccomp[j * CFrameSize + l] ) * cscale[l] + coffset[l] );
- ans[k] += (float)( cbase[k] ) * scale[k % 3] + trans[k % 3];
- tmp = (float)fabs( ans[k] - frames[j * MatWidth + k] - base[k] );
- if ( tmp > maxdev ) {
- maxdev = tmp;
- }
- avedev += tmp;
- numave++;
-
- if ( bmin[k % 3] > ans[k] ) {
- bmin[k % 3] = ans[k];
- }
- if ( bmax[k % 3] < ans[k] ) {
- bmax[k % 3] = ans[k];
- }
- }
- }
- avedev /= (float)numave;
- printf( "%f Max Deviation (inches) %f Ave Dev. (inches)\n",maxdev,avedev );
- free( ans );
-}
-
-void AnimCompressGetMatrix( float *mat ){
- int k,l;
- for ( k = 0; k < MatWidth; k++ )
- for ( l = 0; l < MatHeight; l++ )
- mat[k * MatHeight + l] = best[l * MatWidth + k];
-}
-
-void AnimCompressGetFrames( float *mat ){
- memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
-}
-
-void AnimCompressGetBase( int i,float *x,float *y,float *z ){
- *x = base[i * 3];
- *y = base[i * 3 + 1];
- *z = base[i * 3 + 2];
-}
-
-void AnimCompressEnd(){
- free( matrix );
- free( best );
- free( delta );
- free( comp );
- free( tcomp );
- free( bestcomp );
- free( base );
- free( frames );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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},
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <sys/types.h>
-#include <sys/stat.h>
-
-#if GDEF_OS_WINDOWS
-#include <direct.h>
-#include <windows.h>
-#elif GDEF_OS_NEXT
-#include <libc.h>
-#else // OTHER OSES
-#include <unistd.h>
-#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
-}
+++ /dev/null
-/*
- 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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <sys/types.h>
-#include <sys/stat.h>
-
-#if GDEF_OS_WINDOWS
-#include <direct.h>
-#include <windows.h>
-#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, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">" );
- NMSG_Clear( &msg );
- NMSG_WriteString( &msg, sMsg );
- Net_Send( brdcst_socket, &msg );
- }
-}
-
-void Broadcast_Shutdown(){
- if ( brdcst_socket ) {
- Sys_Printf( "Disconnecting\n" );
- Net_Disconnect( brdcst_socket );
- brdcst_socket = NULL;
- }
-}
-
-// all output ends up through here
-void FPrintf( int flag, char *buf ){
- xmlNodePtr node;
- static qboolean bGotXML = false;
- char level[2];
-
- printf( buf );
-
- // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
- if ( flag == SYS_NOXML ) {
- return;
- }
-
- // ouput an XML file of the run
- // use the DOM interface to build a tree
- /*
- <message level='flag'>
- message string
- .. various nodes to describe corresponding geometry ..
- </message>
- */
- if ( !bGotXML ) {
- // initialize
- doc = xmlNewDoc( "1.0" );
- doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
- bGotXML = true;
- }
- node = xmlNewNode( NULL, "message" );
- 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 );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "l3dslib.h"
-#include "token.h"
-#include "fmodel.h"
-#include "bspfile.h"
-
-#define MAIN3DS 0x4D4D
-#define EDIT3DS 0x3D3D // this is the start of the editor config
-#define EDIT_OBJECT 0x4000
-#define OBJ_TRIMESH 0x4100
-#define TRI_VERTEXL 0x4110
-#define TRI_FACEL1 0x4120
-
-#define MAXVERTS 2000
-
-typedef struct {
- int v[4];
-} tri;
-
-float fverts[MAXVERTS][3];
-tri tris[MAXTRIANGLES];
-
-int bytesread, level, numtris, totaltris;
-int vertsfound, trisfound;
-
-triangle_t *ptri;
-
-
-
-void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles ){
- int pos, bit, i;
-
- if ( nodesList ) {
- *num_mesh_nodes = 1;
- memset( &( *nodesList )[0], 0, sizeof( mesh_node_t ) );
- strcpy( ( *nodesList )[0].name, "default" );
-
- // set all of the tris to be used for the top node
- for ( i = 0; i < ( *numtriangles ); i++ )
- {
- pos = ( i ) >> 3;
- bit = 1 << ( ( i ) & 7 );
-
- ( *nodesList )[0].tris[pos] |= bit;
- }
- }
-}
-
-
-// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
-// start out with a vertex pool and vertex indices for triangles, we have to convert
-// to raw, explicit triangles
-void StoreAliasTriangles( void ){
- int i, j, k;
-
- if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
- Error( "Error: Too many triangles" );
- }
-
- for ( i = 0; i < numtris ; i++ )
- {
- for ( j = 0 ; j < 3 ; j++ )
- {
- for ( k = 0 ; k < 3 ; k++ )
- {
- ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
- }
- }
- }
-
- totaltris += numtris;
- numtris = 0;
- vertsfound = 0;
- trisfound = 0;
-}
-
-
-int ParseVertexL( FILE *input ){
- int i, j, startbytesread, numverts;
- unsigned short tshort;
-
- if ( vertsfound ) {
- Error( "Error: Multiple vertex chunks" );
- }
-
- vertsfound = 1;
- startbytesread = bytesread;
-
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &tshort, sizeof( tshort ), 1, input );
- bytesread += sizeof( tshort );
- numverts = (int)tshort;
-
- if ( numverts > MAXVERTS ) {
- Error( "Error: Too many vertices" );
- }
-
- for ( i = 0 ; i < numverts ; i++ )
- {
- for ( j = 0 ; j < 3 ; j++ )
- {
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &fverts[i][j], sizeof( float ), 1, input );
- bytesread += sizeof( float );
- }
- }
-
- if ( vertsfound && trisfound ) {
- StoreAliasTriangles();
- }
-
- return bytesread - startbytesread;
-}
-
-
-int ParseFaceL1( FILE *input ){
-
- int i, j, startbytesread;
- unsigned short tshort;
-
- if ( trisfound ) {
- Error( "Error: Multiple face chunks" );
- }
-
- trisfound = 1;
- startbytesread = bytesread;
-
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &tshort, sizeof( tshort ), 1, input );
- bytesread += sizeof( tshort );
- numtris = (int)tshort;
-
- if ( numtris > MAXTRIANGLES ) {
- Error( "Error: Too many triangles" );
- }
-
- for ( i = 0 ; i < numtris ; i++ )
- {
- for ( j = 0 ; j < 4 ; j++ )
- {
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &tshort, sizeof( tshort ), 1, input );
- bytesread += sizeof( tshort );
- tris[i].v[j] = (int)tshort;
- }
- }
-
- if ( vertsfound && trisfound ) {
- StoreAliasTriangles();
- }
-
- return bytesread - startbytesread;
-}
-
-
-int ParseChunk( FILE *input ){
-#define BLOCK_SIZE 4096
- char temp[BLOCK_SIZE];
- unsigned short type;
- int i, length, w, t, retval;
-
- level++;
- retval = 0;
-
-// chunk type
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &type, sizeof( type ), 1, input );
- bytesread += sizeof( type );
-
-// chunk length
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &length, sizeof( length ), 1, input );
- bytesread += sizeof( length );
- w = length - 6;
-
-// process chunk if we care about it, otherwise skip it
- switch ( type )
- {
- case TRI_VERTEXL:
- w -= ParseVertexL( input );
- goto ParseSubchunk;
-
- case TRI_FACEL1:
- w -= ParseFaceL1( input );
- goto ParseSubchunk;
-
- case EDIT_OBJECT:
- // read the name
- i = 0;
-
- do
- {
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &temp[i], 1, 1, input );
- i++;
- w--;
- bytesread++;
- } while ( temp[i - 1] );
-
- case MAIN3DS:
- case OBJ_TRIMESH:
- case EDIT3DS:
- // parse through subchunks
-ParseSubchunk:
- while ( w > 0 )
- {
- w -= ParseChunk( input );
- }
-
- retval = length;
- goto Done;
-
- default:
- // skip other chunks
- while ( w > 0 )
- {
- t = w;
-
- if ( t > BLOCK_SIZE ) {
- t = BLOCK_SIZE;
- }
-
- if ( feof( input ) ) {
- Error( "Error: unexpected end of file" );
- }
-
- fread( &temp, t, 1, input );
- bytesread += t;
-
- w -= t;
- }
-
- retval = length;
- goto Done;
- }
-
-Done:
- level--;
- return retval;
-}
-
-
-void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
- FILE *input;
- short int tshort;
-
- if ( nodesList ) {
- *num_mesh_nodes = 0;
- *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
- }
-
- bytesread = 0;
- level = 0;
- numtris = 0;
- totaltris = 0;
- vertsfound = 0;
- trisfound = 0;
-
- if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
- fprintf( stderr,"reader: could not open file '%s'\n", filename );
- exit( 0 );
- }
-
- fread( &tshort, sizeof( tshort ), 1, input );
-
-// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
-// no MAIN3DS
- if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
- fprintf( stderr,"File is not a 3DS file.\n" );
- exit( 0 );
- }
-
-// back to top of file so we can parse the first chunk descriptor
- fseek( input, 0, SEEK_SET );
-
- ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
-
- *pptri = ptri;
-
-// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
-// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
- ParseChunk( input );
-
- if ( vertsfound || trisfound ) {
- Error( "Incomplete triangle set" );
- }
-
- *numtriangles = totaltris;
-
- fclose( input );
-
- DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
-}
-
-//==========================================================================
-//
-// LoadASC
-//
-//==========================================================================
-
-void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
- int i, j;
- int vertexCount;
- struct
- {
- float v[3];
- } *vList;
- int triCount;
- triangle_t *tList;
- float x, y, z;
-// float x2, y2, z2;
-// float rx, ry, rz;
- qboolean goodObject;
-
- if ( nodesList ) {
- *num_mesh_nodes = 0;
- *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
- }
-
- TK_OpenSource( fileName );
-
- goodObject = false;
- while ( goodObject == false )
- {
- TK_Beyond( TK_C_NAMED );
- TK_Beyond( TK_OBJECT );
- TK_Beyond( TK_C_TRI );
- TK_Beyond( TK_MESH );
- TK_BeyondRequire( TK_C_VERTICES, TK_COLON );
- TK_FetchRequire( TK_INTNUMBER );
- vertexCount = tk_IntNumber;
- if ( vertexCount > 0 ) {
- goodObject = true;
- }
- }
- TK_BeyondRequire( TK_C_FACES, TK_COLON );
- TK_FetchRequire( TK_INTNUMBER );
- triCount = tk_IntNumber;
- if ( triCount >= MAXTRIANGLES ) {
- Error( "Too many triangles in file %s\n", fileName );
- }
- *triangleCount = triCount;
- tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
- *triList = tList;
-
- memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
- TK_BeyondRequire( TK_C_VERTEX, TK_LIST );
-
-/* rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
- //rx = (rotation[0]/360.0)*2.0*M_PI;
- ry = (rotation[1]/360.0)*2.0*M_PI;
- rz = (rotation[2]/360.0)*2.0*M_PI;
- */
- vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
- for ( i = 0; i < vertexCount; i++ )
- {
- TK_BeyondRequire( TK_C_VERTEX, TK_INTNUMBER );
- if ( tk_IntNumber != i ) {
- Error( "File '%s', line %d:\nVertex index mismatch.\n",
- tk_SourceName, tk_Line );
- }
- TK_FetchRequireFetch( TK_COLON );
-
- TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
- x = tk_FloatNumber;
- TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
- y = tk_FloatNumber;
- TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
- z = tk_FloatNumber;
-
-/* x2 = x*cos(rz)+y*sin(rz);
- y2 = -x*sin(rz)+y*cos(rz);
- x = x2;
- y = y2;
- y2 = y*cos(rx)+z*sin(rx);
- z2 = -y*sin(rx)+z*cos(rx);
- y = y2;
- z = z2;
- x2 = x*cos(ry)-z*sin(ry);
- z2 = x*sin(ry)+z*cos(ry);
- x = x2;
- z = z2;
- */
- vList[i].v[0] = x;
- vList[i].v[1] = y;
- vList[i].v[2] = z;
- }
- TK_BeyondRequire( TK_C_FACE, TK_LIST );
- for ( i = 0; i < triCount; i++ )
- {
- TK_BeyondRequire( TK_C_FACE, TK_INTNUMBER );
- if ( tk_IntNumber != i ) {
- Error( "File '%s', line %d:\nTriangle index mismatch.\n",
- tk_SourceName, tk_Line );
- }
- for ( j = 0; j < 3; j++ )
- {
- TK_BeyondRequire( TK_IDENTIFIER, TK_COLON );
- TK_FetchRequire( TK_INTNUMBER );
- if ( tk_IntNumber >= vertexCount ) {
- Error( "File '%s', line %d:\nVertex number"
- " > vertexCount: %d\n", tk_SourceName, tk_Line,
- tk_IntNumber );
- }
- tList[i].verts[2 - j][0] = vList[tk_IntNumber].v[0];
- tList[i].verts[2 - j][1] = vList[tk_IntNumber].v[1];
- tList[i].verts[2 - j][2] = vList[tk_IntNumber].v[2];
-#ifdef _QDATA
- tList[i].indicies[2 - j] = tk_IntNumber;
-#endif
- }
-
-/* printf("Face %i:\n v0: %f, %f, %f\n v1: %f, %f, %f\n"
- " v2: %f, %f, %f\n", i,
- tList[i].verts[0][0],
- tList[i].verts[0][1],
- tList[i].verts[0][2],
- tList[i].verts[1][0],
- tList[i].verts[1][1],
- tList[i].verts[1][2],
- tList[i].verts[2][0],
- tList[i].verts[2][1],
- tList[i].verts[2][2]);
- */
- }
-
- DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
-}
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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<height ; i++)
- {
- for (j=0 ; j<width ; j++)
- {
- if ( (*data & 0xc0) != 0xc0)
- *pack++ = *data++;
- else
- {
- *pack++ = 0xc1;
- *pack++ = *data++;
- }
- }
- }
- */
- for ( i = 0 ; i < height ; i++ )
- {
- curByte = *data;
- curRepCount = 0;
- for ( j = 0 ; j < width ; j++ )
- {
- if ( *data == curByte ) {
- curRepCount++;
- data++;
- continue;
- }
- StuffPackedByte( curRepCount, curByte, &pack );
- curByte = *data++;
- curRepCount = 1;
- }
- StuffPackedByte( curRepCount, curByte, &pack );
- }
- // write the palette
- *pack++ = 0x0c; // palette ID byte
- for ( i = 0 ; i < 768 ; i++ )
- *pack++ = *palette++;
-
-// write output file
- length = pack - (byte *)pcx;
- SaveFile( filename, pcx, length );
-
- free( pcx );
-}
-
-
-/*
- ============================================================================
-
- LOAD IMAGE
-
- ============================================================================
- */
-
-/*
- ==============
- Load256Image
-
- Will load either an lbm or pcx, depending on extension.
- Any of the return pointers can be NULL if you don't want them.
- ==============
- */
-void Load256Image( char *name, byte **pixels, byte **palette,
- int *width, int *height ){
- char ext[128];
-
- ExtractFileExtension( name, ext );
- if ( !Q_strcasecmp( ext, "lbm" ) ) {
- LoadLBM( name, pixels, palette );
- if ( width ) {
- *width = bmhd.w;
- }
- if ( height ) {
- *height = bmhd.h;
- }
- }
- else if ( !Q_strcasecmp( ext, "pcx" ) ) {
- LoadPCX( name, pixels, palette, width, height );
- }
- else{
- Error( "%s doesn't have a known image extension", name );
- }
-}
-
-
-/*
- ==============
- Save256Image
-
- Will save either an lbm or pcx, depending on extension.
- ==============
- */
-void Save256Image( char *name, byte *pixels, byte *palette,
- int width, int height ){
- char ext[128];
-
- ExtractFileExtension( name, ext );
- if ( !Q_strcasecmp( ext, "lbm" ) ) {
- WriteLBMfile( name, pixels, width, height, palette );
- }
- else if ( !Q_strcasecmp( ext, "pcx" ) ) {
- WritePCXfile( name, pixels, width, height, palette );
- }
- else{
- Error( "%s doesn't have a known image extension", name );
- }
-}
-
-
-
-
-/*
- ============================================================================
-
- TARGA IMAGE
-
- ============================================================================
- */
-
-typedef struct _TargaHeader
-{
- unsigned char id_length, colormap_type, image_type;
- unsigned short colormap_index, colormap_length;
- unsigned char colormap_size;
- unsigned short x_origin, y_origin, width, height;
- unsigned char pixel_size, attributes;
-} TargaHeader;
-
-int fgetLittleShort( FILE *f ){
- byte b1, b2;
-
- b1 = fgetc( f );
- b2 = fgetc( f );
-
- return( (short)( b1 + ( b2 << 8 ) ) );
-}
-
-int fgetLittleLong( FILE *f ){
- byte b1, b2, b3, b4;
-
- b1 = fgetc( f );
- b2 = fgetc( f );
- b3 = fgetc( f );
- b4 = fgetc( f );
-
- return( b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 ) );
-}
-
-
-/*
- =============
- LoadTGA
- =============
- */
-void LoadTGA( char *name, byte **pixels, int *width, int *height ){
- int columns, rows, numPixels;
- byte *pixbuf;
- byte *rowBuf;
- int row, column;
- FILE *fin;
- byte *targa_rgba;
- TargaHeader targa_header;
- unsigned char red, green, blue, alphabyte;
- unsigned char packetHeader, packetSize, j;
- int flip;
- int mirror;
- int rowOffset;
- int pixDirection;
-
- fin = fopen( name, "rb" );
- if ( !fin ) {
- Error( "Couldn't read %s", name );
- }
-
- targa_header.id_length = fgetc( fin );
- targa_header.colormap_type = fgetc( fin );
- targa_header.image_type = fgetc( fin );
-
- targa_header.colormap_index = fgetLittleShort( fin );
- targa_header.colormap_length = fgetLittleShort( fin );
- targa_header.colormap_size = fgetc( fin );
- targa_header.x_origin = fgetLittleShort( fin );
- targa_header.y_origin = fgetLittleShort( fin );
- targa_header.width = fgetLittleShort( fin );
- targa_header.height = fgetLittleShort( fin );
- targa_header.pixel_size = fgetc( fin );
- targa_header.attributes = fgetc( fin );
- flip = ( targa_header.attributes & 0x020 ) == 0;
- mirror = ( targa_header.attributes & 0x010 ) != 0;
-
- if ( ( targa_header.image_type != 2 ) && ( targa_header.image_type != 10 ) ) {
- Error( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
- }
-
- if ( targa_header.colormap_type || ( ( targa_header.pixel_size != 32 ) && ( targa_header.pixel_size != 24 ) ) ) {
- Error( "Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
- }
-
- columns = targa_header.width;
- rows = targa_header.height;
- numPixels = columns * rows;
-
- if ( width ) {
- *width = columns;
- }
- if ( height ) {
- *height = rows;
- }
-
- if ( !pixels ) {
- return;
- }
-
- targa_rgba = malloc( numPixels * 4 );
- *pixels = targa_rgba;
-
- if ( flip ) {
- pixbuf = targa_rgba + ( ( rows - 1 ) * columns * 4 );
- rowOffset = -columns * 4;
- }
- else
- {
- pixbuf = targa_rgba;
- rowOffset = columns * 4;
- }
- if ( mirror ) {
- pixDirection = -4;
- pixbuf += ( ( columns - 1 ) * 4 );
- }
- else
- {
- pixDirection = 4;
- }
-
- if ( targa_header.id_length ) {
- fseek( fin, targa_header.id_length, SEEK_CUR ); // skip TARGA image comment
-
- }
- if ( targa_header.image_type == 2 ) { // Uncompressed, RGB images
- for ( row = 0; row < rows; row++ )
- {
- rowBuf = pixbuf;
- for ( column = 0; column < columns; column++ )
- {
- 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;
- }
- }
- pixbuf += rowOffset;
- }
- }
- else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images
- for ( row = 0; row < rows; row++ )
- {
- rowBuf = pixbuf;
- for ( column = 0; column < columns; )
- {
- packetHeader = getc( fin );
- packetSize = 1 + ( packetHeader & 0x7f );
- if ( packetHeader & 0x80 ) { // run-length packet
- switch ( targa_header.pixel_size )
- {
- case 24:
- blue = getc( fin );
- green = getc( fin );
- red = getc( fin );
- alphabyte = 255;
- break;
- case 32:
- blue = getc( fin );
- green = getc( fin );
- red = getc( fin );
- alphabyte = getc( fin );
- break;
- }
-
- for ( j = 0; j < packetSize; j++ )
- {
- rowBuf[0] = red;
- rowBuf[1] = green;
- rowBuf[2] = blue;
- rowBuf[3] = alphabyte;
- rowBuf += pixDirection;
- column++;
- if ( column == columns ) { // run spans across rows
- column = 0;
- row++;
- if ( row >= 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;
-}
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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;
- }
- }
-}
+++ /dev/null
-/*
- 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 <math.h>
-/*
- #ifdef DOUBLEVEC_T
- typedef double vec_t;
- #else
- typedef float vec_t;
- #endif
- typedef vec_t vec3_t[3];
- */
-#define SIDE_FRONT 0
-#define SIDE_ON 2
-#define SIDE_BACK 1
-#define SIDE_CROSS -2
-
-#define Q_PI 3.14159265358979323846
-
-extern vec3_t vec3_origin;
-
-#define EQUAL_EPSILON 0.001
-
-qboolean VectorCompare( vec3_t v1, vec3_t v2 );
-
-#define DotProduct( x,y ) ( x[0] * y[0] + x[1] * y[1] + x[2] * y[2] )
-#define VectorSubtract( a,b,c ) {c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; }
-#define VectorAdd( a,b,c ) {c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; }
-#define VectorCopy( a,b ) {b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
-#define VectorScale( a,b,c ) {c[0] = b * a[0]; c[1] = b * a[1]; c[2] = b * a[2]; }
-#define VectorClear( x ) {x[0] = x[1] = x[2] = 0; }
-#define VectorNegate( x ) {x[0] = -x[0]; x[1] = -x[1]; x[2] = -x[2]; }
-
-vec_t Q_rint( vec_t in );
-vec_t _DotProduct( vec3_t v1, vec3_t v2 );
-void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out );
-void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out );
-void _VectorCopy( vec3_t in, vec3_t out );
-void _VectorScale( vec3_t v, vec_t scale, vec3_t out );
-
-double VectorLength( vec3_t v );
-
-void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc );
-
-void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross );
-vec_t VectorNormalize( vec3_t in, vec3_t out );
-vec_t ColorNormalize( vec3_t in, vec3_t out );
-void VectorInverse( vec3_t v );
-
-void ClearBounds( vec3_t mins, vec3_t maxs );
-void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs );
-
-#endif
+++ /dev/null
-/*
- 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 <string.h> /* 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 <d2deek@pmail.net>
-//
-// Author: Jeff Teunissen <d2deek@pmail.net>
-// 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 );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/* -------------------------------------------------------------------------------
-
- 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 <unistd.h>
- #include <pwd.h>
- #include <limits.h>
-#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" );
-}
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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 <windows.h>
-
-materialtype_t defaultmaterialtypes[] =
-{
- {"gravel", MATERIAL_GRAVEL},
- {"metal", MATERIAL_METAL},
- {"stone", MATERIAL_STONE},
- {"wood", MATERIAL_WOOD},
- {NULL, 0}
-};
-
-materialtype_t *materialtypes;
-
-void QFile_ReadMaterialTypes( char* filename ){
- int i;
- FILE *f;
-
- f = fopen( filename, "rb" );
- if ( !f ) {
- materialtypes = defaultmaterialtypes;
- return;
- }
- fclose( f );
-
- free( materialtypes );
- materialtypes = (materialtype_t*)malloc( 256 * sizeof( materialtype_t ) );
-
- LoadScriptFile( filename );
- i = 0;
-
- while ( i < 255 )
- {
- GetScriptToken( true );
- if ( endofscript ) {
- break;
- }
- if ( strcmp( token, "material" ) != 0 ) {
- while ( ScriptTokenAvailable() )
- {
- GetScriptToken( false );
- }
- }
- else
- {
- GetScriptToken( false );
- materialtypes[i].name = (char*)malloc( strlen( token ) + 1 );
- strcpy( materialtypes[i].name, token );
- GetScriptToken( false );
- materialtypes[i].value = atoi( token );
- }
- i++;
- }
- materialtypes[i].name = NULL;
- materialtypes[i].value = 0;
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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 <windows.h>
-
-// Setting default Threads to 1
-int numthreads = 1;
-CRITICAL_SECTION crit;
-static int enter;
-
-void ThreadSetDefault( void ){
- SYSTEM_INFO info;
-
- if ( numthreads == -1 ) { // not set manually
- GetSystemInfo( &info );
- numthreads = info.dwNumberOfProcessors;
- if ( numthreads < 1 || numthreads > 32 ) {
- numthreads = 1;
- }
- }
-
- Sys_Printf( "%i threads\n", numthreads );
-}
-
-
-void ThreadLock( void ){
- if ( !threaded ) {
- return;
- }
- EnterCriticalSection( &crit );
- if ( enter ) {
- Error( "Recursive ThreadLock\n" );
- }
- enter = 1;
-}
-
-void ThreadUnlock( void ){
- if ( !threaded ) {
- return;
- }
- if ( !enter ) {
- Error( "ThreadUnlock without lock\n" );
- }
- enter = 0;
- LeaveCriticalSection( &crit );
-}
-
-/*
- =============
- RunThreadsOn
- =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
- int threadid[MAX_THREADS];
- HANDLE threadhandle[MAX_THREADS];
- int i;
- int start, end;
-
- start = I_FloatTime();
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threaded = true;
-
- //
- // run threads in parallel
- //
- InitializeCriticalSection( &crit );
-
- if ( numthreads == 1 ) { // use same thread
- func( 0 );
- }
- else
- {
- for ( i = 0 ; i < numthreads ; i++ )
- {
- threadhandle[i] = CreateThread(
- NULL, // LPSECURITY_ATTRIBUTES lpsa,
- //0, // DWORD cbStack,
-
- /* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
- ( 4096 * 1024 ),
-
- (LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
- (LPVOID)i, // LPVOID lpvThreadParm,
- 0, // DWORD fdwCreate,
- &threadid[i] );
- }
-
- for ( i = 0 ; i < numthreads ; i++ )
- WaitForSingleObject( threadhandle[i], INFINITE );
- }
- DeleteCriticalSection( &crit );
-
- threaded = false;
- end = I_FloatTime();
- if ( pacifier ) {
- Sys_Printf( " (%i)\n", end - start );
- }
-}
-
-
-#elif GDEF_OS_OSF1
-
-/*
- ===================================================================
-
- OSF1
-
- ===================================================================
- */
-
-int numthreads = 4;
-
-void ThreadSetDefault( void ){
- if ( numthreads == -1 ) { // not set manually
- numthreads = 4;
- }
-}
-
-
-#include <pthread.h>
-
-pthread_mutex_t *my_mutex;
-
-void ThreadLock( void ){
- if ( my_mutex ) {
- pthread_mutex_lock( my_mutex );
- }
-}
-
-void ThreadUnlock( void ){
- if ( my_mutex ) {
- pthread_mutex_unlock( my_mutex );
- }
-}
-
-
-/*
- =============
- RunThreadsOn
- =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
- int i;
- pthread_t work_threads[MAX_THREADS];
- pthread_addr_t status;
- pthread_attr_t attrib;
- pthread_mutexattr_t mattrib;
- int start, end;
-
- start = I_FloatTime();
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threaded = true;
-
- if ( pacifier ) {
- setbuf( stdout, NULL );
- }
-
- if ( !my_mutex ) {
- my_mutex = safe_malloc( sizeof( *my_mutex ) );
- if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
- Error( "pthread_mutex_attr_create failed" );
- }
- if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
- Error( "pthread_mutexattr_setkind_np failed" );
- }
- if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
- Error( "pthread_mutex_init failed" );
- }
- }
-
- if ( pthread_attr_create( &attrib ) == -1 ) {
- Error( "pthread_attr_create failed" );
- }
- if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
- Error( "pthread_attr_setstacksize failed" );
- }
-
- for ( i = 0 ; i < numthreads ; i++ )
- {
- if ( pthread_create( &work_threads[i], attrib
- , (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) {
- Error( "pthread_create failed" );
- }
- }
-
- for ( i = 0 ; i < numthreads ; i++ )
- {
- if ( pthread_join( work_threads[i], &status ) == -1 ) {
- Error( "pthread_join failed" );
- }
- }
-
- threaded = false;
-
- end = I_FloatTime();
- if ( pacifier ) {
- Sys_Printf( " (%i)\n", end - start );
- }
-}
-
-
-#elif GDEF_OS_IRIX
-
-/*
- ===================================================================
-
- IRIX
-
- ===================================================================
- */
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-int numthreads = -1;
-abilock_t lck;
-
-void ThreadSetDefault( void ){
- if ( numthreads == -1 ) {
- numthreads = prctl( PR_MAXPPROCS );
- }
- Sys_Printf( "%i threads\n", numthreads );
- usconfig( CONF_INITUSERS, numthreads );
-}
-
-
-void ThreadLock( void ){
- spin_lock( &lck );
-}
-
-void ThreadUnlock( void ){
- release_lock( &lck );
-}
-
-
-/*
- =============
- RunThreadsOn
- =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
- int i;
- int pid[MAX_THREADS];
- int start, end;
-
- start = I_FloatTime();
- dispatch = 0;
- workcount = workcnt;
- oldf = -1;
- pacifier = showpacifier;
- threaded = true;
-
- if ( pacifier ) {
- setbuf( stdout, NULL );
- }
-
- init_lock( &lck );
-
- for ( i = 0 ; i < numthreads - 1 ; i++ )
- {
- pid[i] = sprocsp( ( void ( * )( void *, size_t ) )func, PR_SALL, (void *)i
- , NULL, 0x200000 ); // 2 meg stacks
- if ( pid[i] == -1 ) {
- perror( "sproc" );
- Error( "sproc failed" );
- }
- }
-
- func( i );
-
- for ( i = 0 ; i < numthreads - 1 ; i++ )
- wait( NULL );
-
- threaded = false;
-
- end = I_FloatTime();
- if ( pacifier ) {
- Sys_Printf( " (%i)\n", end - start );
- }
-}
-
-
-#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 <pthread.h>
-
-typedef struct pt_mutex_s
-{
- pthread_t *owner;
- pthread_mutex_t a_mutex;
- pthread_cond_t cond;
- unsigned int lock;
-} pt_mutex_t;
-
-pt_mutex_t global_lock;
-
-void ThreadLock( void ){
- pt_mutex_t *pt_mutex = &global_lock;
-
- if ( !threaded ) {
- return;
- }
-
- pthread_mutex_lock( &pt_mutex->a_mutex );
- if ( pthread_equal( pthread_self(), (pthread_t)&pt_mutex->owner ) ) {
- pt_mutex->lock++;
- }
- else
- {
- if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
- pt_mutex->owner = (pthread_t *)pthread_self();
- pt_mutex->lock = 1;
- }
- else
- {
- while ( 1 )
- {
- pthread_cond_wait( &pt_mutex->cond, &pt_mutex->a_mutex );
- if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
- pt_mutex->owner = (pthread_t *)pthread_self();
- pt_mutex->lock = 1;
- break;
- }
- }
- }
- }
- pthread_mutex_unlock( &pt_mutex->a_mutex );
-}
-
-void ThreadUnlock( void ){
- pt_mutex_t *pt_mutex = &global_lock;
-
- if ( !threaded ) {
- return;
- }
-
- pthread_mutex_lock( &pt_mutex->a_mutex );
- pt_mutex->lock--;
-
- if ( pt_mutex->lock == 0 ) {
- pt_mutex->owner = NULL;
- pthread_cond_signal( &pt_mutex->cond );
- }
-
- pthread_mutex_unlock( &pt_mutex->a_mutex );
-}
-
-void recursive_mutex_init( pthread_mutexattr_t attribs ){
- pt_mutex_t *pt_mutex = &global_lock;
-
- pt_mutex->owner = NULL;
- if ( pthread_mutex_init( &pt_mutex->a_mutex, &attribs ) != 0 ) {
- Error( "pthread_mutex_init failed\n" );
- }
- if ( pthread_cond_init( &pt_mutex->cond, NULL ) != 0 ) {
- Error( "pthread_cond_init failed\n" );
- }
-
- pt_mutex->lock = 0;
-}
-
-/*
- =============
- RunThreadsOn
- =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
- pthread_mutexattr_t mattrib;
- pthread_t work_threads[MAX_THREADS];
-
- int start, end;
- int i = 0, status = 0;
-
- start = I_FloatTime();
- pacifier = showpacifier;
-
- dispatch = 0;
- oldf = -1;
- workcount = workcnt;
-
- if ( numthreads == 1 ) {
- func( 0 );
- }
- else
- {
- threaded = true;
-
- if ( pacifier ) {
- setbuf( stdout, NULL );
- }
-
- if ( pthread_mutexattr_init( &mattrib ) != 0 ) {
- Error( "pthread_mutexattr_init failed" );
- }
- if ( 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
+++ /dev/null
-/*
- 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[] =
-{
- "<nothing>",
- "<unknown_char>",
- "<EOF>",
- "<identifier>",
- "<string>",
- "<int_number>",
- "<float_number>",
- "(",
- ")",
- "{",
- "}",
- "[",
- "]",
- ":",
- "mesh",
- "model",
- "nodes",
- "rotation",
- "scaling",
- "translation",
- "polygons",
- "position",
- "vertex",
- "vertices",
- "HRCH",
- "Softimage"
-};
-
-// CODE --------------------------------------------------------------------
-
-//==========================================================================
-//
-// TK_Init
-//
-//==========================================================================
-
-void TK_Init( void ){
- int i;
-
- for ( i = 0; i < 256; i++ )
- {
- ASCIIToChrCode[i] = CHR_SPECIAL;
- }
- for ( i = '0'; i <= '9'; i++ )
- {
- ASCIIToChrCode[i] = CHR_NUMBER;
- }
- for ( i = 'A'; i <= 'Z'; i++ )
- {
- ASCIIToChrCode[i] = CHR_LETTER;
- }
- for ( i = 'a'; i <= 'z'; i++ )
- {
- ASCIIToChrCode[i] = CHR_LETTER;
- }
- ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
- ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
- ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
- tk_String = TokenStringBuffer;
- IncLineNumber = FALSE;
- SourceOpen = FALSE;
-}
-
-//==========================================================================
-//
-// TK_OpenSource
-//
-//==========================================================================
-
-void TK_OpenSource( char *fileName ){
- int size;
-
- TK_CloseSource();
- size = LoadFile( fileName, (void **)&FileStart );
- strcpy( tk_SourceName, fileName );
- SourceOpen = TRUE;
- FileEnd = FileStart + size;
- FilePtr = FileStart;
- tk_Line = 1;
- tk_Token = TK_NONE;
- NextChr();
-}
-
-//==========================================================================
-//
-// TK_CloseSource
-//
-//==========================================================================
-
-void TK_CloseSource( void ){
- if ( SourceOpen ) {
- free( FileStart );
- SourceOpen = FALSE;
- }
-}
-
-//==========================================================================
-//
-// TK_Fetch
-//
-//==========================================================================
-
-tokenType_t TK_Fetch( void ){
- while ( Chr == ASCII_SPACE )
- {
- NextChr();
- }
- if ( Chr == '-' ) {
- ProcessNumberToken();
- }
- else{switch ( ASCIIToChrCode[(byte)Chr] )
- {
- case CHR_EOF:
- tk_Token = TK_EOF;
- break;
- case CHR_LETTER:
- ProcessLetterToken();
- break;
- case CHR_NUMBER:
- ProcessNumberToken();
- break;
- case CHR_QUOTE:
- ProcessQuoteToken();
- break;
- default:
- ProcessSpecialToken();
- break;
- }}
- return tk_Token;
-}
-
-//==========================================================================
-//
-// TK_Require
-//
-//==========================================================================
-
-void TK_Require( tokenType_t tokType ){
- if ( tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER ) {
- tk_FloatNumber = (float)tk_IntNumber;
- tk_Token = TK_FLOATNUMBER;
- return;
- }
- if ( tk_Token != tokType ) {
- Error( "File '%s', line %d:\nExpected '%s', found '%s'.\n",
- tk_SourceName, tk_Line, TokenNames[tokType],
- TokenNames[tk_Token] );
- }
-}
-
-void TK_FetchRequire( tokenType_t tokType ){
- TK_Fetch();
- TK_Require( tokType );
-}
-
-tokenType_t TK_RequireFetch( tokenType_t tokType ){
- TK_Require( tokType );
- return TK_Fetch();
-}
-
-tokenType_t TK_FetchRequireFetch( tokenType_t tokType ){
- TK_Fetch();
- TK_Require( tokType );
- return TK_Fetch();
-}
-
-tokenType_t TK_Beyond( tokenType_t tokType ){
- while ( tk_Token != tokType )
- {
- if ( TK_Fetch() == TK_EOF ) {
- Error( "File '%s':\nCould not find token '%s'.\n", // FIXME: TokenNames table not big enuff
- tk_SourceName, TokenNames[tokType] );
- }
- }
- return TK_Fetch();
-}
-
-void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok ){
- TK_Beyond( bTok );
- TK_Require( rTok );
-}
-
-tokenType_t TK_Search( tokenType_t tokType ){
- while ( tk_Token != tokType )
- {
- if ( TK_Fetch() == TK_EOF ) {
- return TK_EOF;
- }
- }
- return TK_Fetch();
-}
-
-tokenType_t TK_Get( tokenType_t tokType ){
- while ( tk_Token != tokType )
- {
- if ( TK_Fetch() == TK_EOF ) {
- Error( "File '%s':\nCould not find token '%s'.\n",
- tk_SourceName, TokenNames[tokType] );
- }
- }
- return tk_Token;
-}
-
-//==========================================================================
-//
-// ProcessLetterToken
-//
-//==========================================================================
-
-static void ProcessLetterToken( void ){
- int i;
- char *text;
-
- i = 0;
- text = TokenStringBuffer;
- while ( ASCIIToChrCode[(byte)Chr] == CHR_LETTER
- || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
- {
- if ( ++i == MAX_IDENTIFIER_LENGTH ) {
- Error( "File '%s', line %d:\nIdentifier too long.\n",
- tk_SourceName, tk_Line );
- }
- *text++ = Chr;
- NextChr();
- }
- *text = 0;
- if ( CheckForKeyword() == FALSE ) {
- tk_Token = TK_IDENTIFIER;
- }
-}
-
-//==========================================================================
-//
-// CheckForKeyword
-//
-//==========================================================================
-
-static qboolean CheckForKeyword( void ){
- int i;
-
- for ( i = 0; Keywords[i].name != NULL; i++ )
- {
- if ( strcmp( tk_String, Keywords[i].name ) == 0 ) {
- tk_Token = Keywords[i].token;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-//==========================================================================
-//
-// ProcessNumberToken
-//
-//==========================================================================
-
-static void ProcessNumberToken( void ){
- char *buffer;
-
- buffer = TempBuffer;
- *buffer++ = Chr;
- NextChr();
- while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
- {
- *buffer++ = Chr;
- NextChr();
- }
- if ( Chr == '.' ) { // Float
- *buffer++ = Chr;
- NextChr(); // Skip period
- while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
- {
- *buffer++ = Chr;
- NextChr();
- }
- *buffer = 0;
- tk_FloatNumber = (float)atof( TempBuffer );
- tk_Token = TK_FLOATNUMBER;
- return;
- }
-
- // Integer
- *buffer = 0;
- tk_IntNumber = atoi( TempBuffer );
- tk_Token = TK_INTNUMBER;
-}
-
-//==========================================================================
-//
-// ProcessQuoteToken
-//
-//==========================================================================
-
-static void ProcessQuoteToken( void ){
- int i;
- char *text;
-
- i = 0;
- text = TokenStringBuffer;
- NextChr();
- while ( Chr != ASCII_QUOTE )
- {
- if ( Chr == EOF_CHARACTER ) {
- Error( "File '%s', line %d:\n<EOF> inside string.\n",
- tk_SourceName, tk_Line );
- }
- if ( ++i > MAX_QUOTED_LENGTH - 1 ) {
- Error( "File '%s', line %d:\nString literal too long.\n",
- tk_SourceName, tk_Line );
- }
- *text++ = Chr;
- NextChr();
- }
- *text = 0;
- NextChr();
- tk_Token = TK_STRING;
-}
-
-//==========================================================================
-//
-// ProcessSpecialToken
-//
-//==========================================================================
-
-static void ProcessSpecialToken( void ){
- char c;
-
- c = Chr;
- NextChr();
- switch ( c )
- {
- case '(':
- tk_Token = TK_LPAREN;
- break;
- case ')':
- tk_Token = TK_RPAREN;
- break;
- case '{':
- tk_Token = TK_LBRACE;
- break;
- case '}':
- tk_Token = TK_RBRACE;
- break;
- case '[':
- tk_Token = TK_LBRACKET;
- break;
- case ']':
- tk_Token = TK_RBRACKET;
- break;
- case ':':
- tk_Token = TK_COLON;
- break;
- default:
- tk_Token = TK_UNKNOWNCHAR;
- break;
- }
-}
-
-//==========================================================================
-//
-// NextChr
-//
-//==========================================================================
-
-static void NextChr( void ){
- if ( FilePtr >= FileEnd ) {
- Chr = EOF_CHARACTER;
- return;
- }
- if ( IncLineNumber == TRUE ) {
- tk_Line++;
- IncLineNumber = FALSE;
- }
- Chr = *FilePtr++;
- if ( Chr < ASCII_SPACE ) {
- if ( Chr == '\n' ) {
- IncLineNumber = TRUE;
- }
- Chr = ASCII_SPACE;
- }
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <stdio.h>
-#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 );
- }
-
- }
-}
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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 <assert.h>
-
-/*
- ========================================================================
-
- .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 <linetype> %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 <linetype> %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 );
- }
-}
+++ /dev/null
-//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
-
+++ /dev/null
-/*
- 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 <windows.h>
-#endif
-
-#if GDEF_OS_MACOS && !defined( XWINDOWS )
-#include <OpenGL/gl.h>
-#else
-#include <GL/gl.h>
-#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 <OPTIONS>
- 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 );
- }
- }
-}
+++ /dev/null
-/*
- 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 <assert.h>
-#include <math.h>
-#include "token.h"
-#include "joints.h"
-#include "angles.h"
-#include "inout.h"
-
-char *SKEL_ROOT_NAMES[] =
-{
- "RAVEN_SPINE"
-};
-
-char *SKEL_NAMES[] =
-{
- "RAVEN_WAIST1",
- "RAVEN_WAIST2",
- "RAVEN_NECK"
-};
-
-int NAME_OFFSETS[] =
-{
- 0
-};
-
-int numJointsForSkeleton[] =
-{
- NUM_JOINTS_RAVEN,
- NUM_JOINTS_BOX
-};
-
-float g_scaling[3];
-float g_rotation[3];
-float g_translation[3];
-
-//==========================================================================
-//
-// LoadHRCClustered
-//
-//==========================================================================
-
-static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
- int i, j;
-
- TK_OpenSource( fileName );
- TK_FetchRequire( TK_HRCH );
- TK_FetchRequire( TK_COLON );
- TK_FetchRequire( TK_SOFTIMAGE );
-
- TK_Beyond( TK_CLUSTERS );
-
- while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
- {
- TK_Require( TK_STRING );
-
- for ( i = 0; i < numJointsForSkeleton[skelType]; ++i )
- {
- if ( stricmp( tk_String, SKEL_NAMES[NAME_OFFSETS[skelType] + i] ) == 0 ) {
- i = -i + numJointsForSkeleton[skelType] - 1;
-
- TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
-
- num_verts[i + 1] = tk_IntNumber;
-
- clusterList[i] = (int *) SafeMalloc( num_verts[i + 1] * sizeof( int ), "LoadHRCClustered" );
- assert( clusterList[i] );
- // currently this function is only called by LoadTriangleListClustered, which in turn is only
- // called by Cmd_Base in qdata. This is where the only call to free for this memory is being made.
-
- TK_Beyond( TK_LBRACE );
-
- for ( j = 0; j < num_verts[i + 1]; ++j )
- {
- TK_Require( TK_INTNUMBER );
- clusterList[i][j] = tk_IntNumber;
- TK_Fetch();
- }
-
- break;
- }
- }
- }
-
- num_verts[0] = numJointsForSkeleton[skelType];
-}
-
-static void LoadHRCGlobals( char *fileName ){
- int i;
-
- TK_OpenSource( fileName );
- TK_FetchRequire( TK_HRCH );
- TK_FetchRequire( TK_COLON );
- TK_FetchRequire( TK_SOFTIMAGE );
- TK_Beyond( TK_MODEL );
-
- TK_Beyond( TK_SCALING );
- for ( i = 0; i < 3; i++ )
- {
- TK_Require( TK_FLOATNUMBER );
- g_scaling[i] = tk_FloatNumber;
- TK_Fetch();
- }
-
- TK_Beyond( TK_ROTATION );
- for ( i = 0; i < 3; i++ )
- {
- TK_Require( TK_FLOATNUMBER );
- g_rotation[i] = tk_FloatNumber;
- TK_Fetch();
- }
-
- TK_Beyond( TK_TRANSLATION );
- for ( i = 0; i < 3; i++ )
- {
- TK_Require( TK_FLOATNUMBER );
- g_translation[i] = tk_FloatNumber;
- TK_Fetch();
- }
-}
-
-static void ParseVec3( vec3_t in ){
- TK_Require( TK_FLOATNUMBER );
- in[1] = tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[2] = tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3( vec3_t in ){
- TK_Require( TK_FLOATNUMBER );
- in[1] = -tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[2] = tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3( vec3_t in ){
- TK_Require( TK_FLOATNUMBER );
- in[1] = tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[2] = tk_FloatNumber;
- TK_FetchRequire( TK_FLOATNUMBER );
- in[0] = tk_FloatNumber;
-}
-
-static void LoadHRCJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
-#define MAX_STACK 64
- int i, j;
- vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
- int curCorrespondingJoint[MAX_STACK];
- int currentStack = 0, stackSize;
- int baseJoint;
- float cx, sx, cy, sy, cz, sz;
- float rx, ry, rz;
- float x2, y2, z2;
-
-
- TK_OpenSource( fileName );
- TK_FetchRequire( TK_HRCH );
- TK_FetchRequire( TK_COLON );
- TK_FetchRequire( TK_SOFTIMAGE );
-
- TK_Beyond( TK_MODEL );
- TK_Beyond( TK_MODEL );
-
-/* while(1)
- {
- TK_Beyond(TK_MODEL);
- TK_BeyondRequire(TK_NAME, TK_STRING);
-
- if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
- break;
- }*/
-
- TK_Beyond( TK_SCALING );
-
- ParseVec3( curScale[currentStack] );
-
- TK_Beyond( TK_ROTATION );
-
- ParseRotation3( curRotation[currentStack] );
-
- TK_Beyond( TK_TRANSLATION );
-
- ParseVec3( curTranslation[currentStack] );
-
- // account for global model translation
- curTranslation[currentStack][1] += g_translation[0];
- curTranslation[currentStack][2] += g_translation[1];
- curTranslation[currentStack][0] += g_translation[2];
-
- ++currentStack;
-
- for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
- {
- while ( 1 )
- {
- TK_Beyond( TK_MODEL );
-
-// TK_BeyondRequire(TK_NAME, TK_STRING);
-
-// if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
- break;
-
- TK_Beyond( TK_SCALING );
-
- ParseVec3( curScale[currentStack] );
-
- TK_Beyond( TK_ROTATION );
-
- ParseRotation3( curRotation[currentStack] );
-
- TK_Beyond( TK_TRANSLATION );
-
- ParseVec3( curTranslation[currentStack] );
-
- curCorrespondingJoint[currentStack] = -1;
-
- ++currentStack;
- }
-
- TK_Beyond( TK_SCALING );
-
- ParseVec3( curScale[currentStack] );
-
- TK_Beyond( TK_ROTATION );
-
- ParseRotation3( curRotation[currentStack] );
-
- jointList[i].rotation[1] = curRotation[currentStack][1];
- jointList[i].rotation[2] = curRotation[currentStack][2];
- jointList[i].rotation[0] = curRotation[currentStack][0];
-
- TK_Beyond( TK_TRANSLATION );
-
- ParseVec3( curTranslation[currentStack] );
-
- jointList[i].placement.origin[1] = curTranslation[currentStack][1];
- jointList[i].placement.origin[2] = curTranslation[currentStack][2];
- jointList[i].placement.origin[0] = curTranslation[currentStack][0];
-
- jointList[i].placement.direction[1] = 7.5;
- jointList[i].placement.direction[2] = 0.0;
- jointList[i].placement.direction[0] = 0.0;
-
- jointList[i].placement.up[1] = 0.0;
- jointList[i].placement.up[2] = 7.5;
- jointList[i].placement.up[0] = 0.0;
-
- curCorrespondingJoint[currentStack] = i;
-
- ++currentStack;
- }
-
- stackSize = currentStack;
-
- for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
- {
- rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
- ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
- rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
-
- cx = cos( rx );
- sx = sin( rx );
-
- cy = cos( ry );
- sy = sin( ry );
-
- cz = cos( rz );
- sz = sin( rz );
-
- // y-axis rotation for direction
- x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
- z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
- jointList[i].placement.direction[0] = x2;
- jointList[i].placement.direction[2] = z2;
-
- // y-axis rotation for up
- x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
- z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
- jointList[i].placement.up[0] = x2;
- jointList[i].placement.up[2] = z2;
-
- // z-axis rotation for direction
- x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
- y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
- jointList[i].placement.direction[0] = x2;
- jointList[i].placement.direction[1] = y2;
-
- // z-axis rotation for up
- x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
- y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
- jointList[i].placement.up[0] = x2;
- jointList[i].placement.up[1] = y2;
-
- // x-axis rotation for direction vector
- y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
- z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
- jointList[i].placement.direction[1] = y2;
- jointList[i].placement.direction[2] = z2;
-
- // x-axis rotation for up vector
- y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
- z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
- jointList[i].placement.up[1] = y2;
- jointList[i].placement.up[2] = z2;
-
- // translate to position in model
- jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
- jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
- jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
-
- // translate to position in model
- jointList[i].placement.up[0] += jointList[i].placement.origin[0];
- jointList[i].placement.up[1] += jointList[i].placement.origin[1];
- jointList[i].placement.up[2] += jointList[i].placement.origin[2];
- }
-
- baseJoint = NUM_JOINTS_RAVEN;
-
- for ( i = stackSize /*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i )
- {
-
- rx = curRotation[i - 1][0] * ANGLE_TO_RAD;
- ry = curRotation[i - 1][1] * ANGLE_TO_RAD;
- rz = curRotation[i - 1][2] * ANGLE_TO_RAD;
-
- cx = cos( rx );
- sx = sin( rx );
-
- cy = cos( ry );
- sy = sin( ry );
-
- cz = cos( rz );
- sz = sin( rz );
-
- for ( j = i - 1; j < stackSize - 1; ++j )
- {
- // y-axis rotation for origin
- x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
- z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
- jointList[j].placement.origin[0] = x2;
- jointList[j].placement.origin[2] = z2;
-
- // y-axis rotation for direction
- x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
- z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
- jointList[j].placement.direction[0] = x2;
- jointList[j].placement.direction[2] = z2;
-
- // y-axis rotation for up
- x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
- z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
- jointList[j].placement.up[0] = x2;
- jointList[j].placement.up[2] = z2;
-
- // z-axis rotation for origin
- x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
- y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
- jointList[j].placement.origin[0] = x2;
- jointList[j].placement.origin[1] = y2;
-
- // z-axis rotation for direction
- x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
- y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
- jointList[j].placement.direction[0] = x2;
- jointList[j].placement.direction[1] = y2;
-
- // z-axis rotation for up
- x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
- y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
- jointList[j].placement.up[0] = x2;
- jointList[j].placement.up[1] = y2;
-
- // x-axis rotation for origin
- y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
- z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
- jointList[j].placement.origin[1] = y2;
- jointList[j].placement.origin[2] = z2;
-
- // x-axis rotation for direction vector
- y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
- z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
- jointList[j].placement.direction[1] = y2;
- jointList[j].placement.direction[2] = z2;
-
- // x-axis rotation for up vector
- y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
- z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
- jointList[j].placement.up[1] = y2;
- jointList[j].placement.up[2] = z2;
-
- if ( curCorrespondingJoint[j + 1] != -1 ) {
- // translate origin
- jointList[j].placement.origin[0] += curTranslation[i - 1][0];
- jointList[j].placement.origin[1] += curTranslation[i - 1][1];
- jointList[j].placement.origin[2] += curTranslation[i - 1][2];
-
- // translate back to local coord
- jointList[j].placement.direction[0] += curTranslation[i - 1][0];
- jointList[j].placement.direction[1] += curTranslation[i - 1][1];
- jointList[j].placement.direction[2] += curTranslation[i - 1][2];
-
- // translate back to local coord
- jointList[j].placement.up[0] += curTranslation[i - 1][0];
- jointList[j].placement.up[1] += curTranslation[i - 1][1];
- jointList[j].placement.up[2] += curTranslation[i - 1][2];
- }
- }
- }
-}
-
-void LoadGlobals( char *fileName ){
- FILE *file1;
- int dot = '.';
- char *dotstart;
- char InputFileName[256];
-
- dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
- if ( !dotstart ) {
- strcpy( InputFileName, fileName );
- strcat( InputFileName, ".hrc" );
- if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
- fclose( file1 );
-
- LoadHRCGlobals( InputFileName );
-
- printf( " - assuming .HRC\n" );
- return;
- }
-
- Error( "\n Could not open file '%s':\n"
- "No HRC match.\n", fileName );
- }
- else
- {
- if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
- printf( "\n" );
- fclose( file1 );
- if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
- LoadHRCGlobals( fileName );
- return;
- }
- }
-
- Error( "Could not open file '%s':\n",fileName );
- }
-}
-
-void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
- FILE *file1;
- int dot = '.';
- char *dotstart;
- char InputFileName[256];
-
- dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
- if ( !dotstart ) {
- strcpy( InputFileName, fileName );
- strcat( InputFileName, ".hrc" );
- if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
- fclose( file1 );
-
- LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
-
- printf( " - assuming .HRC\n" );
- return;
- }
-
- Error( "\n Could not open file '%s':\n"
- "No HRC match.\n", fileName );
- }
- else
- {
- if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
- printf( "\n" );
- fclose( file1 );
- if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
- LoadHRCClustered( fileName, clusterList, num_verts, skelType );
- return;
- }
- }
-
- Error( "Could not open file '%s':\n",fileName );
- }
-}
-
-void LoadJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
- FILE *file1;
- int dot = '.';
- char *dotstart;
- char InputFileName[256];
-
- dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
- if ( !dotstart ) {
- strcpy( InputFileName, fileName );
- strcat( InputFileName, ".hrc" );
- if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
- fclose( file1 );
-
- LoadHRCJointList( InputFileName, jointList, skelType );
-
- printf( " - assuming .HRC\n" );
- return;
- }
-
- Error( "\n Could not open file '%s':\n"
- "No HRC.\n", fileName );
- }
- else
- {
- if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
- printf( "\n" );
- fclose( file1 );
- if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
- LoadHRCJointList( fileName, jointList, skelType );
-
- return;
- }
- }
-
- Error( "Could not open file '%s':\n",fileName );
- }
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <assert.h>
-#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;
- }
-}
+++ /dev/null
-/*
- 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 );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <assert.h>
-#include <globaldefs.h>
-
-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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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;
+++ /dev/null
-/*
- 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 <string.h>
-#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
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <stdio.h>
-#include "resourcemanager.h"
-#include <assert.h>
-
-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
+++ /dev/null
-/*
- 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 <stdlib.h> // 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 );
+++ /dev/null
-/*
- 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;
-}
+++ /dev/null
-/*
- 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 <stdlib.h> // 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];
+++ /dev/null
-/*
- 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 );
+++ /dev/null
-/*
- 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 <assert.h>
-#include <math.h>
-#include <memory.h>
-
-
-// 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 );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <sys/types.h>
-#ifdef NeXT
-#include <sys/dir.h>
-#else
-#include <dirent.h>
-#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 <base.hrc> <skin.pcx> 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 <base.hrc> <skin.pcx> <desired width> <desired height>\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 <directory>]\n"
- " [-release <directory>]\n"
- " [-base <directory>]\n"
- " [-compress]\n"
- " [-pak <file>]\n"
- " [-only <model>]\n"
- " [-keypress]\n"
- " [-3ds]\n"
- " [-materialfile <file>]\n"
- " [-noopts]\n"
- " [-md2]\n"
- " [-fm]\n"
- " [-verbose]\n"
- " [-ignoreUV]\n"
- " [-oldskin]\n"
- " [-publish]\n"
- " [-nomkdir]\n"
- " file.qdt\n"
- "or\n"
- " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>" );
- }
-
- 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;
-}
+++ /dev/null
-/*
- 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 <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#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 );
+++ /dev/null
-//{{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
+++ /dev/null
-/*
- 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 );
-}
+++ /dev/null
-/*
- 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 <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-
-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 );
-}
+++ /dev/null
-/*
- 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 ) );
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- 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 <directory> <framedigits>
-// ==================================
-
-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