allow more light contributions to the grid; remove a weird fudge
[divverent/netradiant.git] / tools / quake3 / q3data / polyset.c
1 /*
2 Copyright (C) 1999-2006 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 {
27         int p, np, op;
28         int numNewPolysets = 0;
29         int numSplitPolysets = 0;
30         polyset_t *newpsets;
31         int sumTriangles = 0;
32
33         for ( p = 0; p < numpolysets; p++ )
34         {
35                 numNewPolysets += psets[p].numtriangles / maxTris + 1;
36         }
37
38         if ( numNewPolysets == numpolysets )
39                 return psets;
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                 {
50                         memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
51                         np++;
52                 }
53                 else
54                 {
55                         sumTriangles = 0;
56
57                         // split this pset into multiple smaller psets
58                         for ( p = 0; p < numSplitPolysets; p++, np++ )
59                         {
60                                 memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
61
62                                 newpsets[np].triangles = psets[op].triangles + sumTriangles;
63
64                                 if ( sumTriangles + maxTris > psets[op].numtriangles )
65                                         newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
66                                 else
67                                         newpsets[np].numtriangles = maxTris;
68
69                                 sumTriangles += newpsets[np].numtriangles;
70                         }
71                 }
72         }
73
74         *pNumNewPolysets = numNewPolysets;
75
76         return newpsets;
77 }
78
79 polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )
80 {
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         else 
90                 Error( "TRI files no longer supported" );
91 //              TRI_LoadPolysets( file, &psets, numpolysets );
92
93 /*
94         //
95         // scale polysets
96         //
97         for ( i = 0; i < psets; i++ )
98         {
99                 int j;
100
101                 for ( j = 0; j < psets[i].numtriangles; j++ )
102                 {
103                 }
104         }
105 */
106
107         //
108         // split polysets if necessary
109         //
110         finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
111
112         return finalpsets;
113 }
114
115 polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )
116 {
117         int p;
118         int sumtriangles = 0;
119
120         polyset_t *oldpsets = psets;
121
122         //
123         // no tag checking because this is an $oldbase and thus shouldn't have any
124         // tags
125         //
126         for ( p = 0; p < numpolysets; p++ )
127         {
128                 sumtriangles += oldpsets[p].numtriangles;
129         }
130
131         psets = calloc( 1, sizeof( polyset_t ) );
132         psets[0].numtriangles = sumtriangles;
133         psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
134
135         // each call to "LoadPolysets" only allocates a single large chunk of
136         // triangle memory that is utilized by all the polysets loaded by
137         // that one call
138         memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
139
140         free( oldpsets[0].triangles );
141         free( oldpsets );
142
143         return psets;
144 }
145
146 static float SnapFloat( float x )
147 {
148         int ix;
149
150         x *= 1.0f / MD3_XYZ_SCALE;
151         ix = ( int ) x;
152         x = ( float ) ix;
153         x *= MD3_XYZ_SCALE;
154
155         return x;
156 }
157
158 void Polyset_SnapSets( polyset_t *psets, int numpolysets )
159 {
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 {
182         int p;
183         int i, t;
184         int vertexIndex[MD3_MAX_TRIANGLES][3];
185         vec3_t verts[MD3_MAX_VERTS];
186         vec3_t normals[MD3_MAX_VERTS];
187         vec3_t faceNormals[MD3_MAX_TRIANGLES];
188
189         //
190         // iterate through polysets
191         //
192         for ( p = 0; p < numpolysets; p++ )
193         {
194                 int numUniqueVertices = 0;
195
196                 assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
197
198                 memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
199                 memset( verts, 0, sizeof( verts ) );
200                 memset( normals, 0, sizeof( normals ) );
201
202                 //
203                 // unique vertices
204                 //
205                 for ( t = 0; t < psets[p].numtriangles; t++ )
206                 {
207                         int j;
208
209                         for ( j = 0; j < 3; j++ )
210                         {
211                                 for ( i = 0; i < numUniqueVertices; i++ )
212                                 {
213                                         if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )
214                                         {
215                                                 break;
216                                         }
217                                 }
218                                 if ( i == numUniqueVertices )
219                                 {
220                                         vertexIndex[t][j] = numUniqueVertices;
221                                         VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );
222                                         numUniqueVertices++;
223                                 }
224                                 else
225                                 {
226                                         vertexIndex[t][j] = i;
227                                 }
228                         }
229                 }
230
231                 //
232                 // compute face normals
233                 //
234                 for ( t = 0; t < psets[p].numtriangles; t++ )
235                 {
236                         vec3_t side0, side1, facenormal;
237
238                         VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
239                         VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);
240
241                         CrossProduct( side0, side1, facenormal );
242                         VectorNormalize( facenormal, faceNormals[t] );
243                 }
244
245                 //
246                 // sum normals and copy them back
247                 //
248                 for ( i = 0; i < numUniqueVertices; i++ )
249                 {
250                         for ( t = 0; t < psets[p].numtriangles; t++ )
251                         {
252                                 if ( vertexIndex[t][0] == i ||
253                                          vertexIndex[t][1] == i ||
254                                          vertexIndex[t][2] == i )
255                                 {
256                                         normals[i][0] += faceNormals[t][0];
257                                         normals[i][1] += faceNormals[t][1];
258                                         normals[i][2] += faceNormals[t][2];
259                                 }
260                         }
261                         VectorNormalize( normals[i], normals[i] );
262                 }
263
264
265                 for ( t = 0; t < psets[p].numtriangles; t++ )
266                 {
267                         VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
268                         VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
269                         VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
270                 }
271         }
272 }
273