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