]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/netradiant-src/libs/picomodel/pm_md3.c
Move all other sources in a separate subfolder
[voretournament/voretournament.git] / misc / mediasource / netradiant-src / libs / picomodel / pm_md3.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
37 /* marker */
38 #define PM_MD3_C
39
40
41
42 /* dependencies */
43 #include "picointernal.h"
44
45
46
47 /* md3 model format */
48 #define MD3_MAGIC                       "IDP3"
49 #define MD3_VERSION                     15
50
51 /* md3 vertex scale */
52 #define MD3_SCALE                 (1.0f / 64.0f)
53
54 /* md3 model frame information */
55 typedef struct md3Frame_s
56 {
57         float           bounds[ 2 ][ 3 ];
58         float           localOrigin[ 3 ];
59         float           radius;
60         char            creator[ 16 ];
61 }
62 md3Frame_t;
63
64 /* md3 model tag information */
65 typedef struct md3Tag_s
66 {
67         char            name[ 64 ];
68         float           origin[ 3 ];
69         float           axis[ 3 ][ 3 ];
70 }
71 md3Tag_t;
72
73 /* md3 surface md3 (one object mesh) */
74 typedef struct md3Surface_s
75 {
76         char            magic[ 4 ];
77         char            name[ 64 ];             /* polyset name */
78         int                     flags;
79         int                     numFrames;              /* all model surfaces should have the same */
80         int                     numShaders;             /* all model surfaces should have the same */
81         int                     numVerts;
82         int                     numTriangles;
83         int                     ofsTriangles;
84         int                     ofsShaders;             /* offset from start of md3Surface_t */
85         int                     ofsSt;                  /* texture coords are common for all frames */
86         int                     ofsVertexes;    /* numVerts * numFrames */
87         int                     ofsEnd;                 /* next surface follows */
88 }
89 md3Surface_t;
90
91 typedef struct md3Shader_s
92 {
93         char            name[ 64 ];
94         int                     shaderIndex;    /* for ingame use */
95 }
96 md3Shader_t;
97
98 typedef struct md3Triangle_s
99 {
100         int                     indexes[ 3 ];
101 }
102 md3Triangle_t;
103
104 typedef struct md3TexCoord_s
105 {
106         float           st[ 2 ];
107 }
108 md3TexCoord_t;
109
110 typedef struct md3Vertex_s
111 {
112         short           xyz[ 3 ];
113         short           normal;
114 }
115 md3Vertex_t;
116
117
118 /* md3 model file md3 structure */
119 typedef struct md3_s
120 {
121         char            magic[ 4 ];             /* MD3_MAGIC */
122         int                     version;
123         char            name[ 64 ];             /* model name */
124         int                     flags;
125         int                     numFrames;
126         int                     numTags;
127         int                     numSurfaces;
128         int                     numSkins;               /* number of skins for the mesh */
129         int                     ofsFrames;              /* offset for first frame */
130         int                     ofsTags;                /* numFrames * numTags */
131         int                     ofsSurfaces;    /* first surface, others follow */
132         int                     ofsEnd;                 /* end of file */
133 }
134 md3_t;
135
136
137
138
139 /*
140 _md3_canload()
141 validates a quake3 arena md3 model file. btw, i use the
142 preceding underscore cause it's a static func referenced
143 by one structure only.
144 */
145
146 static int _md3_canload( PM_PARAMS_CANLOAD )
147 {
148         const md3_t     *md3;
149         
150
151         /* sanity check */
152         if( (size_t) bufSize < ( sizeof( *md3 ) * 2) )
153                 return PICO_PMV_ERROR_SIZE;
154         
155         /* set as md3 */
156         md3     = (const md3_t*) buffer;
157         
158         /* check md3 magic */
159         if( *((const int*) md3->magic) != *((const int*) MD3_MAGIC) ) 
160                 return PICO_PMV_ERROR_IDENT;
161         
162         /* check md3 version */
163         if( _pico_little_long( md3->version ) != MD3_VERSION )
164                 return PICO_PMV_ERROR_VERSION;
165         
166         /* file seems to be a valid md3 */
167         return PICO_PMV_OK;
168 }
169
170
171
172 /*
173 _md3_load()
174 loads a quake3 arena md3 model file.
175 */
176
177 static picoModel_t *_md3_load( PM_PARAMS_LOAD )
178 {
179         int                             i, j;
180         picoByte_t              *bb, *bb0;
181         md3_t                   *md3;
182         md3Surface_t    *surface;
183         md3Shader_t             *shader;
184         md3TexCoord_t   *texCoord;
185         md3Frame_t              *frame;
186         md3Triangle_t   *triangle;
187         md3Vertex_t             *vertex;
188         double                  lat, lng;
189         
190         picoModel_t             *picoModel;
191         picoSurface_t   *picoSurface;
192         picoShader_t    *picoShader;
193         picoVec3_t              xyz, normal;
194         picoVec2_t              st;
195         picoColor_t             color;
196         
197         
198         /* -------------------------------------------------
199         md3 loading
200         ------------------------------------------------- */
201
202
203         /* set as md3 */
204         bb0 = bb = (picoByte_t*) _pico_alloc(bufSize);
205         memcpy(bb, buffer, bufSize);
206         md3     = (md3_t*) bb;
207         
208         /* check ident and version */
209         if( *((int*) md3->magic) != *((int*) MD3_MAGIC) || _pico_little_long( md3->version ) != MD3_VERSION )
210         {
211                 /* not an md3 file (todo: set error) */
212                 _pico_free(bb0);
213                 return NULL;
214         }
215         
216         /* swap md3; sea: swaps fixed */
217         md3->version = _pico_little_long( md3->version );
218         md3->numFrames = _pico_little_long( md3->numFrames );
219         md3->numTags = _pico_little_long( md3->numTags );
220         md3->numSurfaces = _pico_little_long( md3->numSurfaces );
221         md3->numSkins = _pico_little_long( md3->numSkins );
222         md3->ofsFrames = _pico_little_long( md3->ofsFrames );
223         md3->ofsTags = _pico_little_long( md3->ofsTags );
224         md3->ofsSurfaces = _pico_little_long( md3->ofsSurfaces );
225         md3->ofsEnd = _pico_little_long( md3->ofsEnd );
226         
227         /* do frame check */
228         if( md3->numFrames < 1 )
229         {
230                 _pico_printf( PICO_ERROR, "MD3 with 0 frames" );
231                 _pico_free(bb0);
232                 return NULL;
233         }
234         
235         if( frameNum < 0 || frameNum >= md3->numFrames )
236         {
237                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MD3 frame specified" );
238                 _pico_free(bb0);
239                 return NULL;
240         }
241         
242         /* swap frames */
243         frame = (md3Frame_t*) (bb + md3->ofsFrames );
244         for( i = 0; i < md3->numFrames; i++, frame++ )
245         {
246                 frame->radius = _pico_little_float( frame->radius );
247                 for( j = 0; j < 3; j++ )
248                 {
249                         frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
250                         frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
251                         frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
252                 }
253         }
254         
255         /* swap surfaces */
256         surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
257         for( i = 0; i < md3->numSurfaces; i++ )
258         {
259                 /* swap surface md3; sea: swaps fixed */
260                 surface->flags = _pico_little_long( surface->flags );
261                 surface->numFrames = _pico_little_long( surface->numFrames );
262                 surface->numShaders = _pico_little_long( surface->numShaders );
263                 surface->numTriangles = _pico_little_long( surface->numTriangles );
264                 surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
265                 surface->numVerts = _pico_little_long( surface->numVerts );
266                 surface->ofsShaders = _pico_little_long( surface->ofsShaders );
267                 surface->ofsSt = _pico_little_long( surface->ofsSt );
268                 surface->ofsVertexes = _pico_little_long( surface->ofsVertexes );
269                 surface->ofsEnd = _pico_little_long( surface->ofsEnd );
270                 
271                 /* swap triangles */
272                 triangle = (md3Triangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
273                 for( j = 0; j < surface->numTriangles; j++, triangle++ )
274                 {
275                         /* sea: swaps fixed */
276                         triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
277                         triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
278                         triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
279                 }
280                 
281                 /* swap st coords */
282                 texCoord = (md3TexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
283                 for( j = 0; j < surface->numVerts; j++, texCoord++ )
284                 {
285                         texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
286                         texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
287                 }
288                 
289                 /* swap xyz/normals */
290                 vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes);
291                 for( j = 0; j < (surface->numVerts * surface->numFrames); j++, vertex++)
292                 {
293                         vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
294                         vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
295                         vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
296                         vertex->normal   = _pico_little_short( vertex->normal );
297                 }
298                 
299                 /* get next surface */
300                 surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
301         }
302         
303         /* -------------------------------------------------
304         pico model creation
305         ------------------------------------------------- */
306         
307         /* create new pico model */
308         picoModel = PicoNewModel();
309         if( picoModel == NULL )
310         {
311                 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
312                 _pico_free(bb0);
313                 return NULL;
314         }
315         
316         /* do model setup */
317         PicoSetModelFrameNum( picoModel, frameNum );
318         PicoSetModelNumFrames( picoModel, md3->numFrames ); /* sea */
319         PicoSetModelName( picoModel, fileName );
320         PicoSetModelFileName( picoModel, fileName );
321         
322         /* md3 surfaces become picomodel surfaces */
323         surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
324         
325         /* run through md3 surfaces */
326         for( i = 0; i < md3->numSurfaces; i++ )
327         {
328                 /* allocate new pico surface */
329                 picoSurface = PicoNewSurface( picoModel );
330                 if( picoSurface == NULL )
331                 {
332                         _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
333                         PicoFreeModel( picoModel ); /* sea */
334                         _pico_free(bb0);
335                         return NULL;
336                 }
337                 
338                 /* md3 model surfaces are all triangle meshes */
339                 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
340                 
341                 /* set surface name */
342                 PicoSetSurfaceName( picoSurface, surface->name );
343                 
344                 /* create new pico shader -sea */
345                 picoShader = PicoNewShader( picoModel );
346                 if( picoShader == NULL )
347                 {
348                         _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
349                         PicoFreeModel( picoModel );
350                         _pico_free(bb0);
351                         return NULL;
352                 }
353                 
354                 /* detox and set shader name */
355                 shader = (md3Shader_t*) ((picoByte_t*) surface + surface->ofsShaders);
356                 _pico_setfext( shader->name, "" );
357                 _pico_unixify( shader->name );
358                 PicoSetShaderName( picoShader, shader->name );
359                 
360                 /* associate current surface with newly created shader */
361                 PicoSetSurfaceShader( picoSurface, picoShader );
362                 
363                 /* copy indexes */
364                 triangle = (md3Triangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
365                 
366                 for( j = 0; j < surface->numTriangles; j++, triangle++ )
367                 {
368                         PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
369                         PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
370                         PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
371                 }
372                 
373                 /* copy vertexes */
374                 texCoord = (md3TexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
375                 vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes + surface->numVerts * frameNum * sizeof( md3Vertex_t ) );
376                 _pico_set_color( color, 255, 255, 255, 255 );
377                 
378                 for( j = 0; j < surface->numVerts; j++, texCoord++, vertex++ )
379                 {
380                         /* set vertex origin */
381                         xyz[ 0 ] = MD3_SCALE * vertex->xyz[ 0 ];
382                         xyz[ 1 ] = MD3_SCALE * vertex->xyz[ 1 ];
383                         xyz[ 2 ] = MD3_SCALE * vertex->xyz[ 2 ];
384                         PicoSetSurfaceXYZ( picoSurface, j, xyz );
385                         
386                         /* decode lat/lng normal to 3 float normal */
387                         lat = (float) ((vertex->normal >> 8) & 0xff);
388                         lng = (float) (vertex->normal & 0xff);
389                         lat *= PICO_PI / 128;
390                         lng *= PICO_PI / 128;
391                         normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
392                         normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
393                         normal[ 2 ] = (picoVec_t) cos( lng );
394                         PicoSetSurfaceNormal( picoSurface, j, normal );
395                         
396                         /* set st coords */
397                         st[ 0 ] = texCoord->st[ 0 ];
398                         st[ 1 ] = texCoord->st[ 1 ];
399                         PicoSetSurfaceST( picoSurface, 0, j, st );
400
401                         /* set color */
402                         PicoSetSurfaceColor( picoSurface, 0, j, color );
403                 }
404                 
405                 /* get next surface */
406                 surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
407         }
408         
409         /* return the new pico model */
410         _pico_free(bb0);
411         return picoModel;
412 }
413
414
415
416 /* pico file format module definition */
417 const picoModule_t picoModuleMD3 =
418 {
419         "1.3",                                          /* module version string */
420         "Quake 3 Arena",                        /* module display name */
421         "Randy Reddig",                         /* author's name */
422         "2002 Randy Reddig",            /* module copyright */
423         {
424                 "md3", NULL, NULL, NULL /* default extensions to use */
425         },
426         _md3_canload,                           /* validation routine */
427         _md3_load,                                      /* load routine */
428          NULL,                                          /* save validation routine */
429          NULL                                           /* save routine */
430 };