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