]> icculus.org git repositories - divverent/netradiant.git/blob - tools/quake3/q3map2/convert_ase.c
NOW I do it right: #woxblox#
[divverent/netradiant.git] / tools / quake3 / q3map2 / convert_ase.c
1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22 ----------------------------------------------------------------------------------
23
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27 ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define CONVERT_ASE_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41 /*
42 ConvertSurface()
43 converts a bsp drawsurface to an ase chunk
44 */
45
46 int numLightmapsASE = 0;
47 static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin )
48 {
49         int                             i, v, face, a, b, c;
50         bspDrawVert_t   *dv;
51         vec3_t                  normal;
52         char                    name[ 1024 ];
53         
54         
55         /* ignore patches for now */
56         if( ds->surfaceType != MST_PLANAR && ds->surfaceType != MST_TRIANGLE_SOUP )
57                 return;
58         
59         /* print object header for each dsurf */
60         sprintf( name, "mat%dmodel%dsurf%d", ds->shaderNum, modelNum, surfaceNum );
61         fprintf( f, "*GEOMOBJECT\t{\r\n" );
62         fprintf( f, "\t*NODE_NAME\t\"%s\"\r\n", name );
63         fprintf( f, "\t*NODE_TM\t{\r\n" );
64         fprintf( f, "\t\t*NODE_NAME\t\"%s\"\r\n", name );
65         fprintf( f, "\t\t*INHERIT_POS\t0\t0\t0\r\n" );
66         fprintf( f, "\t\t*INHERIT_ROT\t0\t0\t0\r\n" );
67         fprintf( f, "\t\t*INHERIT_SCL\t0\t0\t0\r\n" );
68         fprintf( f, "\t\t*TM_ROW0\t1.0\t0\t0\r\n" );
69         fprintf( f, "\t\t*TM_ROW1\t0\t1.0\t0\r\n" );
70         fprintf( f, "\t\t*TM_ROW2\t0\t0\t1.0\r\n" );
71         fprintf( f, "\t\t*TM_ROW3\t0\t0\t0\r\n" );
72         fprintf( f, "\t\t*TM_POS\t%f\t%f\t%f\r\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] );
73         fprintf( f, "\t}\r\n" );
74         
75         /* print mesh header */
76         fprintf( f, "\t*MESH\t{\r\n" );
77         fprintf( f, "\t\t*TIMEVALUE\t0\r\n" );
78         fprintf( f, "\t\t*MESH_NUMVERTEX\t%d\r\n", ds->numVerts );
79         fprintf( f, "\t\t*MESH_NUMFACES\t%d\r\n", ds->numIndexes / 3 );
80         switch( ds->surfaceType )
81         {
82                 case MST_PLANAR:
83                         fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_PLANAR\"\r\n" );
84                         break;
85                 case MST_TRIANGLE_SOUP:
86                         fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_TRIANGLE_SOUP\"\r\n" );
87                         break;
88         }
89         
90         /* export vertex xyz */
91         fprintf( f, "\t\t*MESH_VERTEX_LIST\t{\r\n" );
92         for( i = 0; i < ds->numVerts; i++ )
93         {
94                 v = i + ds->firstVert;
95                 dv = &bspDrawVerts[ v ];
96                 fprintf( f, "\t\t\t*MESH_VERTEX\t%d\t%f\t%f\t%f\r\n", i, dv->xyz[ 0 ], dv->xyz[ 1 ], dv->xyz[ 2 ] );
97         }
98         fprintf( f, "\t\t}\r\n" );
99
100         /* export vertex normals */
101         fprintf( f, "\t\t*MESH_NORMALS\t{\r\n" );
102         for( i = 0; i < ds->numIndexes; i += 3 )
103         {
104                 face = (i / 3);
105                 a = bspDrawIndexes[ i + ds->firstIndex ];
106                 b = bspDrawIndexes[ i + ds->firstIndex + 1 ];
107                 c = bspDrawIndexes[ i + ds->firstIndex + 2 ];
108                 VectorCopy( bspDrawVerts[ a ].normal, normal );
109                 VectorAdd( normal, bspDrawVerts[ b ].normal, normal );
110                 VectorAdd( normal, bspDrawVerts[ c ].normal, normal );
111                 if( VectorNormalize( normal, normal ) )
112                         fprintf( f, "\t\t\t*MESH_FACENORMAL\t%d\t%f\t%f\t%f\r\n", face, normal[ 0 ], normal[ 1 ], normal[ 2 ] );
113         }
114         for( i = 0; i < ds->numVerts; i++ )
115         {
116                 v = i + ds->firstVert;
117                 dv = &bspDrawVerts[ v ];
118                 fprintf( f, "\t\t\t*MESH_VERTEXNORMAL\t%d\t%f\t%f\t%f\r\n", i, dv->normal[ 0 ], dv->normal[ 1 ], dv->normal[ 2 ] );
119         }
120         fprintf( f, "\t\t}\r\n" );
121         
122         /* export faces */
123         fprintf( f, "\t\t*MESH_FACE_LIST\t{\r\n" );
124         for( i = 0; i < ds->numIndexes; i += 3 )
125         {
126                 face = (i / 3);
127                 a = bspDrawIndexes[ i + ds->firstIndex ];
128                 c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
129                 b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
130                 fprintf( f, "\t\t\t*MESH_FACE\t%d\tA:\t%d\tB:\t%d\tC:\t%d\tAB:\t1\tBC:\t1\tCA:\t1\t*MESH_SMOOTHING\t0\t*MESH_MTLID\t0\r\n",
131                         face, a, b, c );
132         }
133         fprintf( f, "\t\t}\r\n" );
134         
135         /* export vertex st */
136         fprintf( f, "\t\t*MESH_NUMTVERTEX\t%d\r\n", ds->numVerts );
137         fprintf( f, "\t\t*MESH_TVERTLIST\t{\r\n" );
138         for( i = 0; i < ds->numVerts; i++ )
139         {
140                 v = i + ds->firstVert;
141                 dv = &bspDrawVerts[ v ];
142                 fprintf( f, "\t\t\t*MESH_TVERT\t%d\t%f\t%f\t%f\r\n", i, dv->st[ 0 ], (1.0 - dv->st[ 1 ]), 1.0f );
143         }
144         fprintf( f, "\t\t}\r\n" );
145         
146         /* export texture faces */
147         fprintf( f, "\t\t*MESH_NUMTVFACES\t%d\r\n", ds->numIndexes / 3 );
148         fprintf( f, "\t\t*MESH_TFACELIST\t{\r\n" );
149         for( i = 0; i < ds->numIndexes; i += 3 )
150         {
151                 face = (i / 3);
152                 a = bspDrawIndexes[ i + ds->firstIndex ];
153                 c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
154                 b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
155                 fprintf( f, "\t\t\t*MESH_TFACE\t%d\t%d\t%d\t%d\r\n", face, a, b, c );
156         }
157         fprintf( f, "\t\t}\r\n" );
158         
159         /* print mesh footer */
160         fprintf( f, "\t}\r\n" );
161
162         /* print object footer */
163         fprintf( f, "\t*PROP_MOTIONBLUR\t0\r\n" );
164         fprintf( f, "\t*PROP_CASTSHADOW\t1\r\n" );
165         fprintf( f, "\t*PROP_RECVSHADOW\t1\r\n" );
166         if(lightmapsAsTexcoord)
167         {
168                 if(ds->lightmapNum[0] >= 0 && ds->lightmapNum[0] + (int)deluxemap < numLightmapsASE)
169                         fprintf( f, "\t*MATERIAL_REF\t%d\r\n", ds->lightmapNum[0] + deluxemap );
170                 else
171                         Sys_Printf( "WARNING: lightmap %d out of range, not exporting\n", ds->lightmapNum[0] + deluxemap );
172         }
173         else
174                 fprintf( f, "\t*MATERIAL_REF\t%d\r\n", ds->shaderNum );
175         fprintf( f, "}\r\n" );
176 }
177
178
179
180 /*
181 ConvertModel()
182 exports a bsp model to an ase chunk
183 */
184
185 static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
186 {
187         int                                     i, s;
188         bspDrawSurface_t        *ds;
189         
190         
191         /* go through each drawsurf in the model */
192         for( i = 0; i < model->numBSPSurfaces; i++ )
193         {
194                 s = i + model->firstBSPSurface;
195                 ds = &bspDrawSurfaces[ s ];
196                 ConvertSurface( f, model, modelNum, ds, s, origin );
197         }
198 }
199
200
201
202 /*
203 ConvertShader()
204 exports a bsp shader to an ase chunk
205 */
206
207 /*
208         *MATERIAL 0 {
209                 *MATERIAL_NAME "models/test/rock16l"
210                 *MATERIAL_CLASS "Standard"
211                 *MATERIAL_AMBIENT 0.5882        0.5882  0.5882
212                 *MATERIAL_DIFFUSE 0.5882        0.5882  0.5882
213                 *MATERIAL_SPECULAR 0.5882       0.5882  0.5882
214                 *MATERIAL_SHINE 0.0000
215                 *MATERIAL_SHINESTRENGTH 0.0000
216                 *MATERIAL_TRANSPARENCY 0.0000
217                 *MATERIAL_WIRESIZE 1.0000
218                 *MATERIAL_SHADING Phong
219                 *MATERIAL_XP_FALLOFF 0.0000
220                 *MATERIAL_SELFILLUM 0.0000
221                 *MATERIAL_FALLOFF In
222                 *MATERIAL_XP_TYPE Filter
223                 *MAP_DIFFUSE {
224                         *MAP_NAME "Map #2"
225                         *MAP_CLASS "Bitmap"
226                         *MAP_SUBNO 1
227                         *MAP_AMOUNT 1.0000
228                         *BITMAP "models/test/rock16l"
229                         *MAP_TYPE Screen
230                         *UVW_U_OFFSET 0.0000
231                         *UVW_V_OFFSET 0.0000
232                         *UVW_U_TILING 1.0000
233                         *UVW_V_TILING 1.0000
234                         *UVW_ANGLE 0.0000
235                         *UVW_BLUR 1.0000
236                         *UVW_BLUR_OFFSET 0.0000
237                         *UVW_NOUSE_AMT 1.0000
238                         *UVW_NOISE_SIZE 1.0000
239                         *UVW_NOISE_LEVEL 1
240                         *UVW_NOISE_PHASE 0.0000
241                         *BITMAP_FILTER Pyramidal
242                 }
243         }
244 */
245
246 static void ConvertShader( FILE *f, bspShader_t *shader, int shaderNum )
247 {
248         shaderInfo_t    *si;
249         char                    *c, filename[ 1024 ];
250         
251         
252         /* get shader */
253         si = ShaderInfoForShader( shader->shader );
254         if( si == NULL )
255         {
256                 Sys_Printf( "WARNING: NULL shader in BSP\n" );
257                 return;
258         }
259         
260         /* set bitmap filename */
261         if( si->shaderImage->filename[ 0 ] != '*' )
262                 strcpy( filename, si->shaderImage->filename );
263         else
264                 sprintf( filename, "%s.tga", si->shader );
265         for( c = filename; *c != '\0'; c++ )
266                 if( *c == '/' )
267                         *c = '\\';
268         
269         /* print shader info */
270         fprintf( f, "\t*MATERIAL\t%d\t{\r\n", shaderNum );
271         fprintf( f, "\t\t*MATERIAL_NAME\t\"%s\"\r\n", shader->shader );
272         fprintf( f, "\t\t*MATERIAL_CLASS\t\"Standard\"\r\n" );
273         fprintf( f, "\t\t*MATERIAL_DIFFUSE\t%f\t%f\t%f\r\n", si->color[ 0 ], si->color[ 1 ], si->color[ 2 ] );
274         fprintf( f, "\t\t*MATERIAL_SHADING Phong\r\n" );
275         
276         /* print map info */
277         fprintf( f, "\t\t*MAP_DIFFUSE\t{\r\n" );
278         fprintf( f, "\t\t\t*MAP_NAME\t\"%s\"\r\n", shader->shader );
279         fprintf( f, "\t\t\t*MAP_CLASS\t\"Bitmap\"\r\n");
280         fprintf( f, "\t\t\t*MAP_SUBNO\t1\r\n" );
281         fprintf( f, "\t\t\t*MAP_AMOUNT\t1.0\r\n" );
282         fprintf( f, "\t\t\t*MAP_TYPE\tScreen\r\n" );
283         if(shadersAsBitmap)
284                 fprintf( f, "\t\t\t*BITMAP\t\"%s\"\r\n", shader->shader );
285         else
286                 fprintf( f, "\t\t\t*BITMAP\t\"..\\%s\"\r\n", filename );
287         fprintf( f, "\t\t\t*BITMAP_FILTER\tPyramidal\r\n" );
288         fprintf( f, "\t\t}\r\n" );
289         
290         fprintf( f, "\t}\r\n" );
291 }
292 static void ConvertLightmap( FILE *f, const char *base, int lightmapNum )
293 {
294         /* print shader info */
295         fprintf( f, "\t*MATERIAL\t%d\t{\r\n", lightmapNum );
296         fprintf( f, "\t\t*MATERIAL_NAME\t\"lm_%04d\"\r\n", lightmapNum );
297         fprintf( f, "\t\t*MATERIAL_CLASS\t\"Standard\"\r\n" );
298         fprintf( f, "\t\t*MATERIAL_DIFFUSE\t1\t1\t1\r\n");
299         fprintf( f, "\t\t*MATERIAL_SHADING Phong\r\n" );
300         
301         /* print map info */
302         if(lightmapNum >= 0)
303         {
304                 fprintf( f, "\t\t*MAP_DIFFUSE\t{\r\n" );
305                 fprintf( f, "\t\t\t*MAP_NAME\t\"lm_%04d\"\r\n", lightmapNum );
306                 fprintf( f, "\t\t\t*MAP_CLASS\t\"Bitmap\"\r\n");
307                 fprintf( f, "\t\t\t*MAP_SUBNO\t1\r\n" );
308                 fprintf( f, "\t\t\t*MAP_AMOUNT\t1.0\r\n" );
309                 fprintf( f, "\t\t\t*MAP_TYPE\tScreen\r\n" );
310                 fprintf( f, "\t\t\t*BITMAP\t\"%s\\lm_%04d.tga\"\r\n", base, lightmapNum );
311                 fprintf( f, "\t\t\t*BITMAP_FILTER\tPyramidal\r\n" );
312                 fprintf( f, "\t\t}\r\n" );
313         }
314         
315         fprintf( f, "\t}\r\n" );
316 }
317
318
319
320 /*
321 ConvertBSPToASE()
322 exports an 3d studio ase file from the bsp
323 */
324
325 int ConvertBSPToASE( char *bspName )
326 {
327         int                             i, modelNum;
328         FILE                    *f;
329         bspShader_t             *shader;
330         bspModel_t              *model;
331         entity_t                *e;
332         vec3_t                  origin;
333         const char              *key;
334         char                    name[ 1024 ], base[ 1024 ], dirname[ 1024 ];
335         
336         
337         /* note it */
338         Sys_Printf( "--- Convert BSP to ASE ---\n" );
339
340         /* create the ase filename from the bsp name */
341         strcpy( dirname, bspName );
342         StripExtension( dirname );
343         strcpy( name, bspName );
344         StripExtension( name );
345         strcat( name, ".ase" );
346         Sys_Printf( "writing %s\n", name );
347         
348         ExtractFileBase( bspName, base );
349         
350         /* open it */
351         f = fopen( name, "wb" );
352         if( f == NULL )
353                 Error( "Open failed on %s\n", name );
354         
355         /* print header */
356         fprintf( f, "*3DSMAX_ASCIIEXPORT\t200\r\n" );
357         fprintf( f, "*COMMENT\t\"Generated by Q3Map2 (ydnar) -convert -format ase\"\r\n" );
358         fprintf( f, "*SCENE\t{\r\n" );
359         fprintf( f, "\t*SCENE_FILENAME\t\"%s.bsp\"\r\n", base );
360         fprintf( f, "\t*SCENE_FIRSTFRAME\t0\r\n" );
361         fprintf( f, "\t*SCENE_LASTFRAME\t100\r\n" );
362         fprintf( f, "\t*SCENE_FRAMESPEED\t30\r\n" );
363         fprintf( f, "\t*SCENE_TICKSPERFRAME\t160\r\n" );
364         fprintf( f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
365         fprintf( f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
366         fprintf( f, "}\r\n" );
367         
368         /* print materials */
369         fprintf( f, "*MATERIAL_LIST\t{\r\n" );
370         if(lightmapsAsTexcoord)
371         {
372                 int lightmapCount;
373                 for( lightmapCount = 0; lightmapCount < numBSPLightmaps; lightmapCount++ )
374                         ;
375                 for( ; ; lightmapCount++ )
376                 {
377                         char buf[1024];
378                         FILE *tmp;
379                         snprintf(buf, sizeof(buf), "%s/lm_%04d.tga", dirname, lightmapCount);
380                         buf[sizeof(buf) - 1] = 0;
381                         tmp = fopen(buf, "rb");
382                         if(!tmp)
383                                 break;
384                         fclose(tmp);
385                 }
386                 fprintf( f, "\t*MATERIAL_COUNT\t%d\r\n", lightmapCount );
387                 for( i = 0; i < lightmapCount; i++ )
388                         ConvertLightmap( f, base, i );
389                 numLightmapsASE = lightmapCount;
390         }
391         else
392         {
393                 fprintf( f, "\t*MATERIAL_COUNT\t%d\r\n", numBSPShaders );
394                 for( i = 0; i < numBSPShaders; i++ )
395                 {
396                         shader = &bspShaders[ i ];
397                         ConvertShader( f, shader, i );
398                 }
399         }
400         fprintf( f, "}\r\n" );
401         
402         /* walk entity list */
403         for( i = 0; i < numEntities; i++ )
404         {
405                 /* get entity and model */
406                 e = &entities[ i ];
407                 if( i == 0 )
408                         modelNum = 0;
409                 else
410                 {
411                         key = ValueForKey( e, "model" );
412                         if( key[ 0 ] != '*' )
413                                 continue;
414                         modelNum = atoi( key + 1 );
415                 }
416                 model = &bspModels[ modelNum ];
417                 
418                 /* get entity origin */
419                 key = ValueForKey( e, "origin" );
420                 if( key[ 0 ] == '\0' )
421                         VectorClear( origin );
422                 else
423                         GetVectorForKey( e, "origin", origin );
424                 
425                 /* convert model */
426                 ConvertModel( f, model, modelNum, origin );
427         }
428         
429         /* close the file and return */
430         fclose( f );
431         
432         /* return to sender */
433         return 0;
434 }
435
436
437