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