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