]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/common/l3dslib.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / 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 // l3dslib.c: library for loading triangles from an Alias triangle file\r
23 //\r
24 \r
25 #include <stdio.h>\r
26 #include "cmdlib.h"\r
27 #include "inout.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 \r
41 typedef struct {\r
42         int     v[4];\r
43 } tri;\r
44 \r
45 float   fverts[MAXVERTS][3];\r
46 tri             tris[MAXTRIANGLES];\r
47 \r
48 int     bytesread, level, numtris, totaltris;\r
49 int     vertsfound, trisfound;\r
50 \r
51 triangle_t      *ptri;\r
52 \r
53 \r
54 // Alias stores triangles as 3 explicit vertices in .tri files, so even though we\r
55 // start out with a vertex pool and vertex indices for triangles, we have to convert\r
56 // to raw, explicit triangles\r
57 void StoreAliasTriangles (void)\r
58 {\r
59         int             i, j, k;\r
60 \r
61         if ((totaltris + numtris) > MAXTRIANGLES)\r
62                 Error ("Error: Too many triangles");\r
63 \r
64         for (i=0; i<numtris ; i++)\r
65         {\r
66                 for (j=0 ; j<3 ; j++)\r
67                 {\r
68                         for (k=0 ; k<3 ; k++)\r
69                         {\r
70                                 ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];\r
71                         }\r
72                 }\r
73         }\r
74         \r
75         totaltris += numtris;\r
76         numtris = 0;\r
77         vertsfound = 0;\r
78         trisfound = 0;\r
79 }\r
80 \r
81 \r
82 int ParseVertexL (FILE *input)\r
83 {\r
84         int                             i, j, startbytesread, numverts;\r
85         unsigned short  tshort;\r
86 \r
87         if (vertsfound)\r
88                 Error ("Error: Multiple vertex chunks");\r
89 \r
90         vertsfound = 1;\r
91         startbytesread = bytesread;\r
92 \r
93         if (feof(input))\r
94                 Error ("Error: unexpected end of file");\r
95 \r
96         fread(&tshort, sizeof(tshort), 1, input);\r
97         bytesread += sizeof(tshort);\r
98         numverts = (int)tshort;\r
99 \r
100         if (numverts > MAXVERTS)\r
101                 Error ("Error: Too many vertices");\r
102 \r
103         for (i=0 ; i<numverts ; i++)\r
104         {\r
105                 for (j=0 ; j<3 ; j++)\r
106                 {\r
107                         if (feof(input))\r
108                                 Error ("Error: unexpected end of file");\r
109 \r
110                         fread(&fverts[i][j], sizeof(float), 1, input);\r
111                         bytesread += sizeof(float);\r
112                 }\r
113         }\r
114 \r
115         if (vertsfound && trisfound)\r
116                 StoreAliasTriangles ();\r
117 \r
118         return bytesread - startbytesread;\r
119 }\r
120 \r
121 \r
122 int ParseFaceL1 (FILE *input)\r
123 {\r
124 \r
125         int                             i, j, startbytesread;\r
126         unsigned short  tshort;\r
127 \r
128         if (trisfound)\r
129                 Error ("Error: Multiple face chunks");\r
130 \r
131         trisfound = 1;\r
132         startbytesread = bytesread;\r
133 \r
134         if (feof(input))\r
135                 Error ("Error: unexpected end of file");\r
136 \r
137         fread(&tshort, sizeof(tshort), 1, input);\r
138         bytesread += sizeof(tshort);\r
139         numtris = (int)tshort;\r
140 \r
141         if (numtris > MAXTRIANGLES)\r
142                 Error ("Error: Too many triangles");\r
143 \r
144         for (i=0 ; i<numtris ; i++)\r
145         {\r
146                 for (j=0 ; j<4 ; j++)\r
147                 {\r
148                         if (feof(input))\r
149                                 Error ("Error: unexpected end of file");\r
150 \r
151                         fread(&tshort, sizeof(tshort), 1, input);\r
152                         bytesread += sizeof(tshort);\r
153                         tris[i].v[j] = (int)tshort;\r
154                 }\r
155         }\r
156 \r
157         if (vertsfound && trisfound)\r
158                 StoreAliasTriangles ();\r
159 \r
160         return bytesread - startbytesread;\r
161 }\r
162 \r
163 \r
164 int ParseChunk (FILE *input)\r
165 {\r
166 #define BLOCK_SIZE      4096\r
167         char                    temp[BLOCK_SIZE];\r
168         unsigned short  type;\r
169         int                             i, length, w, t, retval;\r
170 \r
171         level++;\r
172         retval = 0;\r
173 \r
174 // chunk type\r
175         if (feof(input))\r
176                 Error ("Error: unexpected end of file");\r
177 \r
178         fread(&type, sizeof(type), 1, input);\r
179         bytesread += sizeof(type);\r
180 \r
181 // chunk length\r
182         if (feof(input))\r
183                 Error ("Error: unexpected end of file");\r
184 \r
185         fread (&length, sizeof(length), 1, input);\r
186         bytesread += sizeof(length);\r
187         w = length - 6;\r
188 \r
189 // process chunk if we care about it, otherwise skip it\r
190         switch (type)\r
191         {\r
192         case TRI_VERTEXL:\r
193                 w -= ParseVertexL (input);\r
194                 goto ParseSubchunk;\r
195 \r
196         case TRI_FACEL1:\r
197                 w -= ParseFaceL1 (input);\r
198                 goto ParseSubchunk;\r
199 \r
200         case EDIT_OBJECT:\r
201         // read the name\r
202                 i = 0;\r
203 \r
204                 do\r
205                 {\r
206                         if (feof(input))\r
207                                 Error ("Error: unexpected end of file");\r
208 \r
209                         fread (&temp[i], 1, 1, input);\r
210                         i++;\r
211                         w--;\r
212                         bytesread++;\r
213                 } while (temp[i-1]);\r
214 \r
215         case MAIN3DS:\r
216         case OBJ_TRIMESH:\r
217         case EDIT3DS:\r
218         // parse through subchunks\r
219 ParseSubchunk:\r
220                 while (w > 0)\r
221                 {\r
222                         w -= ParseChunk (input);\r
223                 }\r
224 \r
225                 retval = length;\r
226                 goto Done;\r
227 \r
228         default:\r
229         // skip other chunks\r
230                 while (w > 0)\r
231                 {\r
232                         t = w;\r
233 \r
234                         if (t > BLOCK_SIZE)\r
235                                 t = BLOCK_SIZE;\r
236 \r
237                         if (feof(input))\r
238                                 Error ("Error: unexpected end of file");\r
239 \r
240                         fread (&temp, t, 1, input);\r
241                         bytesread += t;\r
242 \r
243                         w -= t;\r
244                 }\r
245 \r
246                 retval = length;\r
247                 goto Done;\r
248         }\r
249 \r
250 Done:\r
251         level--;\r
252         return retval;\r
253 }\r
254 \r
255 \r
256 void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)\r
257 {\r
258         FILE        *input;\r
259         short int       tshort;\r
260 \r
261         bytesread = 0;\r
262         level = 0;\r
263         numtris = 0;\r
264         totaltris = 0;\r
265         vertsfound = 0;\r
266         trisfound = 0;\r
267 \r
268         if ((input = fopen(filename, "rb")) == 0) {\r
269                 fprintf(stderr,"reader: could not open file '%s'\n", filename);\r
270                 exit(0);\r
271         }\r
272 \r
273         fread(&tshort, sizeof(tshort), 1, input);\r
274 \r
275 // should only be MAIN3DS, but some files seem to start with EDIT3DS, with\r
276 // no MAIN3DS\r
277         if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {\r
278                 fprintf(stderr,"File is not a 3DS file.\n");\r
279                 exit(0);\r
280         }\r
281 \r
282 // back to top of file so we can parse the first chunk descriptor\r
283         fseek(input, 0, SEEK_SET);\r
284 \r
285         ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));\r
286 \r
287         *pptri = ptri;\r
288 \r
289 // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |\r
290 // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks\r
291         ParseChunk (input);\r
292 \r
293         if (vertsfound || trisfound)\r
294                 Error ("Incomplete triangle set");\r
295 \r
296         *numtriangles = totaltris;\r
297 \r
298         fclose (input);\r
299 }\r
300 \r