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