]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/pm_mdc.c
be93e3382f32c63362843e6f7888993c1c40b9ff
[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
464
465         /* -------------------------------------------------
466            mdc loading
467            ------------------------------------------------- */
468
469
470         /* set as mdc */
471         bb0 = bb = (picoByte_t*) _pico_alloc( bufSize );
472         memcpy( bb, buffer, bufSize );
473         mdc = (mdc_t*) bb;
474
475         /* check ident and version */
476         if ( *( (int*) mdc->magic ) != *( (int*) MDC_MAGIC ) || _pico_little_long( mdc->version ) != MDC_VERSION ) {
477                 /* not an mdc file (todo: set error) */
478                 _pico_free( bb0 );
479                 return NULL;
480         }
481
482         /* swap mdc */
483         mdc->version = _pico_little_long( mdc->version );
484         mdc->numFrames = _pico_little_long( mdc->numFrames );
485         mdc->numTags = _pico_little_long( mdc->numTags );
486         mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );
487         mdc->numSkins = _pico_little_long( mdc->numSkins );
488         mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );
489         mdc->ofsTags = _pico_little_long( mdc->ofsTags );
490         mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );
491         mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );
492         mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );
493
494         /* do frame check */
495         if ( mdc->numFrames < 1 ) {
496                 _pico_printf( PICO_ERROR, "MDC with 0 frames" );
497                 _pico_free( bb0 );
498                 return NULL;
499         }
500
501         if ( frameNum < 0 || frameNum >= mdc->numFrames ) {
502                 _pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );
503                 _pico_free( bb0 );
504                 return NULL;
505         }
506
507         /* swap frames */
508         frame = (mdcFrame_t*) ( bb + mdc->ofsFrames );
509         for ( i = 0; i < mdc->numFrames; i++, frame++ )
510         {
511                 frame->radius = _pico_little_float( frame->radius );
512                 for ( j = 0; j < 3; j++ )
513                 {
514                         frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
515                         frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
516                         frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
517                 }
518         }
519
520         /* swap surfaces */
521         surface = (mdcSurface_t*) ( bb + mdc->ofsSurfaces );
522         for ( i = 0; i < mdc->numSurfaces; i++ )
523         {
524                 /* swap surface mdc */
525                 surface->flags = _pico_little_long( surface->flags );
526                 surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );
527                 surface->numCompFrames = _pico_little_long( surface->numCompFrames );
528                 surface->numShaders = _pico_little_long( surface->numShaders );
529                 surface->numTriangles = _pico_little_long( surface->numTriangles );
530                 surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
531                 surface->numVerts = _pico_little_long( surface->numVerts );
532                 surface->ofsShaders = _pico_little_long( surface->ofsShaders );
533                 surface->ofsSt = _pico_little_long( surface->ofsSt );
534                 surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );
535                 surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );
536                 surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );
537                 surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );
538                 surface->ofsEnd = _pico_little_long( surface->ofsEnd );
539
540                 /* swap triangles */
541                 triangle = (mdcTriangle_t*) ( (picoByte_t*) surface + surface->ofsTriangles );
542                 for ( j = 0; j < surface->numTriangles; j++, triangle++ )
543                 {
544                         /* sea: swaps fixed */
545                         triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
546                         triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
547                         triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
548                 }
549
550                 /* swap st coords */
551                 texCoord = (mdcTexCoord_t*) ( (picoByte_t*) surface + surface->ofsSt );
552                 for ( j = 0; j < surface->numVerts; j++, texCoord++ )
553                 {
554                         texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
555                         texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
556                 }
557
558                 /* swap xyz/normals */
559                 vertex = (mdcVertex_t*) ( (picoByte_t*) surface + surface->ofsXyzNormals );
560                 for ( j = 0; j < ( surface->numVerts * surface->numBaseFrames ); j++, vertex++ )
561                 {
562                         vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
563                         vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
564                         vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
565                         vertex->normal   = _pico_little_short( vertex->normal );
566                 }
567
568                 /* swap xyz/compressed */
569                 vertexComp = (mdcXyzCompressed_t*) ( (picoByte_t*) surface + surface->ofsXyzCompressed );
570                 for ( j = 0; j < ( surface->numVerts * surface->numCompFrames ); j++, vertexComp++ )
571                 {
572                         vertexComp->ofsVec  = _pico_little_long( vertexComp->ofsVec );
573                 }
574
575                 /* swap base frames */
576                 mdcShort = (short *) ( (picoByte_t*) surface + surface->ofsFrameBaseFrames );
577                 for ( j = 0; j < mdc->numFrames; j++, mdcShort++ )
578                 {
579                         *mdcShort   = _pico_little_short( *mdcShort );
580                 }
581
582                 /* swap compressed frames */
583                 mdcShort = (short *) ( (picoByte_t*) surface + surface->ofsFrameCompFrames );
584                 for ( j = 0; j < mdc->numFrames; j++, mdcShort++ )
585                 {
586                         *mdcShort   = _pico_little_short( *mdcShort );
587                 }
588
589                 /* get next surface */
590                 surface = (mdcSurface_t*) ( (picoByte_t*) surface + surface->ofsEnd );
591         }
592
593         /* -------------------------------------------------
594            pico model creation
595            ------------------------------------------------- */
596
597         /* create new pico model */
598         picoModel = PicoNewModel();
599         if ( picoModel == NULL ) {
600                 _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
601                 _pico_free( bb0 );
602                 return NULL;
603         }
604
605         /* do model setup */
606         PicoSetModelFrameNum( picoModel, frameNum );
607         PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */
608         PicoSetModelName( picoModel, fileName );
609         PicoSetModelFileName( picoModel, fileName );
610
611         /* mdc surfaces become picomodel surfaces */
612         surface = (mdcSurface_t*) ( bb + mdc->ofsSurfaces );
613
614         /* run through mdc surfaces */
615         for ( i = 0; i < mdc->numSurfaces; i++ )
616         {
617                 /* allocate new pico surface */
618                 picoSurface = PicoNewSurface( picoModel );
619                 if ( picoSurface == NULL ) {
620                         _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
621                         PicoFreeModel( picoModel ); /* sea */
622                         _pico_free( bb0 );
623                         return NULL;
624                 }
625
626                 /* mdc model surfaces are all triangle meshes */
627                 PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
628
629                 /* set surface name */
630                 PicoSetSurfaceName( picoSurface, surface->name );
631
632                 /* create new pico shader -sea */
633                 picoShader = PicoNewShader( picoModel );
634                 if ( picoShader == NULL ) {
635                         _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
636                         PicoFreeModel( picoModel );
637                         _pico_free( bb0 );
638                         return NULL;
639                 }
640
641                 /* detox and set shader name */
642                 shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
643                 _pico_setfext( shader->name, "" );
644                 _pico_unixify( shader->name );
645                 PicoSetShaderName( picoShader, shader->name );
646
647                 /* associate current surface with newly created shader */
648                 PicoSetSurfaceShader( picoSurface, picoShader );
649
650                 /* copy indexes */
651                 triangle = (mdcTriangle_t *) ( (picoByte_t*) surface + surface->ofsTriangles );
652
653                 for ( j = 0; j < surface->numTriangles; j++, triangle++ )
654                 {
655                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 0 ), (picoIndex_t) triangle->indexes[ 0 ] );
656                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 1 ), (picoIndex_t) triangle->indexes[ 1 ] );
657                         PicoSetSurfaceIndex( picoSurface, ( j * 3 + 2 ), (picoIndex_t) triangle->indexes[ 2 ] );
658                 }
659
660                 /* copy vertexes */
661                 texCoord = (mdcTexCoord_t*) ( (picoByte_t *) surface + surface->ofsSt );
662                 mdcShort = (short *) ( (picoByte_t *) surface + surface->ofsXyzNormals ) + ( (int)*( (short *) ( (picoByte_t *) surface + surface->ofsFrameBaseFrames ) + frameNum ) * surface->numVerts * 4 );
663                 if ( surface->numCompFrames > 0 ) {
664                         mdcCompVert = (short *) ( (picoByte_t *) surface + surface->ofsFrameCompFrames ) + frameNum;
665                         if ( *mdcCompVert >= 0 ) {
666                                 vertexComp = (mdcXyzCompressed_t *) ( (picoByte_t *) surface + surface->ofsXyzCompressed ) + ( *mdcCompVert * surface->numVerts );
667                         }
668                 }
669
670                 for ( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort += 4 )
671                 {
672                         /* set vertex origin */
673                         xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];
674                         xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];
675                         xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];
676
677                         /* add compressed ofsVec */
678                         if ( surface->numCompFrames > 0 && *mdcCompVert >= 0 ) {
679                                 xyz[ 0 ] += ( (float) ( ( vertexComp->ofsVec ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
680                                 xyz[ 1 ] += ( (float) ( ( vertexComp->ofsVec >> 8 ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
681                                 xyz[ 2 ] += ( (float) ( ( vertexComp->ofsVec >> 16 ) & 255 ) - MDC_MAX_OFS ) * MDC_DIST_SCALE;
682                                 PicoSetSurfaceXYZ( picoSurface, j, xyz );
683
684                                 normal[ 0 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 0 ];
685                                 normal[ 1 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 1 ];
686                                 normal[ 2 ] = (float) mdcNormals[ ( vertexComp->ofsVec >> 24 ) ][ 2 ];
687                                 PicoSetSurfaceNormal( picoSurface, j, normal );
688
689                                 vertexComp++;
690                         }
691                         else
692                         {
693                                 PicoSetSurfaceXYZ( picoSurface, j, xyz );
694
695                                 /* decode lat/lng normal to 3 float normal */
696                                 lat = (float) ( ( *( mdcShort + 3 ) >> 8 ) & 0xff );
697                                 lng = (float) ( *( mdcShort + 3 ) & 0xff );
698                                 lat *= PICO_PI / 128;
699                                 lng *= PICO_PI / 128;
700                                 normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
701                                 normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
702                                 normal[ 2 ] = (picoVec_t) cos( lng );
703                                 PicoSetSurfaceNormal( picoSurface, j, normal );
704                         }
705
706                         /* set st coords */
707                         st[ 0 ] = texCoord->st[ 0 ];
708                         st[ 1 ] = texCoord->st[ 1 ];
709                         PicoSetSurfaceST( picoSurface, 0, j, st );
710
711                         /* set color */
712                         PicoSetSurfaceColor( picoSurface, 0, j, picoColor_white );
713                 }
714
715                 /* get next surface */
716                 surface = (mdcSurface_t*) ( (picoByte_t*) surface + surface->ofsEnd );
717         }
718
719         /* return the new pico model */
720         _pico_free( bb0 );
721         return picoModel;
722 }
723
724
725
726 /* pico file format module definition */
727 const picoModule_t picoModuleMDC =
728 {
729         "1.3",                          /* module version string */
730         "RtCW MDC",                     /* module display name */
731         "Arnout van Meer",              /* author's name */
732         "2002 Arnout van Meer",         /* module copyright */
733         {
734                 "mdc", NULL, NULL, NULL     /* default extensions to use */
735         },
736         _mdc_canload,                   /* validation routine */
737         _mdc_load,                      /* load routine */
738         NULL,                           /* save validation routine */
739         NULL                            /* save routine */
740 };