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