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