]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/l3dslib.c
eol style
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / l3dslib.c
1 /*
2 Copyright (C) 1999-2007 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 "inout.h"
29 #include "mathlib.h"
30 #include "trilib.h"
31 #include "l3dslib.h"
32 #include "token.h"
33 #include "fmodel.h"
34 #include "bspfile.h"
35
36 #define MAIN3DS       0x4D4D
37 #define EDIT3DS       0x3D3D  // this is the start of the editor config
38 #define EDIT_OBJECT   0x4000
39 #define OBJ_TRIMESH   0x4100
40 #define TRI_VERTEXL   0x4110
41 #define TRI_FACEL1    0x4120
42
43 #define MAXVERTS        2000
44
45 typedef struct {
46         int     v[4];
47 } tri;
48
49 float   fverts[MAXVERTS][3];
50 tri             tris[MAXTRIANGLES];
51
52 int     bytesread, level, numtris, totaltris;
53 int     vertsfound, trisfound;
54
55 triangle_t      *ptri;
56
57
58
59 void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles)
60 {
61         int pos, bit, i;
62
63         if (nodesList)
64         {
65                 *num_mesh_nodes = 1;
66                 memset(&(*nodesList)[0], 0, sizeof(mesh_node_t));
67                 strcpy((*nodesList)[0].name, "default");
68
69                 // set all of the tris to be used for the top node
70                 for(i = 0; i < (*numtriangles); i++)
71                 {
72                         pos = (i) >> 3;
73                         bit = 1 << ((i) & 7 );
74
75                         (*nodesList)[0].tris[pos] |= bit;
76                 }
77         }
78 }
79
80
81 // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
82 // start out with a vertex pool and vertex indices for triangles, we have to convert
83 // to raw, explicit triangles
84 void StoreAliasTriangles (void)
85 {
86         int             i, j, k;
87
88         if ((totaltris + numtris) > MAXTRIANGLES)
89                 Error ("Error: Too many triangles");
90
91         for (i=0; i<numtris ; i++)
92         {
93                 for (j=0 ; j<3 ; j++)
94                 {
95                         for (k=0 ; k<3 ; k++)
96                         {
97                                 ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
98                         }
99                 }
100         }
101         
102         totaltris += numtris;
103         numtris = 0;
104         vertsfound = 0;
105         trisfound = 0;
106 }
107
108
109 int ParseVertexL (FILE *input)
110 {
111         int                             i, j, startbytesread, numverts;
112         unsigned short  tshort;
113
114         if (vertsfound)
115                 Error ("Error: Multiple vertex chunks");
116
117         vertsfound = 1;
118         startbytesread = bytesread;
119
120         if (feof(input))
121                 Error ("Error: unexpected end of file");
122
123         fread(&tshort, sizeof(tshort), 1, input);
124         bytesread += sizeof(tshort);
125         numverts = (int)tshort;
126
127         if (numverts > MAXVERTS)
128                 Error ("Error: Too many vertices");
129
130         for (i=0 ; i<numverts ; i++)
131         {
132                 for (j=0 ; j<3 ; j++)
133                 {
134                         if (feof(input))
135                                 Error ("Error: unexpected end of file");
136
137                         fread(&fverts[i][j], sizeof(float), 1, input);
138                         bytesread += sizeof(float);
139                 }
140         }
141
142         if (vertsfound && trisfound)
143                 StoreAliasTriangles ();
144
145         return bytesread - startbytesread;
146 }
147
148
149 int ParseFaceL1 (FILE *input)
150 {
151
152         int                             i, j, startbytesread;
153         unsigned short  tshort;
154
155         if (trisfound)
156                 Error ("Error: Multiple face chunks");
157
158         trisfound = 1;
159         startbytesread = bytesread;
160
161         if (feof(input))
162                 Error ("Error: unexpected end of file");
163
164         fread(&tshort, sizeof(tshort), 1, input);
165         bytesread += sizeof(tshort);
166         numtris = (int)tshort;
167
168         if (numtris > MAXTRIANGLES)
169                 Error ("Error: Too many triangles");
170
171         for (i=0 ; i<numtris ; i++)
172         {
173                 for (j=0 ; j<4 ; j++)
174                 {
175                         if (feof(input))
176                                 Error ("Error: unexpected end of file");
177
178                         fread(&tshort, sizeof(tshort), 1, input);
179                         bytesread += sizeof(tshort);
180                         tris[i].v[j] = (int)tshort;
181                 }
182         }
183
184         if (vertsfound && trisfound)
185                 StoreAliasTriangles ();
186
187         return bytesread - startbytesread;
188 }
189
190
191 int ParseChunk (FILE *input)
192 {
193 #define BLOCK_SIZE      4096
194         char                    temp[BLOCK_SIZE];
195         unsigned short  type;
196         int                             i, length, w, t, retval;
197
198         level++;
199         retval = 0;
200
201 // chunk type
202         if (feof(input))
203                 Error ("Error: unexpected end of file");
204
205         fread(&type, sizeof(type), 1, input);
206         bytesread += sizeof(type);
207
208 // chunk length
209         if (feof(input))
210                 Error ("Error: unexpected end of file");
211
212         fread (&length, sizeof(length), 1, input);
213         bytesread += sizeof(length);
214         w = length - 6;
215
216 // process chunk if we care about it, otherwise skip it
217         switch (type)
218         {
219         case TRI_VERTEXL:
220                 w -= ParseVertexL (input);
221                 goto ParseSubchunk;
222
223         case TRI_FACEL1:
224                 w -= ParseFaceL1 (input);
225                 goto ParseSubchunk;
226
227         case EDIT_OBJECT:
228         // read the name
229                 i = 0;
230
231                 do
232                 {
233                         if (feof(input))
234                                 Error ("Error: unexpected end of file");
235
236                         fread (&temp[i], 1, 1, input);
237                         i++;
238                         w--;
239                         bytesread++;
240                 } while (temp[i-1]);
241
242         case MAIN3DS:
243         case OBJ_TRIMESH:
244         case EDIT3DS:
245         // parse through subchunks
246 ParseSubchunk:
247                 while (w > 0)
248                 {
249                         w -= ParseChunk (input);
250                 }
251
252                 retval = length;
253                 goto Done;
254
255         default:
256         // skip other chunks
257                 while (w > 0)
258                 {
259                         t = w;
260
261                         if (t > BLOCK_SIZE)
262                                 t = BLOCK_SIZE;
263
264                         if (feof(input))
265                                 Error ("Error: unexpected end of file");
266
267                         fread (&temp, t, 1, input);
268                         bytesread += t;
269
270                         w -= t;
271                 }
272
273                 retval = length;
274                 goto Done;
275         }
276
277 Done:
278         level--;
279         return retval;
280 }
281
282
283 void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
284 {
285         FILE        *input;
286         short int       tshort;
287
288         if (nodesList)
289         {
290                 *num_mesh_nodes = 0;
291                 *nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
292         }
293
294         bytesread = 0;
295         level = 0;
296         numtris = 0;
297         totaltris = 0;
298         vertsfound = 0;
299         trisfound = 0;
300
301         if ((input = fopen(filename, "rb")) == 0) {
302                 fprintf(stderr,"reader: could not open file '%s'\n", filename);
303                 exit(0);
304         }
305
306         fread(&tshort, sizeof(tshort), 1, input);
307
308 // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
309 // no MAIN3DS
310         if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
311                 fprintf(stderr,"File is not a 3DS file.\n");
312                 exit(0);
313         }
314
315 // back to top of file so we can parse the first chunk descriptor
316         fseek(input, 0, SEEK_SET);
317
318         ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
319
320         *pptri = ptri;
321
322 // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
323 // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
324         ParseChunk (input);
325
326         if (vertsfound || trisfound)
327                 Error ("Incomplete triangle set");
328
329         *numtriangles = totaltris;
330
331         fclose (input);
332
333         DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
334 }
335
336 //==========================================================================
337 //
338 // LoadASC
339 //
340 //==========================================================================
341
342 void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
343 {
344         int                     i, j;
345         int                     vertexCount;
346         struct
347         {
348                 float v[3];
349         }                       *vList;
350         int                     triCount;
351         triangle_t      *tList;
352         float           x, y, z;
353 //      float           x2, y2, z2;
354 //      float           rx, ry, rz;
355         qboolean        goodObject;
356
357         if (nodesList)
358         {
359                 *num_mesh_nodes = 0;
360                 *nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
361         }
362
363         TK_OpenSource(fileName);
364
365         goodObject = false;
366         while(goodObject == false)
367         {
368                 TK_Beyond(TK_C_NAMED);
369                 TK_Beyond(TK_OBJECT);
370                 TK_Beyond(TK_C_TRI);
371                 TK_Beyond(TK_MESH);
372                 TK_BeyondRequire(TK_C_VERTICES, TK_COLON);
373                 TK_FetchRequire(TK_INTNUMBER);
374                 vertexCount = tk_IntNumber;
375                 if(vertexCount > 0)
376                 {
377                         goodObject = true;
378                 }
379         }
380         TK_BeyondRequire(TK_C_FACES, TK_COLON);
381         TK_FetchRequire(TK_INTNUMBER);
382         triCount = tk_IntNumber;
383         if(triCount >= MAXTRIANGLES)
384         {
385                 Error("Too many triangles in file %s\n", fileName);
386         }
387         *triangleCount = triCount;
388         tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
389         *triList = tList;
390
391         memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
392         TK_BeyondRequire(TK_C_VERTEX, TK_LIST);
393
394 /*      rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
395         //rx = (rotation[0]/360.0)*2.0*M_PI;
396         ry = (rotation[1]/360.0)*2.0*M_PI;
397         rz = (rotation[2]/360.0)*2.0*M_PI;
398 */
399         vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
400         for(i = 0; i < vertexCount; i++)
401         {
402                 TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);
403                 if(tk_IntNumber != i)
404                 {
405                         Error("File '%s', line %d:\nVertex index mismatch.\n",
406                                 tk_SourceName, tk_Line);
407                 }
408                 TK_FetchRequireFetch(TK_COLON);
409
410                 TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
411                 x = tk_FloatNumber;
412                 TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
413                 y = tk_FloatNumber;
414                 TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
415                 z = tk_FloatNumber;
416
417 /*              x2 = x*cos(rz)+y*sin(rz);
418                 y2 = -x*sin(rz)+y*cos(rz);
419                 x = x2;
420                 y = y2;
421                 y2 = y*cos(rx)+z*sin(rx);
422                 z2 = -y*sin(rx)+z*cos(rx);
423                 y = y2;
424                 z = z2;
425                 x2 = x*cos(ry)-z*sin(ry);
426                 z2 = x*sin(ry)+z*cos(ry);
427                 x = x2;
428                 z = z2;
429 */
430                 vList[i].v[0] = x;
431                 vList[i].v[1] = y;
432                 vList[i].v[2] = z;
433         }
434         TK_BeyondRequire(TK_C_FACE, TK_LIST);
435         for(i = 0; i < triCount; i++)
436         {
437                 TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);
438                 if(tk_IntNumber != i)
439                 {
440                         Error("File '%s', line %d:\nTriangle index mismatch.\n",
441                                 tk_SourceName, tk_Line);
442                 }
443                 for(j = 0; j < 3; j++)
444                 {
445                         TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);
446                         TK_FetchRequire(TK_INTNUMBER);
447                         if(tk_IntNumber >= vertexCount)
448                         {
449                                 Error("File '%s', line %d:\nVertex number"
450                                         " > vertexCount: %d\n", tk_SourceName, tk_Line,
451                                         tk_IntNumber);
452                         }
453                         tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
454                         tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
455                         tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
456 #ifdef _QDATA
457                         tList[i].indicies[2-j] = tk_IntNumber;
458 #endif
459                 }
460
461 /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
462                         "  v2: %f, %f, %f\n", i,
463                         tList[i].verts[0][0],
464                         tList[i].verts[0][1],
465                         tList[i].verts[0][2],
466                         tList[i].verts[1][0],
467                         tList[i].verts[1][1],
468                         tList[i].verts[1][2],
469                         tList[i].verts[2][0],
470                         tList[i].verts[2][1],
471                         tList[i].verts[2][2]);
472 */
473         }
474
475         DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
476 }