]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/common/trilib.c
89978949e818858dde96ecad47724f20c11b76d0
[xonotic/netradiant.git] / tools / quake3 / common / trilib.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 // trilib.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 "polyset.h"\r
30 #include "trilib.h"\r
31 \r
32 // on disk representation of a face\r
33 \r
34 \r
35 #define FLOAT_START     99999.0\r
36 #define FLOAT_END       -FLOAT_START\r
37 #define MAGIC       123322\r
38 \r
39 //#define NOISY 1\r
40 \r
41 #if defined (__linux__) || defined (__APPLE__)\r
42 #define strlwr strlower\r
43 #endif\r
44 \r
45 typedef struct {\r
46         float v[3];\r
47 } vector;\r
48 \r
49 typedef struct\r
50 {\r
51         vector n;    /* normal */\r
52         vector p;    /* point */\r
53         vector c;    /* color */\r
54         float  u;    /* u */\r
55         float  v;    /* v */\r
56 } aliaspoint_t;\r
57 \r
58 typedef struct {\r
59         aliaspoint_t    pt[3];\r
60 } tf_triangle;\r
61 \r
62 \r
63 static void ByteSwapTri (tf_triangle *tri)\r
64 {\r
65         int             i;\r
66         \r
67         for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)\r
68         {\r
69                 ((int *)tri)[i] = BigLong (((int *)tri)[i]);\r
70         }\r
71 }\r
72 \r
73 static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri )\r
74 {\r
75         tf_triangle tri;\r
76         int i;\r
77 \r
78         for (i = 0; i < count; ++i) {\r
79                 int             j;\r
80 \r
81                 fread( &tri, sizeof(tf_triangle), 1, input );\r
82                 ByteSwapTri (&tri);\r
83                 for (j=0 ; j<3 ; j++)\r
84                 {\r
85                         int             k;\r
86 \r
87                         for (k=0 ; k<3 ; k++)\r
88                         {\r
89                                 ptri->verts[j][k] = tri.pt[j].p.v[k];\r
90                                 ptri->normals[j][k] = tri.pt[j].n.v[k];\r
91 //                              ptri->colors[j][k] = tri.pt[j].c.v[k];\r
92                         }\r
93 \r
94                         ptri->texcoords[j][0] = tri.pt[j].u;\r
95                         ptri->texcoords[j][1] = tri.pt[j].v;\r
96                 }\r
97 \r
98                 ptri++;\r
99                 if ((ptri - tripool ) >= POLYSET_MAXTRIANGLES)\r
100                         Error ("Error: too many triangles; increase POLYSET_MAXTRIANGLES\n");\r
101         }\r
102 }\r
103 \r
104 void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets )\r
105 {\r
106         FILE        *input;\r
107         float       start;\r
108         char        name[256], tex[256];\r
109         int         i, count, magic, pset = 0;\r
110         triangle_t      *ptri;\r
111         polyset_t       *pPSET;\r
112         int                     iLevel;\r
113         int                     exitpattern;\r
114         float           t;\r
115 \r
116         t = -FLOAT_START;\r
117         *((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);\r
118         *((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);\r
119         *((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);\r
120         *((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);\r
121 \r
122         if ((input = fopen(filename, "rb")) == 0)\r
123                 Error ("reader: could not open file '%s'", filename);\r
124 \r
125         iLevel = 0;\r
126 \r
127         fread(&magic, sizeof(int), 1, input);\r
128         if (BigLong(magic) != MAGIC)\r
129                 Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);\r
130 \r
131         pPSET = calloc( 1, POLYSET_MAXPOLYSETS * sizeof( polyset_t ) );\r
132         ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );\r
133 \r
134         *ppPSET = pPSET;\r
135 \r
136         while (feof(input) == 0) {\r
137                 if (fread(&start,  sizeof(float), 1, input) < 1)\r
138                         break;\r
139                 *(int *)&start = BigLong(*(int *)&start);\r
140                 if (*(int *)&start != exitpattern)\r
141                 {\r
142                         if (start == FLOAT_START) {\r
143                                 /* Start of an object or group of objects. */\r
144                                 i = -1;\r
145                                 do {\r
146                                         /* There are probably better ways to read a string from */\r
147                                         /* a file, but this does allow you to do error checking */\r
148                                         /* (which I'm not doing) on a per character basis.      */\r
149                                         ++i;\r
150                                         fread( &(name[i]), sizeof( char ), 1, input);\r
151                                 } while( name[i] != '\0' );\r
152         \r
153                                 if ( i != 0 )\r
154                                         strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );\r
155                                 else\r
156                                         strcpy( pPSET[pset].name , "(unnamed)" );\r
157                                 strlwr( pPSET[pset].name );\r
158 \r
159 //                              indent();\r
160 //                              fprintf(stdout,"OBJECT START: %s\n",name);\r
161                                 fread( &count, sizeof(int), 1, input);\r
162                                 count = BigLong(count);\r
163                                 ++iLevel;\r
164                                 if (count != 0) {\r
165 //                                      indent();\r
166 //                                      fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);\r
167         \r
168                                         i = -1;\r
169                                         do {\r
170                                                 ++i;\r
171                                                 fread( &(tex[i]), sizeof( char ), 1, input);\r
172                                         } while( tex[i] != '\0' );\r
173 \r
174 /*\r
175                                         if ( i != 0 )\r
176                                                 strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );\r
177                                         else\r
178                                                 strcpy( pPSET[pset].texname, "(unnamed)" );\r
179                                         strlwr( pPSET[pset].texname );\r
180 */\r
181 \r
182 //                                      indent();\r
183 //                                      fprintf(stdout,"  Object texture name: '%s'\n",tex);\r
184                                 }\r
185         \r
186                                 /* Else (count == 0) this is the start of a group, and */\r
187                                 /* no texture name is present. */\r
188                         }\r
189                         else if (start == FLOAT_END) {\r
190                                 /* End of an object or group. Yes, the name should be */\r
191                                 /* obvious from context, but it is in here just to be */\r
192                                 /* safe and to provide a little extra information for */\r
193                                 /* those who do not wish to write a recursive reader. */\r
194                                 /* Mea culpa. */\r
195                                 --iLevel;\r
196                                 i = -1;\r
197                                 do {\r
198                                         ++i;\r
199                                         fread( &(name[i]), sizeof( char ), 1, input);\r
200                                 } while( name[i] != '\0' );\r
201 \r
202                                 if ( i != 0 )\r
203                                         strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );\r
204                                 else\r
205                                         strcpy( pPSET[pset].name , "(unnamed)" );\r
206 \r
207                                 strlwr( pPSET[pset].name );\r
208         \r
209 //                              indent();\r
210 //                              fprintf(stdout,"OBJECT END: %s\n",name);\r
211                                 continue;\r
212                         }\r
213                 }\r
214 \r
215 //\r
216 // read the triangles\r
217 //              \r
218                 if ( count > 0 )\r
219                 {\r
220                         pPSET[pset].triangles = ptri;\r
221                         ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );\r
222                         ptri += count;\r
223                         pPSET[pset].numtriangles = count;\r
224                         if ( ++pset >= POLYSET_MAXPOLYSETS )\r
225                         {\r
226                                 Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n");\r
227                         }\r
228                 }\r
229         }\r
230 \r
231         *numpsets = pset;\r
232 \r
233         fclose (input);\r
234 }\r
235 \r