]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/pm_md2.c
Merge commit '48410b113dd2036e69dbf723a39ec9af02fc9b12'
[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         const md2_t     *md2;
304
305         /* sanity check */
306         if( (size_t) bufSize < ( sizeof( *md2 ) * 2) )
307                 return PICO_PMV_ERROR_SIZE;
308         
309         /* set as md2 */
310         md2 = (const md2_t*) buffer;
311         
312         /* check md2 magic */
313         if( *((const int*) md2->magic) != *((const int*) MD2_MAGIC) ) 
314                 return PICO_PMV_ERROR_IDENT;
315         
316         /* check md2 version */
317         if( _pico_little_long( md2->version ) != MD2_VERSION )
318                 return PICO_PMV_ERROR_VERSION;
319
320         /* file seems to be a valid md2 */
321         return PICO_PMV_OK;
322 }
323
324
325
326 // _md2_load() loads a quake2 md2 model file.
327
328
329 static picoModel_t *_md2_load( PM_PARAMS_LOAD )
330 {
331         int                             i, j, dups, dup_index;
332         index_LUT_t             *p_index_LUT, *p_index_LUT2, *p_index_LUT3;
333         index_DUP_LUT_t *p_index_LUT_DUPS;
334         md2Triangle_t   *p_md2Triangle;
335
336         char                    skinname[ MD2_MAX_SKINNAME ];
337         md2_t                   *md2;
338         md2St_t                 *texCoord;
339         md2Frame_t              *frame;
340         md2Triangle_t   *triangle;
341         md2XyzNormal_t  *vertex;
342
343         picoByte_t      *bb, *bb0;
344         picoModel_t             *picoModel;
345         picoSurface_t   *picoSurface;
346         picoShader_t    *picoShader;
347         picoVec3_t              xyz, normal;
348         picoVec2_t              st;
349         picoColor_t             color;
350         
351
352         /* set as md2 */
353         bb0 = bb = (picoByte_t*) _pico_alloc(bufSize);
354         memcpy(bb, buffer, bufSize);
355         md2     = (md2_t*) bb;
356
357         /* check ident and version */
358         if( *((const int*) md2->magic) != *((const int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
359         {
360                 /* not an md2 file (todo: set error) */
361                 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
362                 _pico_free(bb0);
363                 return NULL;
364         }
365         
366         // swap md2
367         md2->version = _pico_little_long( md2->version );
368
369         md2->skinWidth = _pico_little_long( md2->skinWidth );
370         md2->skinHeight = _pico_little_long( md2->skinHeight );
371         md2->frameSize = _pico_little_long( md2->frameSize );
372
373         md2->numSkins = _pico_little_long( md2->numSkins );
374         md2->numXYZ = _pico_little_long( md2->numXYZ );
375         md2->numST = _pico_little_long( md2->numST );
376         md2->numTris = _pico_little_long( md2->numTris );
377         md2->numGLCmds = _pico_little_long( md2->numGLCmds );
378         md2->numFrames = _pico_little_long( md2->numFrames );
379
380         md2->ofsSkins = _pico_little_long( md2->ofsSkins );
381         md2->ofsST = _pico_little_long( md2->ofsST );
382         md2->ofsTris = _pico_little_long( md2->ofsTris );
383         md2->ofsFrames = _pico_little_long( md2->ofsFrames );
384         md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
385         md2->ofsEnd = _pico_little_long( md2->ofsEnd );
386
387         // do frame check
388         if( md2->numFrames < 1 )
389         {
390                 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
391                 _pico_free(bb0);
392                 return NULL;
393         }
394         
395         if( frameNum < 0 || frameNum >= md2->numFrames )
396         {
397                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
398                 _pico_free(bb0);
399                 return NULL;
400         }
401
402         // Setup Frame
403         frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
404
405         // swap frame scale and translation
406         for( i = 0; i < 3; i++ )
407         {
408                 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
409                 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
410         }
411
412         // swap triangles
413         triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
414         for( i = 0; i < md2->numTris; i++, triangle++ )
415         {
416                 for( j = 0; j < 3; j++ )
417                 {
418                         triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
419                         triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
420                 }
421         }
422
423         // swap st coords
424         texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
425         for( i = 0; i < md2->numST; i++, texCoord++ )
426         {
427                 texCoord->s = _pico_little_short( texCoord->s );
428                 texCoord->t = _pico_little_short( texCoord->t );
429         }
430
431         // set Skin Name
432         strncpy(skinname, (const char *) (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
433
434         // Print out md2 values
435         _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 );
436
437         // detox Skin name
438         _pico_setfext( skinname, "" );
439         _pico_unixify( skinname );
440
441         /* create new pico model */
442         picoModel = PicoNewModel();
443         if( picoModel == NULL )
444         {
445                 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
446                 _pico_free(bb0);
447                 return NULL;
448         }
449
450         /* do model setup */
451         PicoSetModelFrameNum( picoModel, frameNum );
452         PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
453         PicoSetModelName( picoModel, fileName );
454         PicoSetModelFileName( picoModel, fileName );
455
456         // allocate new pico surface
457         picoSurface = PicoNewSurface( picoModel );
458         if( picoSurface == NULL )
459         {
460                 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
461                 PicoFreeModel( picoModel );
462                 _pico_free(bb0);
463                 return NULL;
464         }
465
466
467         PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
468         PicoSetSurfaceName( picoSurface, frame->name );
469         picoShader = PicoNewShader( picoModel );
470         if( picoShader == NULL )
471         {
472                 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
473                 PicoFreeModel( picoModel );
474                 _pico_free(bb0);
475                 return NULL;
476         }
477
478         PicoSetShaderName( picoShader, skinname );
479
480         // associate current surface with newly created shader
481         PicoSetSurfaceShader( picoSurface, picoShader );
482
483         // Init LUT for Verts
484         p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
485         for(i=0; i<md2->numXYZ; i++)
486         {
487                 p_index_LUT[i].Vert = -1;
488                 p_index_LUT[i].ST = -1;
489                 p_index_LUT[i].next = NULL;
490         }
491
492         // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
493         dups = 0;
494         for(i=0; i<md2->numTris; i++)
495         {
496                 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
497                 for(j=0; j<3; j++)
498                 {
499                         if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
500                                 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
501
502                         else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
503                                 continue;
504
505                         else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
506                         {       // Add first entry of LL from Main
507                                 p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
508                                 if (p_index_LUT2 == NULL)
509                                         _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
510                                 p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
511                                 p_index_LUT2->Vert = dups;
512                                 p_index_LUT2->ST = p_md2Triangle->index_st[j];
513                                 p_index_LUT2->next = NULL;
514                                 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
515                                 dups++;
516                         }
517                         else // Try to find in LL from Main Entry
518                         {
519                                 p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
520                                 while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
521                                 {
522                                         p_index_LUT3 = p_index_LUT2;
523                                         p_index_LUT2 = p_index_LUT2->next;
524                                 }
525                                 p_index_LUT2 = p_index_LUT3;
526
527                                 if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
528                                 {
529                                         p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
530                                         continue;
531                                 }
532
533                                 if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
534                                 {
535                                         // Add the Entry
536                                         p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
537                                         if (p_index_LUT3 == NULL)
538                                                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
539                                         p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
540                                         p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
541                                         p_index_LUT3->ST = p_md2Triangle->index_st[j];
542                                         p_index_LUT3->next = NULL;
543                                         p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
544                                         dups++;
545                                 }
546                         }
547                 }
548         }
549
550         // malloc and build array for Dup STs
551         p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
552         if (p_index_LUT_DUPS == NULL)
553                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
554
555         dup_index = 0;
556         for(i=0; i<md2->numXYZ; i++)
557         {
558                 p_index_LUT2 = p_index_LUT[i].next;
559                 while (p_index_LUT2 != NULL)
560                 {
561                         p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
562                         p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
563                         dup_index++;
564                         p_index_LUT2 = p_index_LUT2->next;
565                 }
566         }
567
568         // Build Picomodel
569         triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
570         texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
571         vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
572         for( j = 0; j < md2->numTris; j++, triangle++ )
573         {
574                 PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
575                 PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
576                 PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
577         }
578
579         for(i=0; i< md2->numXYZ; i++, vertex++)
580         {
581                 /* set vertex origin */
582                 xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
583                 xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
584                 xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
585                 PicoSetSurfaceXYZ( picoSurface, i , xyz );
586
587                 /* set normal */
588                 normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
589                 normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
590                 normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
591                 PicoSetSurfaceNormal( picoSurface, i , normal );
592
593                 /* set st coords */
594                 st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
595                 st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
596                 PicoSetSurfaceST( picoSurface, 0, i , st );
597         }
598
599         if (dups)
600         {
601                 for(i=0; i<dups; i++)
602                 {
603                         j = p_index_LUT_DUPS[i].OldVert;
604                         /* set vertex origin */
605                         xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
606                         xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
607                         xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
608                         PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
609
610                         /* set normal */
611                         normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
612                         normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
613                         normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
614                         PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
615
616                         /* set st coords */
617                         st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
618                         st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
619                         PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
620                 }
621         }
622
623         /* set color */
624         PicoSetSurfaceColor( picoSurface, 0, 0, color );
625
626         // Free up malloc'ed LL entries
627         for(i=0; i<md2->numXYZ; i++)
628         {
629                 if(p_index_LUT[i].next != NULL)
630                 {
631                         p_index_LUT2 = p_index_LUT[i].next;
632                         do {
633                                 p_index_LUT3 = p_index_LUT2->next;
634                                 _pico_free(p_index_LUT2);
635                                 p_index_LUT2 = p_index_LUT3;
636                                 dups--;
637                         } while (p_index_LUT2 != NULL);
638                 }
639         }
640
641         if (dups)
642                 _pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
643
644         // Free malloc'ed LUTs
645         _pico_free(p_index_LUT);
646         _pico_free(p_index_LUT_DUPS);
647
648         /* return the new pico model */
649         _pico_free(bb0);
650         return picoModel;
651
652 }
653
654
655
656 /* pico file format module definition */
657 const picoModule_t picoModuleMD2 =
658 {
659         "0.875",                                                /* module version string */
660         "Quake 2 MD2",                                  /* module display name */
661         "Nurail",                                               /* author's name */
662         "2003 Nurail",                                  /* module copyright */
663         {
664                 "md2", NULL, NULL, NULL         /* default extensions to use */
665         },
666         _md2_canload,                                   /* validation routine */
667         _md2_load,                                              /* load routine */
668          NULL,                                                  /* save validation routine */
669          NULL                                                   /* save routine */
670 };