257 lines
6 KiB
C
257 lines
6 KiB
C
|
#include <assert.h>
|
||
|
#include "q3data.h"
|
||
|
|
||
|
polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris )
|
||
|
{
|
||
|
int p, np, op;
|
||
|
int numNewPolysets = 0;
|
||
|
int numSplitPolysets = 0;
|
||
|
polyset_t *newpsets;
|
||
|
int sumTriangles = 0;
|
||
|
|
||
|
for ( p = 0; p < numpolysets; p++ )
|
||
|
{
|
||
|
numNewPolysets += psets[p].numtriangles / maxTris + 1;
|
||
|
}
|
||
|
|
||
|
if ( numNewPolysets == numpolysets )
|
||
|
return psets;
|
||
|
|
||
|
printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
|
||
|
|
||
|
newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );
|
||
|
|
||
|
for ( np = 0, op = 0; op < numpolysets; op++ )
|
||
|
{
|
||
|
numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
|
||
|
if ( numSplitPolysets == 1 )
|
||
|
{
|
||
|
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
|
||
|
np++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sumTriangles = 0;
|
||
|
|
||
|
// split this pset into multiple smaller psets
|
||
|
for ( p = 0; p < numSplitPolysets; p++, np++ )
|
||
|
{
|
||
|
memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
|
||
|
|
||
|
newpsets[np].triangles = psets[op].triangles + sumTriangles;
|
||
|
|
||
|
if ( sumTriangles + maxTris > psets[op].numtriangles )
|
||
|
newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
|
||
|
else
|
||
|
newpsets[np].numtriangles = maxTris;
|
||
|
|
||
|
sumTriangles += newpsets[np].numtriangles;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pNumNewPolysets = numNewPolysets;
|
||
|
|
||
|
return newpsets;
|
||
|
}
|
||
|
|
||
|
polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )
|
||
|
{
|
||
|
polyset_t *psets;
|
||
|
polyset_t *finalpsets;
|
||
|
|
||
|
//
|
||
|
// load the frame
|
||
|
//
|
||
|
if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) )
|
||
|
_3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
|
||
|
else
|
||
|
Error( "TRI files no longer supported" );
|
||
|
// TRI_LoadPolysets( file, &psets, numpolysets );
|
||
|
|
||
|
/*
|
||
|
//
|
||
|
// scale polysets
|
||
|
//
|
||
|
for ( i = 0; i < psets; i++ )
|
||
|
{
|
||
|
int j;
|
||
|
|
||
|
for ( j = 0; j < psets[i].numtriangles; j++ )
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// split polysets if necessary
|
||
|
//
|
||
|
finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
|
||
|
|
||
|
return finalpsets;
|
||
|
}
|
||
|
|
||
|
polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )
|
||
|
{
|
||
|
int p;
|
||
|
int sumtriangles = 0;
|
||
|
|
||
|
polyset_t *oldpsets = psets;
|
||
|
|
||
|
//
|
||
|
// no tag checking because this is an $oldbase and thus shouldn't have any
|
||
|
// tags
|
||
|
//
|
||
|
for ( p = 0; p < numpolysets; p++ )
|
||
|
{
|
||
|
sumtriangles += oldpsets[p].numtriangles;
|
||
|
}
|
||
|
|
||
|
psets = calloc( 1, sizeof( polyset_t ) );
|
||
|
psets[0].numtriangles = sumtriangles;
|
||
|
psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
|
||
|
|
||
|
// each call to "LoadPolysets" only allocates a single large chunk of
|
||
|
// triangle memory that is utilized by all the polysets loaded by
|
||
|
// that one call
|
||
|
memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
|
||
|
|
||
|
free( oldpsets[0].triangles );
|
||
|
free( oldpsets );
|
||
|
|
||
|
return psets;
|
||
|
}
|
||
|
|
||
|
static float SnapFloat( float x )
|
||
|
{
|
||
|
int ix;
|
||
|
|
||
|
x *= 1.0f / MD3_XYZ_SCALE;
|
||
|
ix = ( int ) x;
|
||
|
x = ( float ) ix;
|
||
|
x *= MD3_XYZ_SCALE;
|
||
|
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
void Polyset_SnapSets( polyset_t *psets, int numpolysets )
|
||
|
{
|
||
|
int p;
|
||
|
|
||
|
for ( p = 0; p < numpolysets; p++ )
|
||
|
{
|
||
|
int t;
|
||
|
|
||
|
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||
|
{
|
||
|
int v;
|
||
|
|
||
|
for ( v = 0; v < 3; v++ )
|
||
|
{
|
||
|
psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
|
||
|
psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
|
||
|
psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Polyset_ComputeNormals( polyset_t *psets, int numpolysets )
|
||
|
{
|
||
|
int p;
|
||
|
int i, t;
|
||
|
int vertexIndex[MD3_MAX_TRIANGLES][3];
|
||
|
vec3_t verts[MD3_MAX_VERTS];
|
||
|
vec3_t normals[MD3_MAX_VERTS];
|
||
|
vec3_t faceNormals[MD3_MAX_TRIANGLES];
|
||
|
|
||
|
//
|
||
|
// iterate through polysets
|
||
|
//
|
||
|
for ( p = 0; p < numpolysets; p++ )
|
||
|
{
|
||
|
int numUniqueVertices = 0;
|
||
|
|
||
|
assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
|
||
|
|
||
|
memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
|
||
|
memset( verts, 0, sizeof( verts ) );
|
||
|
memset( normals, 0, sizeof( normals ) );
|
||
|
|
||
|
//
|
||
|
// unique vertices
|
||
|
//
|
||
|
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||
|
{
|
||
|
int j;
|
||
|
|
||
|
for ( j = 0; j < 3; j++ )
|
||
|
{
|
||
|
for ( i = 0; i < numUniqueVertices; i++ )
|
||
|
{
|
||
|
if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( i == numUniqueVertices )
|
||
|
{
|
||
|
vertexIndex[t][j] = numUniqueVertices;
|
||
|
VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );
|
||
|
numUniqueVertices++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vertexIndex[t][j] = i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// compute face normals
|
||
|
//
|
||
|
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||
|
{
|
||
|
vec3_t side0, side1, facenormal;
|
||
|
|
||
|
VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
|
||
|
VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);
|
||
|
|
||
|
CrossProduct( side0, side1, facenormal );
|
||
|
VectorNormalize( facenormal, faceNormals[t] );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// sum normals and copy them back
|
||
|
//
|
||
|
for ( i = 0; i < numUniqueVertices; i++ )
|
||
|
{
|
||
|
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||
|
{
|
||
|
if ( vertexIndex[t][0] == i ||
|
||
|
vertexIndex[t][1] == i ||
|
||
|
vertexIndex[t][2] == i )
|
||
|
{
|
||
|
normals[i][0] += faceNormals[t][0];
|
||
|
normals[i][1] += faceNormals[t][1];
|
||
|
normals[i][2] += faceNormals[t][2];
|
||
|
}
|
||
|
}
|
||
|
VectorNormalize( normals[i], normals[i] );
|
||
|
}
|
||
|
|
||
|
|
||
|
for ( t = 0; t < psets[p].numtriangles; t++ )
|
||
|
{
|
||
|
VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
|
||
|
VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
|
||
|
VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
|
||
|
// set this up ready for re-computation of normals over surfaces.
|
||
|
psets[p].triangles[t].normal_recomputed[0] = 0;
|
||
|
psets[p].triangles[t].normal_recomputed[1] = 0;
|
||
|
psets[p].triangles[t].normal_recomputed[2] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|