2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
25 polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris ){
27 int numNewPolysets = 0;
28 int numSplitPolysets = 0;
32 for ( p = 0; p < numpolysets; p++ )
34 numNewPolysets += psets[p].numtriangles / maxTris + 1;
37 if ( numNewPolysets == numpolysets ) {
41 printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
43 newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );
45 for ( np = 0, op = 0; op < numpolysets; op++ )
47 numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
48 if ( numSplitPolysets == 1 ) {
49 memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
56 // split this pset into multiple smaller psets
57 for ( p = 0; p < numSplitPolysets; p++, np++ )
59 memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
61 newpsets[np].triangles = psets[op].triangles + sumTriangles;
63 if ( sumTriangles + maxTris > psets[op].numtriangles ) {
64 newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
67 newpsets[np].numtriangles = maxTris;
70 sumTriangles += newpsets[np].numtriangles;
75 *pNumNewPolysets = numNewPolysets;
80 polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet ){
82 polyset_t *finalpsets;
87 if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) ) {
88 _3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
91 Error( "TRI files no longer supported" );
93 // TRI_LoadPolysets( file, &psets, numpolysets );
99 for ( i = 0; i < psets; i++ )
103 for ( j = 0; j < psets[i].numtriangles; j++ )
110 // split polysets if necessary
112 finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
117 polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets ){
119 int sumtriangles = 0;
121 polyset_t *oldpsets = psets;
124 // no tag checking because this is an $oldbase and thus shouldn't have any
127 for ( p = 0; p < numpolysets; p++ )
129 sumtriangles += oldpsets[p].numtriangles;
132 psets = calloc( 1, sizeof( polyset_t ) );
133 psets[0].numtriangles = sumtriangles;
134 psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
136 // each call to "LoadPolysets" only allocates a single large chunk of
137 // triangle memory that is utilized by all the polysets loaded by
139 memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
141 free( oldpsets[0].triangles );
147 static float SnapFloat( float x ){
150 x *= 1.0f / MD3_XYZ_SCALE;
158 void Polyset_SnapSets( polyset_t *psets, int numpolysets ){
161 for ( p = 0; p < numpolysets; p++ )
165 for ( t = 0; t < psets[p].numtriangles; t++ )
169 for ( v = 0; v < 3; v++ )
171 psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
172 psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
173 psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
179 void Polyset_ComputeNormals( polyset_t *psets, int numpolysets ){
182 int vertexIndex[MD3_MAX_TRIANGLES][3];
183 vec3_t verts[MD3_MAX_VERTS];
184 vec3_t normals[MD3_MAX_VERTS];
185 vec3_t faceNormals[MD3_MAX_TRIANGLES];
188 // iterate through polysets
190 for ( p = 0; p < numpolysets; p++ )
192 int numUniqueVertices = 0;
194 assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
196 memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
197 memset( verts, 0, sizeof( verts ) );
198 memset( normals, 0, sizeof( normals ) );
203 for ( t = 0; t < psets[p].numtriangles; t++ )
207 for ( j = 0; j < 3; j++ )
209 for ( i = 0; i < numUniqueVertices; i++ )
211 if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) ) {
215 if ( i == numUniqueVertices ) {
216 vertexIndex[t][j] = numUniqueVertices;
217 VectorCopy( ( psets[p].triangles[t].verts[j] ), ( verts[numUniqueVertices] ) );
222 vertexIndex[t][j] = i;
228 // compute face normals
230 for ( t = 0; t < psets[p].numtriangles; t++ )
232 vec3_t side0, side1, facenormal;
234 VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
235 VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1 );
237 CrossProduct( side0, side1, facenormal );
238 VectorNormalize( facenormal, faceNormals[t] );
242 // sum normals and copy them back
244 for ( i = 0; i < numUniqueVertices; i++ )
246 for ( t = 0; t < psets[p].numtriangles; t++ )
248 if ( vertexIndex[t][0] == i ||
249 vertexIndex[t][1] == i ||
250 vertexIndex[t][2] == i ) {
251 normals[i][0] += faceNormals[t][0];
252 normals[i][1] += faceNormals[t][1];
253 normals[i][2] += faceNormals[t][2];
256 VectorNormalize( normals[i], normals[i] );
260 for ( t = 0; t < psets[p].numtriangles; t++ )
262 VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
263 VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
264 VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );