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 )
305 /* to keep the compiler happy */
306 *fileName = *fileName;
309 if( bufSize < ( sizeof( *md2 ) * 2) )
310 return PICO_PMV_ERROR_SIZE;
313 md2 = (md2_t*) buffer;
315 /* check md2 magic */
316 if( *((int*) md2->magic) != *((int*) MD2_MAGIC) )
317 return PICO_PMV_ERROR_IDENT;
319 /* check md2 version */
320 if( _pico_little_long( md2->version ) != MD2_VERSION )
321 return PICO_PMV_ERROR_VERSION;
323 /* file seems to be a valid md2 */
329 // _md2_load() loads a quake2 md2 model file.
332 static picoModel_t *_md2_load( PM_PARAMS_LOAD )
334 int i, j, dups, dup_index;
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;
340 char path[ MD2_MAX_SKINNAME ];
341 char skinname[ MD2_MAX_SKINNAME ];
345 md2Triangle_t *triangle;
346 md2XyzNormal_t *vertex;
349 picoModel_t *picoModel;
350 picoSurface_t *picoSurface;
351 picoShader_t *picoShader;
352 picoVec3_t xyz, normal;
358 _pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
361 bb = (picoByte_t*) buffer;
362 md2 = (md2_t*) buffer;
364 /* check ident and version */
365 if( *((int*) md2->magic) != *((int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
367 /* not an md2 file (todo: set error) */
368 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
373 md2->version = _pico_little_long( md2->version );
375 md2->skinWidth = _pico_little_long( md2->skinWidth );
376 md2->skinHeight = _pico_little_long( md2->skinHeight );
377 md2->frameSize = _pico_little_long( md2->frameSize );
379 md2->numSkins = _pico_little_long( md2->numSkins );
380 md2->numXYZ = _pico_little_long( md2->numXYZ );
381 md2->numST = _pico_little_long( md2->numST );
382 md2->numTris = _pico_little_long( md2->numTris );
383 md2->numGLCmds = _pico_little_long( md2->numGLCmds );
384 md2->numFrames = _pico_little_long( md2->numFrames );
386 md2->ofsSkins = _pico_little_long( md2->ofsSkins );
387 md2->ofsST = _pico_little_long( md2->ofsST );
388 md2->ofsTris = _pico_little_long( md2->ofsTris );
389 md2->ofsFrames = _pico_little_long( md2->ofsFrames );
390 md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
391 md2->ofsEnd = _pico_little_long( md2->ofsEnd );
394 if( md2->numFrames < 1 )
396 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
400 if( frameNum < 0 || frameNum >= md2->numFrames )
402 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
407 frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
409 // swap frame scale and translation
410 for( i = 0; i < 3; i++ )
412 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
413 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
417 triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
418 for( i = 0; i < md2->numTris; i++, triangle++ )
420 for( j = 0; j < 3; j++ )
422 triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
423 triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
428 texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
429 for( i = 0; i < md2->numST; i++, texCoord++ )
431 texCoord->s = _pico_little_short( texCoord->s );
432 texCoord->t = _pico_little_short( texCoord->t );
436 strncpy(skinname, (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
438 // Print out md2 values
439 _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 );
441 // relative texture path - allows moving of models in game dir structure without changing the skinpath
442 // e.g. used in ufo:ai
443 if (skinname[0] == '.') {
444 strncpy(path, fileName, MD2_MAX_SKINNAME);
445 for (i = MD2_MAX_SKINNAME; i--;) {
447 if (path[i] == '/' || path[i] == '\\')
451 strncat(path, &skinname[1], MD2_MAX_SKINNAME);
452 strncpy(skinname, path, MD2_MAX_SKINNAME);
454 // Print out md2 values
455 _pico_printf(PICO_VERBOSE,"Relative skin path converted to: \"%s\" (%s)\n", skinname, fileName );
459 _pico_setfext( skinname, "" );
460 _pico_unixify( skinname );
462 /* create new pico model */
463 picoModel = PicoNewModel();
464 if( picoModel == NULL )
466 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
471 PicoSetModelFrameNum( picoModel, frameNum );
472 PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
473 PicoSetModelName( picoModel, fileName );
474 PicoSetModelFileName( picoModel, fileName );
476 // allocate new pico surface
477 picoSurface = PicoNewSurface( picoModel );
478 if( picoSurface == NULL )
480 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
481 PicoFreeModel( picoModel );
486 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
487 PicoSetSurfaceName( picoSurface, frame->name );
488 picoShader = PicoNewShader( picoModel );
489 if( picoShader == NULL )
491 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
492 PicoFreeModel( picoModel );
496 PicoSetShaderName( picoShader, skinname );
498 // associate current surface with newly created shader
499 PicoSetSurfaceShader( picoSurface, picoShader );
501 // Init LUT for Verts
502 p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
503 for(i=0; i<md2->numXYZ; i++)
505 p_index_LUT[i].Vert = -1;
506 p_index_LUT[i].ST = -1;
507 p_index_LUT[i].next = NULL;
510 // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
511 tot_numVerts = md2->numXYZ;
513 for(i=0; i<md2->numTris; i++)
515 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
518 if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
519 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
521 else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
524 else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) ) // Not equal to Main entry, and no LL entry
525 { // Add first entry of LL from Main
526 p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
527 if (p_index_LUT2 == NULL)
528 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
529 p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
530 p_index_LUT2->Vert = dups;
531 p_index_LUT2->ST = p_md2Triangle->index_st[j];
532 p_index_LUT2->next = NULL;
533 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
536 else // Try to find in LL from Main Entry
538 p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
539 while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
541 p_index_LUT3 = p_index_LUT2;
542 p_index_LUT2 = p_index_LUT2->next;
544 p_index_LUT2 = p_index_LUT3;
546 if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
548 p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
552 if ( p_index_LUT2->next == NULL) // Didn't find it. Add entry to LL.
555 p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
556 if (p_index_LUT3 == NULL)
557 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
558 p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
559 p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
560 p_index_LUT3->ST = p_md2Triangle->index_st[j];
561 p_index_LUT3->next = NULL;
562 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
569 // malloc and build array for Dup STs
570 p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
571 if (p_index_LUT_DUPS == NULL)
572 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
575 for(i=0; i<md2->numXYZ; i++)
577 p_index_LUT2 = p_index_LUT[i].next;
578 while (p_index_LUT2 != NULL)
580 p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
581 p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
583 p_index_LUT2 = p_index_LUT2->next;
588 triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
589 texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
590 vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
591 for( j = 0; j < md2->numTris; j++, triangle++ )
593 PicoSetSurfaceIndex( picoSurface, j*3 , triangle->index_xyz[0] );
594 PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
595 PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
598 for(i=0; i< md2->numXYZ; i++, vertex++)
600 /* set vertex origin */
601 xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
602 xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
603 xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
604 PicoSetSurfaceXYZ( picoSurface, i , xyz );
607 normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
608 normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
609 normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
610 PicoSetSurfaceNormal( picoSurface, i , normal );
613 st[ 0 ] = ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
614 st[ 1 ] = (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
615 PicoSetSurfaceST( picoSurface, 0, i , st );
620 for(i=0; i<dups; i++)
622 j = p_index_LUT_DUPS[i].OldVert;
623 /* set vertex origin */
624 xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
625 xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
626 xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
627 PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
630 normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
631 normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
632 normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
633 PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
636 st[ 0 ] = ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
637 st[ 1 ] = (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
638 PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
643 PicoSetSurfaceColor( picoSurface, 0, 0, color );
645 // Free up malloc'ed LL entries
646 for(i=0; i<md2->numXYZ; i++)
648 if(p_index_LUT[i].next != NULL)
650 p_index_LUT2 = p_index_LUT[i].next;
652 p_index_LUT3 = p_index_LUT2->next;
653 _pico_free(p_index_LUT2);
654 p_index_LUT2 = p_index_LUT3;
656 } while (p_index_LUT2 != NULL);
661 _pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
663 // Free malloc'ed LUTs
664 _pico_free(p_index_LUT);
665 _pico_free(p_index_LUT_DUPS);
667 /* return the new pico model */
674 /* pico file format module definition */
675 const picoModule_t picoModuleMD2 =
677 "0.875", /* module version string */
678 "Quake 2 MD2", /* module display name */
679 "Nurail", /* author's name */
680 "2003 Nurail", /* module copyright */
682 "md2", NULL, NULL, NULL /* default extensions to use */
684 _md2_canload, /* validation routine */
685 _md2_load, /* load routine */
686 NULL, /* save validation routine */
687 NULL /* save routine */