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