]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3data/polyset.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake3 / q3data / polyset.c
1 #include <assert.h>\r
2 #include "q3data.h"\r
3 \r
4 polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris )\r
5 {\r
6         int p, np, op;\r
7         int numNewPolysets = 0;\r
8         int numSplitPolysets = 0;\r
9         polyset_t *newpsets;\r
10         int sumTriangles = 0;\r
11 \r
12         for ( p = 0; p < numpolysets; p++ )\r
13         {\r
14                 numNewPolysets += psets[p].numtriangles / maxTris + 1;\r
15         }\r
16 \r
17         if ( numNewPolysets == numpolysets )\r
18                 return psets;\r
19 \r
20         printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );\r
21 \r
22         newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );\r
23 \r
24         for ( np = 0, op = 0; op < numpolysets; op++ )\r
25         {\r
26                 numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;\r
27                 if (  numSplitPolysets == 1 )\r
28                 {\r
29                         memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );\r
30                         np++;\r
31                 }\r
32                 else\r
33                 {\r
34                         sumTriangles = 0;\r
35 \r
36                         // split this pset into multiple smaller psets\r
37                         for ( p = 0; p < numSplitPolysets; p++, np++ )\r
38                         {\r
39                                 memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );\r
40 \r
41                                 newpsets[np].triangles = psets[op].triangles + sumTriangles;\r
42 \r
43                                 if ( sumTriangles + maxTris > psets[op].numtriangles )\r
44                                         newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;\r
45                                 else\r
46                                         newpsets[np].numtriangles = maxTris;\r
47 \r
48                                 sumTriangles += newpsets[np].numtriangles;\r
49                         }\r
50                 }\r
51         }\r
52 \r
53         *pNumNewPolysets = numNewPolysets;\r
54 \r
55         return newpsets;\r
56 }\r
57 \r
58 polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )\r
59 {\r
60         polyset_t *psets;\r
61         polyset_t *finalpsets;\r
62 \r
63         //\r
64         // load the frame\r
65         //\r
66         if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) )\r
67                 _3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );\r
68         else \r
69                 Error( "TRI files no longer supported" );\r
70 //              TRI_LoadPolysets( file, &psets, numpolysets );\r
71 \r
72 /*\r
73         //\r
74         // scale polysets\r
75         //\r
76         for ( i = 0; i < psets; i++ )\r
77         {\r
78                 int j;\r
79 \r
80                 for ( j = 0; j < psets[i].numtriangles; j++ )\r
81                 {\r
82                 }\r
83         }\r
84 */\r
85 \r
86         //\r
87         // split polysets if necessary\r
88         //\r
89         finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );\r
90 \r
91         return finalpsets;\r
92 }\r
93 \r
94 polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )\r
95 {\r
96         int p;\r
97         int sumtriangles = 0;\r
98 \r
99         polyset_t *oldpsets = psets;\r
100 \r
101         //\r
102         // no tag checking because this is an $oldbase and thus shouldn't have any\r
103         // tags\r
104         //\r
105         for ( p = 0; p < numpolysets; p++ )\r
106         {\r
107                 sumtriangles += oldpsets[p].numtriangles;\r
108         }\r
109 \r
110         psets = calloc( 1, sizeof( polyset_t ) );\r
111         psets[0].numtriangles = sumtriangles;\r
112         psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );\r
113 \r
114         // each call to "LoadPolysets" only allocates a single large chunk of\r
115         // triangle memory that is utilized by all the polysets loaded by\r
116         // that one call\r
117         memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );\r
118 \r
119         free( oldpsets[0].triangles );\r
120         free( oldpsets );\r
121 \r
122         return psets;\r
123 }\r
124 \r
125 static float SnapFloat( float x )\r
126 {\r
127         int ix;\r
128 \r
129         x *= 1.0f / MD3_XYZ_SCALE;\r
130         ix = ( int ) x;\r
131         x = ( float ) ix;\r
132         x *= MD3_XYZ_SCALE;\r
133 \r
134         return x;\r
135 }\r
136 \r
137 void Polyset_SnapSets( polyset_t *psets, int numpolysets )\r
138 {\r
139         int p;\r
140 \r
141         for ( p = 0; p < numpolysets; p++ )\r
142         {\r
143                 int t;\r
144 \r
145                 for ( t = 0; t < psets[p].numtriangles; t++ )\r
146                 {\r
147                         int v;\r
148 \r
149                         for ( v = 0; v < 3; v++ )\r
150                         {\r
151                                 psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );\r
152                                 psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );\r
153                                 psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );\r
154                         }\r
155                 }\r
156         }\r
157 }\r
158 \r
159 void Polyset_ComputeNormals( polyset_t *psets, int numpolysets )\r
160 {\r
161         int p;\r
162         int i, t;\r
163         int vertexIndex[MD3_MAX_TRIANGLES][3];\r
164         vec3_t verts[MD3_MAX_VERTS];\r
165         vec3_t normals[MD3_MAX_VERTS];\r
166         vec3_t faceNormals[MD3_MAX_TRIANGLES];\r
167 \r
168         //\r
169         // iterate through polysets\r
170         //\r
171         for ( p = 0; p < numpolysets; p++ )\r
172         {\r
173                 int numUniqueVertices = 0;\r
174 \r
175                 assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );\r
176 \r
177                 memset( vertexIndex, 0xff, sizeof( vertexIndex ) );\r
178                 memset( verts, 0, sizeof( verts ) );\r
179                 memset( normals, 0, sizeof( normals ) );\r
180 \r
181                 //\r
182                 // unique vertices\r
183                 //\r
184                 for ( t = 0; t < psets[p].numtriangles; t++ )\r
185                 {\r
186                         int j;\r
187 \r
188                         for ( j = 0; j < 3; j++ )\r
189                         {\r
190                                 for ( i = 0; i < numUniqueVertices; i++ )\r
191                                 {\r
192                                         if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )\r
193                                         {\r
194                                                 break;\r
195                                         }\r
196                                 }\r
197                                 if ( i == numUniqueVertices )\r
198                                 {\r
199                                         vertexIndex[t][j] = numUniqueVertices;\r
200                                         VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );\r
201                                         numUniqueVertices++;\r
202                                 }\r
203                                 else\r
204                                 {\r
205                                         vertexIndex[t][j] = i;\r
206                                 }\r
207                         }\r
208                 }\r
209 \r
210                 //\r
211                 // compute face normals\r
212                 //\r
213                 for ( t = 0; t < psets[p].numtriangles; t++ )\r
214                 {\r
215                         vec3_t side0, side1, facenormal;\r
216 \r
217                         VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );\r
218                         VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);\r
219 \r
220                         CrossProduct( side0, side1, facenormal );\r
221                         VectorNormalize( facenormal, faceNormals[t] );\r
222                 }\r
223 \r
224                 //\r
225                 // sum normals and copy them back\r
226                 //\r
227                 for ( i = 0; i < numUniqueVertices; i++ )\r
228                 {\r
229                         for ( t = 0; t < psets[p].numtriangles; t++ )\r
230                         {\r
231                                 if ( vertexIndex[t][0] == i ||\r
232                                          vertexIndex[t][1] == i ||\r
233                                          vertexIndex[t][2] == i )\r
234                                 {\r
235                                         normals[i][0] += faceNormals[t][0];\r
236                                         normals[i][1] += faceNormals[t][1];\r
237                                         normals[i][2] += faceNormals[t][2];\r
238                                 }\r
239                         }\r
240                         VectorNormalize( normals[i], normals[i] );\r
241                 }\r
242 \r
243 \r
244                 for ( t = 0; t < psets[p].numtriangles; t++ )\r
245                 {\r
246                         VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );\r
247                         VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );\r
248                         VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );\r
249                 }\r
250         }\r
251 }\r
252 \r