]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/pm_md2.c
initial
[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                    skinname[ MD2_MAX_SKINNAME ];
341         md2_t                   *md2;
342         md2St_t                 *texCoord;
343         md2Frame_t              *frame;
344         md2Triangle_t   *triangle;
345         md2XyzNormal_t  *vertex;
346
347         picoByte_t      *bb;
348         picoModel_t             *picoModel;
349         picoSurface_t   *picoSurface;
350         picoShader_t    *picoShader;
351         picoVec3_t              xyz, normal;
352         picoVec2_t              st;
353         picoColor_t             color;
354         
355
356         /* set as md2 */
357         bb = (picoByte_t*) buffer;
358         md2     = (md2_t*) buffer;
359
360         /* check ident and version */
361         if( *((int*) md2->magic) != *((int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
362         {
363                 /* not an md2 file (todo: set error) */
364                 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
365                 return NULL;
366         }
367         
368         // swap md2
369         md2->version = _pico_little_long( md2->version );
370
371         md2->skinWidth = _pico_little_long( md2->skinWidth );
372         md2->skinHeight = _pico_little_long( md2->skinHeight );
373         md2->frameSize = _pico_little_long( md2->frameSize );
374
375         md2->numSkins = _pico_little_long( md2->numSkins );
376         md2->numXYZ = _pico_little_long( md2->numXYZ );
377         md2->numST = _pico_little_long( md2->numST );
378         md2->numTris = _pico_little_long( md2->numTris );
379         md2->numGLCmds = _pico_little_long( md2->numGLCmds );
380         md2->numFrames = _pico_little_long( md2->numFrames );
381
382         md2->ofsSkins = _pico_little_long( md2->ofsSkins );
383         md2->ofsST = _pico_little_long( md2->ofsST );
384         md2->ofsTris = _pico_little_long( md2->ofsTris );
385         md2->ofsFrames = _pico_little_long( md2->ofsFrames );
386         md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
387         md2->ofsEnd = _pico_little_long( md2->ofsEnd );
388
389         // do frame check
390         if( md2->numFrames < 1 )
391         {
392                 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
393                 return NULL;
394         }
395         
396         if( frameNum < 0 || frameNum >= md2->numFrames )
397         {
398                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
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, (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                 return NULL;
447         }
448
449         /* do model setup */
450         PicoSetModelFrameNum( picoModel, frameNum );
451         PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
452         PicoSetModelName( picoModel, fileName );
453         PicoSetModelFileName( picoModel, fileName );
454
455         // allocate new pico surface
456         picoSurface = PicoNewSurface( picoModel );
457         if( picoSurface == NULL )
458         {
459                 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
460                 PicoFreeModel( picoModel );
461                 return NULL;
462         }
463
464
465         PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
466         PicoSetSurfaceName( picoSurface, frame->name );
467         picoShader = PicoNewShader( picoModel );
468         if( picoShader == NULL )
469         {
470                 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
471                 PicoFreeModel( picoModel );
472                 return NULL;
473         }
474
475         PicoSetShaderName( picoShader, skinname );
476
477         // associate current surface with newly created shader
478         PicoSetSurfaceShader( picoSurface, picoShader );
479
480         // Init LUT for Verts
481         p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
482         for(i=0; i<md2->numXYZ; i++)
483         {
484                 p_index_LUT[i].Vert = -1;
485                 p_index_LUT[i].ST = -1;
486                 p_index_LUT[i].next = NULL;
487         }
488
489         // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
490         tot_numVerts = md2->numXYZ;
491         dups = 0;
492         for(i=0; i<md2->numTris; i++)
493         {
494                 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
495                 for(j=0; j<3; j++)
496                 {
497                         if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
498                                 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
499
500                         else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
501                                 continue;
502
503                         else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
504                         {       // Add first entry of LL from Main
505                                 p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
506                                 if (p_index_LUT2 == NULL)
507                                         _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
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                                 {
527                                         p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
528                                         continue;
529                                 }
530
531                                 if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
532                                 {
533                                         // Add the Entry
534                                         p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
535                                         if (p_index_LUT3 == NULL)
536                                                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
537                                         p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
538                                         p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
539                                         p_index_LUT3->ST = p_md2Triangle->index_st[j];
540                                         p_index_LUT3->next = NULL;
541                                         p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
542                                         dups++;
543                                 }
544                         }
545                 }
546         }
547
548         // malloc and build array for Dup STs
549         p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
550         if (p_index_LUT_DUPS == NULL)
551                 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
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         {
599                 for(i=0; i<dups; i++)
600                 {
601                         j = p_index_LUT_DUPS[i].OldVert;
602                         /* set vertex origin */
603                         xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
604                         xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
605                         xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
606                         PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
607
608                         /* set normal */
609                         normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
610                         normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
611                         normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
612                         PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
613
614                         /* set st coords */
615                         st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
616                         st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
617                         PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
618                 }
619         }
620
621         /* set color */
622         PicoSetSurfaceColor( picoSurface, 0, 0, color );
623
624         // Free up malloc'ed LL entries
625         for(i=0; i<md2->numXYZ; i++)
626         {
627                 if(p_index_LUT[i].next != NULL)
628                 {
629                         p_index_LUT2 = p_index_LUT[i].next;
630                         do {
631                                 p_index_LUT3 = p_index_LUT2->next;
632                                 _pico_free(p_index_LUT2);
633                                 p_index_LUT2 = p_index_LUT3;
634                                 dups--;
635                         } while (p_index_LUT2 != NULL);
636                 }
637         }
638
639         if (dups)
640                 _pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
641
642         // Free malloc'ed LUTs
643         _pico_free(p_index_LUT);
644         _pico_free(p_index_LUT_DUPS);
645
646         /* return the new pico model */
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 };