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;
345 bb0 = bb = (picoByte_t*) _pico_alloc( bufSize );
346 memcpy( bb, buffer, bufSize );
349 /* check ident and version */
350 if ( *( (const int*) md2->magic ) != *( (const int*) MD2_MAGIC ) || _pico_little_long( md2->version ) != MD2_VERSION ) {
351 /* not an md2 file (todo: set error) */
352 _pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
358 md2->version = _pico_little_long( md2->version );
360 md2->skinWidth = _pico_little_long( md2->skinWidth );
361 md2->skinHeight = _pico_little_long( md2->skinHeight );
362 md2->frameSize = _pico_little_long( md2->frameSize );
364 md2->numSkins = _pico_little_long( md2->numSkins );
365 md2->numXYZ = _pico_little_long( md2->numXYZ );
366 md2->numST = _pico_little_long( md2->numST );
367 md2->numTris = _pico_little_long( md2->numTris );
368 md2->numGLCmds = _pico_little_long( md2->numGLCmds );
369 md2->numFrames = _pico_little_long( md2->numFrames );
371 md2->ofsSkins = _pico_little_long( md2->ofsSkins );
372 md2->ofsST = _pico_little_long( md2->ofsST );
373 md2->ofsTris = _pico_little_long( md2->ofsTris );
374 md2->ofsFrames = _pico_little_long( md2->ofsFrames );
375 md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
376 md2->ofsEnd = _pico_little_long( md2->ofsEnd );
379 if ( md2->numFrames < 1 ) {
380 _pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
385 if ( frameNum < 0 || frameNum >= md2->numFrames ) {
386 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
392 frame = (md2Frame_t *) ( bb + md2->ofsFrames + ( sizeof( md2Frame_t ) * frameNum ) );
394 // swap frame scale and translation
395 for ( i = 0; i < 3; i++ )
397 frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
398 frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
402 triangle = (md2Triangle_t *) ( (picoByte_t *) ( bb + md2->ofsTris ) );
403 for ( i = 0; i < md2->numTris; i++, triangle++ )
405 for ( j = 0; j < 3; j++ )
407 triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
408 triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
413 texCoord = (md2St_t*) ( (picoByte_t *) ( bb + md2->ofsST ) );
414 for ( i = 0; i < md2->numST; i++, texCoord++ )
416 texCoord->s = _pico_little_short( texCoord->s );
417 texCoord->t = _pico_little_short( texCoord->t );
421 strncpy( skinname, (const char *) ( bb + md2->ofsSkins ), MD2_MAX_SKINNAME );
423 // Print out md2 values
424 _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 );
427 _pico_setfext( skinname, NULL );
428 _pico_unixify( skinname );
430 /* create new pico model */
431 picoModel = PicoNewModel();
432 if ( picoModel == NULL ) {
433 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
439 PicoSetModelFrameNum( picoModel, frameNum );
440 PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
441 PicoSetModelName( picoModel, fileName );
442 PicoSetModelFileName( picoModel, fileName );
444 // allocate new pico surface
445 picoSurface = PicoNewSurface( picoModel );
446 if ( picoSurface == NULL ) {
447 _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
448 PicoFreeModel( picoModel );
454 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
455 PicoSetSurfaceName( picoSurface, frame->name );
456 picoShader = PicoNewShader( picoModel );
457 if ( picoShader == NULL ) {
458 _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
459 PicoFreeModel( picoModel );
464 PicoSetShaderName( picoShader, skinname );
466 // associate current surface with newly created shader
467 PicoSetSurfaceShader( picoSurface, picoShader );
469 // Init LUT for Verts
470 p_index_LUT = (index_LUT_t *)_pico_alloc( sizeof( index_LUT_t ) * md2->numXYZ );
471 for ( i = 0; i < md2->numXYZ; i++ )
473 p_index_LUT[i].Vert = -1;
474 p_index_LUT[i].ST = -1;
475 p_index_LUT[i].next = NULL;
478 // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
480 for ( i = 0; i < md2->numTris; i++ )
482 p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + ( sizeof( md2Triangle_t ) * i ) );
483 for ( j = 0; j < 3; j++ )
485 if ( p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1 ) { // No Main Entry
486 p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
489 else if ( p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) { // Equal to Main Entry
493 else if ( ( p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL ) ) { // Not equal to Main entry, and no LL entry
494 // Add first entry of LL from Main
495 p_index_LUT2 = (index_LUT_t *)_pico_alloc( sizeof( index_LUT_t ) );
496 if ( p_index_LUT2 == NULL ) {
497 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
499 p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
500 p_index_LUT2->Vert = dups;
501 p_index_LUT2->ST = p_md2Triangle->index_st[j];
502 p_index_LUT2->next = NULL;
503 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
506 else // Try to find in LL from Main Entry
508 p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
509 while ( ( p_index_LUT2 != NULL ) && ( p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert ) ) // Walk down LL
511 p_index_LUT3 = p_index_LUT2;
512 p_index_LUT2 = p_index_LUT2->next;
514 p_index_LUT2 = p_index_LUT3;
516 if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) { // Found it
517 p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
521 if ( p_index_LUT2->next == NULL ) { // Didn't find it. Add entry to LL.
523 p_index_LUT3 = (index_LUT_t *)_pico_alloc( sizeof( index_LUT_t ) );
524 if ( p_index_LUT3 == NULL ) {
525 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
527 p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
528 p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
529 p_index_LUT3->ST = p_md2Triangle->index_st[j];
530 p_index_LUT3->next = NULL;
531 p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
538 // malloc and build array for Dup STs
539 p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc( sizeof( index_DUP_LUT_t ) * dups );
540 if ( p_index_LUT_DUPS == NULL ) {
541 _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
545 for ( i = 0; i < md2->numXYZ; i++ )
547 p_index_LUT2 = p_index_LUT[i].next;
548 while ( p_index_LUT2 != NULL )
550 p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
551 p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
553 p_index_LUT2 = p_index_LUT2->next;
558 triangle = (md2Triangle_t *) ( (picoByte_t *) ( bb + md2->ofsTris ) );
559 texCoord = (md2St_t*) ( (picoByte_t *) ( bb + md2->ofsST ) );
560 vertex = (md2XyzNormal_t*) ( (picoByte_t*) ( frame->verts ) );
561 for ( j = 0; j < md2->numTris; j++, triangle++ )
563 PicoSetSurfaceIndex( picoSurface, j * 3, triangle->index_xyz[0] );
564 PicoSetSurfaceIndex( picoSurface, j * 3 + 1, triangle->index_xyz[1] );
565 PicoSetSurfaceIndex( picoSurface, j * 3 + 2, triangle->index_xyz[2] );
568 for ( i = 0; i < md2->numXYZ; i++, vertex++ )
570 /* set vertex origin */
571 xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
572 xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
573 xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
574 PicoSetSurfaceXYZ( picoSurface, i, xyz );
577 normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
578 normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
579 normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
580 PicoSetSurfaceNormal( picoSurface, i, normal );
583 st[ 0 ] = ( ( texCoord[p_index_LUT[i].ST].s ) / ( (float)md2->skinWidth ) );
584 st[ 1 ] = ( texCoord[p_index_LUT[i].ST].t / ( (float)md2->skinHeight ) );
585 PicoSetSurfaceST( picoSurface, 0, i, st );
588 PicoSetSurfaceColor( picoSurface, 0, i, picoColor_white );
592 for ( i = 0; i < dups; i++ )
594 j = p_index_LUT_DUPS[i].OldVert;
595 /* set vertex origin */
596 xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
597 xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
598 xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
599 PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ, xyz );
602 normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
603 normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
604 normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
605 PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ, normal );
608 st[ 0 ] = ( ( texCoord[p_index_LUT_DUPS[i].ST].s ) / ( (float)md2->skinWidth ) );
609 st[ 1 ] = ( texCoord[p_index_LUT_DUPS[i].ST].t / ( (float)md2->skinHeight ) );
610 PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ, st );
613 PicoSetSurfaceColor( picoSurface, 0, i + md2->numXYZ, picoColor_white );
617 // Free up malloc'ed LL entries
618 for ( i = 0; i < md2->numXYZ; i++ )
620 if ( p_index_LUT[i].next != NULL ) {
621 p_index_LUT2 = p_index_LUT[i].next;
623 p_index_LUT3 = p_index_LUT2->next;
624 _pico_free( p_index_LUT2 );
625 p_index_LUT2 = p_index_LUT3;
627 } while ( p_index_LUT2 != NULL );
632 _pico_printf( PICO_WARNING, " Not all LL mallocs freed\n" );
635 // Free malloc'ed LUTs
636 _pico_free( p_index_LUT );
637 _pico_free( p_index_LUT_DUPS );
639 /* return the new pico model */
647 /* pico file format module definition */
648 const picoModule_t picoModuleMD2 =
650 "0.875", /* module version string */
651 "Quake 2 MD2", /* module display name */
652 "Nurail", /* author's name */
653 "2003 Nurail", /* module copyright */
655 "md2", NULL, NULL, NULL /* default extensions to use */
657 _md2_canload, /* validation routine */
658 _md2_load, /* load routine */
659 NULL, /* save validation routine */
660 NULL /* save routine */