1 /* -----------------------------------------------------------------------------
5 Copyright (c) 2002, Randy Reddig & seaw0lf
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
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.
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.
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.
33 ----------------------------------------------------------------------------- */
36 Nurail: Used pm_md3.c (Randy Reddig) as a template.
44 #include "picointernal.h"
47 /* md2 model format */
48 #define MD2_MAGIC "IDP2"
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
60 #define byte unsigned char
63 typedef struct index_LUT_s
67 struct index_LUT_s *next;
71 typedef struct index_DUP_LUT_s
92 byte v[3]; // scaled byte to fit in frame mins/maxs
93 byte lightnormalindex;
96 typedef struct md2Frame_s
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
106 /* md2 model file md2 structure */
132 float md2_normals[ MD2_NUMVERTEXNORMALS ][ 3 ] =
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 },
301 static int _md2_canload( PM_PARAMS_CANLOAD )
306 if( (size_t) bufSize < ( sizeof( *md2 ) * 2) )
307 return PICO_PMV_ERROR_SIZE;
310 md2 = (const md2_t*) buffer;
312 /* check md2 magic */
313 if( *((const int*) md2->magic) != *((const int*) MD2_MAGIC) )
314 return PICO_PMV_ERROR_IDENT;
316 /* check md2 version */
317 if( _pico_little_long( md2->version ) != MD2_VERSION )
318 return PICO_PMV_ERROR_VERSION;
320 /* file seems to be a valid md2 */
326 // _md2_load() loads a quake2 md2 model file.
329 static picoModel_t *_md2_load( PM_PARAMS_LOAD )
331 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;
337 char skinname[ MD2_MAX_SKINNAME ];
341 md2Triangle_t *triangle;
342 md2XyzNormal_t *vertex;
344 picoByte_t *bb, *bb0;
345 picoModel_t *picoModel;
346 picoSurface_t *picoSurface;
347 picoShader_t *picoShader;
348 picoVec3_t xyz, normal;
354 bb0 = bb = (picoByte_t*) _pico_alloc(bufSize);
355 memcpy(bb, buffer, bufSize);
358 /* check ident and version */
359 if( *((const int*) md2->magic) != *((const int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
361 /* not an md2 file (todo: set error) */
362 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
368 md2->version = _pico_little_long( md2->version );
370 md2->skinWidth = _pico_little_long( md2->skinWidth );
371 md2->skinHeight = _pico_little_long( md2->skinHeight );
372 md2->frameSize = _pico_little_long( md2->frameSize );
374 md2->numSkins = _pico_little_long( md2->numSkins );
375 md2->numXYZ = _pico_little_long( md2->numXYZ );
376 md2->numST = _pico_little_long( md2->numST );
377 md2->numTris = _pico_little_long( md2->numTris );
378 md2->numGLCmds = _pico_little_long( md2->numGLCmds );
379 md2->numFrames = _pico_little_long( md2->numFrames );
381 md2->ofsSkins = _pico_little_long( md2->ofsSkins );
382 md2->ofsST = _pico_little_long( md2->ofsST );
383 md2->ofsTris = _pico_little_long( md2->ofsTris );
384 md2->ofsFrames = _pico_little_long( md2->ofsFrames );
385 md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
386 md2->ofsEnd = _pico_little_long( md2->ofsEnd );
389 if( md2->numFrames < 1 )
391 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
396 if( frameNum < 0 || frameNum >= md2->numFrames )
398 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
404 frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
406 // swap frame scale and translation
407 for( i = 0; i < 3; i++ )
409 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
410 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
414 triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
415 for( i = 0; i < md2->numTris; i++, triangle++ )
417 for( j = 0; j < 3; j++ )
419 triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
420 triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
425 texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
426 for( i = 0; i < md2->numST; i++, texCoord++ )
428 texCoord->s = _pico_little_short( texCoord->s );
429 texCoord->t = _pico_little_short( texCoord->t );
433 strncpy(skinname, (const char *) (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
435 // Print out md2 values
436 _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 );
439 _pico_setfext( skinname, "" );
440 _pico_unixify( skinname );
442 /* create new pico model */
443 picoModel = PicoNewModel();
444 if( picoModel == NULL )
446 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
452 PicoSetModelFrameNum( picoModel, frameNum );
453 PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
454 PicoSetModelName( picoModel, fileName );
455 PicoSetModelFileName( picoModel, fileName );
457 // allocate new pico surface
458 picoSurface = PicoNewSurface( picoModel );
459 if( picoSurface == NULL )
461 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
462 PicoFreeModel( picoModel );
468 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
469 PicoSetSurfaceName( picoSurface, frame->name );
470 picoShader = PicoNewShader( picoModel );
471 if( picoShader == NULL )
473 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
474 PicoFreeModel( picoModel );
479 PicoSetShaderName( picoShader, skinname );
481 // associate current surface with newly created shader
482 PicoSetSurfaceShader( picoSurface, picoShader );
484 // Init LUT for Verts
485 p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
486 for(i=0; i<md2->numXYZ; i++)
488 p_index_LUT[i].Vert = -1;
489 p_index_LUT[i].ST = -1;
490 p_index_LUT[i].next = NULL;
493 // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
494 tot_numVerts = md2->numXYZ;
496 for(i=0; i<md2->numTris; i++)
498 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
501 if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
502 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
504 else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
507 else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) ) // Not equal to Main entry, and no LL entry
508 { // Add first entry of LL from Main
509 p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
510 if (p_index_LUT2 == NULL)
511 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
512 p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
513 p_index_LUT2->Vert = dups;
514 p_index_LUT2->ST = p_md2Triangle->index_st[j];
515 p_index_LUT2->next = NULL;
516 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
519 else // Try to find in LL from Main Entry
521 p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
522 while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
524 p_index_LUT3 = p_index_LUT2;
525 p_index_LUT2 = p_index_LUT2->next;
527 p_index_LUT2 = p_index_LUT3;
529 if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
531 p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
535 if ( p_index_LUT2->next == NULL) // Didn't find it. Add entry to LL.
538 p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
539 if (p_index_LUT3 == NULL)
540 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
541 p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
542 p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
543 p_index_LUT3->ST = p_md2Triangle->index_st[j];
544 p_index_LUT3->next = NULL;
545 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
552 // malloc and build array for Dup STs
553 p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
554 if (p_index_LUT_DUPS == NULL)
555 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
558 for(i=0; i<md2->numXYZ; i++)
560 p_index_LUT2 = p_index_LUT[i].next;
561 while (p_index_LUT2 != NULL)
563 p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
564 p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
566 p_index_LUT2 = p_index_LUT2->next;
571 triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
572 texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
573 vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
574 for( j = 0; j < md2->numTris; j++, triangle++ )
576 PicoSetSurfaceIndex( picoSurface, j*3 , triangle->index_xyz[0] );
577 PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
578 PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
581 for(i=0; i< md2->numXYZ; i++, vertex++)
583 /* set vertex origin */
584 xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
585 xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
586 xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
587 PicoSetSurfaceXYZ( picoSurface, i , xyz );
590 normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
591 normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
592 normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
593 PicoSetSurfaceNormal( picoSurface, i , normal );
596 st[ 0 ] = ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
597 st[ 1 ] = (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
598 PicoSetSurfaceST( picoSurface, 0, i , st );
603 for(i=0; i<dups; i++)
605 j = p_index_LUT_DUPS[i].OldVert;
606 /* set vertex origin */
607 xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
608 xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
609 xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
610 PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
613 normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
614 normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
615 normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
616 PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
619 st[ 0 ] = ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
620 st[ 1 ] = (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
621 PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
626 PicoSetSurfaceColor( picoSurface, 0, 0, color );
628 // Free up malloc'ed LL entries
629 for(i=0; i<md2->numXYZ; i++)
631 if(p_index_LUT[i].next != NULL)
633 p_index_LUT2 = p_index_LUT[i].next;
635 p_index_LUT3 = p_index_LUT2->next;
636 _pico_free(p_index_LUT2);
637 p_index_LUT2 = p_index_LUT3;
639 } while (p_index_LUT2 != NULL);
644 _pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
646 // Free malloc'ed LUTs
647 _pico_free(p_index_LUT);
648 _pico_free(p_index_LUT_DUPS);
650 /* return the new pico model */
658 /* pico file format module definition */
659 const picoModule_t picoModuleMD2 =
661 "0.875", /* module version string */
662 "Quake 2 MD2", /* module display name */
663 "Nurail", /* author's name */
664 "2003 Nurail", /* module copyright */
666 "md2", NULL, NULL, NULL /* default extensions to use */
668 _md2_canload, /* validation routine */
669 _md2_load, /* load routine */
670 NULL, /* save validation routine */
671 NULL /* save routine */