AllocWinding: fix handling of compiler enforced alignment of double
[divverent/netradiant.git] / tools / quake3 / common / l3dslib.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 //
23 // l3dslib.c: library for loading triangles from an Alias triangle file
24 //
25
26 #include <stdio.h>
27 #include "cmdlib.h"
28 #include "mathlib.h"
29 #include "trilib.h"
30 #include "l3dslib.h"
31
32 #define MAIN3DS       0x4D4D
33 #define EDIT3DS       0x3D3D  // this is the start of the editor config
34 #define EDIT_OBJECT   0x4000
35 #define OBJ_TRIMESH   0x4100
36 #define TRI_VERTEXL   0x4110
37 #define TRI_FACEL1    0x4120
38
39 #define MAXVERTS        2000
40 #define MAXTRIANGLES    750
41
42 typedef struct {
43         int     v[4];
44 } tri;
45
46 float   fverts[MAXVERTS][3];
47 tri             tris[MAXTRIANGLES];
48
49 int     bytesread, level, numtris, totaltris;
50 int     vertsfound, trisfound;
51
52 triangle_t      *ptri;
53
54
55 // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
56 // start out with a vertex pool and vertex indices for triangles, we have to convert
57 // to raw, explicit triangles
58 void StoreAliasTriangles (void)
59 {
60         int             i, j, k;
61
62         if ((totaltris + numtris) > MAXTRIANGLES)
63                 Error ("Error: Too many triangles");
64
65         for (i=0; i<numtris ; i++)
66         {
67                 for (j=0 ; j<3 ; j++)
68                 {
69                         for (k=0 ; k<3 ; k++)
70                         {
71                                 ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
72                         }
73                 }
74         }
75         
76         totaltris += numtris;
77         numtris = 0;
78         vertsfound = 0;
79         trisfound = 0;
80 }
81
82
83 int ParseVertexL (FILE *input)
84 {
85         int                             i, j, startbytesread, numverts;
86         unsigned short  tshort;
87
88         if (vertsfound)
89                 Error ("Error: Multiple vertex chunks");
90
91         vertsfound = 1;
92         startbytesread = bytesread;
93
94         if (feof(input))
95                 Error ("Error: unexpected end of file");
96
97         fread(&tshort, sizeof(tshort), 1, input);
98         bytesread += sizeof(tshort);
99         numverts = (int)tshort;
100
101         if (numverts > MAXVERTS)
102                 Error ("Error: Too many vertices");
103
104         for (i=0 ; i<numverts ; i++)
105         {
106                 for (j=0 ; j<3 ; j++)
107                 {
108                         if (feof(input))
109                                 Error ("Error: unexpected end of file");
110
111                         fread(&fverts[i][j], sizeof(float), 1, input);
112                         bytesread += sizeof(float);
113                 }
114         }
115
116         if (vertsfound && trisfound)
117                 StoreAliasTriangles ();
118
119         return bytesread - startbytesread;
120 }
121
122
123 int ParseFaceL1 (FILE *input)
124 {
125
126         int                             i, j, startbytesread;
127         unsigned short  tshort;
128
129         if (trisfound)
130                 Error ("Error: Multiple face chunks");
131
132         trisfound = 1;
133         startbytesread = bytesread;
134
135         if (feof(input))
136                 Error ("Error: unexpected end of file");
137
138         fread(&tshort, sizeof(tshort), 1, input);
139         bytesread += sizeof(tshort);
140         numtris = (int)tshort;
141
142         if (numtris > MAXTRIANGLES)
143                 Error ("Error: Too many triangles");
144
145         for (i=0 ; i<numtris ; i++)
146         {
147                 for (j=0 ; j<4 ; j++)
148                 {
149                         if (feof(input))
150                                 Error ("Error: unexpected end of file");
151
152                         fread(&tshort, sizeof(tshort), 1, input);
153                         bytesread += sizeof(tshort);
154                         tris[i].v[j] = (int)tshort;
155                 }
156         }
157
158         if (vertsfound && trisfound)
159                 StoreAliasTriangles ();
160
161         return bytesread - startbytesread;
162 }
163
164
165 int ParseChunk (FILE *input)
166 {
167 #define BLOCK_SIZE      4096
168         char                    temp[BLOCK_SIZE];
169         unsigned short  type;
170         int                             i, length, w, t, retval;
171
172         level++;
173         retval = 0;
174
175 // chunk type
176         if (feof(input))
177                 Error ("Error: unexpected end of file");
178
179         fread(&type, sizeof(type), 1, input);
180         bytesread += sizeof(type);
181
182 // chunk length
183         if (feof(input))
184                 Error ("Error: unexpected end of file");
185
186         fread (&length, sizeof(length), 1, input);
187         bytesread += sizeof(length);
188         w = length - 6;
189
190 // process chunk if we care about it, otherwise skip it
191         switch (type)
192         {
193         case TRI_VERTEXL:
194                 w -= ParseVertexL (input);
195                 goto ParseSubchunk;
196
197         case TRI_FACEL1:
198                 w -= ParseFaceL1 (input);
199                 goto ParseSubchunk;
200
201         case EDIT_OBJECT:
202         // read the name
203                 i = 0;
204
205                 do
206                 {
207                         if (feof(input))
208                                 Error ("Error: unexpected end of file");
209
210                         fread (&temp[i], 1, 1, input);
211                         i++;
212                         w--;
213                         bytesread++;
214                 } while (temp[i-1]);
215
216         case MAIN3DS:
217         case OBJ_TRIMESH:
218         case EDIT3DS:
219         // parse through subchunks
220 ParseSubchunk:
221                 while (w > 0)
222                 {
223                         w -= ParseChunk (input);
224                 }
225
226                 retval = length;
227                 goto Done;
228
229         default:
230         // skip other chunks
231                 while (w > 0)
232                 {
233                         t = w;
234
235                         if (t > BLOCK_SIZE)
236                                 t = BLOCK_SIZE;
237
238                         if (feof(input))
239                                 Error ("Error: unexpected end of file");
240
241                         fread (&temp, t, 1, input);
242                         bytesread += t;
243
244                         w -= t;
245                 }
246
247                 retval = length;
248                 goto Done;
249         }
250
251 Done:
252         level--;
253         return retval;
254 }
255
256
257 void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
258 {
259         FILE        *input;
260         short int       tshort;
261
262         bytesread = 0;
263         level = 0;
264         numtris = 0;
265         totaltris = 0;
266         vertsfound = 0;
267         trisfound = 0;
268
269         if ((input = fopen(filename, "rb")) == 0) {
270                 fprintf(stderr,"reader: could not open file '%s'\n", filename);
271                 exit(0);
272         }
273
274         fread(&tshort, sizeof(tshort), 1, input);
275
276 // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
277 // no MAIN3DS
278         if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
279                 fprintf(stderr,"File is not a 3DS file.\n");
280                 exit(0);
281         }
282
283 // back to top of file so we can parse the first chunk descriptor
284         fseek(input, 0, SEEK_SET);
285
286         ptri = safe_malloc (MAXTRIANGLES * sizeof(triangle_t));
287
288         *pptri = ptri;
289
290 // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
291 // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
292         ParseChunk (input);
293
294         if (vertsfound || trisfound)
295                 Error ("Incomplete triangle set");
296
297         *numtriangles = totaltris;
298
299         fclose (input);
300 }
301