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.
40 #include "picointernal.h"
43 /* md2 model format */
44 const char *MD2_MAGIC = "IDP2";
45 const int MD2_VERSION = 8;
47 #define MD2_NUMVERTEXNORMALS 162
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;
55 typedef struct index_LUT_s
59 struct index_LUT_s *next;
63 typedef struct index_DUP_LUT_s
84 byte v[3]; // scaled byte to fit in frame mins/maxs
85 byte lightnormalindex;
88 typedef struct md2Frame_s
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
98 /* md2 model file md2 structure */
124 float md2_normals[ MD2_NUMVERTEXNORMALS ][ 3 ] =
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 },
293 static int _md2_canload( PM_PARAMS_CANLOAD ){
297 if ( (size_t) bufSize < ( sizeof( *md2 ) * 2 ) ) {
298 return PICO_PMV_ERROR_SIZE;
302 md2 = (const md2_t*) buffer;
304 /* check md2 magic */
305 if ( *( (const int*) md2->magic ) != *( (const int*) MD2_MAGIC ) ) {
306 return PICO_PMV_ERROR_IDENT;
309 /* check md2 version */
310 if ( _pico_little_long( md2->version ) != MD2_VERSION ) {
311 return PICO_PMV_ERROR_VERSION;
314 /* file seems to be a valid md2 */
320 // _md2_load() loads a quake2 md2 model file.
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;
329 char skinname[ MD2_MAX_SKINNAME ];
333 md2Triangle_t *triangle;
334 md2XyzNormal_t *vertex;
336 picoByte_t *bb, *bb0;
337 picoModel_t *picoModel;
338 picoSurface_t *picoSurface;
339 picoShader_t *picoShader;
340 picoVec3_t xyz, normal;
346 bb0 = bb = (picoByte_t*) _pico_alloc( bufSize );
347 memcpy( bb, buffer, bufSize );
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 );
359 md2->version = _pico_little_long( md2->version );
361 md2->skinWidth = _pico_little_long( md2->skinWidth );
362 md2->skinHeight = _pico_little_long( md2->skinHeight );
363 md2->frameSize = _pico_little_long( md2->frameSize );
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 );
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 );
380 if ( md2->numFrames < 1 ) {
381 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
386 if ( frameNum < 0 || frameNum >= md2->numFrames ) {
387 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
393 frame = (md2Frame_t *) ( bb + md2->ofsFrames + ( sizeof( md2Frame_t ) * frameNum ) );
395 // swap frame scale and translation
396 for ( i = 0; i < 3; i++ )
398 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
399 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
403 triangle = (md2Triangle_t *) ( (picoByte_t *) ( bb + md2->ofsTris ) );
404 for ( i = 0; i < md2->numTris; i++, triangle++ )
406 for ( j = 0; j < 3; j++ )
408 triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
409 triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
414 texCoord = (md2St_t*) ( (picoByte_t *) ( bb + md2->ofsST ) );
415 for ( i = 0; i < md2->numST; i++, texCoord++ )
417 texCoord->s = _pico_little_short( texCoord->s );
418 texCoord->t = _pico_little_short( texCoord->t );
422 strncpy( skinname, (const char *) ( bb + md2->ofsSkins ), MD2_MAX_SKINNAME );
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 );
428 _pico_setfext( skinname, "" );
429 _pico_unixify( skinname );
431 /* create new pico model */
432 picoModel = PicoNewModel();
433 if ( picoModel == NULL ) {
434 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
440 PicoSetModelFrameNum( picoModel, frameNum );
441 PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
442 PicoSetModelName( picoModel, fileName );
443 PicoSetModelFileName( picoModel, fileName );
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 );
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 );
465 PicoSetShaderName( picoShader, skinname );
467 // associate current surface with newly created shader
468 PicoSetSurfaceShader( picoSurface, picoShader );
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++ )
474 p_index_LUT[i].Vert = -1;
475 p_index_LUT[i].ST = -1;
476 p_index_LUT[i].next = NULL;
479 // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
481 for ( i = 0; i < md2->numTris; i++ )
483 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + ( sizeof( md2Triangle_t ) * i ) );
484 for ( j = 0; j < 3; j++ )
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];
490 else if ( p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) { // Equal to Main Entry
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" );
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
507 else // Try to find in LL from Main Entry
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
512 p_index_LUT3 = p_index_LUT2;
513 p_index_LUT2 = p_index_LUT2->next;
515 p_index_LUT2 = p_index_LUT3;
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
522 if ( p_index_LUT2->next == NULL ) { // Didn't find it. Add entry to LL.
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" );
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
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" );
546 for ( i = 0; i < md2->numXYZ; i++ )
548 p_index_LUT2 = p_index_LUT[i].next;
549 while ( p_index_LUT2 != NULL )
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;
554 p_index_LUT2 = p_index_LUT2->next;
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++ )
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] );
569 for ( i = 0; i < md2->numXYZ; i++, vertex++ )
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 );
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 );
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 );
590 for ( i = 0; i < dups; i++ )
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 );
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 );
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 );
613 PicoSetSurfaceColor( picoSurface, 0, 0, color );
615 // Free up malloc'ed LL entries
616 for ( i = 0; i < md2->numXYZ; i++ )
618 if ( p_index_LUT[i].next != NULL ) {
619 p_index_LUT2 = p_index_LUT[i].next;
621 p_index_LUT3 = p_index_LUT2->next;
622 _pico_free( p_index_LUT2 );
623 p_index_LUT2 = p_index_LUT3;
625 } while ( p_index_LUT2 != NULL );
630 _pico_printf( PICO_WARNING, " Not all LL mallocs freed\n" );
633 // Free malloc'ed LUTs
634 _pico_free( p_index_LUT );
635 _pico_free( p_index_LUT_DUPS );
637 /* return the new pico model */
645 /* pico file format module definition */
646 const picoModule_t picoModuleMD2 =
648 "0.875", /* module version string */
649 "Quake 2 MD2", /* module display name */
650 "Nurail", /* author's name */
651 "2003 Nurail", /* module copyright */
653 "md2", NULL, NULL, NULL /* default extensions to use */
655 _md2_canload, /* validation routine */
656 _md2_load, /* load routine */
657 NULL, /* save validation routine */
658 NULL /* save routine */