10 #define MAX_POLYSETS 64
\r
12 #if defined (__linux__) || defined (__APPLE__)
\r
13 #define _strcmpi Q_stricmp
\r
14 #define filelength Q_filelength
\r
15 #define strlwr strlower
\r
22 char polysetNames[MAX_POLYSETS][256];
\r
23 char shaders[MAX_POLYSETS][256];
\r
25 char *buffer, *curpos;
\r
30 static int P3DProcess();
\r
31 static int P3DGetToken( int restOfLine );
\r
33 static char s_token[1024];
\r
34 static int s_curpair;
\r
40 int P3DLoad( const char *filename )
\r
42 FILE *fp = fopen( filename, "rb" );
\r
47 memset( &p3d, 0, sizeof( p3d ) );
\r
49 p3d.len = filelength( fileno( fp ) );
\r
51 p3d.curpos = p3d.buffer = malloc( p3d.len );
\r
53 if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 )
\r
61 return P3DProcess();
\r
77 int CharIsTokenDelimiter( int ch )
\r
84 int P3DSkipToToken( const char *name )
\r
86 while ( P3DGetToken( 0 ) )
\r
88 if ( !_strcmpi( s_token, name ) )
\r
99 int P3DGetToken( int restOfLine )
\r
103 if ( p3d.buffer == 0 )
\r
106 if ( ( p3d.curpos - p3d.buffer ) == p3d.len )
\r
110 while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
\r
111 ( *p3d.curpos <= 32 ) )
\r
116 while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
\r
118 s_token[i] = *p3d.curpos;
\r
123 if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
\r
124 ( ( s_token[i-1] == '\n' ) ) )
\r
136 int P3DGetNextPair( char **psetName, char **associatedShader )
\r
138 if ( s_curpair < p3d.numPairs )
\r
140 *psetName = p3d.polysetNames[s_curpair];
\r
141 *associatedShader = p3d.shaders[s_curpair];
\r
149 int P3DSkipToTokenInBlock( const char *name )
\r
153 while ( P3DGetToken( 0 ) )
\r
155 if ( !_strcmpi( s_token, "}" ) )
\r
157 else if ( !_strcmpi( s_token, "{" ) )
\r
160 if ( !_strcmpi( s_token, name ) )
\r
175 ** Nothing fancy here.
\r
182 // first token should be a string
\r
183 P3DGetToken( 1 ); // Voodoo Ascii File
\r
185 // skip to the first Obj declaration
\r
186 while ( P3DGetToken( 0 ) )
\r
188 if ( !_strcmpi( s_token, "Obj" ) )
\r
192 if ( P3DSkipToToken( "Text" ) )
\r
194 if ( P3DSkipToTokenInBlock( "TMap" ) )
\r
198 if ( !P3DSkipToToken( "Path" ) )
\r
201 if ( !P3DGetToken( 1 ) )
\r
204 while ( s_token[j] != 0 )
\r
206 if ( s_token[j] == '\\' )
\r
209 p3d.shaders[p3d.numPairs][k] = '/';
\r
213 p3d.shaders[p3d.numPairs][k] = s_token[j];
\r
218 p3d.shaders[p3d.numPairs][k] = 0;
\r
221 // strip off any explicit extensions
\r
223 if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 )
\r
237 // skip to the end of the Object and grab its name
\r
239 if ( !P3DSkipToToken( "Name" ) )
\r
242 if ( P3DGetToken( 0 ) )
\r
244 // strip off leading 'Obj_' if it exists
\r
245 if ( strstr( s_token, "Obj_" ) == s_token )
\r
246 strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
\r
248 strcpy( p3d.polysetNames[p3d.numPairs], s_token );
\r
250 // strip off trailing unused color information
\r
251 // if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
\r
252 // *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
\r
271 void SkinFromP3D( const char *file )
\r
273 char filename[1024];
\r
274 char *psetName, *associatedShader;
\r
277 ** a P3D file contains a list of polysets, each with a list of associated
\r
278 ** texture names that constitute it's
\r
282 ** P3D file -> skin
\r
283 ** polyset -> polyset
\r
284 ** texture -> texture.SHADER becomes polyset's shader
\r
286 sprintf( filename, "%s/%s", g_cddir, file );
\r
288 if ( !P3DLoad( filename ) )
\r
289 Error( "unable to load '%s'", filename );
\r
291 while ( P3DGetNextPair( &psetName, &associatedShader ) )
\r
295 // find the polyset in the object that this particular pset/shader pair
\r
296 // corresponds to and append the shader to it
\r
297 for ( i = 0; i < g_data.model.numSurfaces; i++ )
\r
299 if ( !_strcmpi( g_data.surfData[i].header.name, psetName) )
\r
303 if ( strstr( associatedShader, gamedir + 1 ) )
\r
305 p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
\r
309 p = associatedShader;
\r
312 strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
\r
314 g_data.surfData[i].header.numShaders++;
\r