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