jedioutcast/utils/q3data/p3dlib.c
2013-04-04 13:07:40 -05:00

317 lines
5.3 KiB
C

#include "p3dlib.h"
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_POLYSETS 64
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