]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/pm_mdc.c
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / libs / picomodel / pm_mdc.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 /* dependencies */
36 #include "picointernal.h"
37
38 /* mdc model format */
39 const char *MDC_MAGIC = "IDPC";
40 const int MDC_VERSION = 2;
41
42 /* mdc vertex scale */
43 const float MDC_SCALE           = ( 1.0f / 64.0f );
44 const float MDC_MAX_OFS         = 127.0f;
45 const float MDC_DIST_SCALE      = 0.05f;
46
47 /* mdc decoding normal table */
48 double mdcNormals[ 256 ][ 3 ] =
49 {
50         { 1.000000, 0.000000, 0.000000 },
51         { 0.980785, 0.195090, 0.000000 },
52         { 0.923880, 0.382683, 0.000000 },
53         { 0.831470, 0.555570, 0.000000 },
54         { 0.707107, 0.707107, 0.000000 },
55         { 0.555570, 0.831470, 0.000000 },
56         { 0.382683, 0.923880, 0.000000 },
57         { 0.195090, 0.980785, 0.000000 },
58         { -0.000000, 1.000000, 0.000000 },
59         { -0.195090, 0.980785, 0.000000 },
60         { -0.382683, 0.923880, 0.000000 },
61         { -0.555570, 0.831470, 0.000000 },
62         { -0.707107, 0.707107, 0.000000 },
63         { -0.831470, 0.555570, 0.000000 },
64         { -0.923880, 0.382683, 0.000000 },
65         { -0.980785, 0.195090, 0.000000 },
66         { -1.000000, -0.000000, 0.000000 },
67         { -0.980785, -0.195090, 0.000000 },
68         { -0.923880, -0.382683, 0.000000 },
69         { -0.831470, -0.555570, 0.000000 },
70         { -0.707107, -0.707107, 0.000000 },
71         { -0.555570, -0.831469, 0.000000 },
72         { -0.382684, -0.923880, 0.000000 },
73         { -0.195090, -0.980785, 0.000000 },
74         { 0.000000, -1.000000, 0.000000 },
75         { 0.195090, -0.980785, 0.000000 },
76         { 0.382684, -0.923879, 0.000000 },
77         { 0.555570, -0.831470, 0.000000 },
78         { 0.707107, -0.707107, 0.000000 },
79         { 0.831470, -0.555570, 0.000000 },
80         { 0.923880, -0.382683, 0.000000 },
81         { 0.980785, -0.195090, 0.000000 },
82         { 0.980785, 0.000000, -0.195090 },
83         { 0.956195, 0.218245, -0.195090 },
84         { 0.883657, 0.425547, -0.195090 },
85         { 0.766809, 0.611510, -0.195090 },
86         { 0.611510, 0.766809, -0.195090 },
87         { 0.425547, 0.883657, -0.195090 },
88         { 0.218245, 0.956195, -0.195090 },
89         { -0.000000, 0.980785, -0.195090 },
90         { -0.218245, 0.956195, -0.195090 },
91         { -0.425547, 0.883657, -0.195090 },
92         { -0.611510, 0.766809, -0.195090 },
93         { -0.766809, 0.611510, -0.195090 },
94         { -0.883657, 0.425547, -0.195090 },
95         { -0.956195, 0.218245, -0.195090 },
96         { -0.980785, -0.000000, -0.195090 },
97         { -0.956195, -0.218245, -0.195090 },
98         { -0.883657, -0.425547, -0.195090 },
99         { -0.766809, -0.611510, -0.195090 },
100         { -0.611510, -0.766809, -0.195090 },
101         { -0.425547, -0.883657, -0.195090 },
102         { -0.218245, -0.956195, -0.195090 },
103         { 0.000000, -0.980785, -0.195090 },
104         { 0.218245, -0.956195, -0.195090 },
105         { 0.425547, -0.883657, -0.195090 },
106         { 0.611510, -0.766809, -0.195090 },
107         { 0.766809, -0.611510, -0.195090 },
108         { 0.883657, -0.425547, -0.195090 },
109         { 0.956195, -0.218245, -0.195090 },
110         { 0.923880, 0.000000, -0.382683 },
111         { 0.892399, 0.239118, -0.382683 },
112         { 0.800103, 0.461940, -0.382683 },
113         { 0.653281, 0.653281, -0.382683 },
114         { 0.461940, 0.800103, -0.382683 },
115         { 0.239118, 0.892399, -0.382683 },
116         { -0.000000, 0.923880, -0.382683 },
117         { -0.239118, 0.892399, -0.382683 },
118         { -0.461940, 0.800103, -0.382683 },
119         { -0.653281, 0.653281, -0.382683 },
120         { -0.800103, 0.461940, -0.382683 },
121         { -0.892399, 0.239118, -0.382683 },
122         { -0.923880, -0.000000, -0.382683 },
123         { -0.892399, -0.239118, -0.382683 },
124         { -0.800103, -0.461940, -0.382683 },
125         { -0.653282, -0.653281, -0.382683 },
126         { -0.461940, -0.800103, -0.382683 },
127         { -0.239118, -0.892399, -0.382683 },
128         { 0.000000, -0.923880, -0.382683 },
129         { 0.239118, -0.892399, -0.382683 },
130         { 0.461940, -0.800103, -0.382683 },
131         { 0.653281, -0.653282, -0.382683 },
132         { 0.800103, -0.461940, -0.382683 },
133         { 0.892399, -0.239117, -0.382683 },
134         { 0.831470, 0.000000, -0.555570 },
135         { 0.790775, 0.256938, -0.555570 },
136         { 0.672673, 0.488726, -0.555570 },
137         { 0.488726, 0.672673, -0.555570 },
138         { 0.256938, 0.790775, -0.555570 },
139         { -0.000000, 0.831470, -0.555570 },
140         { -0.256938, 0.790775, -0.555570 },
141         { -0.488726, 0.672673, -0.555570 },
142         { -0.672673, 0.488726, -0.555570 },
143         { -0.790775, 0.256938, -0.555570 },
144         { -0.831470, -0.000000, -0.555570 },
145         { -0.790775, -0.256938, -0.555570 },
146         { -0.672673, -0.488726, -0.555570 },
147         { -0.488725, -0.672673, -0.555570 },
148         { -0.256938, -0.790775, -0.555570 },
149         { 0.000000, -0.831470, -0.555570 },
150         { 0.256938, -0.790775, -0.555570 },
151         { 0.488725, -0.672673, -0.555570 },
152         { 0.672673, -0.488726, -0.555570 },
153         { 0.790775, -0.256938, -0.555570 },
154         { 0.707107, 0.000000, -0.707107 },
155         { 0.653281, 0.270598, -0.707107 },
156         { 0.500000, 0.500000, -0.707107 },
157         { 0.270598, 0.653281, -0.707107 },
158         { -0.000000, 0.707107, -0.707107 },
159         { -0.270598, 0.653282, -0.707107 },
160         { -0.500000, 0.500000, -0.707107 },
161         { -0.653281, 0.270598, -0.707107 },
162         { -0.707107, -0.000000, -0.707107 },
163         { -0.653281, -0.270598, -0.707107 },
164         { -0.500000, -0.500000, -0.707107 },
165         { -0.270598, -0.653281, -0.707107 },
166         { 0.000000, -0.707107, -0.707107 },
167         { 0.270598, -0.653281, -0.707107 },
168         { 0.500000, -0.500000, -0.707107 },
169         { 0.653282, -0.270598, -0.707107 },
170         { 0.555570, 0.000000, -0.831470 },
171         { 0.481138, 0.277785, -0.831470 },
172         { 0.277785, 0.481138, -0.831470 },
173         { -0.000000, 0.555570, -0.831470 },
174         { -0.277785, 0.481138, -0.831470 },
175         { -0.481138, 0.277785, -0.831470 },
176         { -0.555570, -0.000000, -0.831470 },
177         { -0.481138, -0.277785, -0.831470 },
178         { -0.277785, -0.481138, -0.831470 },
179         { 0.000000, -0.555570, -0.831470 },
180         { 0.277785, -0.481138, -0.831470 },
181         { 0.481138, -0.277785, -0.831470 },
182         { 0.382683, 0.000000, -0.923880 },
183         { 0.270598, 0.270598, -0.923880 },
184         { -0.000000, 0.382683, -0.923880 },
185         { -0.270598, 0.270598, -0.923880 },
186         { -0.382683, -0.000000, -0.923880 },
187         { -0.270598, -0.270598, -0.923880 },
188         { 0.000000, -0.382683, -0.923880 },
189         { 0.270598, -0.270598, -0.923880 },
190         { 0.195090, 0.000000, -0.980785 },
191         { -0.000000, 0.195090, -0.980785 },
192         { -0.195090, -0.000000, -0.980785 },
193         { 0.000000, -0.195090, -0.980785 },
194         { 0.980785, 0.000000, 0.195090 },
195         { 0.956195, 0.218245, 0.195090 },
196         { 0.883657, 0.425547, 0.195090 },
197         { 0.766809, 0.611510, 0.195090 },
198         { 0.611510, 0.766809, 0.195090 },
199         { 0.425547, 0.883657, 0.195090 },
200         { 0.218245, 0.956195, 0.195090 },
201         { -0.000000, 0.980785, 0.195090 },
202         { -0.218245, 0.956195, 0.195090 },
203         { -0.425547, 0.883657, 0.195090 },
204         { -0.611510, 0.766809, 0.195090 },
205         { -0.766809, 0.611510, 0.195090 },
206         { -0.883657, 0.425547, 0.195090 },
207         { -0.956195, 0.218245, 0.195090 },
208         { -0.980785, -0.000000, 0.195090 },
209         { -0.956195, -0.218245, 0.195090 },
210         { -0.883657, -0.425547, 0.195090 },
211         { -0.766809, -0.611510, 0.195090 },
212         { -0.611510, -0.766809, 0.195090 },
213         { -0.425547, -0.883657, 0.195090 },
214         { -0.218245, -0.956195, 0.195090 },
215         { 0.000000, -0.980785, 0.195090 },
216         { 0.218245, -0.956195, 0.195090 },
217         { 0.425547, -0.883657, 0.195090 },
218         { 0.611510, -0.766809, 0.195090 },
219         { 0.766809, -0.611510, 0.195090 },
220         { 0.883657, -0.425547, 0.195090 },
221         { 0.956195, -0.218245, 0.195090 },
222         { 0.923880, 0.000000, 0.382683 },
223         { 0.892399, 0.239118, 0.382683 },
224         { 0.800103, 0.461940, 0.382683 },
225         { 0.653281, 0.653281, 0.382683 },
226         { 0.461940, 0.800103, 0.382683 },
227         { 0.239118, 0.892399, 0.382683 },
228         { -0.000000, 0.923880, 0.382683 },
229         { -0.239118, 0.892399, 0.382683 },
230         { -0.461940, 0.800103, 0.382683 },
231         { -0.653281, 0.653281, 0.382683 },
232         { -0.800103, 0.461940, 0.382683 },
233         { -0.892399, 0.239118, 0.382683 },
234         { -0.923880, -0.000000, 0.382683 },
235         { -0.892399, -0.239118, 0.382683 },
236         { -0.800103, -0.461940, 0.382683 },
237         { -0.653282, -0.653281, 0.382683 },
238         { -0.461940, -0.800103, 0.382683 },
239         { -0.239118, -0.892399, 0.382683 },
240         { 0.000000, -0.923880, 0.382683 },
241         { 0.239118, -0.892399, 0.382683 },
242         { 0.461940, -0.800103, 0.382683 },
243         { 0.653281, -0.653282, 0.382683 },
244         { 0.800103, -0.461940, 0.382683 },
245         { 0.892399, -0.239117, 0.382683 },
246         { 0.831470, 0.000000, 0.555570 },
247         { 0.790775, 0.256938, 0.555570 },
248         { 0.672673, 0.488726, 0.555570 },
249         { 0.488726, 0.672673, 0.555570 },
250         { 0.256938, 0.790775, 0.555570 },
251         { -0.000000, 0.831470, 0.555570 },
252         { -0.256938, 0.790775, 0.555570 },
253         { -0.488726, 0.672673, 0.555570 },
254         { -0.672673, 0.488726, 0.555570 },
255         { -0.790775, 0.256938, 0.555570 },
256         { -0.831470, -0.000000, 0.555570 },
257         { -0.790775, -0.256938, 0.555570 },
258         { -0.672673, -0.488726, 0.555570 },
259         { -0.488725, -0.672673, 0.555570 },
260         { -0.256938, -0.790775, 0.555570 },
261         { 0.000000, -0.831470, 0.555570 },
262         { 0.256938, -0.790775, 0.555570 },
263         { 0.488725, -0.672673, 0.555570 },
264         { 0.672673, -0.488726, 0.555570 },
265         { 0.790775, -0.256938, 0.555570 },
266         { 0.707107, 0.000000, 0.707107 },
267         { 0.653281, 0.270598, 0.707107 },
268         { 0.500000, 0.500000, 0.707107 },
269         { 0.270598, 0.653281, 0.707107 },
270         { -0.000000, 0.707107, 0.707107 },
271         { -0.270598, 0.653282, 0.707107 },
272         { -0.500000, 0.500000, 0.707107 },
273         { -0.653281, 0.270598, 0.707107 },
274         { -0.707107, -0.000000, 0.707107 },
275         { -0.653281, -0.270598, 0.707107 },
276         { -0.500000, -0.500000, 0.707107 },
277         { -0.270598, -0.653281, 0.707107 },
278         { 0.000000, -0.707107, 0.707107 },
279         { 0.270598, -0.653281, 0.707107 },
280         { 0.500000, -0.500000, 0.707107 },
281         { 0.653282, -0.270598, 0.707107 },
282         { 0.555570, 0.000000, 0.831470 },
283         { 0.481138, 0.277785, 0.831470 },
284         { 0.277785, 0.481138, 0.831470 },
285         { -0.000000, 0.555570, 0.831470 },
286         { -0.277785, 0.481138, 0.831470 },
287         { -0.481138, 0.277785, 0.831470 },
288         { -0.555570, -0.000000, 0.831470 },
289         { -0.481138, -0.277785, 0.831470 },
290         { -0.277785, -0.481138, 0.831470 },
291         { 0.000000, -0.555570, 0.831470 },
292         { 0.277785, -0.481138, 0.831470 },
293         { 0.481138, -0.277785, 0.831470 },
294         { 0.382683, 0.000000, 0.923880 },
295         { 0.270598, 0.270598, 0.923880 },
296         { -0.000000, 0.382683, 0.923880 },
297         { -0.270598, 0.270598, 0.923880 },
298         { -0.382683, -0.000000, 0.923880 },
299         { -0.270598, -0.270598, 0.923880 },
300         { 0.000000, -0.382683, 0.923880 },
301         { 0.270598, -0.270598, 0.923880 },
302         { 0.195090, 0.000000, 0.980785 },
303         { -0.000000, 0.195090, 0.980785 },
304         { -0.195090, -0.000000, 0.980785 },
305         { 0.000000, -0.195090, 0.980785 }
306 };
307
308 /* mdc model frame information */
309 typedef struct mdcFrame_s
310 {
311         float bounds[ 2 ][ 3 ];
312         float localOrigin[ 3 ];
313         float radius;
314         char creator[ 16 ];
315 }
316 mdcFrame_t;
317
318 /* mdc model tag information */
319 typedef struct mdcTag_s
320 {
321         short xyz[3];
322         short angles[3];
323 }
324 mdcTag_t;
325
326 /* mdc surface mdc (one object mesh) */
327 typedef struct mdcSurface_s
328 {
329         char magic[ 4 ];
330         char name[ 64 ];                /* polyset name */
331         int flags;
332         int numCompFrames;              /* all surfaces in a model should have the same */
333         int numBaseFrames;              /* ditto */
334         int numShaders;                 /* all model surfaces should have the same */
335         int numVerts;
336         int numTriangles;
337         int ofsTriangles;
338         int ofsShaders;                 /* offset from start of mdcSurface_t */
339         int ofsSt;                      /* texture coords are common for all frames */
340         int ofsXyzNormals;              /* numVerts * numBaseFrames */
341         int ofsXyzCompressed;           /* numVerts * numCompFrames */
342
343         int ofsFrameBaseFrames;         /* numFrames */
344         int ofsFrameCompFrames;         /* numFrames */
345         int ofsEnd;                     /* next surface follows */
346 }
347 mdcSurface_t;
348
349 typedef struct mdcShader_s
350 {
351         char name[ 64 ];
352         int shaderIndex;            /* for ingame use */
353 }
354 mdcShader_t;
355
356 typedef struct mdcTriangle_s
357 {
358         int indexes[ 3 ];
359 }
360 mdcTriangle_t;
361
362 typedef struct mdcTexCoord_s
363 {
364         float st[ 2 ];
365 }
366 mdcTexCoord_t;
367
368 typedef struct mdcVertex_s
369 {
370         short xyz[ 3 ];
371         short normal;
372 }
373 mdcVertex_t;
374
375 typedef struct mdcXyzCompressed_s
376 {
377         unsigned int ofsVec;        /* offset direction from the last base frame */
378 }
379 mdcXyzCompressed_t;
380
381
382 /* mdc model file mdc structure */
383 typedef struct mdc_s
384 {
385         char magic[ 4 ];            /* MDC_MAGIC */
386         int version;
387         char name[ 64 ];            /* model name */
388         int flags;
389         int numFrames;
390         int numTags;
391         int numSurfaces;
392         int numSkins;               /* number of skins for the mesh */
393         int ofsFrames;              /* offset for first frame */
394         int ofsTagNames;            /* numTags */
395         int ofsTags;                /* numFrames * numTags */
396         int ofsSurfaces;            /* first surface, others follow */
397         int ofsEnd;                 /* end of file */
398 }
399 mdc_t;
400
401
402
403
404 /*
405    _mdc_canload()
406    validates a Return to Castle Wolfenstein model file. btw, i use the
407    preceding underscore cause it's a static func referenced
408    by one structure only.
409  */
410
411 static int _mdc_canload( PM_PARAMS_CANLOAD ){
412         const mdc_t *mdc;
413
414
415         /* sanity check */
416         if ( (size_t) bufSize < ( sizeof( *mdc ) * 2 ) ) {
417                 return PICO_PMV_ERROR_SIZE;
418         }
419
420         /* set as mdc */
421         mdc = (const mdc_t*) buffer;
422
423         /* check mdc magic */
424         if ( *( (const int*) mdc->magic ) != *( (const int*) MDC_MAGIC ) ) {
425                 return PICO_PMV_ERROR_IDENT;
426         }
427
428         /* check mdc version */
429         if ( _pico_little_long( mdc->version ) != MDC_VERSION ) {
430                 return PICO_PMV_ERROR_VERSION;
431         }
432
433         /* file seems to be a valid mdc */
434         return PICO_PMV_OK;
435 }
436
437
438
439 /*
440    _mdc_load()
441    loads a Return to Castle Wolfenstein mdc model file.
442  */
443
444 static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
445         int i, j;
446         picoByte_t          *bb, *bb0;
447         mdc_t               *mdc;
448         mdcSurface_t        *surface;
449         mdcShader_t         *shader;
450         mdcTexCoord_t       *texCoord;
451         mdcFrame_t          *frame;
452         mdcTriangle_t       *triangle;
453         mdcVertex_t         *vertex;
454         mdcXyzCompressed_t  *vertexComp = NULL;
455         short               *mdcShort, *mdcCompVert = NULL;
456         double lat, lng;
457
458         picoModel_t         *picoModel;
459         picoSurface_t       *picoSurface;
460         picoShader_t        *picoShader;
461         picoVec3_t xyz, normal;
462         picoVec2_t st;
463         picoColor_t color;
464
465
466         /* -------------------------------------------------
467            mdc loading
468            ------------------------------------------------- */
469
470
471         /* set as mdc */
472         bb0 = bb = (picoByte_t*) _pico_alloc( bufSize );
473         memcpy( bb, buffer, bufSize );
474         mdc = (mdc_t*) bb;
475
476         /* check ident and version */
477         if ( *( (int*) mdc->magic ) != *( (int*) MDC_MAGIC ) || _pico_little_long( mdc->version ) != MDC_VERSION ) {
478                 /* not an mdc file (todo: set error) */
479                 _pico_free( bb0 );
480                 return NULL;
481         }
482
483         /* swap mdc */
484         mdc->version = _pico_little_long( mdc->version );
485         mdc->numFrames = _pico_little_long( mdc->numFrames );
486         mdc->numTags = _pico_little_long( mdc->numTags );
487         mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );
488         mdc->numSkins = _pico_little_long( mdc->numSkins );
489         mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );
490         mdc->ofsTags = _pico_little_long( mdc->ofsTags );
491         mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );
492         mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );
493         mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );
494
495         /* do frame check */
496         if ( mdc->numFrames < 1 ) {
497                 _pico_printf( PICO_ERROR, "MDC with 0 frames" );
498                 _pico_free( bb0 );
499                 return NULL;
500         }
501
502         if ( frameNum < 0 || frameNum >= mdc->numFrames ) {
503                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );
504                 _pico_free( bb0 );
505                 return NULL;
506         }
507
508         /* swap frames */
509         frame = (mdcFrame_t*) ( bb + mdc->ofsFrames );
510         for ( i = 0; i < mdc->numFrames; i++, frame++ )
511         {
512                 frame->radius = _pico_little_float( frame->radius );
513                 for ( j = 0; j < 3; j++ )
514                 {
515                         frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
516                         frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
517                         frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
518                 }
519         }
520
521         /* swap surfaces */
522         surface = (mdcSurface_t*) ( bb + mdc->ofsSurfaces );
523         for ( i = 0; i < mdc->numSurfaces; i++ )
524         {
525                 /* swap surface mdc */
526                 surface->flags = _pico_little_long( surface->flags );
527                 surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );
528                 surface->numCompFrames = _pico_little_long( surface->numCompFrames );
529                 surface->numShaders = _pico_little_long( surface->numShaders );
530                 surface->numTriangles = _pico_little_long( surface->numTriangles );
531                 surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
532                 surface->numVerts = _pico_little_long( surface->numVerts );
533                 surface->ofsShaders = _pico_little_long( surface->ofsShaders );
534                 surface->ofsSt = _pico_little_long( surface->ofsSt );
535                 surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );
536                 surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );
537                 surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );
538                 surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );
539                 surface->ofsEnd = _pico_little_long( surface->ofsEnd );
540
541                 /* swap triangles */
542                 triangle = (mdcTriangle_t*) ( (picoByte_t*) surface + surface->ofsTriangles );
543                 for ( j = 0; j < surface->numTriangles; j++, triangle++ )
544                 {
545                         /* sea: swaps fixed */
546                         triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
547                         triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
548                         triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
549                 }
550
551                 /* swap st coords */
552                 texCoord = (mdcTexCoord_t*) ( (picoByte_t*) surface + surface->ofsSt );
553                 for ( j = 0; j < surface->numVerts; j++, texCoord++ )
554                 {
555                         texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
556                         texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
557                 }
558
559                 /* swap xyz/normals */
560                 vertex = (mdcVertex_t*) ( (picoByte_t*) surface + surface->ofsXyzNormals );
561                 for ( j = 0; j < ( surface->numVerts * surface->numBaseFrames ); j++, vertex++ )
562                 {
563                         vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
564                         vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
565                         vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
566                         vertex->normal   = _pico_little_short( vertex->normal );
567                 }
568
569                 /* swap xyz/compressed */
570                 vertexComp = (mdcXyzCompressed_t*) ( (picoByte_t*) surface + surface->ofsXyzCompressed );
571                 for ( j = 0; j < ( surface->numVerts * surface->numCompFrames ); j++, vertexComp++ )
572                 {
573                         vertexComp->ofsVec  = _pico_little_long( vertexComp->ofsVec );
574                 }
575
576                 /* swap base frames */
577                 mdcShort = (short *) ( (picoByte_t*) surface + surface->ofsFrameBaseFrames );
578                 for ( j = 0; j < mdc->numFrames; j++, mdcShort++ )
579                 {
580                         *mdcShort   = _pico_little_short( *mdcShort );
581                 }
582
583                 /* swap compressed frames */
584                 mdcShort = (short *) ( (picoByte_t*) surface + surface->ofsFrameCompFrames );
585                 for ( j = 0; j < mdc->numFrames; j++, mdcShort++ )
586                 {
587                         *mdcShort   = _pico_little_short( *mdcShort );
588                 }
589
590                 /* get next surface */
591                 surface = (mdcSurface_t*) ( (picoByte_t*) surface + surface->ofsEnd );
592         }
593
594         /* -------------------------------------------------
595            pico model creation
596            ------------------------------------------------- */
597
598         /* create new pico model */
599         picoModel = PicoNewModel();
600         if ( picoModel == NULL ) {
601                 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
602                 _pico_free( bb0 );
603                 return NULL;
604         }
605
606         /* do model setup */
607         PicoSetModelFrameNum( picoModel, frameNum );
608         PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */
609         PicoSetModelName( picoModel, fileName );
610         PicoSetModelFileName( picoModel, fileName );
611
612         /* mdc surfaces become picomodel surfaces */
613         surface = (mdcSurface_t*) ( bb + mdc->ofsSurfaces );
614
615         /* run through mdc surfaces */
616         for ( i = 0; i < mdc->numSurfaces; i++ )
617         {
618                 /* allocate new pico surface */
619                 picoSurface = PicoNewSurface( picoModel );
620                 if ( picoSurface == NULL ) {
621                         _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
622                         PicoFreeModel( picoModel ); /* sea */
623                         _pico_free( bb0 );
624                         return NULL;
625                 }
626
627                 /* mdc model surfaces are all triangle meshes */
628                 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
629
630                 /* set surface name */
631                 PicoSetSurfaceName( picoSurface, surface->name );
632
633                 /* create new pico shader -sea */
634                 picoShader = PicoNewShader( picoModel );
635                 if ( picoShader == NULL ) {
636                         _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
637                         PicoFreeModel( picoModel );
638                         _pico_free( bb0 );
639                         return NULL;
640                 }
641
642                 /* detox and set shader name */
643                 shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
644                 _pico_setfext( shader->name, "" );
645                 _pico_unixify( shader->name );
646                 PicoSetShaderName( picoShader, shader->name );
647
648                 /* associate current surface with newly created shader */
649                 PicoSetSurfaceShader( picoSurface, picoShader );
650
651                 /* copy indexes */
652                 triangle = (mdcTriangle_t *) ( (picoByte_t*) surface + surface->ofsTriangles );
653
654                 for ( j = 0; j < surface->numTriangles; j++, triangle++ )
655                 {
656                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 0 ), (picoIndex_t) triangle->indexes[ 0 ] );
657                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 1 ), (picoIndex_t) triangle->indexes[ 1 ] );
658                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 2 ), (picoIndex_t) triangle->indexes[ 2 ] );
659                 }
660
661                 /* copy vertexes */
662                 texCoord = (mdcTexCoord_t*) ( (picoByte_t *) surface + surface->ofsSt );
663                 mdcShort = (short *) ( (picoByte_t *) surface + surface->ofsXyzNormals ) + ( (int)*( (short *) ( (picoByte_t *) surface + surface->ofsFrameBaseFrames ) + frameNum ) * surface->numVerts * 4 );
664                 if ( surface->numCompFrames > 0 ) {
665                         mdcCompVert = (short *) ( (picoByte_t *) surface + surface->ofsFrameCompFrames ) + frameNum;
666                         if ( *mdcCompVert >= 0 ) {
667                                 vertexComp = (mdcXyzCompressed_t *) ( (picoByte_t *) surface + surface->ofsXyzCompressed ) + ( *mdcCompVert * surface->numVerts );
668                         }
669                 }
670                 _pico_set_color( color, 255, 255, 255, 255 );
671
672                 for ( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort += 4 )
673                 {
674                         /* set vertex origin */
675                         xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];
676                         xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];
677                         xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];
678
679                         /* add compressed ofsVec */
680                         if ( surface->numCompFrames > 0 && *mdcCompVert >= 0 ) {
681                                 xyz[ 0 ] += ( (float) ( ( vertexComp->ofsVec ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
682                                 xyz[ 1 ] += ( (float) ( ( vertexComp->ofsVec >> 8 ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
683                                 xyz[ 2 ] += ( (float) ( ( vertexComp->ofsVec >> 16 ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
684                                 PicoSetSurfaceXYZ( picoSurface, j, xyz );
685
686                                 normal[ 0 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 0 ];
687                                 normal[ 1 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 1 ];
688                                 normal[ 2 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 2 ];
689                                 PicoSetSurfaceNormal( picoSurface, j, normal );
690
691                                 vertexComp++;
692                         }
693                         else
694                         {
695                                 PicoSetSurfaceXYZ( picoSurface, j, xyz );
696
697                                 /* decode lat/lng normal to 3 float normal */
698                                 lat = (float) ( ( *( mdcShort + 3 ) >> 8 ) & 0xff );
699                                 lng = (float) ( *( mdcShort + 3 ) & 0xff );
700                                 lat *= PICO_PI / 128;
701                                 lng *= PICO_PI / 128;
702                                 normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
703                                 normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
704                                 normal[ 2 ] = (picoVec_t) cos( lng );
705                                 PicoSetSurfaceNormal( picoSurface, j, normal );
706                         }
707
708                         /* set st coords */
709                         st[ 0 ] = texCoord->st[ 0 ];
710                         st[ 1 ] = texCoord->st[ 1 ];
711                         PicoSetSurfaceST( picoSurface, 0, j, st );
712
713                         /* set color */
714                         PicoSetSurfaceColor( picoSurface, 0, j, color );
715                 }
716
717                 /* get next surface */
718                 surface = (mdcSurface_t*) ( (picoByte_t*) surface + surface->ofsEnd );
719         }
720
721         /* return the new pico model */
722         _pico_free( bb0 );
723         return picoModel;
724 }
725
726
727
728 /* pico file format module definition */
729 const picoModule_t picoModuleMDC =
730 {
731         "1.3",                          /* module version string */
732         "RtCW MDC",                     /* module display name */
733         "Arnout van Meer",              /* author's name */
734         "2002 Arnout van Meer",         /* module copyright */
735         {
736                 "mdc", NULL, NULL, NULL     /* default extensions to use */
737         },
738         _mdc_canload,                   /* validation routine */
739         _mdc_load,                      /* load routine */
740         NULL,                           /* save validation routine */
741         NULL                            /* save routine */
742 };