home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / 3dslib.c next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  16.5 KB  |  631 lines

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