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