]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3data/3dslib.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake3 / q3data / 3dslib.c
1 #include <assert.h>\r
2 #include "q3data.h"\r
3 \r
4 static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose );\r
5 \r
6 static qboolean s_verbose;\r
7 \r
8 #define MAX_MATERIALS 100\r
9 #define MAX_NAMED_OBJECTS 100\r
10 #define MAX_MESH_MATERIAL_GROUPS 100\r
11 #define MAX_TRI_OBJECTS 512\r
12 \r
13 static char s_buffer[1000000];\r
14 \r
15 static int ReadString( FILE *fp, char *buffer )\r
16 {\r
17         int i = 0;\r
18         int bytesRead = 0;\r
19 \r
20         do\r
21         {\r
22                 fread( &buffer[i], 1, sizeof( char ), fp );\r
23                 bytesRead++;\r
24         } while ( buffer[i++] != 0 );\r
25         buffer[i] = 0;\r
26 \r
27         return bytesRead;\r
28 }\r
29 \r
30 static int ReadChunkAndLength( FILE *fp, short *chunk, long *len )\r
31 {\r
32         if ( fread( chunk, sizeof( short ), 1, fp ) != 1 )\r
33                 return 0;\r
34         if ( fread( len, sizeof( long ), 1, fp ) != 1 )\r
35                 Error( "Unexpected EOF found" );\r
36         return 1;\r
37 }\r
38 \r
39 static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen )\r
40 {\r
41         unsigned short chunkID;\r
42         long chunkLen;\r
43         long bytesRead = 0;\r
44 \r
45         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
46         {\r
47                 switch ( chunkID )\r
48                 {\r
49                 case _3DS_CHUNK_MAT_MAPNAME:\r
50                         fread( buffer, chunkLen - 6, 1, fp );\r
51                         break;\r
52                 default:\r
53                         fread( s_buffer, chunkLen - 6, 1, fp );\r
54                         break;\r
55                 }\r
56                 bytesRead += chunkLen;\r
57                 if ( bytesRead >= thisChunkLen )\r
58                         return;\r
59         }\r
60 }\r
61 \r
62 static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat )\r
63 {\r
64         long chunkLen;\r
65         unsigned short chunkID;\r
66         long bytesRead = 0;\r
67         _3DSMaterial_t mat;\r
68         char curdir[1024];\r
69         char buffer[2048];\r
70 \r
71         memset( &mat, 0, sizeof( mat ) );\r
72 \r
73         if ( s_verbose )\r
74                 printf( "    >>> MATERIAL LIST\n" );\r
75 \r
76         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
77         {\r
78                 switch ( chunkID )\r
79                 {\r
80                         case _3DS_CHUNK_MAT_NAME:\r
81                                 fread( mat.name, chunkLen - 6, 1, fp );\r
82                                 if ( s_verbose )\r
83                                         printf( "        found mat name '%s'\n", mat.name );\r
84                                 break;\r
85                         case _3DS_CHUNK_TEXMAP:\r
86                                 LoadMapName( fp, mat.texture, chunkLen - 6 );\r
87                                 if ( s_verbose )\r
88                                         printf( "        found texture '%s'\n", mat.texture );\r
89                                 break;\r
90                         case _3DS_CHUNK_SPECMAP:\r
91                                 LoadMapName( fp, mat.specular, chunkLen - 6 );\r
92                                 if ( s_verbose )\r
93                                         printf( "        found specular map '%s'\n", mat.specular );\r
94                                 break;\r
95                         case _3DS_CHUNK_OPACMAP:\r
96                                 LoadMapName( fp, mat.opacity, chunkLen - 6 );\r
97                                 if ( s_verbose )\r
98                                         printf( "        found opacity map '%s'\n", mat.opacity );\r
99                                 break;\r
100                         case _3DS_CHUNK_REFLMAP:\r
101                                 LoadMapName( fp, mat.reflection, chunkLen - 6 );\r
102                                 if ( s_verbose )\r
103                                         printf( "        found reflection map '%s'\n", mat.reflection );\r
104                                 break;\r
105                         case _3DS_CHUNK_BUMPMAP:\r
106                                 LoadMapName( fp, mat.bump, chunkLen - 6 );\r
107                                 if ( s_verbose )\r
108                                         printf( "        found bump map '%s'\n", mat.bump );\r
109                                 break;\r
110                         default:\r
111                                 fread( s_buffer, chunkLen - 6, 1, fp );\r
112                                 break;\r
113                 }\r
114 \r
115                 bytesRead += chunkLen;\r
116 \r
117                 if ( bytesRead >= thisChunkLen )\r
118                         break;\r
119         }\r
120 \r
121         Q_getwd( curdir );\r
122 \r
123         if ( mat.texture[0] )\r
124         {\r
125                 sprintf( buffer, "%s%s", curdir, mat.texture );\r
126                 if ( strstr( buffer, gamedir + 1 ) )\r
127                         strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );\r
128                 else\r
129                         strcpy( mat.texture, buffer );\r
130         }\r
131 \r
132         if ( mat.specular[0] )\r
133         {\r
134                 sprintf( buffer, "%s%s", curdir, mat.specular );\r
135                 if ( strstr( buffer, gamedir + 1 ) )\r
136                         strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );\r
137                 else\r
138                         strcpy( mat.specular, buffer );\r
139         }\r
140 \r
141         if ( mat.bump[0] )\r
142         {\r
143                 sprintf( buffer, "%s%s", curdir, mat.bump );\r
144                 if ( strstr( buffer, gamedir + 1 ) )\r
145                         strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );\r
146                 else\r
147                         strcpy( mat.bump, buffer );\r
148         }\r
149 \r
150         if ( mat.reflection[0] )\r
151         {\r
152                 sprintf( buffer, "%s%s", curdir, mat.reflection );\r
153                 if ( strstr( buffer, gamedir + 1 ) )\r
154                         strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );\r
155                 else\r
156                         strcpy( mat.reflection, buffer );\r
157         }\r
158 \r
159         if ( mat.opacity[0] )\r
160         {\r
161                 sprintf( buffer, "%s%s", curdir, mat.opacity );\r
162                 if ( strstr( buffer, gamedir + 1 ) )\r
163                         strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );\r
164                 else\r
165                         strcpy( mat.opacity, buffer );\r
166         }\r
167 \r
168         *pMat = mat;\r
169 }\r
170 \r
171 static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG )\r
172 {\r
173         _3DSMeshMaterialGroup_t mmg;\r
174 \r
175         memset( &mmg, 0, sizeof( mmg ) );\r
176 \r
177         ReadString( fp, mmg.name );\r
178 \r
179         fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );\r
180         mmg.pFaces = malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );\r
181         fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );\r
182 \r
183         if ( s_verbose )\r
184         {\r
185                 printf( "    >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );\r
186 \r
187                 {\r
188                         int i;\r
189 \r
190                         for ( i = 0; i < mmg.numFaces; i++ )\r
191                         {\r
192                                 printf( "        %d\n", mmg.pFaces[i] );\r
193                         }\r
194                 }\r
195         }\r
196 \r
197         *pMMG = mmg;\r
198 }\r
199 \r
200 static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO )\r
201 {\r
202         long chunkLen;\r
203         unsigned short chunkID;\r
204         int i = 0;\r
205         long bytesRead = 0;\r
206         _3DSTriObject_t triObj;\r
207         _3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];\r
208         int numMeshMaterialGroups = 0;\r
209 \r
210         memset( &triObj, 0, sizeof( triObj ) );\r
211 \r
212         if ( s_verbose )\r
213                 printf( "        >>> NAMED TRI OBJECT\n" );\r
214 \r
215         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
216         {\r
217                 switch ( chunkID )\r
218                 {\r
219                 case _3DS_CHUNK_MSH_MAT_GROUP:\r
220                         LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );\r
221                         bytesRead += chunkLen;\r
222                         numMeshMaterialGroups++;\r
223                         break;\r
224                 case _3DS_CHUNK_FACE_ARRAY:\r
225                         fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );\r
226                         assert( triObj.pFaces == 0 );\r
227 \r
228                         triObj.pFaces = malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );\r
229                         fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );\r
230                         bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;\r
231 \r
232                         if ( s_verbose )\r
233                         {\r
234                                 printf( "            found face array with %d faces\n", triObj.numFaces );\r
235                                 for ( i = 0; i < triObj.numFaces; i++ )\r
236                                 {\r
237                                         printf( "                %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );\r
238                                 }\r
239                         }\r
240 \r
241                         break;\r
242                 case _3DS_CHUNK_POINT_ARRAY:\r
243                         fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );\r
244                         triObj.pPoints = malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );\r
245                         fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );\r
246                         bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;\r
247 \r
248                         // flip points around into our coordinate system\r
249                         for ( i = 0; i < triObj.numPoints; i++ )\r
250                         {\r
251                                 float x, y, z;\r
252 \r
253                                 x = triObj.pPoints[i].x;\r
254                                 y = triObj.pPoints[i].y;\r
255                                 z = triObj.pPoints[i].z;\r
256 \r
257                                 triObj.pPoints[i].x = -y;\r
258                                 triObj.pPoints[i].y = x;\r
259                                 triObj.pPoints[i].z = z;\r
260                         }\r
261 \r
262                         if ( s_verbose )\r
263                         {\r
264                                 printf( "            found point array with %d points\n", triObj.numPoints );\r
265                                 for ( i = 0; i < triObj.numPoints; i++ )\r
266                                 {\r
267                                         printf( "                %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );\r
268                                 }\r
269                         }\r
270                         break;\r
271                 case _3DS_CHUNK_TEX_VERTS:\r
272                         fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );\r
273                         triObj.pTexVerts = malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );\r
274                         fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );\r
275                         bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;\r
276 \r
277                         if ( s_verbose )\r
278                         {\r
279                                 printf( "            found tex vert array with %d tex verts\n", triObj.numTexVerts );\r
280                                 for ( i = 0; i < triObj.numTexVerts; i++ )\r
281                                 {\r
282                                         printf( "                %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );\r
283                                 }\r
284                         }\r
285                         break;\r
286                 default:\r
287                         fread( s_buffer, chunkLen - 6, 1, fp );\r
288                         bytesRead += chunkLen;\r
289                         break;\r
290                 }\r
291 \r
292                 if ( bytesRead >= thisChunkLen )\r
293                         break;\r
294         }\r
295         *pTO = triObj;\r
296 \r
297         if ( numMeshMaterialGroups == 0 )\r
298         {\r
299                 numMeshMaterialGroups = 1;\r
300                 strcpy( meshMaterialGroups[0].name, "(null)" );\r
301                 if ( pTO->numTexVerts ) {\r
302                         printf( "Warning: assigning (null) skin to tri object\n" );\r
303                 }\r
304         }\r
305         else\r
306         {\r
307                 assert( pTO->numFaces == meshMaterialGroups[0].numFaces );\r
308         }\r
309 \r
310         pTO->pMeshMaterialGroups = malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );\r
311         memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );\r
312         pTO->numMeshMaterialGroups = numMeshMaterialGroups;\r
313 \r
314         //\r
315         // sanity checks\r
316         //\r
317         assert( numMeshMaterialGroups <= 1 );\r
318 }\r
319 \r
320 static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO )\r
321 {\r
322         long chunkLen;\r
323         unsigned short chunkID;\r
324         int i = 0;\r
325         long bytesRead = 0;\r
326         char name[100];\r
327         _3DSTriObject_t triObj[MAX_TRI_OBJECTS];\r
328         int numTriObjects = 0;\r
329 \r
330         memset( triObj, 0, sizeof( triObj ) );\r
331 \r
332         bytesRead += ReadString( fp, name );\r
333 \r
334         if ( s_verbose )\r
335                 printf( "    >>> NAMED OBJECT '%s'\n", name );\r
336 \r
337         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
338         {\r
339                 switch ( chunkID )\r
340                 {\r
341                 case _3DS_CHUNK_NAMED_TRI_OBJECT:\r
342                         LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );\r
343                         numTriObjects++;\r
344                         break;\r
345                 default:\r
346                         fread( s_buffer, chunkLen - 6, 1, fp );\r
347                         break;\r
348                 }\r
349 \r
350                 bytesRead += chunkLen;\r
351 \r
352                 if ( bytesRead >= thisChunkLen )\r
353                         break;\r
354         }\r
355 \r
356         strcpy( pNO->name, name );\r
357         pNO->pTriObjects = malloc( sizeof( _3DSTriObject_t ) * numTriObjects );\r
358         memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );\r
359         pNO->numTriObjects = numTriObjects;\r
360 \r
361         assert( numTriObjects <= 1 );\r
362 }\r
363 \r
364 static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC )\r
365 {\r
366         unsigned short chunkID;\r
367         long chunkLen;\r
368         long bytesRead = 0;\r
369         _3DSEditChunk_t editChunk;\r
370 \r
371         _3DSMaterial_t mat[MAX_MATERIALS];\r
372         _3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];\r
373 \r
374         int numMaterials = 0, numNamedObjects = 0;\r
375 \r
376         memset( &editChunk, 0, sizeof( editChunk ) );\r
377 \r
378         if ( s_verbose )\r
379                 printf( ">>> EDIT CHUNK\n" );\r
380 \r
381         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
382         {\r
383                 switch ( chunkID )\r
384                 {\r
385                 case _3DS_CHUNK_MAT_LIST:\r
386                         LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );\r
387                         numMaterials++;\r
388                         break;\r
389                 case _3DS_CHUNK_NAMED_OBJECT:\r
390                         LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );\r
391                         if ( namedObjects[numNamedObjects].numTriObjects != 0 )\r
392                                 ++numNamedObjects;\r
393                         break;\r
394                 case _3DS_CHUNK_MESH_VERSION:\r
395                 default:\r
396                         fread( s_buffer, chunkLen - 6, 1, fp );\r
397                         break;\r
398                 }\r
399 \r
400                 bytesRead += chunkLen;\r
401 \r
402                 if ( bytesRead >= thisChunkLen )\r
403                         break;\r
404         }\r
405 \r
406         if ( numMaterials == 0 )\r
407         {\r
408                 numMaterials = 1;\r
409                 strcpy( mat[0].name, "(null)" );\r
410                 printf( "Warning: no material definitions found\n" );\r
411         }\r
412 \r
413         pEC->numNamedObjects = numNamedObjects;\r
414 \r
415         pEC->pMaterials = malloc( sizeof( _3DSMaterial_t ) * numMaterials );\r
416         pEC->pNamedObjects = malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );\r
417 \r
418         memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );\r
419         memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );\r
420 }\r
421 \r
422 static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose )\r
423 {\r
424         FILE *fp;\r
425         unsigned short chunkID;\r
426         long  chunkLen;\r
427         _3DSEditChunk_t editChunk;\r
428 \r
429         s_verbose = verbose;\r
430 \r
431         if ( ( fp = fopen( filename, "rb" ) ) == 0 )\r
432                 Error( "Unable to open '%s'", filename );\r
433 \r
434         // read magic number\r
435         if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||\r
436                  ( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) )\r
437         {\r
438                 Error( "Missing or incorrect magic number in '%s'", filename );\r
439         }\r
440         if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 )\r
441                 Error( "Unexpected EOF encountered in '%s'", filename );\r
442         // version number\r
443         if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
444                 Error( "Missing version number in '%s'", filename );\r
445         if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 )\r
446                 Error( "Unexpected EOF encountered in '%s'", filename );\r
447 \r
448         while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )\r
449         {\r
450                 switch ( chunkID )\r
451                 {\r
452                         case _3DS_CHUNK_EDIT:\r
453                                 LoadEditChunk( fp, chunkLen - 6, &editChunk );\r
454                                 break;\r
455                         case _3DS_CHUNK_KEYFRAME_DATA:\r
456                                 fread( s_buffer, chunkLen - 6, 1, fp );\r
457                                 break;\r
458                         default:\r
459                                 fread( s_buffer, chunkLen - 6, 1, fp );\r
460                                 break;\r
461                 }\r
462         }\r
463 \r
464         fclose( fp );\r
465 \r
466         p3DS->editChunk = editChunk;\r
467 }\r
468 \r
469 static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris )\r
470 {\r
471         vec3_t faceNormals[POLYSET_MAXTRIANGLES];\r
472         vec3_t vertexNormals[POLYSET_MAXTRIANGLES*3];\r
473         vec3_t side0, side1, facenormal;\r
474         int f, v;\r
475 \r
476         memset( faceNormals, 0, sizeof( faceNormals ) );\r
477         memset( vertexNormals, 0, sizeof( vertexNormals ) );\r
478 \r
479         //\r
480         // compute face normals\r
481         //\r
482         for ( f = 0; f < pTO->numFaces; f++ )\r
483         {\r
484                 VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );\r
485                 VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );\r
486 \r
487                 CrossProduct( side0, side1, facenormal );\r
488                 VectorNormalize( facenormal, faceNormals[f] );\r
489         }\r
490 \r
491         //\r
492         // sum vertex normals\r
493         //\r
494         for ( v = 0; v < pTO->numPoints; v++ )\r
495         {\r
496                 for ( f = 0; f < pTO->numFaces; f++ )\r
497                 {\r
498                         if ( ( pTO->pFaces[f].a == v ) ||\r
499                                  ( pTO->pFaces[f].b == v ) ||\r
500                                  ( pTO->pFaces[f].c == v ) )\r
501                         {\r
502                                 vertexNormals[v][0] += faceNormals[f][0];\r
503                                 vertexNormals[v][1] += faceNormals[f][1];\r
504                                 vertexNormals[v][2] += faceNormals[f][2];\r
505                         }\r
506                 }\r
507 \r
508                 VectorNormalize( vertexNormals[v], vertexNormals[v] );\r
509         }\r
510 \r
511         //\r
512         // copy vertex normals into triangles\r
513         //\r
514         for ( f = 0; f < pTO->numFaces; f++ )\r
515         {\r
516                 int i0 = pTO->pFaces[f].c;\r
517                 int i1 = pTO->pFaces[f].b;\r
518                 int i2 = pTO->pFaces[f].a;\r
519 \r
520                 VectorCopy( vertexNormals[i0], pTris[f].normals[0] );\r
521                 VectorCopy( vertexNormals[i1], pTris[f].normals[1] );\r
522                 VectorCopy( vertexNormals[i2], pTris[f].normals[2] );\r
523         }\r
524 }\r
525 \r
526 /*\r
527 ** void _3DS_LoadPolysets\r
528 */\r
529 void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose )\r
530 {\r
531         _3DS_t _3ds;\r
532         int numPolysets;\r
533         polyset_t *pPSET;\r
534         triangle_t *ptri, *triangles;\r
535         int i;\r
536 \r
537         // load the 3DS\r
538         memset( &_3ds, 0, sizeof( _3ds ) );\r
539         Load3DS( filename, &_3ds, verbose );\r
540 \r
541         // compute information\r
542         numPolysets = _3ds.editChunk.numNamedObjects;\r
543 \r
544         // allocate memory\r
545         pPSET = calloc( 1, numPolysets * sizeof( polyset_t ) );\r
546         triangles = ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );\r
547 \r
548         // copy the data over\r
549         for ( i = 0; i < numPolysets; i++ )\r
550         {\r
551                 char matnamebuf[1024];\r
552                 int j;\r
553                 triangle_t *tri;\r
554                 _3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];\r
555 \r
556                 pPSET[i].triangles = ptri;\r
557                 pPSET[i].numtriangles = pTO->numFaces;\r
558                 strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );\r
559 \r
560                 strcpy( matnamebuf, filename );\r
561                 if ( strrchr( matnamebuf, '/' ) )\r
562                         *( strrchr( matnamebuf, '/' ) + 1 )= 0;\r
563                 strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );\r
564 \r
565                 if ( strstr( matnamebuf, gamedir ) )\r
566                         strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );\r
567                 else\r
568                         strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );\r
569 \r
570                 assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );\r
571 \r
572                 for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )\r
573                 {\r
574                         int i0 = pTO->pFaces[j].c;\r
575                         int i1 = pTO->pFaces[j].b;\r
576                         int i2 = pTO->pFaces[j].a;\r
577 \r
578                         tri->verts[0][0] = pTO->pPoints[i0].x;\r
579                         tri->verts[0][1] = pTO->pPoints[i0].y;\r
580                         tri->verts[0][2] = pTO->pPoints[i0].z;\r
581 \r
582                         tri->verts[1][0] = pTO->pPoints[i1].x;\r
583                         tri->verts[1][1] = pTO->pPoints[i1].y;\r
584                         tri->verts[1][2] = pTO->pPoints[i1].z;\r
585 \r
586                         tri->verts[2][0] = pTO->pPoints[i2].x;\r
587                         tri->verts[2][1] = pTO->pPoints[i2].y;\r
588                         tri->verts[2][2] = pTO->pPoints[i2].z;\r
589 /*\r
590                         for ( k = 0; k < 3; k++ )\r
591                         {\r
592                                 tri->colors[0][k] = 1;\r
593                                 tri->colors[1][k] = 1;\r
594                                 tri->colors[2][k] = 1;\r
595                         }\r
596 */\r
597 \r
598                         if ( pTO->pTexVerts )\r
599                         {\r
600                                 tri->texcoords[0][0] = pTO->pTexVerts[i0].s;\r
601                                 tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;\r
602                                 tri->texcoords[1][0] = pTO->pTexVerts[i1].s;\r
603                                 tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;\r
604                                 tri->texcoords[2][0] = pTO->pTexVerts[i2].s;\r
605                                 tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;\r
606                         }\r
607 \r
608                         tri++;\r
609                 }\r
610 \r
611                 ptri += pPSET[i].numtriangles;\r
612                 assert( ptri - triangles < POLYSET_MAXTRIANGLES );\r
613         }\r
614 \r
615         // compute normal data\r
616 #if 0\r
617         for ( i = 0; i < numPolysets; i++ )\r
618         {\r
619                 // unique vertices based solely on vertex position\r
620                 ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],\r
621                                                  pPSET[i].triangles );\r
622         }\r
623 #endif\r
624 \r
625         free( _3ds.editChunk.pMaterials );\r
626         free( _3ds.editChunk.pNamedObjects );\r
627 \r
628         *ppPSET = pPSET;\r
629         *numpsets = numPolysets;\r
630 }\r