]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/picomodel/pm_mdc.c
set eol-style
[xonotic/netradiant.git] / libs / picomodel / pm_mdc.c
index 3036d1121507b4ef9039762166d78b61defe9e87..27e612e8312c3ffafde5ead50cc52944b8aec518 100644 (file)
-/* -----------------------------------------------------------------------------\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_MDC_C\r
-\r
-\r
-\r
-/* dependencies */\r
-#include "picointernal.h"\r
-\r
-/* mdc model format */\r
-#define MDC_MAGIC                      "IDPC"\r
-#define MDC_VERSION                    2\r
-\r
-/* mdc vertex scale */\r
-#define MDC_SCALE                      (1.0f / 64.0f)\r
-#define        MDC_MAX_OFS                     127.0f\r
-#define        MDC_DIST_SCALE          0.05f\r
-\r
-/* mdc decoding normal table */\r
-double mdcNormals[ 256 ][ 3 ] =\r
-{\r
-       { 1.000000, 0.000000, 0.000000 },\r
-       { 0.980785, 0.195090, 0.000000 },\r
-       { 0.923880, 0.382683, 0.000000 },\r
-       { 0.831470, 0.555570, 0.000000 },\r
-       { 0.707107, 0.707107, 0.000000 },\r
-       { 0.555570, 0.831470, 0.000000 },\r
-       { 0.382683, 0.923880, 0.000000 },\r
-       { 0.195090, 0.980785, 0.000000 },\r
-       { -0.000000, 1.000000, 0.000000 },\r
-       { -0.195090, 0.980785, 0.000000 },\r
-       { -0.382683, 0.923880, 0.000000 },\r
-       { -0.555570, 0.831470, 0.000000 },\r
-       { -0.707107, 0.707107, 0.000000 },\r
-       { -0.831470, 0.555570, 0.000000 },\r
-       { -0.923880, 0.382683, 0.000000 },\r
-       { -0.980785, 0.195090, 0.000000 },\r
-       { -1.000000, -0.000000, 0.000000 },\r
-       { -0.980785, -0.195090, 0.000000 },\r
-       { -0.923880, -0.382683, 0.000000 },\r
-       { -0.831470, -0.555570, 0.000000 },\r
-       { -0.707107, -0.707107, 0.000000 },\r
-       { -0.555570, -0.831469, 0.000000 },\r
-       { -0.382684, -0.923880, 0.000000 },\r
-       { -0.195090, -0.980785, 0.000000 },\r
-       { 0.000000, -1.000000, 0.000000 },\r
-       { 0.195090, -0.980785, 0.000000 },\r
-       { 0.382684, -0.923879, 0.000000 },\r
-       { 0.555570, -0.831470, 0.000000 },\r
-       { 0.707107, -0.707107, 0.000000 },\r
-       { 0.831470, -0.555570, 0.000000 },\r
-       { 0.923880, -0.382683, 0.000000 },\r
-       { 0.980785, -0.195090, 0.000000 },\r
-       { 0.980785, 0.000000, -0.195090 },\r
-       { 0.956195, 0.218245, -0.195090 },\r
-       { 0.883657, 0.425547, -0.195090 },\r
-       { 0.766809, 0.611510, -0.195090 },\r
-       { 0.611510, 0.766809, -0.195090 },\r
-       { 0.425547, 0.883657, -0.195090 },\r
-       { 0.218245, 0.956195, -0.195090 },\r
-       { -0.000000, 0.980785, -0.195090 },\r
-       { -0.218245, 0.956195, -0.195090 },\r
-       { -0.425547, 0.883657, -0.195090 },\r
-       { -0.611510, 0.766809, -0.195090 },\r
-       { -0.766809, 0.611510, -0.195090 },\r
-       { -0.883657, 0.425547, -0.195090 },\r
-       { -0.956195, 0.218245, -0.195090 },\r
-       { -0.980785, -0.000000, -0.195090 },\r
-       { -0.956195, -0.218245, -0.195090 },\r
-       { -0.883657, -0.425547, -0.195090 },\r
-       { -0.766809, -0.611510, -0.195090 },\r
-       { -0.611510, -0.766809, -0.195090 },\r
-       { -0.425547, -0.883657, -0.195090 },\r
-       { -0.218245, -0.956195, -0.195090 },\r
-       { 0.000000, -0.980785, -0.195090 },\r
-       { 0.218245, -0.956195, -0.195090 },\r
-       { 0.425547, -0.883657, -0.195090 },\r
-       { 0.611510, -0.766809, -0.195090 },\r
-       { 0.766809, -0.611510, -0.195090 },\r
-       { 0.883657, -0.425547, -0.195090 },\r
-       { 0.956195, -0.218245, -0.195090 },\r
-       { 0.923880, 0.000000, -0.382683 },\r
-       { 0.892399, 0.239118, -0.382683 },\r
-       { 0.800103, 0.461940, -0.382683 },\r
-       { 0.653281, 0.653281, -0.382683 },\r
-       { 0.461940, 0.800103, -0.382683 },\r
-       { 0.239118, 0.892399, -0.382683 },\r
-       { -0.000000, 0.923880, -0.382683 },\r
-       { -0.239118, 0.892399, -0.382683 },\r
-       { -0.461940, 0.800103, -0.382683 },\r
-       { -0.653281, 0.653281, -0.382683 },\r
-       { -0.800103, 0.461940, -0.382683 },\r
-       { -0.892399, 0.239118, -0.382683 },\r
-       { -0.923880, -0.000000, -0.382683 },\r
-       { -0.892399, -0.239118, -0.382683 },\r
-       { -0.800103, -0.461940, -0.382683 },\r
-       { -0.653282, -0.653281, -0.382683 },\r
-       { -0.461940, -0.800103, -0.382683 },\r
-       { -0.239118, -0.892399, -0.382683 },\r
-       { 0.000000, -0.923880, -0.382683 },\r
-       { 0.239118, -0.892399, -0.382683 },\r
-       { 0.461940, -0.800103, -0.382683 },\r
-       { 0.653281, -0.653282, -0.382683 },\r
-       { 0.800103, -0.461940, -0.382683 },\r
-       { 0.892399, -0.239117, -0.382683 },\r
-       { 0.831470, 0.000000, -0.555570 },\r
-       { 0.790775, 0.256938, -0.555570 },\r
-       { 0.672673, 0.488726, -0.555570 },\r
-       { 0.488726, 0.672673, -0.555570 },\r
-       { 0.256938, 0.790775, -0.555570 },\r
-       { -0.000000, 0.831470, -0.555570 },\r
-       { -0.256938, 0.790775, -0.555570 },\r
-       { -0.488726, 0.672673, -0.555570 },\r
-       { -0.672673, 0.488726, -0.555570 },\r
-       { -0.790775, 0.256938, -0.555570 },\r
-       { -0.831470, -0.000000, -0.555570 },\r
-       { -0.790775, -0.256938, -0.555570 },\r
-       { -0.672673, -0.488726, -0.555570 },\r
-       { -0.488725, -0.672673, -0.555570 },\r
-       { -0.256938, -0.790775, -0.555570 },\r
-       { 0.000000, -0.831470, -0.555570 },\r
-       { 0.256938, -0.790775, -0.555570 },\r
-       { 0.488725, -0.672673, -0.555570 },\r
-       { 0.672673, -0.488726, -0.555570 },\r
-       { 0.790775, -0.256938, -0.555570 },\r
-       { 0.707107, 0.000000, -0.707107 },\r
-       { 0.653281, 0.270598, -0.707107 },\r
-       { 0.500000, 0.500000, -0.707107 },\r
-       { 0.270598, 0.653281, -0.707107 },\r
-       { -0.000000, 0.707107, -0.707107 },\r
-       { -0.270598, 0.653282, -0.707107 },\r
-       { -0.500000, 0.500000, -0.707107 },\r
-       { -0.653281, 0.270598, -0.707107 },\r
-       { -0.707107, -0.000000, -0.707107 },\r
-       { -0.653281, -0.270598, -0.707107 },\r
-       { -0.500000, -0.500000, -0.707107 },\r
-       { -0.270598, -0.653281, -0.707107 },\r
-       { 0.000000, -0.707107, -0.707107 },\r
-       { 0.270598, -0.653281, -0.707107 },\r
-       { 0.500000, -0.500000, -0.707107 },\r
-       { 0.653282, -0.270598, -0.707107 },\r
-       { 0.555570, 0.000000, -0.831470 },\r
-       { 0.481138, 0.277785, -0.831470 },\r
-       { 0.277785, 0.481138, -0.831470 },\r
-       { -0.000000, 0.555570, -0.831470 },\r
-       { -0.277785, 0.481138, -0.831470 },\r
-       { -0.481138, 0.277785, -0.831470 },\r
-       { -0.555570, -0.000000, -0.831470 },\r
-       { -0.481138, -0.277785, -0.831470 },\r
-       { -0.277785, -0.481138, -0.831470 },\r
-       { 0.000000, -0.555570, -0.831470 },\r
-       { 0.277785, -0.481138, -0.831470 },\r
-       { 0.481138, -0.277785, -0.831470 },\r
-       { 0.382683, 0.000000, -0.923880 },\r
-       { 0.270598, 0.270598, -0.923880 },\r
-       { -0.000000, 0.382683, -0.923880 },\r
-       { -0.270598, 0.270598, -0.923880 },\r
-       { -0.382683, -0.000000, -0.923880 },\r
-       { -0.270598, -0.270598, -0.923880 },\r
-       { 0.000000, -0.382683, -0.923880 },\r
-       { 0.270598, -0.270598, -0.923880 },\r
-       { 0.195090, 0.000000, -0.980785 },\r
-       { -0.000000, 0.195090, -0.980785 },\r
-       { -0.195090, -0.000000, -0.980785 },\r
-       { 0.000000, -0.195090, -0.980785 },\r
-       { 0.980785, 0.000000, 0.195090 },\r
-       { 0.956195, 0.218245, 0.195090 },\r
-       { 0.883657, 0.425547, 0.195090 },\r
-       { 0.766809, 0.611510, 0.195090 },\r
-       { 0.611510, 0.766809, 0.195090 },\r
-       { 0.425547, 0.883657, 0.195090 },\r
-       { 0.218245, 0.956195, 0.195090 },\r
-       { -0.000000, 0.980785, 0.195090 },\r
-       { -0.218245, 0.956195, 0.195090 },\r
-       { -0.425547, 0.883657, 0.195090 },\r
-       { -0.611510, 0.766809, 0.195090 },\r
-       { -0.766809, 0.611510, 0.195090 },\r
-       { -0.883657, 0.425547, 0.195090 },\r
-       { -0.956195, 0.218245, 0.195090 },\r
-       { -0.980785, -0.000000, 0.195090 },\r
-       { -0.956195, -0.218245, 0.195090 },\r
-       { -0.883657, -0.425547, 0.195090 },\r
-       { -0.766809, -0.611510, 0.195090 },\r
-       { -0.611510, -0.766809, 0.195090 },\r
-       { -0.425547, -0.883657, 0.195090 },\r
-       { -0.218245, -0.956195, 0.195090 },\r
-       { 0.000000, -0.980785, 0.195090 },\r
-       { 0.218245, -0.956195, 0.195090 },\r
-       { 0.425547, -0.883657, 0.195090 },\r
-       { 0.611510, -0.766809, 0.195090 },\r
-       { 0.766809, -0.611510, 0.195090 },\r
-       { 0.883657, -0.425547, 0.195090 },\r
-       { 0.956195, -0.218245, 0.195090 },\r
-       { 0.923880, 0.000000, 0.382683 },\r
-       { 0.892399, 0.239118, 0.382683 },\r
-       { 0.800103, 0.461940, 0.382683 },\r
-       { 0.653281, 0.653281, 0.382683 },\r
-       { 0.461940, 0.800103, 0.382683 },\r
-       { 0.239118, 0.892399, 0.382683 },\r
-       { -0.000000, 0.923880, 0.382683 },\r
-       { -0.239118, 0.892399, 0.382683 },\r
-       { -0.461940, 0.800103, 0.382683 },\r
-       { -0.653281, 0.653281, 0.382683 },\r
-       { -0.800103, 0.461940, 0.382683 },\r
-       { -0.892399, 0.239118, 0.382683 },\r
-       { -0.923880, -0.000000, 0.382683 },\r
-       { -0.892399, -0.239118, 0.382683 },\r
-       { -0.800103, -0.461940, 0.382683 },\r
-       { -0.653282, -0.653281, 0.382683 },\r
-       { -0.461940, -0.800103, 0.382683 },\r
-       { -0.239118, -0.892399, 0.382683 },\r
-       { 0.000000, -0.923880, 0.382683 },\r
-       { 0.239118, -0.892399, 0.382683 },\r
-       { 0.461940, -0.800103, 0.382683 },\r
-       { 0.653281, -0.653282, 0.382683 },\r
-       { 0.800103, -0.461940, 0.382683 },\r
-       { 0.892399, -0.239117, 0.382683 },\r
-       { 0.831470, 0.000000, 0.555570 },\r
-       { 0.790775, 0.256938, 0.555570 },\r
-       { 0.672673, 0.488726, 0.555570 },\r
-       { 0.488726, 0.672673, 0.555570 },\r
-       { 0.256938, 0.790775, 0.555570 },\r
-       { -0.000000, 0.831470, 0.555570 },\r
-       { -0.256938, 0.790775, 0.555570 },\r
-       { -0.488726, 0.672673, 0.555570 },\r
-       { -0.672673, 0.488726, 0.555570 },\r
-       { -0.790775, 0.256938, 0.555570 },\r
-       { -0.831470, -0.000000, 0.555570 },\r
-       { -0.790775, -0.256938, 0.555570 },\r
-       { -0.672673, -0.488726, 0.555570 },\r
-       { -0.488725, -0.672673, 0.555570 },\r
-       { -0.256938, -0.790775, 0.555570 },\r
-       { 0.000000, -0.831470, 0.555570 },\r
-       { 0.256938, -0.790775, 0.555570 },\r
-       { 0.488725, -0.672673, 0.555570 },\r
-       { 0.672673, -0.488726, 0.555570 },\r
-       { 0.790775, -0.256938, 0.555570 },\r
-       { 0.707107, 0.000000, 0.707107 },\r
-       { 0.653281, 0.270598, 0.707107 },\r
-       { 0.500000, 0.500000, 0.707107 },\r
-       { 0.270598, 0.653281, 0.707107 },\r
-       { -0.000000, 0.707107, 0.707107 },\r
-       { -0.270598, 0.653282, 0.707107 },\r
-       { -0.500000, 0.500000, 0.707107 },\r
-       { -0.653281, 0.270598, 0.707107 },\r
-       { -0.707107, -0.000000, 0.707107 },\r
-       { -0.653281, -0.270598, 0.707107 },\r
-       { -0.500000, -0.500000, 0.707107 },\r
-       { -0.270598, -0.653281, 0.707107 },\r
-       { 0.000000, -0.707107, 0.707107 },\r
-       { 0.270598, -0.653281, 0.707107 },\r
-       { 0.500000, -0.500000, 0.707107 },\r
-       { 0.653282, -0.270598, 0.707107 },\r
-       { 0.555570, 0.000000, 0.831470 },\r
-       { 0.481138, 0.277785, 0.831470 },\r
-       { 0.277785, 0.481138, 0.831470 },\r
-       { -0.000000, 0.555570, 0.831470 },\r
-       { -0.277785, 0.481138, 0.831470 },\r
-       { -0.481138, 0.277785, 0.831470 },\r
-       { -0.555570, -0.000000, 0.831470 },\r
-       { -0.481138, -0.277785, 0.831470 },\r
-       { -0.277785, -0.481138, 0.831470 },\r
-       { 0.000000, -0.555570, 0.831470 },\r
-       { 0.277785, -0.481138, 0.831470 },\r
-       { 0.481138, -0.277785, 0.831470 },\r
-       { 0.382683, 0.000000, 0.923880 },\r
-       { 0.270598, 0.270598, 0.923880 },\r
-       { -0.000000, 0.382683, 0.923880 },\r
-       { -0.270598, 0.270598, 0.923880 },\r
-       { -0.382683, -0.000000, 0.923880 },\r
-       { -0.270598, -0.270598, 0.923880 },\r
-       { 0.000000, -0.382683, 0.923880 },\r
-       { 0.270598, -0.270598, 0.923880 },\r
-       { 0.195090, 0.000000, 0.980785 },\r
-       { -0.000000, 0.195090, 0.980785 },\r
-       { -0.195090, -0.000000, 0.980785 },\r
-       { 0.000000, -0.195090, 0.980785 }\r
-};\r
-\r
-/* mdc model frame information */\r
-typedef struct mdcFrame_s\r
-{\r
-       float           bounds[ 2 ][ 3 ];\r
-       float           localOrigin[ 3 ];\r
-       float           radius;\r
-       char            creator[ 16 ];\r
-}\r
-mdcFrame_t;\r
-\r
-/* mdc model tag information */\r
-typedef struct mdcTag_s\r
-{\r
-       short           xyz[3];\r
-       short           angles[3];\r
-}\r
-mdcTag_t;\r
-\r
-/* mdc surface mdc (one object mesh) */\r
-typedef struct mdcSurface_s\r
-{\r
-       char            magic[ 4 ];\r
-       char            name[ 64 ];                     /* polyset name */\r
-       int                     flags;\r
-       int                     numCompFrames;          /* all surfaces in a model should have the same */\r
-       int                     numBaseFrames;          /* ditto */\r
-       int                     numShaders;                     /* all model surfaces should have the same */\r
-       int                     numVerts;\r
-       int                     numTriangles;\r
-       int                     ofsTriangles;\r
-       int                     ofsShaders;                     /* offset from start of mdcSurface_t */\r
-       int                     ofsSt;                          /* texture coords are common for all frames */\r
-       int                     ofsXyzNormals;          /* numVerts * numBaseFrames */\r
-       int                     ofsXyzCompressed;       /* numVerts * numCompFrames */\r
-\r
-       int                     ofsFrameBaseFrames;     /* numFrames */\r
-       int                     ofsFrameCompFrames;     /* numFrames */\r
-       int                     ofsEnd;                         /* next surface follows */\r
-}\r
-mdcSurface_t;\r
-\r
-typedef struct mdcShader_s\r
-{\r
-       char            name[ 64 ];\r
-       int                     shaderIndex;    /* for ingame use */\r
-}\r
-mdcShader_t;\r
-\r
-typedef struct mdcTriangle_s\r
-{\r
-       int                     indexes[ 3 ];\r
-}\r
-mdcTriangle_t;\r
-\r
-typedef struct mdcTexCoord_s\r
-{\r
-       float           st[ 2 ];\r
-}\r
-mdcTexCoord_t;\r
-\r
-typedef struct mdcVertex_s\r
-{\r
-       short           xyz[ 3 ];\r
-       short           normal;\r
-}\r
-mdcVertex_t;\r
-\r
-typedef struct mdcXyzCompressed_s\r
-{\r
-       unsigned int    ofsVec;         /* offset direction from the last base frame */\r
-}\r
-mdcXyzCompressed_t;\r
-\r
-\r
-/* mdc model file mdc structure */\r
-typedef struct mdc_s\r
-{\r
-       char            magic[ 4 ];             /* MDC_MAGIC */\r
-       int                     version;\r
-       char            name[ 64 ];             /* model name */\r
-       int                     flags;\r
-       int                     numFrames;\r
-       int                     numTags;\r
-       int                     numSurfaces;\r
-       int                     numSkins;               /* number of skins for the mesh */\r
-       int                     ofsFrames;              /* offset for first frame */\r
-       int                     ofsTagNames;    /* numTags */\r
-       int                     ofsTags;                /* numFrames * numTags */\r
-       int                     ofsSurfaces;    /* first surface, others follow */\r
-       int                     ofsEnd;                 /* end of file */\r
-}\r
-mdc_t;\r
-\r
-\r
-\r
-\r
-/*\r
-_mdc_canload()\r
-validates a Return to Castle Wolfenstein model file. btw, i use the\r
-preceding underscore cause it's a static func referenced\r
-by one structure only.\r
-*/\r
-\r
-static int _mdc_canload( PM_PARAMS_CANLOAD )\r
-{\r
-       mdc_t   *mdc;\r
-       \r
-\r
-       /* to keep the compiler happy */\r
-       *fileName = *fileName;\r
-       \r
-       /* sanity check */\r
-       if( bufSize < ( sizeof( *mdc ) * 2) )\r
-               return PICO_PMV_ERROR_SIZE;\r
-       \r
-       /* set as mdc */\r
-       mdc     = (mdc_t*) buffer;\r
-       \r
-       /* check mdc magic */\r
-       if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) ) \r
-               return PICO_PMV_ERROR_IDENT;\r
-       \r
-       /* check mdc version */\r
-       if( _pico_little_long( mdc->version ) != MDC_VERSION )\r
-               return PICO_PMV_ERROR_VERSION;\r
-       \r
-       /* file seems to be a valid mdc */\r
-       return PICO_PMV_OK;\r
-}\r
-\r
-\r
-\r
-/*\r
-_mdc_load()\r
-loads a Return to Castle Wolfenstein mdc model file.\r
-*/\r
-\r
-static picoModel_t *_mdc_load( PM_PARAMS_LOAD )\r
-{\r
-       int                                     i, j;\r
-       picoByte_t                      *bb;\r
-       mdc_t                           *mdc;\r
-       mdcSurface_t            *surface;\r
-       mdcShader_t                     *shader;\r
-       mdcTexCoord_t           *texCoord;\r
-       mdcFrame_t                      *frame;\r
-       mdcTriangle_t           *triangle;\r
-       mdcVertex_t                     *vertex;\r
-       mdcXyzCompressed_t      *vertexComp;\r
-       short                           *mdcShort, *mdcCompVert;\r
-       double                          lat, lng;\r
-       \r
-       picoModel_t                     *picoModel;\r
-       picoSurface_t           *picoSurface;\r
-       picoShader_t            *picoShader;\r
-       picoVec3_t                      xyz, normal;\r
-       picoVec2_t                      st;\r
-       picoColor_t                     color;\r
-       \r
-       \r
-       /* -------------------------------------------------\r
-       mdc loading\r
-       ------------------------------------------------- */\r
-\r
-\r
-       /* set as mdc */\r
-       bb = (picoByte_t*) buffer;\r
-       mdc     = (mdc_t*) buffer;\r
-       \r
-       /* check ident and version */\r
-       if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) || _pico_little_long( mdc->version ) != MDC_VERSION )\r
-       {\r
-               /* not an mdc file (todo: set error) */\r
-               return NULL;\r
-       }\r
-       \r
-       /* swap mdc */\r
-       mdc->version = _pico_little_long( mdc->version );\r
-       mdc->numFrames = _pico_little_long( mdc->numFrames );\r
-       mdc->numTags = _pico_little_long( mdc->numTags );\r
-       mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );\r
-       mdc->numSkins = _pico_little_long( mdc->numSkins );\r
-       mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );\r
-       mdc->ofsTags = _pico_little_long( mdc->ofsTags );\r
-       mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );\r
-       mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );\r
-       mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );\r
-       \r
-       /* do frame check */\r
-       if( mdc->numFrames < 1 )\r
-       {\r
-               _pico_printf( PICO_ERROR, "MDC with 0 frames" );\r
-               return NULL;\r
-       }\r
-       \r
-       if( frameNum < 0 || frameNum >= mdc->numFrames )\r
-       {\r
-               _pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );\r
-               return NULL;\r
-       }\r
-       \r
-       /* swap frames */\r
-       frame = (mdcFrame_t*) (bb + mdc->ofsFrames );\r
-       for( i = 0; i < mdc->numFrames; i++, frame++ )\r
-       {\r
-               frame->radius = _pico_little_float( frame->radius );\r
-               for( j = 0; j < 3; j++ )\r
-               {\r
-                       frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );\r
-                       frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );\r
-                       frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );\r
-               }\r
-       }\r
-       \r
-       /* swap surfaces */\r
-       surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);\r
-       for( i = 0; i < mdc->numSurfaces; i++ )\r
-       {\r
-               /* swap surface mdc */\r
-               surface->flags = _pico_little_long( surface->flags );\r
-               surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );\r
-               surface->numCompFrames = _pico_little_long( surface->numCompFrames );\r
-               surface->numShaders = _pico_little_long( surface->numShaders );\r
-               surface->numTriangles = _pico_little_long( surface->numTriangles );\r
-               surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );\r
-               surface->numVerts = _pico_little_long( surface->numVerts );\r
-               surface->ofsShaders = _pico_little_long( surface->ofsShaders );\r
-               surface->ofsSt = _pico_little_long( surface->ofsSt );\r
-               surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );\r
-               surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );\r
-               surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );\r
-               surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );\r
-               surface->ofsEnd = _pico_little_long( surface->ofsEnd );\r
-               \r
-               /* swap triangles */\r
-               triangle = (mdcTriangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);\r
-               for( j = 0; j < surface->numTriangles; j++, triangle++ )\r
-               {\r
-                       /* sea: swaps fixed */\r
-                       triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );\r
-                       triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );\r
-                       triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );\r
-               }\r
-               \r
-               /* swap st coords */\r
-               texCoord = (mdcTexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);\r
-               for( j = 0; j < surface->numVerts; j++, texCoord++ )\r
-               {\r
-                       texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );\r
-                       texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );\r
-               }\r
-               \r
-               /* swap xyz/normals */\r
-               vertex = (mdcVertex_t*) ((picoByte_t*) surface + surface->ofsXyzNormals);\r
-               for( j = 0; j < (surface->numVerts * surface->numBaseFrames); j++, vertex++)\r
-               {\r
-                       vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );\r
-                       vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );\r
-                       vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );\r
-                       vertex->normal   = _pico_little_short( vertex->normal );\r
-               }\r
-\r
-               /* swap xyz/compressed */\r
-               vertexComp = (mdcXyzCompressed_t*) ((picoByte_t*) surface + surface->ofsXyzCompressed);\r
-               for( j = 0; j < (surface->numVerts * surface->numCompFrames); j++, vertexComp++)\r
-               {\r
-                       vertexComp->ofsVec      = _pico_little_long( vertexComp->ofsVec );\r
-               }\r
-\r
-               /* swap base frames */\r
-               mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameBaseFrames);\r
-               for( j = 0; j < mdc->numFrames; j++, mdcShort++)\r
-               {\r
-                       *mdcShort       = _pico_little_short( *mdcShort );\r
-               }\r
-\r
-               /* swap compressed frames */\r
-               mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameCompFrames);\r
-               for( j = 0; j < mdc->numFrames; j++, mdcShort++)\r
-               {\r
-                       *mdcShort       = _pico_little_short( *mdcShort );\r
-               }\r
-               \r
-               /* get next surface */\r
-               surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);\r
-       }\r
-       \r
-       /* -------------------------------------------------\r
-       pico model creation\r
-       ------------------------------------------------- */\r
-       \r
-       /* create new pico model */\r
-       picoModel = PicoNewModel();\r
-       if( picoModel == NULL )\r
-       {\r
-               _pico_printf( PICO_ERROR, "Unable to allocate a new model" );\r
-               return NULL;\r
-       }\r
-       \r
-       /* do model setup */\r
-       PicoSetModelFrameNum( picoModel, frameNum );\r
-       PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */\r
-       PicoSetModelName( picoModel, fileName );\r
-       PicoSetModelFileName( picoModel, fileName );\r
-       \r
-       /* mdc surfaces become picomodel surfaces */\r
-       surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);\r
-       \r
-       /* run through mdc surfaces */\r
-       for( i = 0; i < mdc->numSurfaces; i++ )\r
-       {\r
-               /* allocate new pico surface */\r
-               picoSurface = PicoNewSurface( picoModel );\r
-               if( picoSurface == NULL )\r
-               {\r
-                       _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );\r
-                       PicoFreeModel( picoModel ); /* sea */\r
-                       return NULL;\r
-               }\r
-               \r
-               /* mdc model surfaces are all triangle meshes */\r
-               PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );\r
-               \r
-               /* set surface name */\r
-               PicoSetSurfaceName( picoSurface, surface->name );\r
-               \r
-               /* create new pico shader -sea */\r
-               picoShader = PicoNewShader( picoModel );\r
-               if( picoShader == NULL )\r
-               {\r
-                       _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );\r
-                       PicoFreeModel( picoModel );\r
-                       return NULL;\r
-               }\r
-               \r
-               /* detox and set shader name */\r
-               shader = (mdcShader_t*) ((picoByte_t*) surface + surface->ofsShaders);\r
-               _pico_setfext( shader->name, "" );\r
-               _pico_unixify( shader->name );\r
-               PicoSetShaderName( picoShader, shader->name );\r
-               \r
-               /* associate current surface with newly created shader */\r
-               PicoSetSurfaceShader( picoSurface, picoShader );\r
-               \r
-               /* copy indexes */\r
-               triangle = (mdcTriangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);\r
-               \r
-               for( j = 0; j < surface->numTriangles; j++, triangle++ )\r
-               {\r
-                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );\r
-                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );\r
-                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );\r
-               }\r
-               \r
-               /* copy vertexes */\r
-               texCoord = (mdcTexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);\r
-    mdcShort = (short *) ((picoByte_t *) surface + surface->ofsXyzNormals) + ((int)*((short *) ((picoByte_t *) surface + surface->ofsFrameBaseFrames) + frameNum) * surface->numVerts * 4);\r
-               if( surface->numCompFrames > 0 )\r
-               {\r
-                       mdcCompVert = (short *) ((picoByte_t *) surface + surface->ofsFrameCompFrames) + frameNum;\r
-                       if( *mdcCompVert >= 0 )\r
-                               vertexComp = (mdcXyzCompressed_t *) ((picoByte_t *) surface + surface->ofsXyzCompressed) + (*mdcCompVert * surface->numVerts);\r
-               }\r
-               _pico_set_color( color, 255, 255, 255, 255 );\r
-               \r
-               for( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort+=4 )\r
-               {\r
-                       /* set vertex origin */\r
-                       xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];\r
-                       xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];\r
-                       xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];\r
-\r
-                       /* add compressed ofsVec */\r
-                       if( surface->numCompFrames > 0 && *mdcCompVert >= 0 )\r
-                       {               \r
-                               xyz[ 0 ] += ((float) ((vertexComp->ofsVec) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;\r
-                               xyz[ 1 ] += ((float) ((vertexComp->ofsVec >> 8) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;\r
-                               xyz[ 2 ] += ((float) ((vertexComp->ofsVec >> 16) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;\r
-                               PicoSetSurfaceXYZ( picoSurface, j, xyz );\r
-\r
-                               normal[ 0 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 0 ];\r
-                               normal[ 1 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 1 ];\r
-                               normal[ 2 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 2 ];\r
-                               PicoSetSurfaceNormal( picoSurface, j, normal );\r
-\r
-                               vertexComp++;\r
-                       }\r
-                       else\r
-                       {                       \r
-                               PicoSetSurfaceXYZ( picoSurface, j, xyz );\r
-\r
-                               /* decode lat/lng normal to 3 float normal */\r
-                               lat = (float) ((*(mdcShort + 3) >> 8) & 0xff);\r
-                               lng = (float) (*(mdcShort + 3) & 0xff);\r
-                               lat *= PICO_PI / 128;\r
-                               lng *= PICO_PI / 128;\r
-                               normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );\r
-                               normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );\r
-                               normal[ 2 ] = (picoVec_t) cos( lng );\r
-                               PicoSetSurfaceNormal( picoSurface, j, normal );\r
-                       }\r
-                       \r
-                       /* set st coords */\r
-                       st[ 0 ] = texCoord->st[ 0 ];\r
-                       st[ 1 ] = texCoord->st[ 1 ];\r
-                       PicoSetSurfaceST( picoSurface, 0, j, st );\r
-\r
-                       /* set color */\r
-                       PicoSetSurfaceColor( picoSurface, 0, j, color );\r
-               }\r
-               \r
-               /* get next surface */\r
-               surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);\r
-       }\r
-       \r
-       /* return the new pico model */\r
-       return picoModel;\r
-}\r
-\r
-\r
-\r
-/* pico file format module definition */\r
-const picoModule_t picoModuleMDC =\r
-{\r
-       "1.3",                                                  /* module version string */\r
-       "RtCW MDC",                                             /* module display name */\r
-       "Arnout van Meer",                              /* author's name */\r
-       "2002 Arnout van Meer",                 /* module copyright */\r
-       {\r
-               "mdc", NULL, NULL, NULL         /* default extensions to use */\r
-       },\r
-       _mdc_canload,                                   /* validation routine */\r
-       _mdc_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.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_MDC_C
+
+
+
+/* dependencies */
+#include "picointernal.h"
+
+/* mdc model format */
+#define MDC_MAGIC                      "IDPC"
+#define MDC_VERSION                    2
+
+/* mdc vertex scale */
+#define MDC_SCALE                      (1.0f / 64.0f)
+#define        MDC_MAX_OFS                     127.0f
+#define        MDC_DIST_SCALE          0.05f
+
+/* mdc decoding normal table */
+double mdcNormals[ 256 ][ 3 ] =
+{
+       { 1.000000, 0.000000, 0.000000 },
+       { 0.980785, 0.195090, 0.000000 },
+       { 0.923880, 0.382683, 0.000000 },
+       { 0.831470, 0.555570, 0.000000 },
+       { 0.707107, 0.707107, 0.000000 },
+       { 0.555570, 0.831470, 0.000000 },
+       { 0.382683, 0.923880, 0.000000 },
+       { 0.195090, 0.980785, 0.000000 },
+       { -0.000000, 1.000000, 0.000000 },
+       { -0.195090, 0.980785, 0.000000 },
+       { -0.382683, 0.923880, 0.000000 },
+       { -0.555570, 0.831470, 0.000000 },
+       { -0.707107, 0.707107, 0.000000 },
+       { -0.831470, 0.555570, 0.000000 },
+       { -0.923880, 0.382683, 0.000000 },
+       { -0.980785, 0.195090, 0.000000 },
+       { -1.000000, -0.000000, 0.000000 },
+       { -0.980785, -0.195090, 0.000000 },
+       { -0.923880, -0.382683, 0.000000 },
+       { -0.831470, -0.555570, 0.000000 },
+       { -0.707107, -0.707107, 0.000000 },
+       { -0.555570, -0.831469, 0.000000 },
+       { -0.382684, -0.923880, 0.000000 },
+       { -0.195090, -0.980785, 0.000000 },
+       { 0.000000, -1.000000, 0.000000 },
+       { 0.195090, -0.980785, 0.000000 },
+       { 0.382684, -0.923879, 0.000000 },
+       { 0.555570, -0.831470, 0.000000 },
+       { 0.707107, -0.707107, 0.000000 },
+       { 0.831470, -0.555570, 0.000000 },
+       { 0.923880, -0.382683, 0.000000 },
+       { 0.980785, -0.195090, 0.000000 },
+       { 0.980785, 0.000000, -0.195090 },
+       { 0.956195, 0.218245, -0.195090 },
+       { 0.883657, 0.425547, -0.195090 },
+       { 0.766809, 0.611510, -0.195090 },
+       { 0.611510, 0.766809, -0.195090 },
+       { 0.425547, 0.883657, -0.195090 },
+       { 0.218245, 0.956195, -0.195090 },
+       { -0.000000, 0.980785, -0.195090 },
+       { -0.218245, 0.956195, -0.195090 },
+       { -0.425547, 0.883657, -0.195090 },
+       { -0.611510, 0.766809, -0.195090 },
+       { -0.766809, 0.611510, -0.195090 },
+       { -0.883657, 0.425547, -0.195090 },
+       { -0.956195, 0.218245, -0.195090 },
+       { -0.980785, -0.000000, -0.195090 },
+       { -0.956195, -0.218245, -0.195090 },
+       { -0.883657, -0.425547, -0.195090 },
+       { -0.766809, -0.611510, -0.195090 },
+       { -0.611510, -0.766809, -0.195090 },
+       { -0.425547, -0.883657, -0.195090 },
+       { -0.218245, -0.956195, -0.195090 },
+       { 0.000000, -0.980785, -0.195090 },
+       { 0.218245, -0.956195, -0.195090 },
+       { 0.425547, -0.883657, -0.195090 },
+       { 0.611510, -0.766809, -0.195090 },
+       { 0.766809, -0.611510, -0.195090 },
+       { 0.883657, -0.425547, -0.195090 },
+       { 0.956195, -0.218245, -0.195090 },
+       { 0.923880, 0.000000, -0.382683 },
+       { 0.892399, 0.239118, -0.382683 },
+       { 0.800103, 0.461940, -0.382683 },
+       { 0.653281, 0.653281, -0.382683 },
+       { 0.461940, 0.800103, -0.382683 },
+       { 0.239118, 0.892399, -0.382683 },
+       { -0.000000, 0.923880, -0.382683 },
+       { -0.239118, 0.892399, -0.382683 },
+       { -0.461940, 0.800103, -0.382683 },
+       { -0.653281, 0.653281, -0.382683 },
+       { -0.800103, 0.461940, -0.382683 },
+       { -0.892399, 0.239118, -0.382683 },
+       { -0.923880, -0.000000, -0.382683 },
+       { -0.892399, -0.239118, -0.382683 },
+       { -0.800103, -0.461940, -0.382683 },
+       { -0.653282, -0.653281, -0.382683 },
+       { -0.461940, -0.800103, -0.382683 },
+       { -0.239118, -0.892399, -0.382683 },
+       { 0.000000, -0.923880, -0.382683 },
+       { 0.239118, -0.892399, -0.382683 },
+       { 0.461940, -0.800103, -0.382683 },
+       { 0.653281, -0.653282, -0.382683 },
+       { 0.800103, -0.461940, -0.382683 },
+       { 0.892399, -0.239117, -0.382683 },
+       { 0.831470, 0.000000, -0.555570 },
+       { 0.790775, 0.256938, -0.555570 },
+       { 0.672673, 0.488726, -0.555570 },
+       { 0.488726, 0.672673, -0.555570 },
+       { 0.256938, 0.790775, -0.555570 },
+       { -0.000000, 0.831470, -0.555570 },
+       { -0.256938, 0.790775, -0.555570 },
+       { -0.488726, 0.672673, -0.555570 },
+       { -0.672673, 0.488726, -0.555570 },
+       { -0.790775, 0.256938, -0.555570 },
+       { -0.831470, -0.000000, -0.555570 },
+       { -0.790775, -0.256938, -0.555570 },
+       { -0.672673, -0.488726, -0.555570 },
+       { -0.488725, -0.672673, -0.555570 },
+       { -0.256938, -0.790775, -0.555570 },
+       { 0.000000, -0.831470, -0.555570 },
+       { 0.256938, -0.790775, -0.555570 },
+       { 0.488725, -0.672673, -0.555570 },
+       { 0.672673, -0.488726, -0.555570 },
+       { 0.790775, -0.256938, -0.555570 },
+       { 0.707107, 0.000000, -0.707107 },
+       { 0.653281, 0.270598, -0.707107 },
+       { 0.500000, 0.500000, -0.707107 },
+       { 0.270598, 0.653281, -0.707107 },
+       { -0.000000, 0.707107, -0.707107 },
+       { -0.270598, 0.653282, -0.707107 },
+       { -0.500000, 0.500000, -0.707107 },
+       { -0.653281, 0.270598, -0.707107 },
+       { -0.707107, -0.000000, -0.707107 },
+       { -0.653281, -0.270598, -0.707107 },
+       { -0.500000, -0.500000, -0.707107 },
+       { -0.270598, -0.653281, -0.707107 },
+       { 0.000000, -0.707107, -0.707107 },
+       { 0.270598, -0.653281, -0.707107 },
+       { 0.500000, -0.500000, -0.707107 },
+       { 0.653282, -0.270598, -0.707107 },
+       { 0.555570, 0.000000, -0.831470 },
+       { 0.481138, 0.277785, -0.831470 },
+       { 0.277785, 0.481138, -0.831470 },
+       { -0.000000, 0.555570, -0.831470 },
+       { -0.277785, 0.481138, -0.831470 },
+       { -0.481138, 0.277785, -0.831470 },
+       { -0.555570, -0.000000, -0.831470 },
+       { -0.481138, -0.277785, -0.831470 },
+       { -0.277785, -0.481138, -0.831470 },
+       { 0.000000, -0.555570, -0.831470 },
+       { 0.277785, -0.481138, -0.831470 },
+       { 0.481138, -0.277785, -0.831470 },
+       { 0.382683, 0.000000, -0.923880 },
+       { 0.270598, 0.270598, -0.923880 },
+       { -0.000000, 0.382683, -0.923880 },
+       { -0.270598, 0.270598, -0.923880 },
+       { -0.382683, -0.000000, -0.923880 },
+       { -0.270598, -0.270598, -0.923880 },
+       { 0.000000, -0.382683, -0.923880 },
+       { 0.270598, -0.270598, -0.923880 },
+       { 0.195090, 0.000000, -0.980785 },
+       { -0.000000, 0.195090, -0.980785 },
+       { -0.195090, -0.000000, -0.980785 },
+       { 0.000000, -0.195090, -0.980785 },
+       { 0.980785, 0.000000, 0.195090 },
+       { 0.956195, 0.218245, 0.195090 },
+       { 0.883657, 0.425547, 0.195090 },
+       { 0.766809, 0.611510, 0.195090 },
+       { 0.611510, 0.766809, 0.195090 },
+       { 0.425547, 0.883657, 0.195090 },
+       { 0.218245, 0.956195, 0.195090 },
+       { -0.000000, 0.980785, 0.195090 },
+       { -0.218245, 0.956195, 0.195090 },
+       { -0.425547, 0.883657, 0.195090 },
+       { -0.611510, 0.766809, 0.195090 },
+       { -0.766809, 0.611510, 0.195090 },
+       { -0.883657, 0.425547, 0.195090 },
+       { -0.956195, 0.218245, 0.195090 },
+       { -0.980785, -0.000000, 0.195090 },
+       { -0.956195, -0.218245, 0.195090 },
+       { -0.883657, -0.425547, 0.195090 },
+       { -0.766809, -0.611510, 0.195090 },
+       { -0.611510, -0.766809, 0.195090 },
+       { -0.425547, -0.883657, 0.195090 },
+       { -0.218245, -0.956195, 0.195090 },
+       { 0.000000, -0.980785, 0.195090 },
+       { 0.218245, -0.956195, 0.195090 },
+       { 0.425547, -0.883657, 0.195090 },
+       { 0.611510, -0.766809, 0.195090 },
+       { 0.766809, -0.611510, 0.195090 },
+       { 0.883657, -0.425547, 0.195090 },
+       { 0.956195, -0.218245, 0.195090 },
+       { 0.923880, 0.000000, 0.382683 },
+       { 0.892399, 0.239118, 0.382683 },
+       { 0.800103, 0.461940, 0.382683 },
+       { 0.653281, 0.653281, 0.382683 },
+       { 0.461940, 0.800103, 0.382683 },
+       { 0.239118, 0.892399, 0.382683 },
+       { -0.000000, 0.923880, 0.382683 },
+       { -0.239118, 0.892399, 0.382683 },
+       { -0.461940, 0.800103, 0.382683 },
+       { -0.653281, 0.653281, 0.382683 },
+       { -0.800103, 0.461940, 0.382683 },
+       { -0.892399, 0.239118, 0.382683 },
+       { -0.923880, -0.000000, 0.382683 },
+       { -0.892399, -0.239118, 0.382683 },
+       { -0.800103, -0.461940, 0.382683 },
+       { -0.653282, -0.653281, 0.382683 },
+       { -0.461940, -0.800103, 0.382683 },
+       { -0.239118, -0.892399, 0.382683 },
+       { 0.000000, -0.923880, 0.382683 },
+       { 0.239118, -0.892399, 0.382683 },
+       { 0.461940, -0.800103, 0.382683 },
+       { 0.653281, -0.653282, 0.382683 },
+       { 0.800103, -0.461940, 0.382683 },
+       { 0.892399, -0.239117, 0.382683 },
+       { 0.831470, 0.000000, 0.555570 },
+       { 0.790775, 0.256938, 0.555570 },
+       { 0.672673, 0.488726, 0.555570 },
+       { 0.488726, 0.672673, 0.555570 },
+       { 0.256938, 0.790775, 0.555570 },
+       { -0.000000, 0.831470, 0.555570 },
+       { -0.256938, 0.790775, 0.555570 },
+       { -0.488726, 0.672673, 0.555570 },
+       { -0.672673, 0.488726, 0.555570 },
+       { -0.790775, 0.256938, 0.555570 },
+       { -0.831470, -0.000000, 0.555570 },
+       { -0.790775, -0.256938, 0.555570 },
+       { -0.672673, -0.488726, 0.555570 },
+       { -0.488725, -0.672673, 0.555570 },
+       { -0.256938, -0.790775, 0.555570 },
+       { 0.000000, -0.831470, 0.555570 },
+       { 0.256938, -0.790775, 0.555570 },
+       { 0.488725, -0.672673, 0.555570 },
+       { 0.672673, -0.488726, 0.555570 },
+       { 0.790775, -0.256938, 0.555570 },
+       { 0.707107, 0.000000, 0.707107 },
+       { 0.653281, 0.270598, 0.707107 },
+       { 0.500000, 0.500000, 0.707107 },
+       { 0.270598, 0.653281, 0.707107 },
+       { -0.000000, 0.707107, 0.707107 },
+       { -0.270598, 0.653282, 0.707107 },
+       { -0.500000, 0.500000, 0.707107 },
+       { -0.653281, 0.270598, 0.707107 },
+       { -0.707107, -0.000000, 0.707107 },
+       { -0.653281, -0.270598, 0.707107 },
+       { -0.500000, -0.500000, 0.707107 },
+       { -0.270598, -0.653281, 0.707107 },
+       { 0.000000, -0.707107, 0.707107 },
+       { 0.270598, -0.653281, 0.707107 },
+       { 0.500000, -0.500000, 0.707107 },
+       { 0.653282, -0.270598, 0.707107 },
+       { 0.555570, 0.000000, 0.831470 },
+       { 0.481138, 0.277785, 0.831470 },
+       { 0.277785, 0.481138, 0.831470 },
+       { -0.000000, 0.555570, 0.831470 },
+       { -0.277785, 0.481138, 0.831470 },
+       { -0.481138, 0.277785, 0.831470 },
+       { -0.555570, -0.000000, 0.831470 },
+       { -0.481138, -0.277785, 0.831470 },
+       { -0.277785, -0.481138, 0.831470 },
+       { 0.000000, -0.555570, 0.831470 },
+       { 0.277785, -0.481138, 0.831470 },
+       { 0.481138, -0.277785, 0.831470 },
+       { 0.382683, 0.000000, 0.923880 },
+       { 0.270598, 0.270598, 0.923880 },
+       { -0.000000, 0.382683, 0.923880 },
+       { -0.270598, 0.270598, 0.923880 },
+       { -0.382683, -0.000000, 0.923880 },
+       { -0.270598, -0.270598, 0.923880 },
+       { 0.000000, -0.382683, 0.923880 },
+       { 0.270598, -0.270598, 0.923880 },
+       { 0.195090, 0.000000, 0.980785 },
+       { -0.000000, 0.195090, 0.980785 },
+       { -0.195090, -0.000000, 0.980785 },
+       { 0.000000, -0.195090, 0.980785 }
+};
+
+/* mdc model frame information */
+typedef struct mdcFrame_s
+{
+       float           bounds[ 2 ][ 3 ];
+       float           localOrigin[ 3 ];
+       float           radius;
+       char            creator[ 16 ];
+}
+mdcFrame_t;
+
+/* mdc model tag information */
+typedef struct mdcTag_s
+{
+       short           xyz[3];
+       short           angles[3];
+}
+mdcTag_t;
+
+/* mdc surface mdc (one object mesh) */
+typedef struct mdcSurface_s
+{
+       char            magic[ 4 ];
+       char            name[ 64 ];                     /* polyset name */
+       int                     flags;
+       int                     numCompFrames;          /* all surfaces in a model should have the same */
+       int                     numBaseFrames;          /* ditto */
+       int                     numShaders;                     /* all model surfaces should have the same */
+       int                     numVerts;
+       int                     numTriangles;
+       int                     ofsTriangles;
+       int                     ofsShaders;                     /* offset from start of mdcSurface_t */
+       int                     ofsSt;                          /* texture coords are common for all frames */
+       int                     ofsXyzNormals;          /* numVerts * numBaseFrames */
+       int                     ofsXyzCompressed;       /* numVerts * numCompFrames */
+
+       int                     ofsFrameBaseFrames;     /* numFrames */
+       int                     ofsFrameCompFrames;     /* numFrames */
+       int                     ofsEnd;                         /* next surface follows */
+}
+mdcSurface_t;
+
+typedef struct mdcShader_s
+{
+       char            name[ 64 ];
+       int                     shaderIndex;    /* for ingame use */
+}
+mdcShader_t;
+
+typedef struct mdcTriangle_s
+{
+       int                     indexes[ 3 ];
+}
+mdcTriangle_t;
+
+typedef struct mdcTexCoord_s
+{
+       float           st[ 2 ];
+}
+mdcTexCoord_t;
+
+typedef struct mdcVertex_s
+{
+       short           xyz[ 3 ];
+       short           normal;
+}
+mdcVertex_t;
+
+typedef struct mdcXyzCompressed_s
+{
+       unsigned int    ofsVec;         /* offset direction from the last base frame */
+}
+mdcXyzCompressed_t;
+
+
+/* mdc model file mdc structure */
+typedef struct mdc_s
+{
+       char            magic[ 4 ];             /* MDC_MAGIC */
+       int                     version;
+       char            name[ 64 ];             /* model name */
+       int                     flags;
+       int                     numFrames;
+       int                     numTags;
+       int                     numSurfaces;
+       int                     numSkins;               /* number of skins for the mesh */
+       int                     ofsFrames;              /* offset for first frame */
+       int                     ofsTagNames;    /* numTags */
+       int                     ofsTags;                /* numFrames * numTags */
+       int                     ofsSurfaces;    /* first surface, others follow */
+       int                     ofsEnd;                 /* end of file */
+}
+mdc_t;
+
+
+
+
+/*
+_mdc_canload()
+validates a Return to Castle Wolfenstein model file. btw, i use the
+preceding underscore cause it's a static func referenced
+by one structure only.
+*/
+
+static int _mdc_canload( PM_PARAMS_CANLOAD )
+{
+       mdc_t   *mdc;
+       
+
+       /* to keep the compiler happy */
+       *fileName = *fileName;
+       
+       /* sanity check */
+       if( bufSize < ( sizeof( *mdc ) * 2) )
+               return PICO_PMV_ERROR_SIZE;
+       
+       /* set as mdc */
+       mdc     = (mdc_t*) buffer;
+       
+       /* check mdc magic */
+       if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) ) 
+               return PICO_PMV_ERROR_IDENT;
+       
+       /* check mdc version */
+       if( _pico_little_long( mdc->version ) != MDC_VERSION )
+               return PICO_PMV_ERROR_VERSION;
+       
+       /* file seems to be a valid mdc */
+       return PICO_PMV_OK;
+}
+
+
+
+/*
+_mdc_load()
+loads a Return to Castle Wolfenstein mdc model file.
+*/
+
+static picoModel_t *_mdc_load( PM_PARAMS_LOAD )
+{
+       int                                     i, j;
+       picoByte_t                      *bb;
+       mdc_t                           *mdc;
+       mdcSurface_t            *surface;
+       mdcShader_t                     *shader;
+       mdcTexCoord_t           *texCoord;
+       mdcFrame_t                      *frame;
+       mdcTriangle_t           *triangle;
+       mdcVertex_t                     *vertex;
+       mdcXyzCompressed_t      *vertexComp;
+       short                           *mdcShort, *mdcCompVert;
+       double                          lat, lng;
+       
+       picoModel_t                     *picoModel;
+       picoSurface_t           *picoSurface;
+       picoShader_t            *picoShader;
+       picoVec3_t                      xyz, normal;
+       picoVec2_t                      st;
+       picoColor_t                     color;
+       
+       
+       /* -------------------------------------------------
+       mdc loading
+       ------------------------------------------------- */
+
+
+       /* set as mdc */
+       bb = (picoByte_t*) buffer;
+       mdc     = (mdc_t*) buffer;
+       
+       /* check ident and version */
+       if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) || _pico_little_long( mdc->version ) != MDC_VERSION )
+       {
+               /* not an mdc file (todo: set error) */
+               return NULL;
+       }
+       
+       /* swap mdc */
+       mdc->version = _pico_little_long( mdc->version );
+       mdc->numFrames = _pico_little_long( mdc->numFrames );
+       mdc->numTags = _pico_little_long( mdc->numTags );
+       mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );
+       mdc->numSkins = _pico_little_long( mdc->numSkins );
+       mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );
+       mdc->ofsTags = _pico_little_long( mdc->ofsTags );
+       mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );
+       mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );
+       mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );
+       
+       /* do frame check */
+       if( mdc->numFrames < 1 )
+       {
+               _pico_printf( PICO_ERROR, "MDC with 0 frames" );
+               return NULL;
+       }
+       
+       if( frameNum < 0 || frameNum >= mdc->numFrames )
+       {
+               _pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );
+               return NULL;
+       }
+       
+       /* swap frames */
+       frame = (mdcFrame_t*) (bb + mdc->ofsFrames );
+       for( i = 0; i < mdc->numFrames; i++, frame++ )
+       {
+               frame->radius = _pico_little_float( frame->radius );
+               for( j = 0; j < 3; j++ )
+               {
+                       frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
+                       frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
+                       frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
+               }
+       }
+       
+       /* swap surfaces */
+       surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
+       for( i = 0; i < mdc->numSurfaces; i++ )
+       {
+               /* swap surface mdc */
+               surface->flags = _pico_little_long( surface->flags );
+               surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );
+               surface->numCompFrames = _pico_little_long( surface->numCompFrames );
+               surface->numShaders = _pico_little_long( surface->numShaders );
+               surface->numTriangles = _pico_little_long( surface->numTriangles );
+               surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
+               surface->numVerts = _pico_little_long( surface->numVerts );
+               surface->ofsShaders = _pico_little_long( surface->ofsShaders );
+               surface->ofsSt = _pico_little_long( surface->ofsSt );
+               surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );
+               surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );
+               surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );
+               surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );
+               surface->ofsEnd = _pico_little_long( surface->ofsEnd );
+               
+               /* swap triangles */
+               triangle = (mdcTriangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
+               for( j = 0; j < surface->numTriangles; j++, triangle++ )
+               {
+                       /* sea: swaps fixed */
+                       triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
+                       triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
+                       triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
+               }
+               
+               /* swap st coords */
+               texCoord = (mdcTexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
+               for( j = 0; j < surface->numVerts; j++, texCoord++ )
+               {
+                       texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
+                       texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
+               }
+               
+               /* swap xyz/normals */
+               vertex = (mdcVertex_t*) ((picoByte_t*) surface + surface->ofsXyzNormals);
+               for( j = 0; j < (surface->numVerts * surface->numBaseFrames); j++, vertex++)
+               {
+                       vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
+                       vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
+                       vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
+                       vertex->normal   = _pico_little_short( vertex->normal );
+               }
+
+               /* swap xyz/compressed */
+               vertexComp = (mdcXyzCompressed_t*) ((picoByte_t*) surface + surface->ofsXyzCompressed);
+               for( j = 0; j < (surface->numVerts * surface->numCompFrames); j++, vertexComp++)
+               {
+                       vertexComp->ofsVec      = _pico_little_long( vertexComp->ofsVec );
+               }
+
+               /* swap base frames */
+               mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameBaseFrames);
+               for( j = 0; j < mdc->numFrames; j++, mdcShort++)
+               {
+                       *mdcShort       = _pico_little_short( *mdcShort );
+               }
+
+               /* swap compressed frames */
+               mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameCompFrames);
+               for( j = 0; j < mdc->numFrames; j++, mdcShort++)
+               {
+                       *mdcShort       = _pico_little_short( *mdcShort );
+               }
+               
+               /* get next surface */
+               surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+       }
+       
+       /* -------------------------------------------------
+       pico model creation
+       ------------------------------------------------- */
+       
+       /* create new pico model */
+       picoModel = PicoNewModel();
+       if( picoModel == NULL )
+       {
+               _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+               return NULL;
+       }
+       
+       /* do model setup */
+       PicoSetModelFrameNum( picoModel, frameNum );
+       PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */
+       PicoSetModelName( picoModel, fileName );
+       PicoSetModelFileName( picoModel, fileName );
+       
+       /* mdc surfaces become picomodel surfaces */
+       surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
+       
+       /* run through mdc surfaces */
+       for( i = 0; i < mdc->numSurfaces; i++ )
+       {
+               /* allocate new pico surface */
+               picoSurface = PicoNewSurface( picoModel );
+               if( picoSurface == NULL )
+               {
+                       _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+                       PicoFreeModel( picoModel ); /* sea */
+                       return NULL;
+               }
+               
+               /* mdc model surfaces are all triangle meshes */
+               PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+               
+               /* set surface name */
+               PicoSetSurfaceName( picoSurface, surface->name );
+               
+               /* create new pico shader -sea */
+               picoShader = PicoNewShader( picoModel );
+               if( picoShader == NULL )
+               {
+                       _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+                       PicoFreeModel( picoModel );
+                       return NULL;
+               }
+               
+               /* detox and set shader name */
+               shader = (mdcShader_t*) ((picoByte_t*) surface + surface->ofsShaders);
+               _pico_setfext( shader->name, "" );
+               _pico_unixify( shader->name );
+               PicoSetShaderName( picoShader, shader->name );
+               
+               /* associate current surface with newly created shader */
+               PicoSetSurfaceShader( picoSurface, picoShader );
+               
+               /* copy indexes */
+               triangle = (mdcTriangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
+               
+               for( j = 0; j < surface->numTriangles; j++, triangle++ )
+               {
+                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
+                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
+                       PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
+               }
+               
+               /* copy vertexes */
+               texCoord = (mdcTexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
+    mdcShort = (short *) ((picoByte_t *) surface + surface->ofsXyzNormals) + ((int)*((short *) ((picoByte_t *) surface + surface->ofsFrameBaseFrames) + frameNum) * surface->numVerts * 4);
+               if( surface->numCompFrames > 0 )
+               {
+                       mdcCompVert = (short *) ((picoByte_t *) surface + surface->ofsFrameCompFrames) + frameNum;
+                       if( *mdcCompVert >= 0 )
+                               vertexComp = (mdcXyzCompressed_t *) ((picoByte_t *) surface + surface->ofsXyzCompressed) + (*mdcCompVert * surface->numVerts);
+               }
+               _pico_set_color( color, 255, 255, 255, 255 );
+               
+               for( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort+=4 )
+               {
+                       /* set vertex origin */
+                       xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];
+                       xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];
+                       xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];
+
+                       /* add compressed ofsVec */
+                       if( surface->numCompFrames > 0 && *mdcCompVert >= 0 )
+                       {               
+                               xyz[ 0 ] += ((float) ((vertexComp->ofsVec) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+                               xyz[ 1 ] += ((float) ((vertexComp->ofsVec >> 8) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+                               xyz[ 2 ] += ((float) ((vertexComp->ofsVec >> 16) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+                               PicoSetSurfaceXYZ( picoSurface, j, xyz );
+
+                               normal[ 0 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 0 ];
+                               normal[ 1 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 1 ];
+                               normal[ 2 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 2 ];
+                               PicoSetSurfaceNormal( picoSurface, j, normal );
+
+                               vertexComp++;
+                       }
+                       else
+                       {                       
+                               PicoSetSurfaceXYZ( picoSurface, j, xyz );
+
+                               /* decode lat/lng normal to 3 float normal */
+                               lat = (float) ((*(mdcShort + 3) >> 8) & 0xff);
+                               lng = (float) (*(mdcShort + 3) & 0xff);
+                               lat *= PICO_PI / 128;
+                               lng *= PICO_PI / 128;
+                               normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
+                               normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
+                               normal[ 2 ] = (picoVec_t) cos( lng );
+                               PicoSetSurfaceNormal( picoSurface, j, normal );
+                       }
+                       
+                       /* set st coords */
+                       st[ 0 ] = texCoord->st[ 0 ];
+                       st[ 1 ] = texCoord->st[ 1 ];
+                       PicoSetSurfaceST( picoSurface, 0, j, st );
+
+                       /* set color */
+                       PicoSetSurfaceColor( picoSurface, 0, j, color );
+               }
+               
+               /* get next surface */
+               surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+       }
+       
+       /* return the new pico model */
+       return picoModel;
+}
+
+
+
+/* pico file format module definition */
+const picoModule_t picoModuleMDC =
+{
+       "1.3",                                                  /* module version string */
+       "RtCW MDC",                                             /* module display name */
+       "Arnout van Meer",                              /* author's name */
+       "2002 Arnout van Meer",                 /* module copyright */
+       {
+               "mdc", NULL, NULL, NULL         /* default extensions to use */
+       },
+       _mdc_canload,                                   /* validation routine */
+       _mdc_load,                                              /* load routine */
+        NULL,                                                  /* save validation routine */
+        NULL                                                   /* save routine */
+};