-/* -----------------------------------------------------------------------------\r
-\r
-PicoModel Library\r
-\r
-Copyright (c) 2002, Randy Reddig & seaw0lf\r
-All rights reserved.\r
-\r
-Redistribution and use in source and binary forms, with or without modification,\r
-are permitted provided that the following conditions are met:\r
-\r
-Redistributions of source code must retain the above copyright notice, this list\r
-of conditions and the following disclaimer.\r
-\r
-Redistributions in binary form must reproduce the above copyright notice, this\r
-list of conditions and the following disclaimer in the documentation and/or\r
-other materials provided with the distribution.\r
-\r
-Neither the names of the copyright holders nor the names of its contributors may\r
-be used to endorse or promote products derived from this software without\r
-specific prior written permission.\r
-\r
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
------------------------------------------------------------------------------ */\r
-\r
-\r
-\r
-/* marker */\r
-#define PM_MS3D_C\r
-\r
-/* dependencies */\r
-#include "picointernal.h"\r
-\r
-/* disable warnings */\r
-#ifdef _WIN32\r
-#pragma warning( disable:4100 ) /* unref param */\r
-#endif\r
-\r
-/* remarks:\r
- * - loader seems stable\r
- * todo:\r
- * - fix uv coordinate problem\r
- * - check for buffer overflows ('bufptr' accesses)\r
- */\r
-/* uncomment when debugging this module */\r
- #define DEBUG_PM_MS3D\r
- #define DEBUG_PM_MS3D_EX\r
-\r
-/* plain white */\r
-static picoColor_t white = { 255,255,255,255 };\r
-\r
-/* ms3d limits */\r
-#define MS3D_MAX_VERTS 8192\r
-#define MS3D_MAX_TRIS 16384\r
-#define MS3D_MAX_GROUPS 128\r
-#define MS3D_MAX_MATERIALS 128\r
-#define MS3D_MAX_JOINTS 128\r
-#define MS3D_MAX_KEYFRAMES 216\r
-\r
-/* ms3d flags */\r
-#define MS3D_SELECTED 1\r
-#define MS3D_HIDDEN 2\r
-#define MS3D_SELECTED2 4\r
-#define MS3D_DIRTY 8\r
-\r
-/* this freaky loader needs byte alignment */\r
-#pragma pack(push, 1)\r
-\r
-/* ms3d header */\r
-typedef struct SMsHeader\r
-{\r
- char magic[10];\r
- int version;\r
-}\r
-TMsHeader;\r
-\r
-/* ms3d vertex */\r
-typedef struct SMsVertex\r
-{\r
- unsigned char flags; /* sel, sel2, or hidden */\r
- float xyz[3];\r
- char boneID; /* -1 means 'no bone' */\r
- unsigned char refCount;\r
-}\r
-TMsVertex;\r
-\r
-/* ms3d triangle */\r
-typedef struct SMsTriangle\r
-{\r
- unsigned short flags; /* sel, sel2, or hidden */\r
- unsigned short vertexIndices[3];\r
- float vertexNormals[3][3];\r
- float s[3];\r
- float t[3];\r
- unsigned char smoothingGroup; /* 1 - 32 */\r
- unsigned char groupIndex;\r
-}\r
-TMsTriangle;\r
-\r
-/* ms3d material */\r
-typedef struct SMsMaterial\r
-{\r
- char name[32];\r
- float ambient[4];\r
- float diffuse[4];\r
- float specular[4];\r
- float emissive[4];\r
- float shininess; /* range 0..128 */\r
- float transparency; /* range 0..1 */\r
- unsigned char mode;\r
- char texture [128]; /* texture.bmp */\r
- char alphamap[128]; /* alpha.bmp */\r
-}\r
-TMsMaterial;\r
-\r
-// ms3d group (static part)\r
-// followed by a variable size block (see below)\r
-typedef struct SMsGroup\r
-{\r
- unsigned char flags; // sel, hidden\r
- char name[32];\r
- unsigned short numTriangles;\r
-/*\r
- unsigned short triangleIndices[ numTriangles ];\r
- char materialIndex; // -1 means 'no material'\r
-*/\r
-}\r
-TMsGroup;\r
-\r
-// ms3d joint\r
-typedef struct SMsJoint\r
-{\r
- unsigned char flags;\r
- char name[32];\r
- char parentName[32];\r
- float rotation[3];\r
- float translation[3];\r
- unsigned short numRotationKeyframes;\r
- unsigned short numTranslationKeyframes;\r
-}\r
-TMsJoint;\r
-\r
-// ms3d keyframe\r
-typedef struct SMsKeyframe\r
-{\r
- float time;\r
- float parameter[3];\r
-}\r
-TMsKeyframe;\r
-\r
-/* restore previous data alignment */\r
-#pragma pack(pop)\r
-\r
-/* _ms3d_canload:\r
- * validates a milkshape3d model file.\r
- */\r
-static int _ms3d_canload( PM_PARAMS_CANLOAD )\r
-{\r
- TMsHeader *hdr;\r
- \r
- \r
- /* to keep the compiler happy */\r
- *fileName = *fileName;\r
-\r
- /* sanity check */\r
- if (bufSize < sizeof(TMsHeader))\r
- return PICO_PMV_ERROR_SIZE;\r
-\r
- /* get ms3d header */\r
- hdr = (TMsHeader *)buffer;\r
-\r
- /* check ms3d magic */\r
- if (strncmp(hdr->magic,"MS3D000000",10) != 0)\r
- return PICO_PMV_ERROR_IDENT;\r
-\r
- /* check ms3d version */\r
- if (_pico_little_long(hdr->version) < 3 ||\r
- _pico_little_long(hdr->version) > 4)\r
- {\r
- _pico_printf( PICO_ERROR,"MS3D file ignored. Only MS3D 1.3 and 1.4 is supported." );\r
- return PICO_PMV_ERROR_VERSION;\r
- }\r
- /* file seems to be a valid ms3d */\r
- return PICO_PMV_OK;\r
-}\r
-\r
-static unsigned char *GetWord( unsigned char *bufptr, int *out )\r
-{\r
- if (bufptr == NULL) return NULL;\r
- *out = _pico_little_short( *(unsigned short *)bufptr );\r
- return( bufptr + 2 );\r
-}\r
-\r
-/* _ms3d_load:\r
- * loads a milkshape3d model file.\r
-*/\r
-static picoModel_t *_ms3d_load( PM_PARAMS_LOAD )\r
-{\r
- picoModel_t *model;\r
- unsigned char *bufptr;\r
- int shaderRefs[ MS3D_MAX_GROUPS ];\r
- int numGroups;\r
- int numMaterials;\r
-// unsigned char *ptrToGroups;\r
- int numVerts;\r
- unsigned char *ptrToVerts;\r
- int numTris;\r
- unsigned char *ptrToTris;\r
- int i,k,m;\r
-\r
- /* create new pico model */\r
- model = PicoNewModel();\r
- if (model == NULL) return NULL;\r
-\r
- /* do model setup */\r
- PicoSetModelFrameNum( model, frameNum );\r
- PicoSetModelName( model, fileName );\r
- PicoSetModelFileName( model, fileName );\r
-\r
- /* skip header */\r
- bufptr = (unsigned char *)buffer + sizeof(TMsHeader);\r
-\r
- /* get number of vertices */\r
- bufptr = GetWord( bufptr,&numVerts );\r
- ptrToVerts = bufptr;\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("NumVertices: %d\n",numVerts);\r
-#endif\r
- /* swap verts */\r
- for (i=0; i<numVerts; i++)\r
- {\r
- TMsVertex *vertex;\r
- vertex = (TMsVertex *)bufptr;\r
- bufptr += sizeof( TMsVertex );\r
-\r
- vertex->xyz[ 0 ] = _pico_little_float( vertex->xyz[ 0 ] );\r
- vertex->xyz[ 1 ] = _pico_little_float( vertex->xyz[ 1 ] );\r
- vertex->xyz[ 2 ] = _pico_little_float( vertex->xyz[ 2 ] );\r
-\r
-#ifdef DEBUG_PM_MS3D_EX_\r
- printf("Vertex: x: %f y: %f z: %f\n",\r
- msvd[i]->vertex[0],\r
- msvd[i]->vertex[1],\r
- msvd[i]->vertex[2]);\r
-#endif\r
- }\r
- /* get number of triangles */\r
- bufptr = GetWord( bufptr,&numTris );\r
- ptrToTris = bufptr;\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("NumTriangles: %d\n",numTris);\r
-#endif\r
- /* swap tris */\r
- for (i=0; i<numTris; i++)\r
- {\r
- TMsTriangle *triangle;\r
- triangle = (TMsTriangle *)bufptr;\r
- bufptr += sizeof( TMsTriangle );\r
-\r
- triangle->flags = _pico_little_short( triangle->flags );\r
-\r
- /* run through all tri verts */\r
- for (k=0; k<3; k++)\r
- {\r
- /* swap tex coords */\r
- triangle->s[ k ] = _pico_little_float( triangle->s[ k ] );\r
- triangle->t[ k ] = _pico_little_float( triangle->t[ k ] );\r
-\r
- /* swap fields */\r
- triangle->vertexIndices[ k ] = _pico_little_short( triangle->vertexIndices[ k ] );\r
- triangle->vertexNormals[ 0 ][ k ] = _pico_little_float( triangle->vertexNormals[ 0 ][ k ] );\r
- triangle->vertexNormals[ 1 ][ k ] = _pico_little_float( triangle->vertexNormals[ 1 ][ k ] );\r
- triangle->vertexNormals[ 2 ][ k ] = _pico_little_float( triangle->vertexNormals[ 2 ][ k ] );\r
-\r
- /* check for out of range indices */\r
- if (triangle->vertexIndices[ k ] >= numVerts)\r
- {\r
- _pico_printf( PICO_ERROR,"Vertex %d index %d out of range (%d, max %d)",i,k,triangle->vertexIndices[k],numVerts-1);\r
- PicoFreeModel( model );\r
- return NULL; /* yuck */\r
- }\r
- }\r
- }\r
- /* get number of groups */\r
- bufptr = GetWord( bufptr,&numGroups );\r
-// ptrToGroups = bufptr;\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("NumGroups: %d\n",numGroups);\r
-#endif\r
- /* run through all groups in model */\r
- for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)\r
- {\r
- picoSurface_t *surface;\r
- TMsGroup *group;\r
-\r
- group = (TMsGroup *)bufptr;\r
- bufptr += sizeof( TMsGroup );\r
-\r
- /* we ignore hidden groups */\r
- if (group->flags & MS3D_HIDDEN)\r
- {\r
- bufptr += (group->numTriangles * 2) + 1;\r
- continue;\r
- }\r
- /* forced null term of group name */\r
- group->name[ 31 ] = '\0';\r
-\r
- /* create new pico surface */\r
- surface = PicoNewSurface( model );\r
- if (surface == NULL)\r
- {\r
- PicoFreeModel( model );\r
- return NULL;\r
- }\r
- /* do surface setup */\r
- PicoSetSurfaceType( surface,PICO_TRIANGLES );\r
- PicoSetSurfaceName( surface,group->name );\r
-\r
- /* process triangle indices */\r
- for (k=0; k<group->numTriangles; k++)\r
- {\r
- TMsTriangle *triangle;\r
- unsigned int triangleIndex;\r
-\r
- /* get triangle index */\r
- bufptr = GetWord( bufptr,(int *)&triangleIndex );\r
-\r
- /* get ptr to triangle data */\r
- triangle = (TMsTriangle *)(ptrToTris + (sizeof(TMsTriangle) * triangleIndex));\r
-\r
- /* run through triangle vertices */\r
- for (m=0; m<3; m++)\r
- {\r
- TMsVertex *vertex;\r
- unsigned int vertexIndex;\r
- picoVec2_t texCoord;\r
-\r
- /* get ptr to vertex data */\r
- vertexIndex = triangle->vertexIndices[ m ];\r
- vertex = (TMsVertex *)(ptrToVerts + (sizeof(TMsVertex) * vertexIndex));\r
-\r
- /* store vertex origin */\r
- PicoSetSurfaceXYZ( surface,vertexIndex,vertex->xyz );\r
-\r
- /* store vertex color */\r
- PicoSetSurfaceColor( surface,0,vertexIndex,white );\r
-\r
- /* store vertex normal */\r
- PicoSetSurfaceNormal( surface,vertexIndex,triangle->vertexNormals[ m ] );\r
-\r
- /* store current face vertex index */\r
- PicoSetSurfaceIndex( surface,(k * 3 + (2 - m)),(picoIndex_t)vertexIndex );\r
-\r
- /* get texture vertex coord */\r
- texCoord[ 0 ] = triangle->s[ m ];\r
- texCoord[ 1 ] = -triangle->t[ m ]; /* flip t */\r
-\r
- /* store texture vertex coord */\r
- PicoSetSurfaceST( surface,0,vertexIndex,texCoord );\r
- }\r
- }\r
- /* store material */\r
- shaderRefs[ i ] = *bufptr++;\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("Group %d: '%s' (%d tris)\n",i,group->name,group->numTriangles);\r
-#endif\r
- }\r
- /* get number of materials */\r
- bufptr = GetWord( bufptr,&numMaterials );\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("NumMaterials: %d\n",numMaterials);\r
-#endif\r
- /* run through all materials in model */\r
- for (i=0; i<numMaterials; i++)\r
- {\r
- picoShader_t *shader;\r
- picoColor_t ambient,diffuse,specular;\r
- TMsMaterial *material;\r
- int k;\r
-\r
- material = (TMsMaterial *)bufptr;\r
- bufptr += sizeof( TMsMaterial );\r
-\r
- /* null term strings */\r
- material->name [ 31 ] = '\0';\r
- material->texture [ 127 ] = '\0';\r
- material->alphamap[ 127 ] = '\0';\r
-\r
- /* ltrim strings */\r
- _pico_strltrim( material->name );\r
- _pico_strltrim( material->texture );\r
- _pico_strltrim( material->alphamap );\r
-\r
- /* rtrim strings */\r
- _pico_strrtrim( material->name );\r
- _pico_strrtrim( material->texture );\r
- _pico_strrtrim( material->alphamap );\r
-\r
- /* create new pico shader */\r
- shader = PicoNewShader( model );\r
- if (shader == NULL)\r
- {\r
- PicoFreeModel( model );\r
- return NULL;\r
- }\r
- /* scale shader colors */\r
- for (k=0; k<4; k++)\r
- {\r
- ambient [ k ] = (picoByte_t) (material->ambient[ k ] * 255);\r
- diffuse [ k ] = (picoByte_t) (material->diffuse[ k ] * 255);\r
- specular[ k ] = (picoByte_t) (material->specular[ k ] * 255);\r
- }\r
- /* set shader colors */\r
- PicoSetShaderAmbientColor( shader,ambient );\r
- PicoSetShaderDiffuseColor( shader,diffuse );\r
- PicoSetShaderSpecularColor( shader,specular );\r
-\r
- /* set shader transparency */\r
- PicoSetShaderTransparency( shader,material->transparency );\r
-\r
- /* set shader shininess (0..127) */\r
- PicoSetShaderShininess( shader,material->shininess );\r
-\r
- /* set shader name */\r
- PicoSetShaderName( shader,material->name );\r
-\r
- /* set shader texture map name */\r
- PicoSetShaderMapName( shader,material->texture );\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("Material %d: '%s' ('%s','%s')\n",i,material->name,material->texture,material->alphamap);\r
-#endif\r
- }\r
- /* assign shaders to surfaces */\r
- for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)\r
- {\r
- picoSurface_t *surface;\r
- picoShader_t *shader;\r
-\r
- /* sanity check */\r
- if (shaderRefs[ i ] >= MS3D_MAX_MATERIALS ||\r
- shaderRefs[ i ] < 0)\r
- continue;\r
-\r
- /* get surface */\r
- surface = PicoGetModelSurface( model,i );\r
- if (surface == NULL) continue;\r
-\r
- /* get shader */\r
- shader = PicoGetModelShader( model,shaderRefs[ i ] );\r
- if (shader == NULL) continue;\r
-\r
- /* assign shader */\r
- PicoSetSurfaceShader( surface,shader );\r
-\r
-#ifdef DEBUG_PM_MS3D\r
- printf("Mapped: %d ('%s') to %d (%s)\n",\r
- shaderRefs[i],shader->name,i,surface->name);\r
-#endif\r
- }\r
- /* return allocated pico model */\r
- return model;\r
-// return NULL;\r
-}\r
-\r
-/* pico file format module definition */\r
-const picoModule_t picoModuleMS3D =\r
-{\r
- "0.4-a", /* module version string */\r
- "Milkshape 3D", /* module display name */\r
- "seaw0lf", /* author's name */\r
- "2002 seaw0lf", /* module copyright */\r
- {\r
- "ms3d",NULL,NULL,NULL /* default extensions to use */\r
- },\r
- _ms3d_canload, /* validation routine */\r
- _ms3d_load, /* load routine */\r
- NULL, /* save validation routine */\r
- NULL /* save routine */\r
-};\r
+/* -----------------------------------------------------------------------------
+
+ PicoModel Library
+
+ Copyright (c) 2002, Randy Reddig & seaw0lf
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this list
+ of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+
+ Neither the names of the copyright holders nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------------------- */
+
+/* dependencies */
+#include "picointernal.h"
+#include "globaldefs.h"
+
+/* disable warnings */
+#if GDEF_COMPILER_MSVC
+#pragma warning( disable:4100 ) /* unref param */
+#endif
+
+/* remarks:
+ * - loader seems stable
+ * todo:
+ * - fix uv coordinate problem
+ * - check for buffer overflows ('bufptr' accesses)
+ */
+/* uncomment when debugging this module */
+ #define DEBUG_PM_MS3D
+ #define DEBUG_PM_MS3D_EX
+
+/* ms3d limits */
+const int MS3D_MAX_VERTS = 8192;
+const int MS3D_MAX_TRIS = 16384;
+const int MS3D_MAX_GROUPS = 128;
+const int MS3D_MAX_MATERIALS = 128;
+const int MS3D_MAX_JOINTS = 128;
+const int MS3D_MAX_KEYFRAMES = 216;
+
+/* ms3d flags */
+const int MS3D_SELECTED = 1;
+const int MS3D_HIDDEN = 2;
+const int MS3D_SELECTED2 = 4;
+const int MS3D_DIRTY = 8;
+
+/* this freaky loader needs byte alignment */
+#pragma pack(push, 1)
+
+/* ms3d header */
+typedef struct SMsHeader
+{
+ char magic[10];
+ int version;
+}
+TMsHeader;
+
+/* ms3d vertex */
+typedef struct SMsVertex
+{
+ unsigned char flags; /* sel, sel2, or hidden */
+ float xyz[3];
+ char boneID; /* -1 means 'no bone' */
+ unsigned char refCount;
+}
+TMsVertex;
+
+/* ms3d triangle */
+typedef struct SMsTriangle
+{
+ unsigned short flags; /* sel, sel2, or hidden */
+ unsigned short vertexIndices[3];
+ float vertexNormals[3][3];
+ float s[3];
+ float t[3];
+ unsigned char smoothingGroup; /* 1 - 32 */
+ unsigned char groupIndex;
+}
+TMsTriangle;
+
+/* ms3d material */
+typedef struct SMsMaterial
+{
+ char name[32];
+ float ambient[4];
+ float diffuse[4];
+ float specular[4];
+ float emissive[4];
+ float shininess; /* range 0..128 */
+ float transparency; /* range 0..1 */
+ unsigned char mode;
+ char texture [128]; /* texture.bmp */
+ char alphamap[128]; /* alpha.bmp */
+}
+TMsMaterial;
+
+// ms3d group (static part)
+// followed by a variable size block (see below)
+typedef struct SMsGroup
+{
+ unsigned char flags; // sel, hidden
+ char name[32];
+ unsigned short numTriangles;
+/*
+ unsigned short triangleIndices[ numTriangles ];
+ char materialIndex; // -1 means 'no material'
+ */
+}
+TMsGroup;
+
+// ms3d joint
+typedef struct SMsJoint
+{
+ unsigned char flags;
+ char name[32];
+ char parentName[32];
+ float rotation[3];
+ float translation[3];
+ unsigned short numRotationKeyframes;
+ unsigned short numTranslationKeyframes;
+}
+TMsJoint;
+
+// ms3d keyframe
+typedef struct SMsKeyframe
+{
+ float time;
+ float parameter[3];
+}
+TMsKeyframe;
+
+/* restore previous data alignment */
+#pragma pack(pop)
+
+/* _ms3d_canload:
+ * validates a milkshape3d model file.
+ */
+static int _ms3d_canload( PM_PARAMS_CANLOAD ){
+ const TMsHeader *hdr;
+
+
+ /* sanity check */
+ if ( (size_t) bufSize < sizeof( TMsHeader ) ) {
+ return PICO_PMV_ERROR_SIZE;
+ }
+
+ /* get ms3d header */
+ hdr = (const TMsHeader *)buffer;
+
+ /* check ms3d magic */
+ if ( strncmp( hdr->magic,"MS3D000000",10 ) != 0 ) {
+ return PICO_PMV_ERROR_IDENT;
+ }
+
+ /* check ms3d version */
+ if ( _pico_little_long( hdr->version ) < 3 ||
+ _pico_little_long( hdr->version ) > 4 ) {
+ _pico_printf( PICO_ERROR,"MS3D file ignored. Only MS3D 1.3 and 1.4 is supported." );
+ return PICO_PMV_ERROR_VERSION;
+ }
+ /* file seems to be a valid ms3d */
+ return PICO_PMV_OK;
+}
+
+static unsigned char *GetWord( unsigned char *bufptr, int *out ){
+ if ( bufptr == NULL ) {
+ return NULL;
+ }
+ *out = _pico_little_short( *(unsigned short *)bufptr );
+ return( bufptr + 2 );
+}
+
+/* _ms3d_load:
+ * loads a milkshape3d model file.
+ */
+static picoModel_t *_ms3d_load( PM_PARAMS_LOAD ){
+ picoModel_t *model;
+ unsigned char *bufptr, *bufptr0;
+ int shaderRefs[ MS3D_MAX_GROUPS ];
+ int numGroups;
+ int numMaterials;
+// unsigned char *ptrToGroups;
+ int numVerts;
+ unsigned char *ptrToVerts;
+ int numTris;
+ unsigned char *ptrToTris;
+ int i,k,m;
+
+ /* create new pico model */
+ model = PicoNewModel();
+ if ( model == NULL ) {
+ return NULL;
+ }
+
+ /* do model setup */
+ PicoSetModelFrameNum( model, frameNum );
+ PicoSetModelName( model, fileName );
+ PicoSetModelFileName( model, fileName );
+
+ bufptr0 = bufptr = (picoByte_t*) _pico_alloc( bufSize );
+ memcpy( bufptr, buffer, bufSize );
+ /* skip header */
+ bufptr += sizeof( TMsHeader );
+
+ /* get number of vertices */
+ bufptr = GetWord( bufptr,&numVerts );
+ ptrToVerts = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+ printf( "NumVertices: %d\n",numVerts );
+#endif
+ /* swap verts */
+ for ( i = 0; i < numVerts; i++ )
+ {
+ TMsVertex *vertex;
+ vertex = (TMsVertex *)bufptr;
+ bufptr += sizeof( TMsVertex );
+
+ vertex->xyz[ 0 ] = _pico_little_float( vertex->xyz[ 0 ] );
+ vertex->xyz[ 1 ] = _pico_little_float( vertex->xyz[ 1 ] );
+ vertex->xyz[ 2 ] = _pico_little_float( vertex->xyz[ 2 ] );
+
+#ifdef DEBUG_PM_MS3D_EX_
+ printf( "Vertex: x: %f y: %f z: %f\n",
+ msvd[i]->vertex[0],
+ msvd[i]->vertex[1],
+ msvd[i]->vertex[2] );
+#endif
+ }
+ /* get number of triangles */
+ bufptr = GetWord( bufptr,&numTris );
+ ptrToTris = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+ printf( "NumTriangles: %d\n",numTris );
+#endif
+ /* swap tris */
+ for ( i = 0; i < numTris; i++ )
+ {
+ TMsTriangle *triangle;
+ triangle = (TMsTriangle *)bufptr;
+ bufptr += sizeof( TMsTriangle );
+
+ triangle->flags = _pico_little_short( triangle->flags );
+
+ /* run through all tri verts */
+ for ( k = 0; k < 3; k++ )
+ {
+ /* swap tex coords */
+ triangle->s[ k ] = _pico_little_float( triangle->s[ k ] );
+ triangle->t[ k ] = _pico_little_float( triangle->t[ k ] );
+
+ /* swap fields */
+ triangle->vertexIndices[ k ] = _pico_little_short( triangle->vertexIndices[ k ] );
+ triangle->vertexNormals[ 0 ][ k ] = _pico_little_float( triangle->vertexNormals[ 0 ][ k ] );
+ triangle->vertexNormals[ 1 ][ k ] = _pico_little_float( triangle->vertexNormals[ 1 ][ k ] );
+ triangle->vertexNormals[ 2 ][ k ] = _pico_little_float( triangle->vertexNormals[ 2 ][ k ] );
+
+ /* check for out of range indices */
+ if ( triangle->vertexIndices[ k ] >= numVerts ) {
+ _pico_printf( PICO_ERROR,"Vertex %d index %d out of range (%d, max %d)",i,k,triangle->vertexIndices[k],numVerts - 1 );
+ PicoFreeModel( model );
+ _pico_free( bufptr0 );
+ return NULL; /* yuck */
+ }
+ }
+ }
+ /* get number of groups */
+ bufptr = GetWord( bufptr,&numGroups );
+// ptrToGroups = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+ printf( "NumGroups: %d\n",numGroups );
+#endif
+ /* run through all groups in model */
+ for ( i = 0; i < numGroups && i < MS3D_MAX_GROUPS; i++ )
+ {
+ picoSurface_t *surface;
+ TMsGroup *group;
+
+ group = (TMsGroup *)bufptr;
+ bufptr += sizeof( TMsGroup );
+
+ /* we ignore hidden groups */
+ if ( group->flags & MS3D_HIDDEN ) {
+ bufptr += ( group->numTriangles * 2 ) + 1;
+ continue;
+ }
+ /* forced null term of group name */
+ group->name[ 31 ] = '\0';
+
+ /* create new pico surface */
+ surface = PicoNewSurface( model );
+ if ( surface == NULL ) {
+ PicoFreeModel( model );
+ _pico_free( bufptr0 );
+ return NULL;
+ }
+ /* do surface setup */
+ PicoSetSurfaceType( surface,PICO_TRIANGLES );
+ PicoSetSurfaceName( surface,group->name );
+
+ /* process triangle indices */
+ for ( k = 0; k < group->numTriangles; k++ )
+ {
+ TMsTriangle *triangle;
+ unsigned int triangleIndex;
+
+ /* get triangle index */
+ bufptr = GetWord( bufptr,(int *)&triangleIndex );
+
+ /* get ptr to triangle data */
+ triangle = (TMsTriangle *)( ptrToTris + ( sizeof( TMsTriangle ) * triangleIndex ) );
+
+ /* run through triangle vertices */
+ for ( m = 0; m < 3; m++ )
+ {
+ TMsVertex *vertex;
+ unsigned int vertexIndex;
+ picoVec2_t texCoord;
+
+ /* get ptr to vertex data */
+ vertexIndex = triangle->vertexIndices[ m ];
+ vertex = (TMsVertex *)( ptrToVerts + ( sizeof( TMsVertex ) * vertexIndex ) );
+
+ /* store vertex origin */
+ PicoSetSurfaceXYZ( surface,vertexIndex,vertex->xyz );
+
+ /* store vertex color */
+ PicoSetSurfaceColor( surface, 0, vertexIndex, picoColor_white );
+
+ /* store vertex normal */
+ PicoSetSurfaceNormal( surface,vertexIndex,triangle->vertexNormals[ m ] );
+
+ /* store current face vertex index */
+ PicoSetSurfaceIndex( surface,( k * 3 + ( 2 - m ) ),(picoIndex_t)vertexIndex );
+
+ /* get texture vertex coord */
+ texCoord[ 0 ] = triangle->s[ m ];
+ texCoord[ 1 ] = -triangle->t[ m ]; /* flip t */
+
+ /* store texture vertex coord */
+ PicoSetSurfaceST( surface,0,vertexIndex,texCoord );
+ }
+ }
+ /* store material */
+ shaderRefs[ i ] = *bufptr++;
+
+#ifdef DEBUG_PM_MS3D
+ printf( "Group %d: '%s' (%d tris)\n",i,group->name,group->numTriangles );
+#endif
+ }
+ /* get number of materials */
+ bufptr = GetWord( bufptr,&numMaterials );
+
+#ifdef DEBUG_PM_MS3D
+ printf( "NumMaterials: %d\n",numMaterials );
+#endif
+ /* run through all materials in model */
+ for ( i = 0; i < numMaterials; i++ )
+ {
+ picoShader_t *shader;
+ picoColor_t ambient,diffuse,specular;
+ TMsMaterial *material;
+ int k;
+
+ material = (TMsMaterial *)bufptr;
+ bufptr += sizeof( TMsMaterial );
+
+ /* null term strings */
+ material->name [ 31 ] = '\0';
+ material->texture [ 127 ] = '\0';
+ material->alphamap[ 127 ] = '\0';
+
+ /* ltrim strings */
+ _pico_strltrim( material->name );
+ _pico_strltrim( material->texture );
+ _pico_strltrim( material->alphamap );
+
+ /* rtrim strings */
+ _pico_strrtrim( material->name );
+ _pico_strrtrim( material->texture );
+ _pico_strrtrim( material->alphamap );
+
+ /* create new pico shader */
+ shader = PicoNewShader( model );
+ if ( shader == NULL ) {
+ PicoFreeModel( model );
+ _pico_free( bufptr0 );
+ return NULL;
+ }
+ /* scale shader colors */
+ for ( k = 0; k < 4; k++ )
+ {
+ ambient [ k ] = (picoByte_t) ( material->ambient[ k ] * 255 );
+ diffuse [ k ] = (picoByte_t) ( material->diffuse[ k ] * 255 );
+ specular[ k ] = (picoByte_t) ( material->specular[ k ] * 255 );
+ }
+ /* set shader colors */
+ PicoSetShaderAmbientColor( shader,ambient );
+ PicoSetShaderDiffuseColor( shader,diffuse );
+ PicoSetShaderSpecularColor( shader,specular );
+
+ /* set shader transparency */
+ PicoSetShaderTransparency( shader,material->transparency );
+
+ /* set shader shininess (0..127) */
+ PicoSetShaderShininess( shader,material->shininess );
+
+ /* set shader name */
+ PicoSetShaderName( shader,material->name );
+
+ /* set shader texture map name */
+ PicoSetShaderMapName( shader,material->texture );
+
+#ifdef DEBUG_PM_MS3D
+ printf( "Material %d: '%s' ('%s','%s')\n",i,material->name,material->texture,material->alphamap );
+#endif
+ }
+ /* assign shaders to surfaces */
+ for ( i = 0; i < numGroups && i < MS3D_MAX_GROUPS; i++ )
+ {
+ picoSurface_t *surface;
+ picoShader_t *shader;
+
+ /* sanity check */
+ if ( shaderRefs[ i ] >= MS3D_MAX_MATERIALS ||
+ shaderRefs[ i ] < 0 ) {
+ continue;
+ }
+
+ /* get surface */
+ surface = PicoGetModelSurface( model,i );
+ if ( surface == NULL ) {
+ continue;
+ }
+
+ /* get shader */
+ shader = PicoGetModelShader( model,shaderRefs[ i ] );
+ if ( shader == NULL ) {
+ continue;
+ }
+
+ /* assign shader */
+ PicoSetSurfaceShader( surface,shader );
+
+#ifdef DEBUG_PM_MS3D
+ printf( "Mapped: %d ('%s') to %d (%s)\n",
+ shaderRefs[i],shader->name,i,surface->name );
+#endif
+ }
+ /* return allocated pico model */
+ _pico_free( bufptr0 );
+ return model;
+// return NULL;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleMS3D =
+{
+ "0.4-a", /* module version string */
+ "Milkshape 3D", /* module display name */
+ "seaw0lf", /* author's name */
+ "2002 seaw0lf", /* module copyright */
+ {
+ "ms3d",NULL,NULL,NULL /* default extensions to use */
+ },
+ _ms3d_canload, /* validation routine */
+ _ms3d_load, /* load routine */
+ NULL, /* save validation routine */
+ NULL /* save routine */
+};