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