mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 00:49:29 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
12
tools/quake3/q3data/.cvsignore
Normal file
12
tools/quake3/q3data/.cvsignore
Normal file
@@ -0,0 +1,12 @@
|
||||
q3map
|
||||
*.d
|
||||
*.o
|
||||
*.bak
|
||||
*.BAK
|
||||
*~
|
||||
*.ncb
|
||||
*.plg
|
||||
*.opt
|
||||
*.log
|
||||
Debug
|
||||
Release
|
||||
2
tools/quake3/q3data/.cvswrappers
Normal file
2
tools/quake3/q3data/.cvswrappers
Normal file
@@ -0,0 +1,2 @@
|
||||
*.dsp -m 'COPY' -k 'b'
|
||||
*.dsw -m 'COPY' -k 'b'
|
||||
651
tools/quake3/q3data/3dslib.c
Normal file
651
tools/quake3/q3data/3dslib.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "q3data.h"
|
||||
|
||||
static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose );
|
||||
|
||||
static qboolean s_verbose;
|
||||
|
||||
#define MAX_MATERIALS 100
|
||||
#define MAX_NAMED_OBJECTS 100
|
||||
#define MAX_MESH_MATERIAL_GROUPS 100
|
||||
#define MAX_TRI_OBJECTS 512
|
||||
|
||||
static char s_buffer[1000000];
|
||||
|
||||
static int ReadString( FILE *fp, char *buffer )
|
||||
{
|
||||
int i = 0;
|
||||
int bytesRead = 0;
|
||||
|
||||
do
|
||||
{
|
||||
fread( &buffer[i], 1, sizeof( char ), fp );
|
||||
bytesRead++;
|
||||
} while ( buffer[i++] != 0 );
|
||||
buffer[i] = 0;
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
static int ReadChunkAndLength( FILE *fp, short *chunk, long *len )
|
||||
{
|
||||
if ( fread( chunk, sizeof( short ), 1, fp ) != 1 )
|
||||
return 0;
|
||||
if ( fread( len, sizeof( long ), 1, fp ) != 1 )
|
||||
Error( "Unexpected EOF found" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen )
|
||||
{
|
||||
unsigned short chunkID;
|
||||
long chunkLen;
|
||||
long bytesRead = 0;
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_MAT_MAPNAME:
|
||||
fread( buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
}
|
||||
bytesRead += chunkLen;
|
||||
if ( bytesRead >= thisChunkLen )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat )
|
||||
{
|
||||
long chunkLen;
|
||||
unsigned short chunkID;
|
||||
long bytesRead = 0;
|
||||
_3DSMaterial_t mat;
|
||||
char curdir[1024];
|
||||
char buffer[2048];
|
||||
|
||||
memset( &mat, 0, sizeof( mat ) );
|
||||
|
||||
if ( s_verbose )
|
||||
printf( " >>> MATERIAL LIST\n" );
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_MAT_NAME:
|
||||
fread( mat.name, chunkLen - 6, 1, fp );
|
||||
if ( s_verbose )
|
||||
printf( " found mat name '%s'\n", mat.name );
|
||||
break;
|
||||
case _3DS_CHUNK_TEXMAP:
|
||||
LoadMapName( fp, mat.texture, chunkLen - 6 );
|
||||
if ( s_verbose )
|
||||
printf( " found texture '%s'\n", mat.texture );
|
||||
break;
|
||||
case _3DS_CHUNK_SPECMAP:
|
||||
LoadMapName( fp, mat.specular, chunkLen - 6 );
|
||||
if ( s_verbose )
|
||||
printf( " found specular map '%s'\n", mat.specular );
|
||||
break;
|
||||
case _3DS_CHUNK_OPACMAP:
|
||||
LoadMapName( fp, mat.opacity, chunkLen - 6 );
|
||||
if ( s_verbose )
|
||||
printf( " found opacity map '%s'\n", mat.opacity );
|
||||
break;
|
||||
case _3DS_CHUNK_REFLMAP:
|
||||
LoadMapName( fp, mat.reflection, chunkLen - 6 );
|
||||
if ( s_verbose )
|
||||
printf( " found reflection map '%s'\n", mat.reflection );
|
||||
break;
|
||||
case _3DS_CHUNK_BUMPMAP:
|
||||
LoadMapName( fp, mat.bump, chunkLen - 6 );
|
||||
if ( s_verbose )
|
||||
printf( " found bump map '%s'\n", mat.bump );
|
||||
break;
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
}
|
||||
|
||||
bytesRead += chunkLen;
|
||||
|
||||
if ( bytesRead >= thisChunkLen )
|
||||
break;
|
||||
}
|
||||
|
||||
Q_getwd( curdir );
|
||||
|
||||
if ( mat.texture[0] )
|
||||
{
|
||||
sprintf( buffer, "%s%s", curdir, mat.texture );
|
||||
if ( strstr( buffer, gamedir + 1 ) )
|
||||
strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
|
||||
else
|
||||
strcpy( mat.texture, buffer );
|
||||
}
|
||||
|
||||
if ( mat.specular[0] )
|
||||
{
|
||||
sprintf( buffer, "%s%s", curdir, mat.specular );
|
||||
if ( strstr( buffer, gamedir + 1 ) )
|
||||
strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
|
||||
else
|
||||
strcpy( mat.specular, buffer );
|
||||
}
|
||||
|
||||
if ( mat.bump[0] )
|
||||
{
|
||||
sprintf( buffer, "%s%s", curdir, mat.bump );
|
||||
if ( strstr( buffer, gamedir + 1 ) )
|
||||
strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
|
||||
else
|
||||
strcpy( mat.bump, buffer );
|
||||
}
|
||||
|
||||
if ( mat.reflection[0] )
|
||||
{
|
||||
sprintf( buffer, "%s%s", curdir, mat.reflection );
|
||||
if ( strstr( buffer, gamedir + 1 ) )
|
||||
strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
|
||||
else
|
||||
strcpy( mat.reflection, buffer );
|
||||
}
|
||||
|
||||
if ( mat.opacity[0] )
|
||||
{
|
||||
sprintf( buffer, "%s%s", curdir, mat.opacity );
|
||||
if ( strstr( buffer, gamedir + 1 ) )
|
||||
strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
|
||||
else
|
||||
strcpy( mat.opacity, buffer );
|
||||
}
|
||||
|
||||
*pMat = mat;
|
||||
}
|
||||
|
||||
static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG )
|
||||
{
|
||||
_3DSMeshMaterialGroup_t mmg;
|
||||
|
||||
memset( &mmg, 0, sizeof( mmg ) );
|
||||
|
||||
ReadString( fp, mmg.name );
|
||||
|
||||
fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );
|
||||
mmg.pFaces = malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );
|
||||
fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );
|
||||
|
||||
if ( s_verbose )
|
||||
{
|
||||
printf( " >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < mmg.numFaces; i++ )
|
||||
{
|
||||
printf( " %d\n", mmg.pFaces[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pMMG = mmg;
|
||||
}
|
||||
|
||||
static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO )
|
||||
{
|
||||
long chunkLen;
|
||||
unsigned short chunkID;
|
||||
int i = 0;
|
||||
long bytesRead = 0;
|
||||
_3DSTriObject_t triObj;
|
||||
_3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];
|
||||
int numMeshMaterialGroups = 0;
|
||||
|
||||
memset( &triObj, 0, sizeof( triObj ) );
|
||||
|
||||
if ( s_verbose )
|
||||
printf( " >>> NAMED TRI OBJECT\n" );
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_MSH_MAT_GROUP:
|
||||
LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );
|
||||
bytesRead += chunkLen;
|
||||
numMeshMaterialGroups++;
|
||||
break;
|
||||
case _3DS_CHUNK_FACE_ARRAY:
|
||||
fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );
|
||||
assert( triObj.pFaces == 0 );
|
||||
|
||||
triObj.pFaces = malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );
|
||||
fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );
|
||||
bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;
|
||||
|
||||
if ( s_verbose )
|
||||
{
|
||||
printf( " found face array with %d faces\n", triObj.numFaces );
|
||||
for ( i = 0; i < triObj.numFaces; i++ )
|
||||
{
|
||||
printf( " %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case _3DS_CHUNK_POINT_ARRAY:
|
||||
fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );
|
||||
triObj.pPoints = malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );
|
||||
fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );
|
||||
bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;
|
||||
|
||||
// flip points around into our coordinate system
|
||||
for ( i = 0; i < triObj.numPoints; i++ )
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
x = triObj.pPoints[i].x;
|
||||
y = triObj.pPoints[i].y;
|
||||
z = triObj.pPoints[i].z;
|
||||
|
||||
triObj.pPoints[i].x = -y;
|
||||
triObj.pPoints[i].y = x;
|
||||
triObj.pPoints[i].z = z;
|
||||
}
|
||||
|
||||
if ( s_verbose )
|
||||
{
|
||||
printf( " found point array with %d points\n", triObj.numPoints );
|
||||
for ( i = 0; i < triObj.numPoints; i++ )
|
||||
{
|
||||
printf( " %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _3DS_CHUNK_TEX_VERTS:
|
||||
fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );
|
||||
triObj.pTexVerts = malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );
|
||||
fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );
|
||||
bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;
|
||||
|
||||
if ( s_verbose )
|
||||
{
|
||||
printf( " found tex vert array with %d tex verts\n", triObj.numTexVerts );
|
||||
for ( i = 0; i < triObj.numTexVerts; i++ )
|
||||
{
|
||||
printf( " %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
bytesRead += chunkLen;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( bytesRead >= thisChunkLen )
|
||||
break;
|
||||
}
|
||||
*pTO = triObj;
|
||||
|
||||
if ( numMeshMaterialGroups == 0 )
|
||||
{
|
||||
numMeshMaterialGroups = 1;
|
||||
strcpy( meshMaterialGroups[0].name, "(null)" );
|
||||
if ( pTO->numTexVerts ) {
|
||||
printf( "Warning: assigning (null) skin to tri object\n" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( pTO->numFaces == meshMaterialGroups[0].numFaces );
|
||||
}
|
||||
|
||||
pTO->pMeshMaterialGroups = malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );
|
||||
memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );
|
||||
pTO->numMeshMaterialGroups = numMeshMaterialGroups;
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
assert( numMeshMaterialGroups <= 1 );
|
||||
}
|
||||
|
||||
static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO )
|
||||
{
|
||||
long chunkLen;
|
||||
unsigned short chunkID;
|
||||
int i = 0;
|
||||
long bytesRead = 0;
|
||||
char name[100];
|
||||
_3DSTriObject_t triObj[MAX_TRI_OBJECTS];
|
||||
int numTriObjects = 0;
|
||||
|
||||
memset( triObj, 0, sizeof( triObj ) );
|
||||
|
||||
bytesRead += ReadString( fp, name );
|
||||
|
||||
if ( s_verbose )
|
||||
printf( " >>> NAMED OBJECT '%s'\n", name );
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_NAMED_TRI_OBJECT:
|
||||
LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );
|
||||
numTriObjects++;
|
||||
break;
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
}
|
||||
|
||||
bytesRead += chunkLen;
|
||||
|
||||
if ( bytesRead >= thisChunkLen )
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy( pNO->name, name );
|
||||
pNO->pTriObjects = malloc( sizeof( _3DSTriObject_t ) * numTriObjects );
|
||||
memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );
|
||||
pNO->numTriObjects = numTriObjects;
|
||||
|
||||
assert( numTriObjects <= 1 );
|
||||
}
|
||||
|
||||
static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC )
|
||||
{
|
||||
unsigned short chunkID;
|
||||
long chunkLen;
|
||||
long bytesRead = 0;
|
||||
_3DSEditChunk_t editChunk;
|
||||
|
||||
_3DSMaterial_t mat[MAX_MATERIALS];
|
||||
_3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];
|
||||
|
||||
int numMaterials = 0, numNamedObjects = 0;
|
||||
|
||||
memset( &editChunk, 0, sizeof( editChunk ) );
|
||||
|
||||
if ( s_verbose )
|
||||
printf( ">>> EDIT CHUNK\n" );
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_MAT_LIST:
|
||||
LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );
|
||||
numMaterials++;
|
||||
break;
|
||||
case _3DS_CHUNK_NAMED_OBJECT:
|
||||
LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );
|
||||
if ( namedObjects[numNamedObjects].numTriObjects != 0 )
|
||||
++numNamedObjects;
|
||||
break;
|
||||
case _3DS_CHUNK_MESH_VERSION:
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
}
|
||||
|
||||
bytesRead += chunkLen;
|
||||
|
||||
if ( bytesRead >= thisChunkLen )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( numMaterials == 0 )
|
||||
{
|
||||
numMaterials = 1;
|
||||
strcpy( mat[0].name, "(null)" );
|
||||
printf( "Warning: no material definitions found\n" );
|
||||
}
|
||||
|
||||
pEC->numNamedObjects = numNamedObjects;
|
||||
|
||||
pEC->pMaterials = malloc( sizeof( _3DSMaterial_t ) * numMaterials );
|
||||
pEC->pNamedObjects = malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );
|
||||
|
||||
memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );
|
||||
memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );
|
||||
}
|
||||
|
||||
static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose )
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned short chunkID;
|
||||
long chunkLen;
|
||||
_3DSEditChunk_t editChunk;
|
||||
|
||||
s_verbose = verbose;
|
||||
|
||||
if ( ( fp = fopen( filename, "rb" ) ) == 0 )
|
||||
Error( "Unable to open '%s'", filename );
|
||||
|
||||
// read magic number
|
||||
if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||
|
||||
( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) )
|
||||
{
|
||||
Error( "Missing or incorrect magic number in '%s'", filename );
|
||||
}
|
||||
if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 )
|
||||
Error( "Unexpected EOF encountered in '%s'", filename );
|
||||
// version number
|
||||
if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
Error( "Missing version number in '%s'", filename );
|
||||
if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 )
|
||||
Error( "Unexpected EOF encountered in '%s'", filename );
|
||||
|
||||
while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
|
||||
{
|
||||
switch ( chunkID )
|
||||
{
|
||||
case _3DS_CHUNK_EDIT:
|
||||
LoadEditChunk( fp, chunkLen - 6, &editChunk );
|
||||
break;
|
||||
case _3DS_CHUNK_KEYFRAME_DATA:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
default:
|
||||
fread( s_buffer, chunkLen - 6, 1, fp );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
|
||||
p3DS->editChunk = editChunk;
|
||||
}
|
||||
|
||||
static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris )
|
||||
{
|
||||
vec3_t faceNormals[POLYSET_MAXTRIANGLES];
|
||||
vec3_t vertexNormals[POLYSET_MAXTRIANGLES*3];
|
||||
vec3_t side0, side1, facenormal;
|
||||
int f, v;
|
||||
|
||||
memset( faceNormals, 0, sizeof( faceNormals ) );
|
||||
memset( vertexNormals, 0, sizeof( vertexNormals ) );
|
||||
|
||||
//
|
||||
// compute face normals
|
||||
//
|
||||
for ( f = 0; f < pTO->numFaces; f++ )
|
||||
{
|
||||
VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );
|
||||
VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );
|
||||
|
||||
CrossProduct( side0, side1, facenormal );
|
||||
VectorNormalize( facenormal, faceNormals[f] );
|
||||
}
|
||||
|
||||
//
|
||||
// sum vertex normals
|
||||
//
|
||||
for ( v = 0; v < pTO->numPoints; v++ )
|
||||
{
|
||||
for ( f = 0; f < pTO->numFaces; f++ )
|
||||
{
|
||||
if ( ( pTO->pFaces[f].a == v ) ||
|
||||
( pTO->pFaces[f].b == v ) ||
|
||||
( pTO->pFaces[f].c == v ) )
|
||||
{
|
||||
vertexNormals[v][0] += faceNormals[f][0];
|
||||
vertexNormals[v][1] += faceNormals[f][1];
|
||||
vertexNormals[v][2] += faceNormals[f][2];
|
||||
}
|
||||
}
|
||||
|
||||
VectorNormalize( vertexNormals[v], vertexNormals[v] );
|
||||
}
|
||||
|
||||
//
|
||||
// copy vertex normals into triangles
|
||||
//
|
||||
for ( f = 0; f < pTO->numFaces; f++ )
|
||||
{
|
||||
int i0 = pTO->pFaces[f].c;
|
||||
int i1 = pTO->pFaces[f].b;
|
||||
int i2 = pTO->pFaces[f].a;
|
||||
|
||||
VectorCopy( vertexNormals[i0], pTris[f].normals[0] );
|
||||
VectorCopy( vertexNormals[i1], pTris[f].normals[1] );
|
||||
VectorCopy( vertexNormals[i2], pTris[f].normals[2] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** void _3DS_LoadPolysets
|
||||
*/
|
||||
void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose )
|
||||
{
|
||||
_3DS_t _3ds;
|
||||
int numPolysets;
|
||||
polyset_t *pPSET;
|
||||
triangle_t *ptri, *triangles;
|
||||
int i;
|
||||
|
||||
// load the 3DS
|
||||
memset( &_3ds, 0, sizeof( _3ds ) );
|
||||
Load3DS( filename, &_3ds, verbose );
|
||||
|
||||
// compute information
|
||||
numPolysets = _3ds.editChunk.numNamedObjects;
|
||||
|
||||
// allocate memory
|
||||
pPSET = calloc( 1, numPolysets * sizeof( polyset_t ) );
|
||||
triangles = ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
|
||||
|
||||
// copy the data over
|
||||
for ( i = 0; i < numPolysets; i++ )
|
||||
{
|
||||
char matnamebuf[1024];
|
||||
int j;
|
||||
triangle_t *tri;
|
||||
_3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];
|
||||
|
||||
pPSET[i].triangles = ptri;
|
||||
pPSET[i].numtriangles = pTO->numFaces;
|
||||
strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );
|
||||
|
||||
strcpy( matnamebuf, filename );
|
||||
if ( strrchr( matnamebuf, '/' ) )
|
||||
*( strrchr( matnamebuf, '/' ) + 1 )= 0;
|
||||
strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );
|
||||
|
||||
if ( strstr( matnamebuf, gamedir ) )
|
||||
strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );
|
||||
else
|
||||
strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );
|
||||
|
||||
assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );
|
||||
|
||||
for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )
|
||||
{
|
||||
int i0 = pTO->pFaces[j].c;
|
||||
int i1 = pTO->pFaces[j].b;
|
||||
int i2 = pTO->pFaces[j].a;
|
||||
|
||||
tri->verts[0][0] = pTO->pPoints[i0].x;
|
||||
tri->verts[0][1] = pTO->pPoints[i0].y;
|
||||
tri->verts[0][2] = pTO->pPoints[i0].z;
|
||||
|
||||
tri->verts[1][0] = pTO->pPoints[i1].x;
|
||||
tri->verts[1][1] = pTO->pPoints[i1].y;
|
||||
tri->verts[1][2] = pTO->pPoints[i1].z;
|
||||
|
||||
tri->verts[2][0] = pTO->pPoints[i2].x;
|
||||
tri->verts[2][1] = pTO->pPoints[i2].y;
|
||||
tri->verts[2][2] = pTO->pPoints[i2].z;
|
||||
/*
|
||||
for ( k = 0; k < 3; k++ )
|
||||
{
|
||||
tri->colors[0][k] = 1;
|
||||
tri->colors[1][k] = 1;
|
||||
tri->colors[2][k] = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
if ( pTO->pTexVerts )
|
||||
{
|
||||
tri->texcoords[0][0] = pTO->pTexVerts[i0].s;
|
||||
tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;
|
||||
tri->texcoords[1][0] = pTO->pTexVerts[i1].s;
|
||||
tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;
|
||||
tri->texcoords[2][0] = pTO->pTexVerts[i2].s;
|
||||
tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;
|
||||
}
|
||||
|
||||
tri++;
|
||||
}
|
||||
|
||||
ptri += pPSET[i].numtriangles;
|
||||
assert( ptri - triangles < POLYSET_MAXTRIANGLES );
|
||||
}
|
||||
|
||||
// compute normal data
|
||||
#if 0
|
||||
for ( i = 0; i < numPolysets; i++ )
|
||||
{
|
||||
// unique vertices based solely on vertex position
|
||||
ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],
|
||||
pPSET[i].triangles );
|
||||
}
|
||||
#endif
|
||||
|
||||
free( _3ds.editChunk.pMaterials );
|
||||
free( _3ds.editChunk.pNamedObjects );
|
||||
|
||||
*ppPSET = pPSET;
|
||||
*numpsets = numPolysets;
|
||||
}
|
||||
139
tools/quake3/q3data/3dslib.h
Normal file
139
tools/quake3/q3data/3dslib.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z;
|
||||
} _3DSPoint_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short a, b, c;
|
||||
short flags;
|
||||
} _3DSFace_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float s, t;
|
||||
} _3DSTexVert_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[100];
|
||||
short numFaces;
|
||||
short *pFaces;
|
||||
} _3DSMeshMaterialGroup_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[80];
|
||||
|
||||
char texture[100];
|
||||
char specular[100];
|
||||
char reflection[100];
|
||||
char bump[100];
|
||||
char opacity[100];
|
||||
} _3DSMaterial_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short numFaces, numPoints, numTexVerts;
|
||||
int numMeshMaterialGroups;
|
||||
|
||||
_3DSPoint_t *pPoints;
|
||||
_3DSFace_t *pFaces;
|
||||
_3DSTexVert_t *pTexVerts;
|
||||
|
||||
_3DSMeshMaterialGroup_t *pMeshMaterialGroups;
|
||||
} _3DSTriObject_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[100];
|
||||
|
||||
int numTriObjects;
|
||||
_3DSTriObject_t *pTriObjects;
|
||||
} _3DSNamedObject_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numNamedObjects;
|
||||
int numMaterials;
|
||||
|
||||
_3DSNamedObject_t *pNamedObjects;
|
||||
_3DSMaterial_t *pMaterials;
|
||||
|
||||
} _3DSEditChunk_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
_3DSEditChunk_t editChunk;
|
||||
} _3DS_t;
|
||||
|
||||
#define _3DS_CHUNK_NULL 0x0000
|
||||
#define _3DS_CHUNK_UNKNOWN0 0x0001
|
||||
#define _3DS_CHUNK_M3D_VERSION 0x0002
|
||||
#define _3DS_CHUNK_M3D_KFVERSION 0x0005
|
||||
#define _3DS_CHUNK_COLOR_F 0x0010
|
||||
#define _3DS_CHUNK_COLOR_24 0x0011
|
||||
#define _3DS_CHUNK_LIN_COLOR_24 0x0012
|
||||
#define _3DS_CHUNK_LIN_COLOR_F 0x0013
|
||||
#define _3DS_CHUNK_INT_PERCENTAGE 0x0030
|
||||
#define _3DS_CHUNK_FLOAT_PERCENT 0x0031
|
||||
#define _3DS_CHUNK_MASTER_SCALE 0x0100
|
||||
#define _3DS_CHUNK_CHUNK_TYPE 0x0995
|
||||
#define _3DS_CHUNK_CHUNK_UNIQUE 0x0996
|
||||
#define _3DS_CHUNK_NOT_CHUNK 0x0997
|
||||
#define _3DS_CHUNK_CONTAINER 0x0998
|
||||
#define _3DS_CHUNK_IS_CHUNK 0x0999
|
||||
#define _3DS_CHUNK_C_SXP_SELFI_MASKDATA 0x0c3c
|
||||
|
||||
#define _3DS_CHUNK_BITMAP 0x1100
|
||||
#define _3DS_CHUNK_USE_BITMAP 0x1101
|
||||
#define _3DS_CHUNK_SOLID_BGND 0x1200
|
||||
#define _3DS_CHUNK_USE_SOLID_BGND 0x1201
|
||||
|
||||
#define _3DS_CHUNK_EDIT 0x3d3d
|
||||
#define _3DS_CHUNK_MESH_VERSION 0x3d3e
|
||||
|
||||
#define _3DS_CHUNK_NAMED_OBJECT 0x4000
|
||||
#define _3DS_CHUNK_NAMED_TRI_OBJECT 0x4100
|
||||
#define _3DS_CHUNK_POINT_ARRAY 0x4110
|
||||
#define _3DS_CHUNK_POINT_FLAG_ARRAY 0x4111
|
||||
#define _3DS_CHUNK_FACE_ARRAY 0x4120
|
||||
#define _3DS_CHUNK_MSH_MAT_GROUP 0x4130
|
||||
#define _3DS_CHUNK_TEX_VERTS 0x4140
|
||||
#define _3DS_CHUNK_SMOOTH_GROUP 0x4150
|
||||
#define _3DS_CHUNK_MESH_MATRIX 0x4160
|
||||
#define _3DS_CHUNK_MAGIC 0x4d4d
|
||||
|
||||
#define _3DS_CHUNK_MAT_NAME 0xa000
|
||||
#define _3DS_CHUNK_TEXMAP 0xa200
|
||||
#define _3DS_CHUNK_SPECMAP 0xa204
|
||||
#define _3DS_CHUNK_OPACMAP 0xa210
|
||||
#define _3DS_CHUNK_REFLMAP 0xa220
|
||||
#define _3DS_CHUNK_BUMPMAP 0xa230
|
||||
#define _3DS_CHUNK_MAT_MAPNAME 0xa300
|
||||
#define _3DS_CHUNK_MAT_LIST 0xafff
|
||||
|
||||
#define _3DS_CHUNK_KEYFRAME_DATA 0xb000
|
||||
|
||||
void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose );
|
||||
771
tools/quake3/q3data/compress.c
Normal file
771
tools/quake3/q3data/compress.c
Normal file
@@ -0,0 +1,771 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "q3data.h"
|
||||
|
||||
#if 0
|
||||
/*
|
||||
==================
|
||||
MTF
|
||||
==================
|
||||
*/
|
||||
cblock_t MTF (cblock_t in)
|
||||
{
|
||||
int i, j, b, code;
|
||||
byte *out_p;
|
||||
int index[256];
|
||||
cblock_t out;
|
||||
|
||||
out_p = out.data = malloc(in.count + 4);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
index[i] = i;
|
||||
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
{
|
||||
b = in.data[i];
|
||||
code = index[b];
|
||||
*out_p++ = code;
|
||||
|
||||
// shuffle b indexes to 0
|
||||
for (j=0 ; j<256 ; j++)
|
||||
if (index[j] < code)
|
||||
index[j]++;
|
||||
index[b] = 0;
|
||||
}
|
||||
|
||||
out.count = out_p - out.data;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
||||
int bwt_size;
|
||||
byte *bwt_data;
|
||||
|
||||
int bwtCompare (const void *elem1, const void *elem2)
|
||||
{
|
||||
int i;
|
||||
int i1, i2;
|
||||
int b1, b2;
|
||||
|
||||
i1 = *(int *)elem1;
|
||||
i2 = *(int *)elem2;
|
||||
|
||||
for (i=0 ; i<bwt_size ; i++)
|
||||
{
|
||||
b1 = bwt_data[i1];
|
||||
b2 = bwt_data[i2];
|
||||
if (b1 < b2)
|
||||
return -1;
|
||||
if (b1 > b2)
|
||||
return 1;
|
||||
if (++i1 == bwt_size)
|
||||
i1 = 0;
|
||||
if (++i2 == bwt_size)
|
||||
i2 = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BWT
|
||||
==================
|
||||
*/
|
||||
cblock_t BWT (cblock_t in)
|
||||
{
|
||||
int *sorted;
|
||||
int i;
|
||||
byte *out_p;
|
||||
cblock_t out;
|
||||
|
||||
bwt_size = in.count;
|
||||
bwt_data = in.data;
|
||||
|
||||
sorted = malloc(in.count*sizeof(*sorted));
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
sorted[i] = i;
|
||||
qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
|
||||
|
||||
out_p = out.data = malloc(in.count + 8);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
// write head index
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
if (sorted[i] == 0)
|
||||
break;
|
||||
*out_p++ = i&255;
|
||||
*out_p++ = (i>>8)&255;
|
||||
*out_p++ = (i>>16)&255;
|
||||
*out_p++ = (i>>24)&255;
|
||||
|
||||
// write the L column
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
*out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
|
||||
|
||||
free (sorted);
|
||||
|
||||
out.count = out_p - out.data;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
typedef struct hnode_s
|
||||
{
|
||||
int count;
|
||||
qboolean used;
|
||||
int children[2];
|
||||
} hnode_t;
|
||||
|
||||
int numhnodes;
|
||||
hnode_t hnodes[512];
|
||||
unsigned charbits[256];
|
||||
int charbitscount[256];
|
||||
|
||||
int SmallestNode (void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void BuildChars (int nodenum, unsigned bits, int bitcount)
|
||||
{
|
||||
hnode_t *node;
|
||||
|
||||
if (nodenum < 256)
|
||||
{
|
||||
if (bitcount > 32)
|
||||
Error ("bitcount > 32");
|
||||
charbits[nodenum] = bits;
|
||||
charbitscount[nodenum] = bitcount;
|
||||
return;
|
||||
}
|
||||
|
||||
node = &hnodes[nodenum];
|
||||
bits <<= 1;
|
||||
BuildChars (node->children[0], bits, bitcount+1);
|
||||
bits |= 1;
|
||||
BuildChars (node->children[1], bits, bitcount+1);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Huffman
|
||||
==================
|
||||
*/
|
||||
cblock_t Huffman (cblock_t in)
|
||||
{
|
||||
int i;
|
||||
hnode_t *node;
|
||||
int outbits, c;
|
||||
unsigned bits;
|
||||
byte *out_p;
|
||||
cblock_t out;
|
||||
int max, maxchar;
|
||||
|
||||
// count
|
||||
memset (hnodes, 0, sizeof(hnodes));
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
hnodes[in.data[i]].count++;
|
||||
|
||||
// normalize counts
|
||||
max = 0;
|
||||
maxchar = 0;
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
if (hnodes[i].count > max)
|
||||
{
|
||||
max = hnodes[i].count;
|
||||
maxchar = i;
|
||||
}
|
||||
}
|
||||
if (max == 0)
|
||||
Error ("Huffman: max == 0");
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
hnodes[i].count = (hnodes[i].count*255+max-1) / max;
|
||||
}
|
||||
|
||||
// build the nodes
|
||||
numhnodes = 256;
|
||||
while (numhnodes != 511)
|
||||
{
|
||||
node = &hnodes[numhnodes];
|
||||
|
||||
// pick two lowest counts
|
||||
node->children[0] = SmallestNode ();
|
||||
if (node->children[0] == -1)
|
||||
break; // no more
|
||||
|
||||
node->children[1] = SmallestNode ();
|
||||
if (node->children[1] == -1)
|
||||
{
|
||||
if (node->children[0] != numhnodes-1)
|
||||
Error ("Bad smallestnode");
|
||||
break;
|
||||
}
|
||||
node->count = hnodes[node->children[0]].count +
|
||||
hnodes[node->children[1]].count;
|
||||
numhnodes++;
|
||||
}
|
||||
|
||||
BuildChars (numhnodes-1, 0, 0);
|
||||
|
||||
out_p = out.data = malloc(in.count*2 + 1024);
|
||||
memset (out_p, 0, in.count*2+1024);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
// save out the 256 normalized counts so the tree can be recreated
|
||||
for (i=0 ; i<256 ; i++)
|
||||
*out_p++ = hnodes[i].count;
|
||||
|
||||
// write bits
|
||||
outbits = 0;
|
||||
for (i=0 ; i<in.count ; i++)
|
||||
{
|
||||
c = charbitscount[in.data[i]];
|
||||
bits = charbits[in.data[i]];
|
||||
while (c)
|
||||
{
|
||||
c--;
|
||||
if (bits & (1<<c))
|
||||
out_p[outbits>>3] |= 1<<(outbits&7);
|
||||
outbits++;
|
||||
}
|
||||
}
|
||||
|
||||
out_p += (outbits+7)>>3;
|
||||
|
||||
out.count = out_p - out.data;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
RLE
|
||||
==================
|
||||
*/
|
||||
#define RLE_CODE 0xe8
|
||||
#define RLE_TRIPPLE 0xe9
|
||||
|
||||
int rle_counts[256];
|
||||
int rle_bytes[256];
|
||||
|
||||
cblock_t RLE (cblock_t in)
|
||||
{
|
||||
int i;
|
||||
byte *out_p;
|
||||
int val;
|
||||
int repeat;
|
||||
cblock_t out;
|
||||
|
||||
out_p = out.data = malloc (in.count*2);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
for (i=0 ; i<in.count ; )
|
||||
{
|
||||
val = in.data[i];
|
||||
rle_bytes[val]++;
|
||||
repeat = 1;
|
||||
i++;
|
||||
while (i<in.count && repeat < 255 && in.data[i] == val)
|
||||
{
|
||||
repeat++;
|
||||
i++;
|
||||
}
|
||||
if (repeat < 256)
|
||||
rle_counts[repeat]++;
|
||||
if (repeat > 3 || val == RLE_CODE)
|
||||
{
|
||||
*out_p++ = RLE_CODE;
|
||||
*out_p++ = val;
|
||||
*out_p++ = repeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (repeat--)
|
||||
*out_p++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
out.count = out_p - out.data;
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
unsigned lzss_head[256];
|
||||
unsigned lzss_next[0x20000];
|
||||
|
||||
/*
|
||||
==================
|
||||
LZSS
|
||||
==================
|
||||
*/
|
||||
#define BACK_WINDOW 0x10000
|
||||
#define BACK_BITS 16
|
||||
#define FRONT_WINDOW 16
|
||||
#define FRONT_BITS 4
|
||||
cblock_t LZSS (cblock_t in)
|
||||
{
|
||||
int i;
|
||||
byte *out_p;
|
||||
cblock_t out;
|
||||
int val;
|
||||
int j, start, max;
|
||||
int bestlength, beststart;
|
||||
int outbits;
|
||||
|
||||
if (in.count >= sizeof(lzss_next)/4)
|
||||
Error ("LZSS: too big");
|
||||
|
||||
memset (lzss_head, -1, sizeof(lzss_head));
|
||||
|
||||
out_p = out.data = malloc (in.count*2);
|
||||
memset (out.data, 0, in.count*2);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
outbits = 0;
|
||||
for (i=0 ; i<in.count ; )
|
||||
{
|
||||
val = in.data[i];
|
||||
#if 1
|
||||
// chained search
|
||||
bestlength = 0;
|
||||
beststart = 0;
|
||||
|
||||
max = FRONT_WINDOW;
|
||||
if (i + max > in.count)
|
||||
max = in.count - i;
|
||||
|
||||
start = lzss_head[val];
|
||||
while (start != -1 && start >= i-BACK_WINDOW)
|
||||
{
|
||||
// count match length
|
||||
for (j=0 ; j<max ; j++)
|
||||
if (in.data[start+j] != in.data[i+j])
|
||||
break;
|
||||
if (j > bestlength)
|
||||
{
|
||||
bestlength = j;
|
||||
beststart = start;
|
||||
}
|
||||
start = lzss_next[start];
|
||||
}
|
||||
|
||||
#else
|
||||
// slow simple search
|
||||
// search for a match
|
||||
max = FRONT_WINDOW;
|
||||
if (i + max > in.count)
|
||||
max = in.count - i;
|
||||
|
||||
start = i - BACK_WINDOW;
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
bestlength = 0;
|
||||
beststart = 0;
|
||||
for ( ; start < i ; start++)
|
||||
{
|
||||
if (in.data[start] != val)
|
||||
continue;
|
||||
// count match length
|
||||
for (j=0 ; j<max ; j++)
|
||||
if (in.data[start+j] != in.data[i+j])
|
||||
break;
|
||||
if (j > bestlength)
|
||||
{
|
||||
bestlength = j;
|
||||
beststart = start;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
beststart = BACK_WINDOW - (i-beststart);
|
||||
|
||||
if (bestlength < 3)
|
||||
{ // output a single char
|
||||
bestlength = 1;
|
||||
|
||||
out_p[outbits>>3] |= 1<<(outbits&7); // set bit to mark char
|
||||
outbits++;
|
||||
for (j=0 ; j<8 ; j++, outbits++)
|
||||
if (val & (1<<j) )
|
||||
out_p[outbits>>3] |= 1<<(outbits&7);
|
||||
}
|
||||
else
|
||||
{ // output a phrase
|
||||
outbits++; // leave a 0 bit to mark phrase
|
||||
for (j=0 ; j<BACK_BITS ; j++, outbits++)
|
||||
if (beststart & (1<<j) )
|
||||
out_p[outbits>>3] |= 1<<(outbits&7);
|
||||
for (j=0 ; j<FRONT_BITS ; j++, outbits++)
|
||||
if (bestlength & (1<<j) )
|
||||
out_p[outbits>>3] |= 1<<(outbits&7);
|
||||
}
|
||||
|
||||
while (bestlength--)
|
||||
{
|
||||
val = in.data[i];
|
||||
lzss_next[i] = lzss_head[val];
|
||||
lzss_head[val] = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
out_p += (outbits+7)>>3;
|
||||
out.count = out_p - out.data;
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
#define MIN_REPT 15
|
||||
#define MAX_REPT 0
|
||||
#define HUF_TOKENS (256+MAX_REPT)
|
||||
|
||||
unsigned charbits1[256][HUF_TOKENS];
|
||||
int charbitscount1[256][HUF_TOKENS];
|
||||
|
||||
hnode_t hnodes1[256][HUF_TOKENS*2];
|
||||
int numhnodes1[256];
|
||||
|
||||
int order0counts[256];
|
||||
|
||||
/*
|
||||
==================
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
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;
|
||||
#if 1
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Huffman1_Build
|
||||
==================
|
||||
*/
|
||||
byte scaled[256][HUF_TOKENS];
|
||||
void Huffman1_Build (FILE *f)
|
||||
{
|
||||
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;
|
||||
for (j=0 ; j<HUF_TOKENS ; j++)
|
||||
{ // easy to overflow 32 bits here!
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// count up the total bits
|
||||
total = 0;
|
||||
for (i=0 ; i<256 ; i++)
|
||||
for (j=0 ; j<256 ; j++)
|
||||
total += charbitscount1[i][j] * hnodes1[i][j].count;
|
||||
|
||||
total = (total+7)/8;
|
||||
printf ("%i bytes huffman1 compressed\n", total);
|
||||
#endif
|
||||
|
||||
fwrite (scaled, 1, sizeof(scaled), f);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
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 = malloc(in.count*2 + 1024);
|
||||
memset (out_p, 0, in.count*2+1024);
|
||||
|
||||
// write count
|
||||
*out_p++ = in.count&255;
|
||||
*out_p++ = (in.count>>8)&255;
|
||||
*out_p++ = (in.count>>16)&255;
|
||||
*out_p++ = (in.count>>24)&255;
|
||||
|
||||
// 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;
|
||||
#if 1
|
||||
// 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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
out_p += (outbits+7)>>3;
|
||||
|
||||
out.count = out_p - out.data;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
486
tools/quake3/q3data/images.c
Normal file
486
tools/quake3/q3data/images.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "q3data.h"
|
||||
|
||||
byte *byteimage, *lbmpalette;
|
||||
int byteimagewidth, byteimageheight;
|
||||
|
||||
|
||||
char mip_prefix[1024]; // directory to dump the textures in
|
||||
|
||||
qboolean colormap_issued;
|
||||
byte colormap_palette[768];
|
||||
|
||||
/*
|
||||
==============
|
||||
Cmd_Grab
|
||||
|
||||
$grab filename x y width height
|
||||
==============
|
||||
*/
|
||||
void Cmd_Grab (void)
|
||||
{
|
||||
int xl,yl,w,h,y;
|
||||
byte *cropped;
|
||||
char savename[1024];
|
||||
char dest[1024];
|
||||
|
||||
GetToken (qfalse);
|
||||
|
||||
if (token[0] == '/' || token[0] == '\\')
|
||||
sprintf (savename, "%s%s.pcx", writedir, token+1);
|
||||
else
|
||||
sprintf (savename, "%spics/%s.pcx", writedir, token);
|
||||
|
||||
if (g_release)
|
||||
{
|
||||
if (token[0] == '/' || token[0] == '\\')
|
||||
sprintf (dest, "%s.pcx", token+1);
|
||||
else
|
||||
sprintf (dest, "pics/%s.pcx", token);
|
||||
|
||||
ReleaseFile (dest);
|
||||
return;
|
||||
}
|
||||
|
||||
GetToken (qfalse);
|
||||
xl = atoi (token);
|
||||
GetToken (qfalse);
|
||||
yl = atoi (token);
|
||||
GetToken (qfalse);
|
||||
w = atoi (token);
|
||||
GetToken (qfalse);
|
||||
h = atoi (token);
|
||||
|
||||
if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
|
||||
Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
|
||||
|
||||
// crop it to the proper size
|
||||
cropped = malloc (w*h);
|
||||
for (y=0 ; y<h ; y++)
|
||||
{
|
||||
memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
|
||||
}
|
||||
|
||||
// save off the new image
|
||||
printf ("saving %s\n", savename);
|
||||
CreatePath (savename);
|
||||
WritePCXfile (savename, cropped, w, h, lbmpalette);
|
||||
|
||||
free (cropped);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Cmd_Raw
|
||||
|
||||
$grab filename x y width height
|
||||
==============
|
||||
*/
|
||||
void Cmd_Raw (void)
|
||||
{
|
||||
int xl,yl,w,h,y;
|
||||
byte *cropped;
|
||||
char savename[1024];
|
||||
char dest[1024];
|
||||
|
||||
GetToken (qfalse);
|
||||
|
||||
sprintf (savename, "%s%s.lmp", writedir, token);
|
||||
|
||||
if (g_release)
|
||||
{
|
||||
sprintf (dest, "%s.lmp", token);
|
||||
ReleaseFile (dest);
|
||||
return;
|
||||
}
|
||||
|
||||
GetToken (qfalse);
|
||||
xl = atoi (token);
|
||||
GetToken (qfalse);
|
||||
yl = atoi (token);
|
||||
GetToken (qfalse);
|
||||
w = atoi (token);
|
||||
GetToken (qfalse);
|
||||
h = atoi (token);
|
||||
|
||||
if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
|
||||
Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
|
||||
|
||||
// crop it to the proper size
|
||||
cropped = malloc (w*h);
|
||||
for (y=0 ; y<h ; y++)
|
||||
{
|
||||
memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
|
||||
}
|
||||
|
||||
// save off the new image
|
||||
printf ("saving %s\n", savename);
|
||||
CreatePath (savename);
|
||||
|
||||
SaveFile (savename, cropped, w*h);
|
||||
|
||||
free (cropped);
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
COLORMAP GRABBING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============
|
||||
BestColor
|
||||
===============
|
||||
*/
|
||||
byte BestColor (int r, int g, int b, int start, int stop)
|
||||
{
|
||||
int i;
|
||||
int dr, dg, db;
|
||||
int bestdistortion, distortion;
|
||||
int bestcolor;
|
||||
byte *pal;
|
||||
|
||||
//
|
||||
// let any color go to 0 as a last resort
|
||||
//
|
||||
bestdistortion = 256*256*4;
|
||||
bestcolor = 0;
|
||||
|
||||
pal = colormap_palette + start*3;
|
||||
for (i=start ; i<= stop ; i++)
|
||||
{
|
||||
dr = r - (int)pal[0];
|
||||
dg = g - (int)pal[1];
|
||||
db = b - (int)pal[2];
|
||||
pal += 3;
|
||||
distortion = dr*dr + dg*dg + db*db;
|
||||
if (distortion < bestdistortion)
|
||||
{
|
||||
if (!distortion)
|
||||
return i; // perfect match
|
||||
|
||||
bestdistortion = distortion;
|
||||
bestcolor = i;
|
||||
}
|
||||
}
|
||||
|
||||
return bestcolor;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
Cmd_Colormap
|
||||
|
||||
$colormap filename
|
||||
|
||||
the brightes colormap is first in the table (FIXME: reverse this now?)
|
||||
|
||||
64 rows of 256 : lightmaps
|
||||
256 rows of 256 : translucency table
|
||||
==============
|
||||
*/
|
||||
void Cmd_Colormap (void)
|
||||
{
|
||||
int levels, brights;
|
||||
int l, c;
|
||||
float frac, red, green, blue;
|
||||
float range;
|
||||
byte *cropped, *lump_p;
|
||||
char savename[1024];
|
||||
char dest[1024];
|
||||
|
||||
colormap_issued = qtrue;
|
||||
if (!g_release)
|
||||
memcpy (colormap_palette, lbmpalette, 768);
|
||||
|
||||
if (!TokenAvailable ())
|
||||
{ // just setting colormap_issued
|
||||
return;
|
||||
}
|
||||
|
||||
GetToken (qfalse);
|
||||
sprintf (savename, "%spics/%s.pcx", writedir, token);
|
||||
|
||||
if (g_release)
|
||||
{
|
||||
sprintf (dest, "pics/%s.pcx", token);
|
||||
ReleaseFile (dest);
|
||||
return;
|
||||
}
|
||||
|
||||
range = 2;
|
||||
levels = 64;
|
||||
brights = 1; // ignore 255 (transparent)
|
||||
|
||||
cropped = malloc((levels+256)*256);
|
||||
lump_p = cropped;
|
||||
|
||||
// shaded levels
|
||||
for (l=0;l<levels;l++)
|
||||
{
|
||||
frac = range - range*(float)l/(levels-1);
|
||||
for (c=0 ; c<256-brights ; c++)
|
||||
{
|
||||
red = lbmpalette[c*3];
|
||||
green = lbmpalette[c*3+1];
|
||||
blue = lbmpalette[c*3+2];
|
||||
|
||||
red = (int)(red*frac+0.5);
|
||||
green = (int)(green*frac+0.5);
|
||||
blue = (int)(blue*frac+0.5);
|
||||
|
||||
//
|
||||
// note: 254 instead of 255 because 255 is the transparent color, and we
|
||||
// don't want anything remapping to that
|
||||
// don't use color 0, because NT can't remap that (or 255)
|
||||
//
|
||||
*lump_p++ = BestColor(red,green,blue, 1, 254);
|
||||
}
|
||||
|
||||
// fullbrights allways stay the same
|
||||
for ( ; c<256 ; c++)
|
||||
*lump_p++ = c;
|
||||
}
|
||||
|
||||
// 66% transparancy table
|
||||
for (l=0;l<255;l++)
|
||||
{
|
||||
for (c=0 ; c<255 ; c++)
|
||||
{
|
||||
red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
|
||||
green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
|
||||
blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
|
||||
|
||||
*lump_p++ = BestColor(red,green,blue, 1, 254);
|
||||
}
|
||||
*lump_p++ = 255;
|
||||
}
|
||||
for (c=0 ; c<256 ; c++)
|
||||
*lump_p++ = 255;
|
||||
|
||||
// save off the new image
|
||||
printf ("saving %s\n", savename);
|
||||
CreatePath (savename);
|
||||
WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
|
||||
|
||||
free (cropped);
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
MIPTEX GRABBING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
byte pixdata[256];
|
||||
|
||||
int d_red, d_green, d_blue;
|
||||
|
||||
byte palmap[32][32][32];
|
||||
qboolean palmap_built;
|
||||
|
||||
/*
|
||||
=============
|
||||
FindColor
|
||||
=============
|
||||
*/
|
||||
int FindColor (int r, int g, int b)
|
||||
{
|
||||
int bestcolor;
|
||||
|
||||
if (r > 255)
|
||||
r = 255;
|
||||
if (r < 0)
|
||||
r = 0;
|
||||
if (g > 255)
|
||||
g = 255;
|
||||
if (g < 0)
|
||||
g = 0;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
if (b < 0)
|
||||
b = 0;
|
||||
#ifndef TABLECOLORS
|
||||
bestcolor = BestColor (r, g, b, 0, 254);
|
||||
#else
|
||||
bestcolor = palmap[r>>3][g>>3][b>>3];
|
||||
#endif
|
||||
|
||||
return bestcolor;
|
||||
}
|
||||
|
||||
|
||||
void BuildPalmap (void)
|
||||
{
|
||||
#ifdef TABLECOLORS
|
||||
int r, g, b;
|
||||
int bestcolor;
|
||||
|
||||
if (palmap_built)
|
||||
return;
|
||||
palmap_built = qtrue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
ENVIRONMENT MAP GRABBING
|
||||
|
||||
Creates six pcx files from tga files without any palette edge seams
|
||||
also copies the tga files for GL rendering.
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
// 3dstudio environment map suffixes
|
||||
char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
|
||||
|
||||
/*
|
||||
=================
|
||||
Cmd_Environment
|
||||
=================
|
||||
*/
|
||||
void Cmd_Environment (void)
|
||||
{
|
||||
char name[1024];
|
||||
int i, x, y;
|
||||
byte image[256*256];
|
||||
byte *tga;
|
||||
|
||||
GetToken (qfalse);
|
||||
|
||||
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", writedir, token, suf[i]);
|
||||
if (FileTime (name) != -1)
|
||||
printf ("%s already exists, not overwriting.\n", name);
|
||||
else
|
||||
WritePCXfile (name, image, 256, 256, colormap_palette);
|
||||
}
|
||||
}
|
||||
|
||||
214
tools/quake3/q3data/md3lib.c
Normal file
214
tools/quake3/q3data/md3lib.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "md3lib.h"
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
#define filelength Q_filelength
|
||||
#endif
|
||||
|
||||
/*
|
||||
** MD3_ComputeTagFromTri
|
||||
*/
|
||||
void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float pTri[3][3] )
|
||||
{
|
||||
float len[3];
|
||||
vec3_t axes[3], sides[3];
|
||||
int longestSide, shortestSide, hypotSide;
|
||||
int origin;
|
||||
int j;
|
||||
float d;
|
||||
|
||||
memset( axes, 0, sizeof( axes ) );
|
||||
memset( sides, 0, sizeof( sides ) );
|
||||
|
||||
//
|
||||
// compute sides
|
||||
//
|
||||
for ( j = 0; j < 3; j++ )
|
||||
{
|
||||
sides[j][0] = pTri[(j+1)%3][0] - pTri[j][0];
|
||||
sides[j][1] = pTri[(j+1)%3][1] - pTri[j][1];
|
||||
sides[j][2] = pTri[(j+1)%3][2] - pTri[j][2];
|
||||
|
||||
len[j] = ( float ) sqrt( DotProduct( sides[j], sides[j] ) );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( len[0] > len[1] && len[0] > len[2] )
|
||||
{
|
||||
longestSide = 0; shortestSide = 1; origin = 2;
|
||||
}
|
||||
else if ( len[1] > len[0] && len[1] > len[2] )
|
||||
{
|
||||
longestSide = 1; shortestSide = 2; origin = 0;
|
||||
}
|
||||
else if ( len[2] > len[0] && len[2] > len[1] )
|
||||
{
|
||||
longestSide = 2; shortestSide = 0; origin = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error( "invalid tag triangle, must be a right triangle with unequal length sides" );
|
||||
}
|
||||
#endif
|
||||
if ( len[0] > len[1] && len[0] > len[2] ) {
|
||||
hypotSide = 0;
|
||||
origin = 2;
|
||||
} else if ( len[1] > len[0] && len[1] > len[2] ) {
|
||||
hypotSide = 1;
|
||||
origin = 0;
|
||||
} else if ( len[2] > len[0] && len[2] > len[1] ) {
|
||||
hypotSide = 2;
|
||||
origin = 1;
|
||||
}
|
||||
len[hypotSide] = -1;
|
||||
|
||||
if ( len[0] > len[1] && len[0] > len[2] ) {
|
||||
longestSide = 0;
|
||||
} else if ( len[1] > len[0] && len[1] > len[2] ) {
|
||||
longestSide = 1;
|
||||
} else if ( len[2] > len[0] && len[2] > len[1] ) {
|
||||
longestSide = 2;
|
||||
}
|
||||
len[longestSide] = -1;
|
||||
|
||||
if ( len[0] > len[1] && len[0] > len[2] ) {
|
||||
shortestSide = 0;
|
||||
} else if ( len[1] > len[0] && len[1] > len[2] ) {
|
||||
shortestSide = 1;
|
||||
} else if ( len[2] > len[0] && len[2] > len[1] ) {
|
||||
shortestSide = 2;
|
||||
}
|
||||
len[shortestSide] = -1;
|
||||
|
||||
|
||||
|
||||
// VectorNormalize( sides[shortestSide], axes[0] );
|
||||
// VectorNormalize( sides[longestSide], axes[1] );
|
||||
VectorNormalize( sides[longestSide], axes[0] );
|
||||
VectorNormalize( sides[shortestSide], axes[1] );
|
||||
|
||||
// project shortest side so that it is exactly 90 degrees to the longer side
|
||||
d = DotProduct( axes[0], axes[1] );
|
||||
VectorMA( axes[0], -d, axes[1], axes[0] );
|
||||
VectorNormalize( axes[0], axes[0] );
|
||||
|
||||
CrossProduct( sides[longestSide], sides[shortestSide], axes[2] );
|
||||
VectorNormalize( axes[2], axes[2] );
|
||||
|
||||
pTag->origin[0] = pTri[origin][0];
|
||||
pTag->origin[1] = pTri[origin][1];
|
||||
pTag->origin[2] = pTri[origin][2];
|
||||
|
||||
VectorCopy( axes[0], pTag->axis[0] );
|
||||
VectorCopy( axes[1], pTag->axis[1] );
|
||||
VectorCopy( axes[2], pTag->axis[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
MD3_Dump
|
||||
==============
|
||||
*/
|
||||
void MD3_Dump( const char *filename )
|
||||
{
|
||||
md3Header_t header;
|
||||
md3Tag_t *pTag;
|
||||
md3Surface_t *pSurface;
|
||||
FILE *fp;
|
||||
void *_buffer;
|
||||
void *buffer;
|
||||
long fileSize;
|
||||
int i;
|
||||
|
||||
if ( ( fp = fopen( filename, "rb" ) ) == 0 )
|
||||
{
|
||||
Error( "Unable to open '%s'\n", filename );
|
||||
}
|
||||
|
||||
fileSize = filelength( fileno( fp ) );
|
||||
_buffer = malloc( filelength( fileno( fp ) ) );
|
||||
fread( _buffer, fileSize, 1, fp );
|
||||
fclose( fp );
|
||||
|
||||
buffer = ( char * ) _buffer;
|
||||
header = *( md3Header_t * ) _buffer;
|
||||
|
||||
if ( header.ident != MD3_IDENT )
|
||||
{
|
||||
Error( "Incorrect ident for '%s'\n", filename );
|
||||
}
|
||||
|
||||
printf( "Contents of '%s'\n", filename );
|
||||
printf( " version: %d\n", header.version );
|
||||
printf( " name: %s\n", header.name );
|
||||
printf( " num frames: %d\n", header.numFrames );
|
||||
printf( " num tags: %d\n", header.numTags );
|
||||
printf( " num surfaces: %d\n", header.numSurfaces );
|
||||
printf( " num skins: %d\n", header.numSkins );
|
||||
printf( " file size: %d\n", fileSize );
|
||||
|
||||
printf( "--- TAGS ---\n" );
|
||||
pTag = ( md3Tag_t * ) ( ( ( char * ) buffer ) + header.ofsTags );
|
||||
for ( i = 0; i < header.numTags; i++, pTag++ )
|
||||
{
|
||||
printf( " tag %d ('%s')\n", i, pTag->name );
|
||||
printf( " origin: %f,%f,%f\n", pTag->origin[0], pTag->origin[1], pTag->origin[2] );
|
||||
printf( " vf: %f,%f,%f\n", pTag->axis[0][0], pTag->axis[0][1], pTag->axis[0][2] );
|
||||
printf( " vr: %f,%f,%f\n", pTag->axis[1][0], pTag->axis[1][1], pTag->axis[1][2] );
|
||||
printf( " vu: %f,%f,%f\n", pTag->axis[2][0], pTag->axis[2][1], pTag->axis[2][2] );
|
||||
}
|
||||
|
||||
printf( "--- SURFACES ---\n" );
|
||||
pSurface = ( md3Surface_t * ) ( ( ( char * ) buffer ) + header.ofsSurfaces );
|
||||
|
||||
for ( i = 0; i < header.numSurfaces; i++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
md3Shader_t *pShader = ( md3Shader_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsShaders );
|
||||
|
||||
printf( "\n surface %d ('%s')\n", i, pSurface->name );
|
||||
printf( " num frames: %d\n", pSurface->numFrames );
|
||||
printf( " num shaders: %d\n", pSurface->numShaders );
|
||||
printf( " num tris: %d\n", pSurface->numTriangles );
|
||||
printf( " num verts: %d\n", pSurface->numVerts );
|
||||
|
||||
if ( pSurface->numShaders > 0 )
|
||||
{
|
||||
printf( " --- SHADERS ---\n" );
|
||||
|
||||
for ( j = 0; j < pSurface->numShaders; j++, pShader++ )
|
||||
{
|
||||
printf( " shader %d ('%s')\n", j, pShader->name );
|
||||
}
|
||||
}
|
||||
pSurface = ( md3Surface_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsEnd );
|
||||
}
|
||||
|
||||
free( _buffer );
|
||||
}
|
||||
|
||||
28
tools/quake3/q3data/md3lib.h
Normal file
28
tools/quake3/q3data/md3lib.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../common/cmdlib.h"
|
||||
#include "mathlib.h"
|
||||
#include "../common/qfiles.h"
|
||||
|
||||
void MD3_Dump( const char *filename );
|
||||
void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float tri[3][3] );
|
||||
2155
tools/quake3/q3data/models.c
Normal file
2155
tools/quake3/q3data/models.c
Normal file
File diff suppressed because it is too large
Load Diff
151
tools/quake3/q3data/oldstuff.c
Normal file
151
tools/quake3/q3data/oldstuff.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
** ReindexTriangle
|
||||
**
|
||||
** Given a triangle_t, find which indices match into the associated
|
||||
** surface's base triangles.
|
||||
*/
|
||||
static void ReindexTriangle( int surfno, triangle_t *pTri, int indices[3] )
|
||||
{
|
||||
int t, i;
|
||||
md3SurfaceData_t *pSurfData = &g_data.surfData[surfno];
|
||||
int matches[3][3];
|
||||
int numMatches = 0;
|
||||
|
||||
|
||||
indices[0] = -1;
|
||||
indices[1] = -1;
|
||||
indices[2] = -1;
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
numMatches = 0;
|
||||
|
||||
matches[i][0] = -1;
|
||||
matches[i][1] = -1;
|
||||
matches[i][2] = -1;
|
||||
|
||||
for ( t = 0; t < pSurfData->header.numVerts; t++ )
|
||||
{
|
||||
if ( !VectorCompare( pTri->verts[i], pSurfData->baseVertexes[t].xyz ) )
|
||||
continue;
|
||||
|
||||
/*
|
||||
if ( !VectorCompare( pTri->normals[i], pSurfData->baseVertexes[t].normal ) )
|
||||
continue;
|
||||
if ( pTri->texcoords[i][0] != pSurfData->baseVertexes[t].st[0] )
|
||||
continue;
|
||||
if ( pTri->texcoords[i][1] != pSurfData->baseVertexes[t].st[1] )
|
||||
continue;
|
||||
*/
|
||||
|
||||
matches[i][numMatches++] = t;
|
||||
}
|
||||
|
||||
if ( indices[i] == -1 )
|
||||
{
|
||||
// Error( "Could not ReindexTriangle, vertex not found" );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for ( t = 0; t < psets[i].numtriangles; t++ )
|
||||
{
|
||||
int b;
|
||||
|
||||
bTri = &g_data.surfData[i].baseTriangles[t];
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
bVert = &bTri->v[j];
|
||||
|
||||
// get the xyz index
|
||||
for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
|
||||
{
|
||||
if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
|
||||
( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
|
||||
( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
|
||||
( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
|
||||
{
|
||||
break; // this vertex is already in the base vertex list
|
||||
}
|
||||
}
|
||||
|
||||
if (k == g_data.surfData[i].header.numVerts) { // new index
|
||||
g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
|
||||
g_data.surfData[i].header.numVerts++;
|
||||
}
|
||||
|
||||
bVert->index = k;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *FindFrameFile (const char *frame)
|
||||
{
|
||||
int time1;
|
||||
char file1[1024];
|
||||
static char retname[1024];
|
||||
char base[32];
|
||||
char suffix[32];
|
||||
const 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;
|
||||
|
||||
// check for 'run1.tri'
|
||||
sprintf (file1, "%s/%s%s.tri", g_cddir, base, suffix);
|
||||
time1 = FileTime (file1);
|
||||
if (time1 != -1)
|
||||
{
|
||||
sprintf (retname, "%s%s.tri", base, suffix);
|
||||
return retname;
|
||||
}
|
||||
|
||||
// check for 'run.1'
|
||||
sprintf (file1, "%s/%s.%s",g_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;
|
||||
}
|
||||
|
||||
#endif
|
||||
345
tools/quake3/q3data/p3dlib.c
Normal file
345
tools/quake3/q3data/p3dlib.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "p3dlib.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_POLYSETS 64
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
#define _strcmpi Q_stricmp
|
||||
#define filelength Q_filelength
|
||||
#define strlwr strlower
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
long len;
|
||||
|
||||
int numPairs;
|
||||
char polysetNames[MAX_POLYSETS][256];
|
||||
char shaders[MAX_POLYSETS][256];
|
||||
|
||||
char *buffer, *curpos;
|
||||
} p3d_t;
|
||||
|
||||
static p3d_t p3d;
|
||||
|
||||
static int P3DProcess();
|
||||
static int P3DGetToken( int restOfLine );
|
||||
|
||||
static char s_token[1024];
|
||||
static int s_curpair;
|
||||
|
||||
/*
|
||||
** P3DLoad
|
||||
**
|
||||
*/
|
||||
int P3DLoad( const char *filename )
|
||||
{
|
||||
FILE *fp = fopen( filename, "rb" );
|
||||
|
||||
if ( !fp )
|
||||
return 0;
|
||||
|
||||
memset( &p3d, 0, sizeof( p3d ) );
|
||||
|
||||
p3d.len = filelength( fileno( fp ) );
|
||||
|
||||
p3d.curpos = p3d.buffer = malloc( p3d.len );
|
||||
|
||||
if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 )
|
||||
{
|
||||
fclose( fp );
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
|
||||
return P3DProcess();
|
||||
}
|
||||
|
||||
/*
|
||||
** P3DClose
|
||||
**
|
||||
*/
|
||||
void P3DClose()
|
||||
{
|
||||
if ( p3d.buffer )
|
||||
{
|
||||
free( p3d.buffer );
|
||||
p3d.buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CharIsTokenDelimiter( int ch )
|
||||
{
|
||||
if ( ch <= 32 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int P3DSkipToToken( const char *name )
|
||||
{
|
||||
while ( P3DGetToken( 0 ) )
|
||||
{
|
||||
if ( !_strcmpi( s_token, name ) )
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** P3DGetToken
|
||||
**
|
||||
*/
|
||||
int P3DGetToken( int restOfLine )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if ( p3d.buffer == 0 )
|
||||
return 0;
|
||||
|
||||
if ( ( p3d.curpos - p3d.buffer ) == p3d.len )
|
||||
return 0;
|
||||
|
||||
// skip over crap
|
||||
while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
|
||||
( *p3d.curpos <= 32 ) )
|
||||
{
|
||||
p3d.curpos++;
|
||||
}
|
||||
|
||||
while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
|
||||
{
|
||||
s_token[i] = *p3d.curpos;
|
||||
|
||||
p3d.curpos++;
|
||||
i++;
|
||||
|
||||
if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
|
||||
( ( s_token[i-1] == '\n' ) ) )
|
||||
{
|
||||
s_token[i-1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s_token[i] = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int P3DGetNextPair( char **psetName, char **associatedShader )
|
||||
{
|
||||
if ( s_curpair < p3d.numPairs )
|
||||
{
|
||||
*psetName = p3d.polysetNames[s_curpair];
|
||||
*associatedShader = p3d.shaders[s_curpair];
|
||||
s_curpair++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int P3DSkipToTokenInBlock( const char *name )
|
||||
{
|
||||
int iLevel = 0;
|
||||
|
||||
while ( P3DGetToken( 0 ) )
|
||||
{
|
||||
if ( !_strcmpi( s_token, "}" ) )
|
||||
iLevel--;
|
||||
else if ( !_strcmpi( s_token, "{" ) )
|
||||
iLevel++;
|
||||
|
||||
if ( !_strcmpi( s_token, name ) )
|
||||
return 1;
|
||||
|
||||
if ( iLevel == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** P3DProcess
|
||||
**
|
||||
** Nothing fancy here.
|
||||
*/
|
||||
int P3DProcess()
|
||||
{
|
||||
|
||||
s_curpair = 0;
|
||||
|
||||
// first token should be a string
|
||||
P3DGetToken( 1 ); // Voodoo Ascii File
|
||||
|
||||
// skip to the first Obj declaration
|
||||
while ( P3DGetToken( 0 ) )
|
||||
{
|
||||
if ( !_strcmpi( s_token, "Obj" ) )
|
||||
{
|
||||
int j = 0, k = 0;
|
||||
|
||||
if ( P3DSkipToToken( "Text" ) )
|
||||
{
|
||||
if ( P3DSkipToTokenInBlock( "TMap" ) )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ( !P3DSkipToToken( "Path" ) )
|
||||
return 0;
|
||||
|
||||
if ( !P3DGetToken( 1 ) )
|
||||
return 0;
|
||||
|
||||
while ( s_token[j] != 0 )
|
||||
{
|
||||
if ( s_token[j] == '\\' )
|
||||
{
|
||||
j++;
|
||||
p3d.shaders[p3d.numPairs][k] = '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
p3d.shaders[p3d.numPairs][k] = s_token[j];
|
||||
}
|
||||
j++;
|
||||
k++;
|
||||
}
|
||||
p3d.shaders[p3d.numPairs][k] = 0;
|
||||
|
||||
//
|
||||
// strip off any explicit extensions
|
||||
//
|
||||
if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 )
|
||||
{
|
||||
while ( *p )
|
||||
{
|
||||
if ( *p == '.' )
|
||||
{
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// skip to the end of the Object and grab its name
|
||||
//
|
||||
if ( !P3DSkipToToken( "Name" ) )
|
||||
return 0;
|
||||
|
||||
if ( P3DGetToken( 0 ) )
|
||||
{
|
||||
// strip off leading 'Obj_' if it exists
|
||||
if ( strstr( s_token, "Obj_" ) == s_token )
|
||||
strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
|
||||
else
|
||||
strcpy( p3d.polysetNames[p3d.numPairs], s_token );
|
||||
|
||||
// strip off trailing unused color information
|
||||
// if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
|
||||
// *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
|
||||
|
||||
p3d.numPairs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_curpair = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SkinFromP3D( const char *file )
|
||||
{
|
||||
char filename[1024];
|
||||
char *psetName, *associatedShader;
|
||||
|
||||
/*
|
||||
** a P3D file contains a list of polysets, each with a list of associated
|
||||
** texture names that constitute it's
|
||||
**
|
||||
** Thus:
|
||||
**
|
||||
** P3D file -> skin
|
||||
** polyset -> polyset
|
||||
** texture -> texture.SHADER becomes polyset's shader
|
||||
*/
|
||||
sprintf( filename, "%s/%s", g_cddir, file );
|
||||
|
||||
if ( !P3DLoad( filename ) )
|
||||
Error( "unable to load '%s'", filename );
|
||||
|
||||
while ( P3DGetNextPair( &psetName, &associatedShader ) )
|
||||
{
|
||||
int i;
|
||||
|
||||
// find the polyset in the object that this particular pset/shader pair
|
||||
// corresponds to and append the shader to it
|
||||
for ( i = 0; i < g_data.model.numSurfaces; i++ )
|
||||
{
|
||||
if ( !_strcmpi( g_data.surfData[i].header.name, psetName) )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ( strstr( associatedShader, gamedir + 1 ) )
|
||||
{
|
||||
p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = associatedShader;
|
||||
}
|
||||
|
||||
strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
|
||||
|
||||
g_data.surfData[i].header.numShaders++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
P3DClose();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
29
tools/quake3/q3data/p3dlib.h
Normal file
29
tools/quake3/q3data/p3dlib.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#define P3D_GET_CROSSLINE 1
|
||||
#define P3D_GET_RESTOFLINE 2
|
||||
|
||||
int P3DLoad( const char *filename );
|
||||
void P3DClose();
|
||||
|
||||
int P3DGetNextPair( char **name, char **associatedShader );
|
||||
273
tools/quake3/q3data/polyset.c
Normal file
273
tools/quake3/q3data/polyset.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "q3data.h"
|
||||
|
||||
polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris )
|
||||
{
|
||||
int p, np, op;
|
||||
int numNewPolysets = 0;
|
||||
int numSplitPolysets = 0;
|
||||
polyset_t *newpsets;
|
||||
int sumTriangles = 0;
|
||||
|
||||
for ( p = 0; p < numpolysets; p++ )
|
||||
{
|
||||
numNewPolysets += psets[p].numtriangles / maxTris + 1;
|
||||
}
|
||||
|
||||
if ( numNewPolysets == numpolysets )
|
||||
return psets;
|
||||
|
||||
printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
|
||||
|
||||
newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );
|
||||
|
||||
for ( np = 0, op = 0; op < numpolysets; op++ )
|
||||
{
|
||||
numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
|
||||
if ( numSplitPolysets == 1 )
|
||||
{
|
||||
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
|
||||
np++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sumTriangles = 0;
|
||||
|
||||
// split this pset into multiple smaller psets
|
||||
for ( p = 0; p < numSplitPolysets; p++, np++ )
|
||||
{
|
||||
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
|
||||
|
||||
newpsets[np].triangles = psets[op].triangles + sumTriangles;
|
||||
|
||||
if ( sumTriangles + maxTris > psets[op].numtriangles )
|
||||
newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
|
||||
else
|
||||
newpsets[np].numtriangles = maxTris;
|
||||
|
||||
sumTriangles += newpsets[np].numtriangles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pNumNewPolysets = numNewPolysets;
|
||||
|
||||
return newpsets;
|
||||
}
|
||||
|
||||
polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )
|
||||
{
|
||||
polyset_t *psets;
|
||||
polyset_t *finalpsets;
|
||||
|
||||
//
|
||||
// load the frame
|
||||
//
|
||||
if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) )
|
||||
_3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
|
||||
else
|
||||
Error( "TRI files no longer supported" );
|
||||
// TRI_LoadPolysets( file, &psets, numpolysets );
|
||||
|
||||
/*
|
||||
//
|
||||
// scale polysets
|
||||
//
|
||||
for ( i = 0; i < psets; i++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
for ( j = 0; j < psets[i].numtriangles; j++ )
|
||||
{
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// split polysets if necessary
|
||||
//
|
||||
finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
|
||||
|
||||
return finalpsets;
|
||||
}
|
||||
|
||||
polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )
|
||||
{
|
||||
int p;
|
||||
int sumtriangles = 0;
|
||||
|
||||
polyset_t *oldpsets = psets;
|
||||
|
||||
//
|
||||
// no tag checking because this is an $oldbase and thus shouldn't have any
|
||||
// tags
|
||||
//
|
||||
for ( p = 0; p < numpolysets; p++ )
|
||||
{
|
||||
sumtriangles += oldpsets[p].numtriangles;
|
||||
}
|
||||
|
||||
psets = calloc( 1, sizeof( polyset_t ) );
|
||||
psets[0].numtriangles = sumtriangles;
|
||||
psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
|
||||
|
||||
// each call to "LoadPolysets" only allocates a single large chunk of
|
||||
// triangle memory that is utilized by all the polysets loaded by
|
||||
// that one call
|
||||
memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
|
||||
|
||||
free( oldpsets[0].triangles );
|
||||
free( oldpsets );
|
||||
|
||||
return psets;
|
||||
}
|
||||
|
||||
static float SnapFloat( float x )
|
||||
{
|
||||
int ix;
|
||||
|
||||
x *= 1.0f / MD3_XYZ_SCALE;
|
||||
ix = ( int ) x;
|
||||
x = ( float ) ix;
|
||||
x *= MD3_XYZ_SCALE;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void Polyset_SnapSets( polyset_t *psets, int numpolysets )
|
||||
{
|
||||
int p;
|
||||
|
||||
for ( p = 0; p < numpolysets; p++ )
|
||||
{
|
||||
int t;
|
||||
|
||||
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||||
{
|
||||
int v;
|
||||
|
||||
for ( v = 0; v < 3; v++ )
|
||||
{
|
||||
psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
|
||||
psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
|
||||
psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Polyset_ComputeNormals( polyset_t *psets, int numpolysets )
|
||||
{
|
||||
int p;
|
||||
int i, t;
|
||||
int vertexIndex[MD3_MAX_TRIANGLES][3];
|
||||
vec3_t verts[MD3_MAX_VERTS];
|
||||
vec3_t normals[MD3_MAX_VERTS];
|
||||
vec3_t faceNormals[MD3_MAX_TRIANGLES];
|
||||
|
||||
//
|
||||
// iterate through polysets
|
||||
//
|
||||
for ( p = 0; p < numpolysets; p++ )
|
||||
{
|
||||
int numUniqueVertices = 0;
|
||||
|
||||
assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
|
||||
|
||||
memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
|
||||
memset( verts, 0, sizeof( verts ) );
|
||||
memset( normals, 0, sizeof( normals ) );
|
||||
|
||||
//
|
||||
// unique vertices
|
||||
//
|
||||
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
for ( j = 0; j < 3; j++ )
|
||||
{
|
||||
for ( i = 0; i < numUniqueVertices; i++ )
|
||||
{
|
||||
if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == numUniqueVertices )
|
||||
{
|
||||
vertexIndex[t][j] = numUniqueVertices;
|
||||
VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );
|
||||
numUniqueVertices++;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexIndex[t][j] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// compute face normals
|
||||
//
|
||||
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||||
{
|
||||
vec3_t side0, side1, facenormal;
|
||||
|
||||
VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
|
||||
VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);
|
||||
|
||||
CrossProduct( side0, side1, facenormal );
|
||||
VectorNormalize( facenormal, faceNormals[t] );
|
||||
}
|
||||
|
||||
//
|
||||
// sum normals and copy them back
|
||||
//
|
||||
for ( i = 0; i < numUniqueVertices; i++ )
|
||||
{
|
||||
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||||
{
|
||||
if ( vertexIndex[t][0] == i ||
|
||||
vertexIndex[t][1] == i ||
|
||||
vertexIndex[t][2] == i )
|
||||
{
|
||||
normals[i][0] += faceNormals[t][0];
|
||||
normals[i][1] += faceNormals[t][1];
|
||||
normals[i][2] += faceNormals[t][2];
|
||||
}
|
||||
}
|
||||
VectorNormalize( normals[i], normals[i] );
|
||||
}
|
||||
|
||||
|
||||
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||||
{
|
||||
VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
|
||||
VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
|
||||
VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
666
tools/quake3/q3data/q3data.c
Normal file
666
tools/quake3/q3data/q3data.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "q3data.h"
|
||||
#include "md3lib.h"
|
||||
|
||||
#include "vfs.h"
|
||||
|
||||
qboolean g_verbose;
|
||||
qboolean g_stripify = qtrue;
|
||||
qboolean g_release; // don't grab, copy output data to new tree
|
||||
char g_releasedir[1024]; // c:\quake2\baseq2, etc
|
||||
qboolean g_archive; // don't grab, copy source data to new tree
|
||||
char g_only[256]; // if set, only grab this cd
|
||||
qboolean g_skipmodel; // set true when a cd is not g_only
|
||||
|
||||
// bogus externs for some TA hacks (common/ using them against q3map)
|
||||
char *moddir = NULL;
|
||||
// some old defined that was in cmdlib lost during merge
|
||||
char writedir[1024];
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
#define strlwr strlower
|
||||
#endif
|
||||
|
||||
/*
|
||||
=======================================================
|
||||
|
||||
PAK FILES
|
||||
|
||||
=======================================================
|
||||
*/
|
||||
|
||||
unsigned Com_BlockChecksum (void *buffer, int length);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[56];
|
||||
int filepos, filelen;
|
||||
} packfile_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char id[4];
|
||||
int dirofs;
|
||||
int dirlen;
|
||||
} packheader_t;
|
||||
|
||||
packfile_t pfiles[16384];
|
||||
FILE *pakfile;
|
||||
packfile_t *pf;
|
||||
packheader_t pakheader;
|
||||
|
||||
/*
|
||||
==============
|
||||
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)
|
||||
{
|
||||
char source[1024];
|
||||
char dest[1024];
|
||||
|
||||
if (!g_release)
|
||||
return;
|
||||
|
||||
sprintf (source, "%s%s", gamedir, filename);
|
||||
sprintf (dest, "%s/%s", g_releasedir, filename);
|
||||
printf ("copying to %s\n", dest);
|
||||
QCopyFile (source, dest);
|
||||
return;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// shader
|
||||
// opaque
|
||||
// opaque 2
|
||||
// blend
|
||||
// blend 2
|
||||
char names[5][1024];
|
||||
int num;
|
||||
} ShaderFiles_t;
|
||||
|
||||
ShaderFiles_t s_shaderFiles;
|
||||
|
||||
void FindShaderFiles( char *filename )
|
||||
{
|
||||
char buffer[1024];
|
||||
char stripped[1024];
|
||||
char linebuffer[1024];
|
||||
int len, i;
|
||||
char *buf;
|
||||
char *diffuseExtensions[] =
|
||||
{
|
||||
".TGA",
|
||||
".WAL",
|
||||
".PCX",
|
||||
0
|
||||
};
|
||||
char *otherExtensions[] =
|
||||
{
|
||||
".specular.TGA",
|
||||
".blend.TGA",
|
||||
".alpha.TGA",
|
||||
0
|
||||
};
|
||||
|
||||
s_shaderFiles.num = 0;
|
||||
|
||||
strcpy( stripped, filename );
|
||||
if ( strrchr( stripped, '.' ) )
|
||||
*strrchr( stripped, '.' ) = 0;
|
||||
strcat( stripped, ".shader" );
|
||||
|
||||
if ( FileExists( stripped ) )
|
||||
{
|
||||
char *p;
|
||||
char mapa[512], mapb[512];
|
||||
|
||||
strcpy( s_shaderFiles.names[s_shaderFiles.num], stripped );
|
||||
s_shaderFiles.num++;
|
||||
|
||||
// load and parse
|
||||
len = LoadFile( stripped, (void **)&buf);
|
||||
|
||||
p = buf;
|
||||
|
||||
while ( p - buf < len )
|
||||
{
|
||||
i = 0;
|
||||
|
||||
// skip spaces
|
||||
while ( *p == ' ' || *p == '\n' || *p == '\t' )
|
||||
p++;
|
||||
|
||||
// grab rest of the line
|
||||
while ( *p != 0 && *p != '\n' )
|
||||
{
|
||||
linebuffer[i] = *p;
|
||||
i++;
|
||||
p++;
|
||||
}
|
||||
if ( *p == '\n' )
|
||||
p++;
|
||||
linebuffer[i] = 0;
|
||||
|
||||
strlwr( linebuffer );
|
||||
|
||||
// see if the line specifies an opaque map or blendmap
|
||||
if ( strstr( linebuffer, "opaquemap" ) == linebuffer ||
|
||||
strstr( linebuffer, "blendmap" ) == linebuffer )
|
||||
{
|
||||
int j;
|
||||
|
||||
i = 0;
|
||||
|
||||
mapa[0] = mapb[0] = 0;
|
||||
|
||||
// skip past the keyword
|
||||
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
|
||||
i++;
|
||||
// skip past spaces
|
||||
while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
|
||||
i++;
|
||||
|
||||
// grab first map name
|
||||
j = 0;
|
||||
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
|
||||
{
|
||||
mapa[j] = linebuffer[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
mapa[j] = 0;
|
||||
|
||||
// skip past spaces
|
||||
while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
|
||||
i++;
|
||||
|
||||
// grab second map name
|
||||
j = 0;
|
||||
while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
|
||||
{
|
||||
mapb[j] = linebuffer[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
mapb[j] = 0;
|
||||
|
||||
// store map names
|
||||
if ( mapa[0] != 0 && mapa[0] != '-' )
|
||||
{
|
||||
sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapa );
|
||||
s_shaderFiles.num++;
|
||||
}
|
||||
if ( mapb[0] != 0 && mapb[0] != '-' && mapb[0] != '^' && mapb[0] != '*' )
|
||||
{
|
||||
sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapb );
|
||||
s_shaderFiles.num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( strrchr( stripped, '.' ) )
|
||||
*strrchr( stripped, '.' ) = 0;
|
||||
|
||||
// look for diffuse maps
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
strcpy( buffer, stripped );
|
||||
strcat( buffer, diffuseExtensions[i] );
|
||||
if ( FileExists( buffer ) )
|
||||
{
|
||||
strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
|
||||
s_shaderFiles.num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
strcpy( buffer, stripped );
|
||||
strcat( buffer, otherExtensions[i] );
|
||||
if ( FileExists( buffer ) )
|
||||
{
|
||||
strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
|
||||
s_shaderFiles.num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReleaseShader
|
||||
|
||||
Copies all needed files for a shader to the release directory
|
||||
==============
|
||||
*/
|
||||
void ReleaseShader( char *filename )
|
||||
{
|
||||
char fullpath[1024];
|
||||
char dest[1024];
|
||||
char stripped[1024];
|
||||
int i;
|
||||
|
||||
sprintf( fullpath, "%s%s", gamedir, filename );
|
||||
|
||||
FindShaderFiles( fullpath );
|
||||
|
||||
for ( i = 0; i < s_shaderFiles.num; i++ )
|
||||
{
|
||||
strcpy( stripped, s_shaderFiles.names[i] );
|
||||
if ( strstr( stripped, gamedir ) )
|
||||
{
|
||||
memmove( stripped, stripped+ strlen( gamedir ), strlen( stripped ) );
|
||||
}
|
||||
sprintf( dest, "%s/%s", g_releasedir, stripped );
|
||||
printf ("copying to %s\n", dest );
|
||||
QCopyFile( s_shaderFiles.names[i], dest );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_File
|
||||
|
||||
This is only used to cause a file to be copied during a release
|
||||
build (default.cfg, maps, etc)
|
||||
===============
|
||||
*/
|
||||
void Cmd_File (void)
|
||||
{
|
||||
GetToken (qfalse);
|
||||
ReleaseFile (token);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
PackDirectory_r
|
||||
|
||||
===============
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#include "io.h"
|
||||
void PackDirectory_r (char *dir)
|
||||
{
|
||||
struct _finddata_t fileinfo;
|
||||
int handle;
|
||||
char dirstring[1024];
|
||||
char filename[1024];
|
||||
|
||||
sprintf (dirstring, "%s%s/*.*", gamedir, dir);
|
||||
|
||||
handle = _findfirst (dirstring, &fileinfo);
|
||||
if (handle == -1)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
sprintf (filename, "%s/%s", dir, fileinfo.name);
|
||||
if (fileinfo.attrib & _A_SUBDIR)
|
||||
{ // directory
|
||||
if (fileinfo.name[0] != '.') // don't pak . and ..
|
||||
PackDirectory_r (filename);
|
||||
continue;
|
||||
}
|
||||
// copy or pack the file
|
||||
ReleaseFile (filename);
|
||||
} while (_findnext( handle, &fileinfo ) != -1);
|
||||
|
||||
_findclose (handle);
|
||||
}
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/dir.h>
|
||||
#else
|
||||
#include <sys/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)
|
||||
{
|
||||
GetToken (qfalse);
|
||||
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_stricmp(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];
|
||||
|
||||
while (TokenAvailable ())
|
||||
{
|
||||
GetToken (qfalse);
|
||||
sprintf (map, "maps/%s.bsp", token);
|
||||
ReleaseFile (map);
|
||||
|
||||
if (!g_release)
|
||||
continue;
|
||||
|
||||
// get all the texture references
|
||||
sprintf (map, "%smaps/%s.bsp", gamedir, token);
|
||||
LoadBSPFile( map );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
ParseScript
|
||||
===============
|
||||
*/
|
||||
void ParseScript (void)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
do
|
||||
{ // look for a line starting with a $ command
|
||||
GetToken (qtrue);
|
||||
if (endofscript)
|
||||
return;
|
||||
if (token[0] == '$')
|
||||
break;
|
||||
while (TokenAvailable())
|
||||
GetToken (qfalse);
|
||||
} while (1);
|
||||
|
||||
//
|
||||
// model commands
|
||||
//
|
||||
if (!strcmp (token, "$modelname"))
|
||||
Cmd_Modelname ();
|
||||
else if (!strcmp (token, "$base"))
|
||||
Cmd_Base ();
|
||||
else if ( !strcmp( token, "$exit" ) )
|
||||
break;
|
||||
else if ( !strcmp( token, "$3dsconvert" ) )
|
||||
Cmd_3DSConvert();
|
||||
else if (!strcmp (token, "$spritebase"))
|
||||
Cmd_SpriteBase ();
|
||||
else if (!strcmp (token, "$cd"))
|
||||
Cmd_Cd ();
|
||||
else if (!strcmp (token, "$origin"))
|
||||
Cmd_Origin ();
|
||||
else if (!strcmp (token, "$scale"))
|
||||
Cmd_ScaleUp ();
|
||||
else if (!strcmp (token, "$frame"))
|
||||
Cmd_Frame ();
|
||||
else if (!strcmp (token, "$skin" ))
|
||||
Cmd_Skin();
|
||||
else if (!strcmp (token, "$spriteshader"))
|
||||
Cmd_SpriteShader();
|
||||
else if (!strcmp( token, "$aseconvert" ))
|
||||
Cmd_ASEConvert( qfalse );
|
||||
else if (!strcmp( token, "$aseanimconvert" ) )
|
||||
Cmd_ASEConvert( qtrue );
|
||||
|
||||
//
|
||||
// image commands
|
||||
//
|
||||
else if (!strcmp (token, "$grab"))
|
||||
Cmd_Grab ();
|
||||
else if (!strcmp (token, "$raw"))
|
||||
Cmd_Raw ();
|
||||
else if (!strcmp (token, "$colormap"))
|
||||
Cmd_Colormap ();
|
||||
else if (!strcmp (token, "$environment"))
|
||||
Cmd_Environment ();
|
||||
|
||||
//
|
||||
// video
|
||||
//
|
||||
else if (!strcmp (token, "$video"))
|
||||
Cmd_Video ();
|
||||
//
|
||||
// misc
|
||||
//
|
||||
else if (!strcmp (token, "$file"))
|
||||
Cmd_File ();
|
||||
else if (!strcmp (token, "$dir"))
|
||||
Cmd_Dir ();
|
||||
else if (!strcmp (token, "$maps"))
|
||||
Cmd_Maps ();
|
||||
else
|
||||
Error ("bad command %s\n", token);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/*
|
||||
==============
|
||||
main
|
||||
==============
|
||||
*/
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
static int i; // VC4.2 compiler bug if auto...
|
||||
char path[1024];
|
||||
|
||||
// using GtkRadiant's versioning next to Id's versioning
|
||||
printf ("Q3Data - (c) 1999 Id Software Inc.\n");
|
||||
printf ("GtkRadiant - v" RADIANT_VERSION " " __DATE__ "\n");
|
||||
|
||||
ExpandWildcards (&argc, &argv);
|
||||
|
||||
for (i=1 ; i<argc ; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-archive"))
|
||||
{
|
||||
archive = qtrue;
|
||||
strcpy (archivedir, argv[i+1]);
|
||||
printf ("Archiving source to: %s\n", archivedir);
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-release"))
|
||||
{
|
||||
g_release = qtrue;
|
||||
strcpy (g_releasedir, argv[i+1]);
|
||||
printf ("Copy output to: %s\n", g_releasedir);
|
||||
i++;
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-nostrips" ) )
|
||||
{
|
||||
g_stripify = qfalse;
|
||||
printf( "Not optimizing for strips\n" );
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-writedir" ) )
|
||||
{
|
||||
strcpy( writedir, argv[i+1] );
|
||||
printf( "Write output to: %s\n", writedir );
|
||||
i++;
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-verbose" ) )
|
||||
{
|
||||
g_verbose = qtrue;
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-dump" ) )
|
||||
{
|
||||
printf( "Dumping contents of: '%s'\n", argv[i+1] );
|
||||
if ( strstr( argv[i+1], ".md3" ) )
|
||||
{
|
||||
MD3_Dump( argv[i+1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
Error( "Do not know how to dump the contents of '%s'\n", argv[i+1] );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-3dsconvert" ) )
|
||||
{
|
||||
// NOTE TTimo this is broken, tried on a sample .3ds
|
||||
// what happens .. it calls the Convert3DStoMD3,
|
||||
// which calls the scriptlib function in non initialized state .. and crashes
|
||||
printf( "Converting %s.3DS to %s.MD3\n", argv[i+1], argv[i+1] );
|
||||
SetQdirFromPath( argv[i+1] );
|
||||
vfsInitDirectory( gamedir );
|
||||
Convert3DStoMD3( argv[i+1] );
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-only"))
|
||||
{
|
||||
strcpy (g_only, argv[i+1]);
|
||||
printf ("Only grabbing %s\n", g_only);
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-gamedir"))
|
||||
{
|
||||
strcpy(gamedir, argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
else if (argv[i][0] == '-')
|
||||
Error ("Unknown option \"%s\"", argv[i]);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == argc)
|
||||
Error ("usage: q3data [-archive <directory>] [-dump <file.md3>] [-release <directory>] [-only <model>] [-3dsconvert <file.3ds>] [-verbose] [file.qdt]");
|
||||
|
||||
for ( ; i<argc ; i++)
|
||||
{
|
||||
printf ("--------------- %s ---------------\n", argv[i]);
|
||||
// load the script
|
||||
strcpy (path, argv[i]);
|
||||
DefaultExtension (path, ".qdt");
|
||||
if(!gamedir[0])
|
||||
SetQdirFromPath (path);
|
||||
// NOTE TTimo
|
||||
// q3data went through a partial conversion to use the vfs
|
||||
// it was never actually tested before 1.1.1
|
||||
// the code is still mostly using direct file access calls
|
||||
vfsInitDirectory( gamedir );
|
||||
LoadScriptFile (ExpandArg(path), -1);
|
||||
|
||||
//
|
||||
// parse it
|
||||
//
|
||||
ParseScript ();
|
||||
|
||||
// write out the last model
|
||||
FinishModel ( TYPE_UNKNOWN );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
200
tools/quake3/q3data/q3data.dsp
Normal file
200
tools/quake3/q3data/q3data.dsp
Normal file
@@ -0,0 +1,200 @@
|
||||
# Microsoft Developer Studio Project File - Name="q3data" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=q3data - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "q3data.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "q3data.mak" CFG="q3data - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "q3data - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "q3data - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "q3data"
|
||||
# PROP Scc_LocalPath ".."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "q3data - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 glib-2.0.lib l_net.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /stack:0xf42400 /subsystem:console /debug /machine:I386 /libpath:"..\..\..\libs\pak\release" /libpath:"..\..\..\libs\l_net\release" /libpath:"..\..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "q3data - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\common" /I "..\..\..\..\libxml2\include" /I "..\..\..\libs" /I "..\..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 glib-2.0.lib l_net.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /stack:0xf42400 /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\libs\l_net\Debug" /libpath:"..\..\..\libs\pak\Debug" /libpath:"..\..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "q3data - Win32 Release"
|
||||
# Name "q3data - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\3dslib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\3dslib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\aselib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\aselib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\bspfile.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\cmdlib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\compress.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\imagelib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\images.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\inout.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3lib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md3lib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\md4.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\models.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\p3dlib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\p3dlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\polyset.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\polyset.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\q3data.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\q3data.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\scriplib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\stripper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\trilib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\unzip.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\unzip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\vfs.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\video.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
99
tools/quake3/q3data/q3data.h
Normal file
99
tools/quake3/q3data/q3data.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// q3data.h
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../common/cmdlib.h"
|
||||
#include "scriplib.h"
|
||||
#include "mathlib.h"
|
||||
#include "polyset.h"
|
||||
#include "trilib.h"
|
||||
#include "imagelib.h"
|
||||
#include "qthreads.h"
|
||||
#include "l3dslib.h"
|
||||
#include "bspfile.h"
|
||||
#include "p3dlib.h"
|
||||
#include "3dslib.h"
|
||||
#include "aselib.h"
|
||||
#include "md3lib.h"
|
||||
|
||||
void Cmd_ASEConvert( qboolean grabAnims );
|
||||
void Cmd_3DSConvert( void );
|
||||
void Cmd_Modelname (void);
|
||||
void Cmd_SpriteBase (void);
|
||||
void Cmd_Base (void);
|
||||
void Cmd_Cd (void);
|
||||
void Cmd_Origin (void);
|
||||
void Cmd_ScaleUp (void);
|
||||
void Cmd_Frame (void);
|
||||
void Cmd_Modelname (void);
|
||||
void Cmd_SpriteShader(void);
|
||||
void Cmd_Skin(void);
|
||||
void Cmd_Skinsize (void);
|
||||
void FinishModel (int type);
|
||||
|
||||
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_Video (void);
|
||||
|
||||
void ReleaseFile (char *filename);
|
||||
void ReleaseShader( char *filename );
|
||||
|
||||
void Convert3DStoMD3( const char *filename );
|
||||
|
||||
void OrderMesh( int input[][3], int output[][3], int numTris );
|
||||
|
||||
extern byte *byteimage, *lbmpalette;
|
||||
extern int byteimagewidth, byteimageheight;
|
||||
|
||||
extern qboolean g_release; // don't grab, copy output data to new tree
|
||||
extern char g_releasedir[1024]; // c:\quake2\baseq2, etc
|
||||
extern qboolean g_archive; // don't grab, copy source data to new tree
|
||||
extern qboolean do3ds;
|
||||
extern char g_only[256]; // if set, only grab this cd
|
||||
extern qboolean g_skipmodel; // set true when a cd is not g_only
|
||||
extern qboolean g_verbose;
|
||||
|
||||
extern char *trifileext;
|
||||
|
||||
#define TYPE_ITEM 0
|
||||
#define TYPE_PLAYER 1
|
||||
#define TYPE_WEAPON 2
|
||||
#define TYPE_HAND 3
|
||||
#define TYPE_UNKNOWN 4
|
||||
207
tools/quake3/q3data/q3data.vcproj
Normal file
207
tools/quake3/q3data/q3data.vcproj
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="q3data">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\common,..\..\..\..\libxml2\include,..\..\..\libs,..\..\..\..\gtk2-win32\include\glib-2.0,..\..\..\..\gtk2-win32\lib\glib-2.0\include,..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||
RuntimeLibrary="3"
|
||||
PrecompiledHeaderFile=".\Debug/q3data.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="glib-2.0.lib wsock32.lib libxml2.lib"
|
||||
OutputFile=".\Debug/q3data.exe"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""..\..\..\..\libxml2\win32\binaries-debug";..\..\..\libs\l_net\Debug;..\..\..\libs\pak\Debug;"..\..\..\..\gtk2-win32\lib\""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/q3data.pdb"
|
||||
SubSystem="1"
|
||||
StackReserveSize="16000000"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Debug/q3data.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\common,..\..\..\..\libxml2\include,..\..\..\libs,..\..\..\..\gtk2-win32\include\glib-2.0,..\..\..\..\gtk2-win32\lib\glib-2.0\include,..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
PrecompiledHeaderFile=".\Release/q3data.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="glib-2.0.lib wsock32.lib libxml2.lib"
|
||||
OutputFile=".\Release/q3data.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="..\..\..\libs\pak\release;..\..\..\libs\l_net\release;"..\..\..\..\libxml2\win32\binaries-release";"..\..\..\..\gtk2-win32\lib\""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Release/q3data.pdb"
|
||||
SubSystem="1"
|
||||
StackReserveSize="16000000"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Release/q3data.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\3dslib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\3dslib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\aselib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\aselib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\bspfile.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\cmdlib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\compress.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\imagelib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\images.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\inout.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3lib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\md3lib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\md4.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\models.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\p3dlib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\p3dlib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\polyset.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\polyset.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\q3data.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\q3data.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\scriplib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stripper.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\trilib.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\unzip.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\unzip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\vfs.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\video.c">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
303
tools/quake3/q3data/stripper.c
Normal file
303
tools/quake3/q3data/stripper.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int s_used[8192]; // same as MD3_MAX_TRIANGLES
|
||||
|
||||
/*
|
||||
** FindNextTriangleInStrip
|
||||
**
|
||||
** Given a surface and triangle this tries to find the next triangle
|
||||
** in the strip that would continue the strip. The next triangle in
|
||||
** the strip should have the same winding as this triangle.
|
||||
*/
|
||||
static int FindNextTriangleInStripOrFan( int mesh[][3], int tri, int orientation, int numTris, int odd )
|
||||
{
|
||||
int t;
|
||||
int sum = 0;
|
||||
int currentTri[3];
|
||||
int side;
|
||||
int a, b, c;
|
||||
int refa, refb;
|
||||
|
||||
currentTri[0] = mesh[tri][(0+orientation)%3];
|
||||
currentTri[1] = mesh[tri][(1+orientation)%3];
|
||||
currentTri[2] = mesh[tri][(2+orientation)%3];
|
||||
|
||||
if ( odd )
|
||||
{
|
||||
refa = currentTri[1];
|
||||
refb = currentTri[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
refa = currentTri[2];
|
||||
refb = currentTri[0];
|
||||
}
|
||||
|
||||
// go through all triangles and look for sides that match
|
||||
// this triangle's
|
||||
for ( t = 0; t < numTris; t++ )
|
||||
{
|
||||
// don't check against self or against previously used triangles
|
||||
if ( t == tri )
|
||||
continue;
|
||||
if ( s_used[t] )
|
||||
continue;
|
||||
|
||||
// check all three sides of the candidate triangle
|
||||
for ( side = 0; side < 3; side++ )
|
||||
{
|
||||
// check only the second (abutting) side
|
||||
if ( ( refa == mesh[t][(side+1)%3] ) &&
|
||||
( refb == mesh[t][side] ) )
|
||||
{
|
||||
|
||||
a = mesh[t][0];
|
||||
b = mesh[t][1];
|
||||
c = mesh[t][2];
|
||||
|
||||
// rotate the candidate triangle to align it properly in the strip
|
||||
if ( side == 1 )
|
||||
{
|
||||
mesh[t][0] = b;
|
||||
mesh[t][1] = c;
|
||||
mesh[t][2] = a;
|
||||
}
|
||||
else if ( side == 2 )
|
||||
{
|
||||
mesh[t][0] = c;
|
||||
mesh[t][1] = a;
|
||||
mesh[t][2] = b;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
Error( "fans not implemented yet" );
|
||||
|
||||
// check only the third (abutting) side
|
||||
if ( ( currentTri[2] == pSurf->baseTriangles[t].v[side].index ) &&
|
||||
( currentTri[0] == pSurf->baseTriangles[t].v[(side+1)%3].index ) )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** StripLength
|
||||
*/
|
||||
static int StripLength( int mesh[][3], int strip[][3], int tri, int orientation, int numInputTris, int fillNo )
|
||||
{
|
||||
int stripIndex = 0;
|
||||
int next;
|
||||
|
||||
int odd = 1;
|
||||
|
||||
strip[stripIndex][0] = mesh[tri][(0+orientation)%3];
|
||||
strip[stripIndex][1] = mesh[tri][(1+orientation)%3];
|
||||
strip[stripIndex][2] = mesh[tri][(2+orientation)%3];
|
||||
s_used[tri] = fillNo;
|
||||
stripIndex++;
|
||||
|
||||
next = tri;
|
||||
|
||||
while ( ( next = FindNextTriangleInStripOrFan( mesh, next, orientation, numInputTris, odd ) ) != -1 )
|
||||
{
|
||||
s_used[next] = fillNo;
|
||||
odd = !odd;
|
||||
strip[stripIndex][0] = mesh[next][0];
|
||||
strip[stripIndex][1] = mesh[next][1];
|
||||
strip[stripIndex][2] = mesh[next][2];
|
||||
stripIndex++;
|
||||
|
||||
// all iterations after first need to be with an unrotated reference triangle
|
||||
orientation = 0;
|
||||
}
|
||||
|
||||
return stripIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
** BuildOptimizedList
|
||||
**
|
||||
** Attempts to build the longest strip/fan possible. Does not adhere
|
||||
** to pure strip or fan, will intermix between the two so long as some
|
||||
** type of connectivity can be maintained.
|
||||
*/
|
||||
#define MAX_ORIENTATIONS 3
|
||||
#define MAX_MATCHED_SIDES 4
|
||||
#define MAX_SEED_TRIANGLES 16
|
||||
|
||||
static int BuildOptimizedList( int mesh[][3], int strip[][3], int numInputTris )
|
||||
{
|
||||
int t;
|
||||
int stripLen = 0;
|
||||
int startTri = -1;
|
||||
int bestTri = -1, bestLength = 0, bestOrientation = -1;
|
||||
int matchedSides = 0;
|
||||
int orientation = 0;
|
||||
int seedTriangles[MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
|
||||
int seedLengths[MAX_ORIENTATIONS][MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
|
||||
int numSeeds[MAX_MATCHED_SIDES] = { 0, 0, 0 };
|
||||
int i;
|
||||
|
||||
// build a ranked list of candidate seed triangles based on
|
||||
// number of offshoot strips. Precedence goes to orphans,
|
||||
// then corners, then edges, and interiors.
|
||||
memset( seedTriangles, 0xff, sizeof( seedTriangles ) );
|
||||
memset( seedLengths, 0xff, sizeof( seedLengths ) );
|
||||
|
||||
for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
|
||||
{
|
||||
// find the triangle with lowest number of child strips
|
||||
for ( t = 0; t < numInputTris; t++ )
|
||||
{
|
||||
int orientation;
|
||||
int n;
|
||||
|
||||
if ( s_used[t] )
|
||||
continue;
|
||||
|
||||
// try the candidate triangle in three different orientations
|
||||
matchedSides = 0;
|
||||
for ( orientation = 0; orientation < 3; orientation++ )
|
||||
{
|
||||
if ( ( n = FindNextTriangleInStripOrFan( mesh, t, orientation, numInputTris, 1 ) ) != -1 )
|
||||
{
|
||||
matchedSides++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( matchedSides == i )
|
||||
{
|
||||
seedTriangles[i][numSeeds[i]] = t;
|
||||
numSeeds[i]++;
|
||||
if ( numSeeds[i] == MAX_SEED_TRIANGLES )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have a list of potential seed triangles, so we now go through each
|
||||
// potential candidate and look to see which produces the longest strip
|
||||
// and select our startTri based on this
|
||||
for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
for ( j = 0; j < numSeeds[i]; j++ )
|
||||
{
|
||||
for ( orientation = 0; orientation < 3; orientation++ )
|
||||
{
|
||||
int k;
|
||||
|
||||
seedLengths[orientation][i][j] = StripLength( mesh, strip, seedTriangles[i][j], orientation, numInputTris, 2 );
|
||||
|
||||
if ( seedLengths[orientation][i][j] > bestLength )
|
||||
{
|
||||
bestTri = seedTriangles[i][j];
|
||||
bestLength = seedLengths[orientation][i][j];
|
||||
bestOrientation = orientation;
|
||||
}
|
||||
|
||||
for ( k = 0; k < numInputTris; k++ )
|
||||
{
|
||||
if ( s_used[k] == 2 )
|
||||
s_used[k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestTri != -1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// build the strip for real
|
||||
if ( bestTri != -1 )
|
||||
{
|
||||
stripLen = StripLength( mesh, strip, bestTri, bestOrientation, numInputTris, 1 );
|
||||
}
|
||||
|
||||
return stripLen;
|
||||
}
|
||||
|
||||
/*
|
||||
** OrderMesh
|
||||
**
|
||||
** Given an input mesh and an output mesh, this routine will reorder
|
||||
** the triangles within the mesh into strips/fans.
|
||||
*/
|
||||
void OrderMesh( int input[][3], int output[][3], int numTris )
|
||||
{
|
||||
int i;
|
||||
int sumStrippedTriangles = 0;
|
||||
int strippedTriangles;
|
||||
int totalStrips = 0;
|
||||
int strip[8192][3]; // could dump directly into 'output', but
|
||||
// this helps with debugging
|
||||
|
||||
memset( s_used, 0, sizeof( s_used ) );
|
||||
|
||||
#if 0
|
||||
FILE *fp = fopen( "strip.txt", "wt" );
|
||||
|
||||
for ( i = 0; i < numTris; i++ )
|
||||
{
|
||||
fprintf( fp, "%4d: %3d %3d %3d\n", i, input[i][0], input[i][1], input[i][2] );
|
||||
}
|
||||
fclose( fp );
|
||||
#endif
|
||||
|
||||
// while there are still triangles that are not part of a strip
|
||||
while ( sumStrippedTriangles < numTris )
|
||||
{
|
||||
// build a strip
|
||||
strippedTriangles = BuildOptimizedList( input, strip, numTris );
|
||||
|
||||
for ( i = 0; i < strippedTriangles; i++ )
|
||||
{
|
||||
output[sumStrippedTriangles+i][0] = strip[i][0];
|
||||
output[sumStrippedTriangles+i][1] = strip[i][1];
|
||||
output[sumStrippedTriangles+i][2] = strip[i][2];
|
||||
}
|
||||
|
||||
sumStrippedTriangles += strippedTriangles;
|
||||
totalStrips++;
|
||||
}
|
||||
|
||||
printf( "Triangles on surface: %d\n", sumStrippedTriangles );
|
||||
printf( "Total strips from surface: %d\n", totalStrips );
|
||||
printf( "Average strip length: %f\n", ( float ) sumStrippedTriangles / totalStrips );
|
||||
}
|
||||
1153
tools/quake3/q3data/video.c
Normal file
1153
tools/quake3/q3data/video.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user