]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3data/p3dlib.c
set eol-style
[xonotic/netradiant.git] / tools / quake3 / q3data / p3dlib.c
1 #include "p3dlib.h"
2
3 #ifdef _WIN32
4 #include <io.h>
5 #endif
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9
10 #define MAX_POLYSETS 64
11
12 #if defined (__linux__) || defined (__APPLE__)
13 #define _strcmpi Q_stricmp
14 #define filelength Q_filelength
15 #define strlwr strlower
16 #endif
17 typedef struct
18 {
19         long len;
20
21         int      numPairs;
22         char polysetNames[MAX_POLYSETS][256];
23         char shaders[MAX_POLYSETS][256];
24
25         char *buffer, *curpos;
26 } p3d_t;
27
28 static p3d_t p3d;
29
30 static int P3DProcess();
31 static int P3DGetToken( int restOfLine );
32
33 static char s_token[1024];
34 static int      s_curpair;
35
36 /*
37 ** P3DLoad
38 **
39 */
40 int P3DLoad( const char *filename )
41 {
42         FILE *fp = fopen( filename, "rb" );
43
44         if ( !fp )
45                 return 0;
46
47         memset( &p3d, 0, sizeof( p3d ) );
48
49         p3d.len = filelength( fileno( fp ) );
50
51         p3d.curpos = p3d.buffer = malloc( p3d.len );
52
53         if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 )
54         {
55                 fclose( fp );
56                 return 0;
57         }
58
59         fclose( fp );
60
61         return P3DProcess();
62 }
63
64 /*
65 ** P3DClose
66 **
67 */
68 void P3DClose()
69 {
70         if ( p3d.buffer )
71         {
72                 free( p3d.buffer );
73                 p3d.buffer = 0;
74         }
75 }
76
77 int CharIsTokenDelimiter( int ch )
78 {
79         if ( ch <= 32 )
80                 return 1;
81         return 0;
82 }
83
84 int P3DSkipToToken( const char *name )
85 {
86         while ( P3DGetToken( 0 ) )
87         {
88                 if ( !_strcmpi( s_token, name ) )
89                         return 1;
90         }
91
92         return 0;
93 }
94
95 /*
96 ** P3DGetToken
97 **
98 */
99 int P3DGetToken( int restOfLine )
100 {
101         int i = 0;
102
103         if ( p3d.buffer == 0 )
104                 return 0;
105
106         if ( ( p3d.curpos - p3d.buffer ) == p3d.len )
107                 return 0;
108
109         // skip over crap
110         while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
111                     ( *p3d.curpos <= 32 ) )
112         {
113                 p3d.curpos++;
114         }
115
116         while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
117         {
118                 s_token[i] = *p3d.curpos;
119
120                 p3d.curpos++;
121                 i++;
122
123                 if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
124                          ( ( s_token[i-1] == '\n' ) ) )
125                 {
126                         s_token[i-1] = 0;
127                         break;
128                 }
129         }
130
131         s_token[i] = 0;
132
133         return 1;
134 }
135
136 int P3DGetNextPair( char **psetName, char **associatedShader )
137 {
138         if ( s_curpair < p3d.numPairs )
139         {
140                 *psetName = p3d.polysetNames[s_curpair];
141                 *associatedShader = p3d.shaders[s_curpair];
142                 s_curpair++;
143                 return 1;
144         }
145
146         return 0;
147 }
148
149 int P3DSkipToTokenInBlock( const char *name )
150 {
151         int iLevel = 0;
152
153         while ( P3DGetToken( 0 ) ) 
154         {
155                 if ( !_strcmpi( s_token, "}" ) )
156                         iLevel--;
157                 else if ( !_strcmpi( s_token, "{" ) )
158                         iLevel++;
159
160                 if ( !_strcmpi( s_token, name ) )
161                         return 1;
162
163                 if ( iLevel == 0 )
164                 {
165                         return 0;
166                 }
167         }
168
169         return 0;
170 }
171
172 /*
173 ** P3DProcess
174 **
175 ** Nothing fancy here.
176 */
177 int P3DProcess()
178 {
179
180         s_curpair = 0;
181
182         // first token should be a string
183         P3DGetToken( 1 );               // Voodoo Ascii File
184
185         // skip to the first Obj declaration
186         while ( P3DGetToken( 0 ) )
187         {
188                 if ( !_strcmpi( s_token, "Obj" ) )
189                 {
190                         int j = 0, k = 0;
191
192                         if ( P3DSkipToToken( "Text" ) )
193                         {
194                                 if ( P3DSkipToTokenInBlock( "TMap" ) )
195                                 {
196                                         char *p;
197
198                                         if ( !P3DSkipToToken( "Path" ) )
199                                                 return 0;
200
201                                         if ( !P3DGetToken( 1 ) )
202                                                 return 0;
203
204                                         while ( s_token[j] != 0 )
205                                         {
206                                                 if ( s_token[j] == '\\' )
207                                                 {
208                                                         j++;
209                                                         p3d.shaders[p3d.numPairs][k] = '/';
210                                                 }
211                                                 else
212                                                 {
213                                                         p3d.shaders[p3d.numPairs][k] = s_token[j];
214                                                 }
215                                                 j++;
216                                                 k++;
217                                         }
218                                         p3d.shaders[p3d.numPairs][k] = 0;
219
220                                         //
221                                         // strip off any explicit extensions
222                                         //
223                                         if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 )
224                                         {
225                                                 while ( *p )
226                                                 {
227                                                         if ( *p == '.' ) 
228                                                         {
229                                                                 *p = 0;
230                                                                 break;
231                                                         }
232                                                         p++;
233                                                 }
234                                         }
235
236                                         //
237                                         // skip to the end of the Object and grab its name
238                                         //
239                                         if ( !P3DSkipToToken( "Name" ) )
240                                                 return 0;
241
242                                         if ( P3DGetToken( 0 ) )
243                                         {
244                                                 // strip off leading 'Obj_' if it exists
245                                                 if ( strstr( s_token, "Obj_" ) == s_token )
246                                                         strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
247                                                 else
248                                                         strcpy( p3d.polysetNames[p3d.numPairs], s_token );
249
250                                                 // strip off trailing unused color information
251 //                                              if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
252 //                                                      *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
253
254                                                 p3d.numPairs++;
255                                         }
256                                         else
257                                         {
258                                                 return 0;
259                                         }
260                                 }
261                         }
262                 }
263         }
264
265         s_curpair = 0;
266
267         return 1;
268 }
269
270 #if 0
271 void SkinFromP3D( const char *file )
272 {
273         char filename[1024];
274         char *psetName, *associatedShader;
275
276         /*
277         ** a P3D file contains a list of polysets, each with a list of associated
278         ** texture names that constitute it's
279         **
280         ** Thus:
281         **
282         ** P3D file -> skin
283         ** polyset  -> polyset
284         **   texture -> texture.SHADER becomes polyset's shader
285         */
286         sprintf( filename, "%s/%s", g_cddir, file );
287
288         if ( !P3DLoad( filename ) )
289                 Error( "unable to load '%s'", filename );
290
291         while ( P3DGetNextPair( &psetName, &associatedShader ) )
292         {
293                 int i;
294
295                 // find the polyset in the object that this particular pset/shader pair
296                 // corresponds to and append the shader to it
297                 for ( i = 0; i < g_data.model.numSurfaces; i++ )
298                 {
299                         if ( !_strcmpi( g_data.surfData[i].header.name, psetName) )
300                         {
301                                 char *p;
302
303                                 if ( strstr( associatedShader, gamedir + 1 ) )
304                                 {
305                                         p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
306                                 }
307                                 else
308                                 {
309                                         p = associatedShader;
310                                 }
311
312                                 strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
313
314                                 g_data.surfData[i].header.numShaders++;
315                         }
316                 }
317
318         }
319
320         P3DClose();
321 }
322 #endif
323
324