]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/pm_md2.c
merge branch work back into trunk
[xonotic/netradiant.git] / libs / picomodel / pm_md2.c
1 /* -----------------------------------------------------------------------------
2
3 PicoModel Library 
4
5 Copyright (c) 2002, Randy Reddig & seaw0lf
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
13
14 Redistributions in binary form must reproduce the above copyright notice, this
15 list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
17
18 Neither the names of the copyright holders nor the names of its contributors may
19 be used to endorse or promote products derived from this software without
20 specific prior written permission. 
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 ----------------------------------------------------------------------------- */
34
35 /*
36 Nurail: Used pm_md3.c (Randy Reddig) as a template.
37 */
38
39
40 /* marker */
41 #define PM_MD2_C
42
43 /* dependencies */
44 #include "picointernal.h"
45
46
47 /* md2 model format */
48 #define MD2_MAGIC                               "IDP2"
49 #define MD2_VERSION                             8
50
51 #define MD2_NUMVERTEXNORMALS    162
52 #define MD2_MAX_SKINNAME                64
53 #define MD2_MAX_TRIANGLES               4096
54 #define MD2_MAX_VERTS                   2048
55 #define MD2_MAX_FRAMES                  512
56 #define MD2_MAX_MD2SKINS                32
57 #define MD2_MAX_SKINNAME                64
58
59 #ifndef byte
60         #define byte unsigned char
61 #endif
62
63 typedef struct index_LUT_s
64 {
65         short   Vert;
66         short   ST;
67         struct  index_LUT_s     *next;
68
69 } index_LUT_t;
70
71 typedef struct index_DUP_LUT_s
72 {
73         short                   ST;
74         short                   OldVert;
75
76 } index_DUP_LUT_t;
77
78 typedef struct
79 {
80         short   s;
81         short   t;
82 } md2St_t;
83
84 typedef struct
85 {
86         short   index_xyz[3];
87         short   index_st[3];
88 } md2Triangle_t;
89
90 typedef struct
91 {
92         byte    v[3];                   // scaled byte to fit in frame mins/maxs
93         byte    lightnormalindex;
94 } md2XyzNormal_t;
95
96 typedef struct md2Frame_s
97 {
98         float           scale[3];       // multiply byte verts by this
99         float           translate[3];   // then add this
100         char            name[16];       // frame name from grabbing
101         md2XyzNormal_t  verts[1];       // variable sized
102 }
103 md2Frame_t;
104
105
106 /* md2 model file md2 structure */
107 typedef struct md2_s
108 {
109         char    magic[ 4 ];
110         int     version;
111
112         int     skinWidth;
113         int     skinHeight;
114         int     frameSize;
115
116         int     numSkins;
117         int     numXYZ;
118         int     numST;
119         int     numTris;
120         int     numGLCmds;
121         int     numFrames;
122
123         int     ofsSkins;
124         int     ofsST;
125         int     ofsTris;
126         int     ofsFrames;
127         int     ofsGLCmds;
128         int     ofsEnd;
129 }
130 md2_t;
131
132 float   md2_normals[ MD2_NUMVERTEXNORMALS ][ 3 ] =
133 {
134         { -0.525731f, 0.000000f, 0.850651f },
135         { -0.442863f, 0.238856f, 0.864188f }, 
136         { -0.295242f, 0.000000f, 0.955423f }, 
137         { -0.309017f, 0.500000f, 0.809017f }, 
138         { -0.162460f, 0.262866f, 0.951056f }, 
139         { 0.000000f, 0.000000f, 1.000000f },
140         { 0.000000f, 0.850651f, 0.525731f },
141         { -0.147621f, 0.716567f, 0.681718f },
142         { 0.147621f, 0.716567f, 0.681718f }, 
143         { 0.000000f, 0.525731f, 0.850651f }, 
144         { 0.309017f, 0.500000f, 0.809017f }, 
145         { 0.525731f, 0.000000f, 0.850651f }, 
146         { 0.295242f, 0.000000f, 0.955423f }, 
147         { 0.442863f, 0.238856f, 0.864188f }, 
148         { 0.162460f, 0.262866f, 0.951056f }, 
149         { -0.681718f, 0.147621f, 0.716567f }, 
150         { -0.809017f, 0.309017f, 0.500000f }, 
151         { -0.587785f, 0.425325f, 0.688191f }, 
152         { -0.850651f, 0.525731f, 0.000000f }, 
153         { -0.864188f, 0.442863f, 0.238856f }, 
154         { -0.716567f, 0.681718f, 0.147621f }, 
155         { -0.688191f, 0.587785f, 0.425325f }, 
156         { -0.500000f, 0.809017f, 0.309017f }, 
157         { -0.238856f, 0.864188f, 0.442863f }, 
158         { -0.425325f, 0.688191f, 0.587785f }, 
159         { -0.716567f, 0.681718f, -0.147621f }, 
160         { -0.500000f, 0.809017f, -0.309017f }, 
161         { -0.525731f, 0.850651f, 0.000000f }, 
162         { 0.000000f, 0.850651f, -0.525731f }, 
163         { -0.238856f, 0.864188f, -0.442863f }, 
164         { 0.000000f, 0.955423f, -0.295242f }, 
165         { -0.262866f, 0.951056f, -0.162460f }, 
166         { 0.000000f, 1.000000f, 0.000000f }, 
167         { 0.000000f, 0.955423f, 0.295242f }, 
168         { -0.262866f, 0.951056f, 0.162460f }, 
169         { 0.238856f, 0.864188f, 0.442863f }, 
170         { 0.262866f, 0.951056f, 0.162460f }, 
171         { 0.500000f, 0.809017f, 0.309017f }, 
172         { 0.238856f, 0.864188f, -0.442863f }, 
173         { 0.262866f, 0.951056f, -0.162460f }, 
174         { 0.500000f, 0.809017f, -0.309017f }, 
175         { 0.850651f, 0.525731f, 0.000000f }, 
176         { 0.716567f, 0.681718f, 0.147621f }, 
177         { 0.716567f, 0.681718f, -0.147621f }, 
178         { 0.525731f, 0.850651f, 0.000000f }, 
179         { 0.425325f, 0.688191f, 0.587785f }, 
180         { 0.864188f, 0.442863f, 0.238856f }, 
181         { 0.688191f, 0.587785f, 0.425325f }, 
182         { 0.809017f, 0.309017f, 0.500000f }, 
183         { 0.681718f, 0.147621f, 0.716567f }, 
184         { 0.587785f, 0.425325f, 0.688191f }, 
185         { 0.955423f, 0.295242f, 0.000000f }, 
186         { 1.000000f, 0.000000f, 0.000000f }, 
187         { 0.951056f, 0.162460f, 0.262866f }, 
188         { 0.850651f, -0.525731f, 0.000000f }, 
189         { 0.955423f, -0.295242f, 0.000000f }, 
190         { 0.864188f, -0.442863f, 0.238856f }, 
191         { 0.951056f, -0.162460f, 0.262866f }, 
192         { 0.809017f, -0.309017f, 0.500000f }, 
193         { 0.681718f, -0.147621f, 0.716567f }, 
194         { 0.850651f, 0.000000f, 0.525731f }, 
195         { 0.864188f, 0.442863f, -0.238856f }, 
196         { 0.809017f, 0.309017f, -0.500000f }, 
197         { 0.951056f, 0.162460f, -0.262866f }, 
198         { 0.525731f, 0.000000f, -0.850651f }, 
199         { 0.681718f, 0.147621f, -0.716567f }, 
200         { 0.681718f, -0.147621f, -0.716567f }, 
201         { 0.850651f, 0.000000f, -0.525731f }, 
202         { 0.809017f, -0.309017f, -0.500000f }, 
203         { 0.864188f, -0.442863f, -0.238856f }, 
204         { 0.951056f, -0.162460f, -0.262866f }, 
205         { 0.147621f, 0.716567f, -0.681718f }, 
206         { 0.309017f, 0.500000f, -0.809017f }, 
207         { 0.425325f, 0.688191f, -0.587785f }, 
208         { 0.442863f, 0.238856f, -0.864188f }, 
209         { 0.587785f, 0.425325f, -0.688191f }, 
210         { 0.688191f, 0.587785f, -0.425325f }, 
211         { -0.147621f, 0.716567f, -0.681718f }, 
212         { -0.309017f, 0.500000f, -0.809017f }, 
213         { 0.000000f, 0.525731f, -0.850651f }, 
214         { -0.525731f, 0.000000f, -0.850651f }, 
215         { -0.442863f, 0.238856f, -0.864188f }, 
216         { -0.295242f, 0.000000f, -0.955423f }, 
217         { -0.162460f, 0.262866f, -0.951056f }, 
218         { 0.000000f, 0.000000f, -1.000000f }, 
219         { 0.295242f, 0.000000f, -0.955423f }, 
220         { 0.162460f, 0.262866f, -0.951056f }, 
221         { -0.442863f, -0.238856f, -0.864188f }, 
222         { -0.309017f, -0.500000f, -0.809017f }, 
223         { -0.162460f, -0.262866f, -0.951056f }, 
224         { 0.000000f, -0.850651f, -0.525731f }, 
225         { -0.147621f, -0.716567f, -0.681718f }, 
226         { 0.147621f, -0.716567f, -0.681718f }, 
227         { 0.000000f, -0.525731f, -0.850651f }, 
228         { 0.309017f, -0.500000f, -0.809017f }, 
229         { 0.442863f, -0.238856f, -0.864188f }, 
230         { 0.162460f, -0.262866f, -0.951056f }, 
231         { 0.238856f, -0.864188f, -0.442863f }, 
232         { 0.500000f, -0.809017f, -0.309017f }, 
233         { 0.425325f, -0.688191f, -0.587785f }, 
234         { 0.716567f, -0.681718f, -0.147621f }, 
235         { 0.688191f, -0.587785f, -0.425325f }, 
236         { 0.587785f, -0.425325f, -0.688191f }, 
237         { 0.000000f, -0.955423f, -0.295242f }, 
238         { 0.000000f, -1.000000f, 0.000000f }, 
239         { 0.262866f, -0.951056f, -0.162460f }, 
240         { 0.000000f, -0.850651f, 0.525731f }, 
241         { 0.000000f, -0.955423f, 0.295242f }, 
242         { 0.238856f, -0.864188f, 0.442863f }, 
243         { 0.262866f, -0.951056f, 0.162460f }, 
244         { 0.500000f, -0.809017f, 0.309017f }, 
245         { 0.716567f, -0.681718f, 0.147621f }, 
246         { 0.525731f, -0.850651f, 0.000000f }, 
247         { -0.238856f, -0.864188f, -0.442863f }, 
248         { -0.500000f, -0.809017f, -0.309017f }, 
249         { -0.262866f, -0.951056f, -0.162460f }, 
250         { -0.850651f, -0.525731f, 0.000000f }, 
251         { -0.716567f, -0.681718f, -0.147621f }, 
252         { -0.716567f, -0.681718f, 0.147621f }, 
253         { -0.525731f, -0.850651f, 0.000000f }, 
254         { -0.500000f, -0.809017f, 0.309017f }, 
255         { -0.238856f, -0.864188f, 0.442863f }, 
256         { -0.262866f, -0.951056f, 0.162460f }, 
257         { -0.864188f, -0.442863f, 0.238856f }, 
258         { -0.809017f, -0.309017f, 0.500000f }, 
259         { -0.688191f, -0.587785f, 0.425325f }, 
260         { -0.681718f, -0.147621f, 0.716567f }, 
261         { -0.442863f, -0.238856f, 0.864188f }, 
262         { -0.587785f, -0.425325f, 0.688191f }, 
263         { -0.309017f, -0.500000f, 0.809017f }, 
264         { -0.147621f, -0.716567f, 0.681718f }, 
265         { -0.425325f, -0.688191f, 0.587785f }, 
266         { -0.162460f, -0.262866f, 0.951056f }, 
267         { 0.442863f, -0.238856f, 0.864188f }, 
268         { 0.162460f, -0.262866f, 0.951056f }, 
269         { 0.309017f, -0.500000f, 0.809017f }, 
270         { 0.147621f, -0.716567f, 0.681718f }, 
271         { 0.000000f, -0.525731f, 0.850651f }, 
272         { 0.425325f, -0.688191f, 0.587785f }, 
273         { 0.587785f, -0.425325f, 0.688191f }, 
274         { 0.688191f, -0.587785f, 0.425325f }, 
275         { -0.955423f, 0.295242f, 0.000000f }, 
276         { -0.951056f, 0.162460f, 0.262866f }, 
277         { -1.000000f, 0.000000f, 0.000000f }, 
278         { -0.850651f, 0.000000f, 0.525731f }, 
279         { -0.955423f, -0.295242f, 0.000000f }, 
280         { -0.951056f, -0.162460f, 0.262866f }, 
281         { -0.864188f, 0.442863f, -0.238856f }, 
282         { -0.951056f, 0.162460f, -0.262866f }, 
283         { -0.809017f, 0.309017f, -0.500000f }, 
284         { -0.864188f, -0.442863f, -0.238856f },
285         { -0.951056f, -0.162460f, -0.262866f }, 
286         { -0.809017f, -0.309017f, -0.500000f }, 
287         { -0.681718f, 0.147621f, -0.716567f }, 
288         { -0.681718f, -0.147621f, -0.716567f }, 
289         { -0.850651f, 0.000000f, -0.525731f }, 
290         { -0.688191f, 0.587785f, -0.425325f }, 
291         { -0.587785f, 0.425325f, -0.688191f }, 
292         { -0.425325f, 0.688191f, -0.587785f }, 
293         { -0.425325f, -0.688191f, -0.587785f }, 
294         { -0.587785f, -0.425325f, -0.688191f }, 
295         { -0.688191f, -0.587785f, -0.425325f }, 
296 };
297
298
299 // _md2_canload()
300
301 static int _md2_canload( PM_PARAMS_CANLOAD )
302 {
303         md2_t   *md2;
304
305         /* to keep the compiler happy */
306         *fileName = *fileName;
307
308         /* sanity check */
309         if( bufSize < ( sizeof( *md2 ) * 2) )
310                 return PICO_PMV_ERROR_SIZE;
311         
312         /* set as md2 */
313         md2 = (md2_t*) buffer;
314         
315         /* check md2 magic */
316         if( *((int*) md2->magic) != *((int*) MD2_MAGIC) ) 
317                 return PICO_PMV_ERROR_IDENT;
318         
319         /* check md2 version */
320         if( _pico_little_long( md2->version ) != MD2_VERSION )
321                 return PICO_PMV_ERROR_VERSION;
322
323         /* file seems to be a valid md2 */
324         return PICO_PMV_OK;
325 }
326
327
328
329 // _md2_load() loads a quake2 md2 model file.
330
331
332 static picoModel_t *_md2_load( PM_PARAMS_LOAD )
333 {
334         int                             i, j, dups, dup_index;
335         short                   tot_numVerts;
336         index_LUT_t             *p_index_LUT, *p_index_LUT2, *p_index_LUT3;
337         index_DUP_LUT_t *p_index_LUT_DUPS;
338         md2Triangle_t   *p_md2Triangle;
339
340         char                    path[ MD2_MAX_SKINNAME ];
341         char                    skinname[ MD2_MAX_SKINNAME ];
342         md2_t                   *md2;
343         md2St_t                 *texCoord;
344         md2Frame_t              *frame;
345         md2Triangle_t   *triangle;
346         md2XyzNormal_t  *vertex;
347
348         picoByte_t      *bb;
349         picoModel_t             *picoModel;
350         picoSurface_t   *picoSurface;
351         picoShader_t    *picoShader;
352         picoVec3_t              xyz, normal;
353         picoVec2_t              st;
354         picoColor_t             color;
355         
356
357         // md2 loading
358         _pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
359
360         /* set as md2 */
361         bb = (picoByte_t*) buffer;
362         md2     = (md2_t*) buffer;
363
364         /* check ident and version */
365         if( *((int*) md2->magic) != *((int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
366         {
367                 /* not an md2 file (todo: set error) */
368                 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
369                 return NULL;
370         }
371         
372         // swap md2
373         md2->version = _pico_little_long( md2->version );
374
375         md2->skinWidth = _pico_little_long( md2->skinWidth );
376         md2->skinHeight = _pico_little_long( md2->skinHeight );
377         md2->frameSize = _pico_little_long( md2->frameSize );
378
379         md2->numSkins = _pico_little_long( md2->numSkins );
380         md2->numXYZ = _pico_little_long( md2->numXYZ );
381         md2->numST = _pico_little_long( md2->numST );
382         md2->numTris = _pico_little_long( md2->numTris );
383         md2->numGLCmds = _pico_little_long( md2->numGLCmds );
384         md2->numFrames = _pico_little_long( md2->numFrames );
385
386         md2->ofsSkins = _pico_little_long( md2->ofsSkins );
387         md2->ofsST = _pico_little_long( md2->ofsST );
388         md2->ofsTris = _pico_little_long( md2->ofsTris );
389         md2->ofsFrames = _pico_little_long( md2->ofsFrames );
390         md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
391         md2->ofsEnd = _pico_little_long( md2->ofsEnd );
392
393         // do frame check
394         if( md2->numFrames < 1 )
395         {
396                 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
397                 return NULL;
398         }
399         
400         if( frameNum < 0 || frameNum >= md2->numFrames )
401         {
402                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
403                 return NULL;
404         }
405
406         // Setup Frame
407         frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
408
409         // swap frame scale and translation
410         for( i = 0; i < 3; i++ )
411         {
412                 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
413                 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
414         }
415
416         // swap triangles
417         triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
418         for( i = 0; i < md2->numTris; i++, triangle++ )
419         {
420                 for( j = 0; j < 3; j++ )
421                 {
422                         triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
423                         triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
424                 }
425         }
426
427         // swap st coords
428         texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
429         for( i = 0; i < md2->numST; i++, texCoord++ )
430         {
431                 texCoord->s = _pico_little_short( texCoord->s );
432                 texCoord->t = _pico_little_short( texCoord->t );
433         }
434
435         // set Skin Name
436         strncpy(skinname, (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
437
438         // Print out md2 values
439         _pico_printf(PICO_VERBOSE,"Skins: %d  Verts: %d  STs: %d  Triangles: %d  Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, skinname );
440
441         // relative texture path - allows moving of models in game dir structure without changing the skinpath
442         // e.g. used in ufo:ai
443         if (skinname[0] == '.') {
444                 strncpy(path, fileName, MD2_MAX_SKINNAME);
445                 for (i = MD2_MAX_SKINNAME; i--;) {
446                         // skip filename
447                         if (path[i] == '/' || path[i] == '\\')
448                                 break;
449                         path[i] = '\0';
450                 }
451                 strncat(path, &skinname[1], MD2_MAX_SKINNAME);
452                 strncpy(skinname, path, MD2_MAX_SKINNAME);
453
454                 // Print out md2 values
455                 _pico_printf(PICO_VERBOSE,"Relative skin path converted to: \"%s\" (%s)\n", skinname, fileName );
456         }
457         
458         // detox Skin name
459         _pico_setfext( skinname, "" );
460         _pico_unixify( skinname );
461
462         /* create new pico model */
463         picoModel = PicoNewModel();
464         if( picoModel == NULL )
465         {
466                 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
467                 return NULL;
468         }
469
470         /* do model setup */
471         PicoSetModelFrameNum( picoModel, frameNum );
472         PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
473         PicoSetModelName( picoModel, fileName );
474         PicoSetModelFileName( picoModel, fileName );
475
476         // allocate new pico surface
477         picoSurface = PicoNewSurface( picoModel );
478         if( picoSurface == NULL )
479         {
480                 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
481                 PicoFreeModel( picoModel );
482                 return NULL;
483         }
484
485
486         PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
487         PicoSetSurfaceName( picoSurface, frame->name );
488         picoShader = PicoNewShader( picoModel );
489         if( picoShader == NULL )
490         {
491                 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
492                 PicoFreeModel( picoModel );
493                 return NULL;
494         }
495
496         PicoSetShaderName( picoShader, skinname );
497
498         // associate current surface with newly created shader
499         PicoSetSurfaceShader( picoSurface, picoShader );
500
501         // Init LUT for Verts
502         p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
503         for(i=0; i<md2->numXYZ; i++)
504         {
505                 p_index_LUT[i].Vert = -1;
506                 p_index_LUT[i].ST = -1;
507                 p_index_LUT[i].next = NULL;
508         }
509
510         // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
511         tot_numVerts = md2->numXYZ;
512         dups = 0;
513         for(i=0; i<md2->numTris; i++)
514         {
515                 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
516                 for(j=0; j<3; j++)
517                 {
518                         if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
519                                 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
520
521                         else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
522                                 continue;
523
524                         else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
525                         {       // Add first entry of LL from Main
526                                 p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
527                                 if (p_index_LUT2 == NULL)
528                                         _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
529                                 p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
530                                 p_index_LUT2->Vert = dups;
531                                 p_index_LUT2->ST = p_md2Triangle->index_st[j];
532                                 p_index_LUT2->next = NULL;
533                                 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
534                                 dups++;
535                         }
536                         else // Try to find in LL from Main Entry
537                         {
538                                 p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
539                                 while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
540                                 {
541                                         p_index_LUT3 = p_index_LUT2;
542                                         p_index_LUT2 = p_index_LUT2->next;
543                                 }
544                                 p_index_LUT2 = p_index_LUT3;
545
546                                 if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
547                                 {
548                                         p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
549                                         continue;
550                                 }
551
552                                 if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
553                                 {
554                                         // Add the Entry
555                                         p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
556                                         if (p_index_LUT3 == NULL)
557                                                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
558                                         p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
559                                         p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
560                                         p_index_LUT3->ST = p_md2Triangle->index_st[j];
561                                         p_index_LUT3->next = NULL;
562                                         p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
563                                         dups++;
564                                 }
565                         }
566                 }
567         }
568
569         // malloc and build array for Dup STs
570         p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
571         if (p_index_LUT_DUPS == NULL)
572                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
573
574         dup_index = 0;
575         for(i=0; i<md2->numXYZ; i++)
576         {
577                 p_index_LUT2 = p_index_LUT[i].next;
578                 while (p_index_LUT2 != NULL)
579                 {
580                         p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
581                         p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
582                         dup_index++;
583                         p_index_LUT2 = p_index_LUT2->next;
584                 }
585         }
586
587         // Build Picomodel
588         triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
589         texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
590         vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
591         for( j = 0; j < md2->numTris; j++, triangle++ )
592         {
593                 PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
594                 PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
595                 PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
596         }
597
598         for(i=0; i< md2->numXYZ; i++, vertex++)
599         {
600                 /* set vertex origin */
601                 xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
602                 xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
603                 xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
604                 PicoSetSurfaceXYZ( picoSurface, i , xyz );
605
606                 /* set normal */
607                 normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
608                 normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
609                 normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
610                 PicoSetSurfaceNormal( picoSurface, i , normal );
611
612                 /* set st coords */
613                 st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
614                 st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
615                 PicoSetSurfaceST( picoSurface, 0, i , st );
616         }
617
618         if (dups)
619         {
620                 for(i=0; i<dups; i++)
621                 {
622                         j = p_index_LUT_DUPS[i].OldVert;
623                         /* set vertex origin */
624                         xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
625                         xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
626                         xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
627                         PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
628
629                         /* set normal */
630                         normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
631                         normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
632                         normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
633                         PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
634
635                         /* set st coords */
636                         st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
637                         st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
638                         PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
639                 }
640         }
641
642         /* set color */
643         PicoSetSurfaceColor( picoSurface, 0, 0, color );
644
645         // Free up malloc'ed LL entries
646         for(i=0; i<md2->numXYZ; i++)
647         {
648                 if(p_index_LUT[i].next != NULL)
649                 {
650                         p_index_LUT2 = p_index_LUT[i].next;
651                         do {
652                                 p_index_LUT3 = p_index_LUT2->next;
653                                 _pico_free(p_index_LUT2);
654                                 p_index_LUT2 = p_index_LUT3;
655                                 dups--;
656                         } while (p_index_LUT2 != NULL);
657                 }
658         }
659
660         if (dups)
661                 _pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
662
663         // Free malloc'ed LUTs
664         _pico_free(p_index_LUT);
665         _pico_free(p_index_LUT_DUPS);
666
667         /* return the new pico model */
668         return picoModel;
669
670 }
671
672
673
674 /* pico file format module definition */
675 const picoModule_t picoModuleMD2 =
676 {
677         "0.875",                                                /* module version string */
678         "Quake 2 MD2",                                  /* module display name */
679         "Nurail",                                               /* author's name */
680         "2003 Nurail",                                  /* module copyright */
681         {
682                 "md2", NULL, NULL, NULL         /* default extensions to use */
683         },
684         _md2_canload,                                   /* validation routine */
685         _md2_load,                                              /* load routine */
686          NULL,                                                  /* save validation routine */
687          NULL                                                   /* save routine */
688 };