models.c
来自「quake3工具源码。包括生成bsp文件」· C语言 代码 · 共 2,185 行 · 第 1/4 页
C
2,185 行
// int width, height, iwidth, iheight, swidth;
// float s_scale, t_scale;
// float scale;
// vec3_t mins, maxs;
float *pbasevert;
/*
//
// find bounds of all the verts on the base frame
//
ClearBounds (mins, maxs);
for (i=0 ; i<numtri ; i++)
for (j=0 ; j<3 ; j++)
AddPointToBounds (ptri[i].verts[j], mins, maxs);
for (i=0 ; i<3 ; i++)
{
mins[i] = floor(mins[i]);
maxs[i] = ceil(maxs[i]);
}
width = maxs[0] - mins[0];
height = maxs[2] - mins[2];
if (!g_data.fixedwidth)
{ // old style
scale = 8;
if (width*scale >= 150)
scale = 150.0 / width;
if (height*scale >= 190)
scale = 190.0 / height;
s_scale = t_scale = scale;
iwidth = ceil(width*s_scale);
iheight = ceil(height*t_scale);
iwidth += 4;
iheight += 4;
}
else
{ // new style
iwidth = g_data.fixedwidth / 2;
iheight = g_data.fixedheight;
s_scale = (float)(iwidth-4) / width;
t_scale = (float)(iheight-4) / height;
}
// make the width a multiple of 4; some hardware requires this, and it ensures
// dword alignment for each scan
swidth = iwidth*2;
g_data.skinwidth = (swidth + 3) & ~3;
g_data.skinheight = iheight;
*/
for (i=0; i<numtri ; i++, ptri++, bTri++)
{
int j;
for (j=0 ; j<3 ; j++)
{
pbasevert = ptri->verts[j];
VectorCopy( ptri->verts[j], bTri->v[j].xyz);
VectorCopy( ptri->normals[j], bTri->v[j].normal );
bTri->v[j].st[0] = ptri->texcoords[j][0];
bTri->v[j].st[1] = ptri->texcoords[j][1];
}
}
}
static void BuildBaseFrame( const char *filename, ObjectAnimationFrame_t *pOAF )
{
baseTriangle_t *bTri;
baseVertex_t *bVert;
int i, j;
// calculate the base triangles
for ( i = 0; i < g_data.model.numSurfaces; i++ )
{
CopyTrianglesToBaseTriangles( pOAF->surfaces[i]->triangles,
pOAF->surfaces[i]->numtriangles,
g_data.surfData[i].baseTriangles );
strcpy( g_data.surfData[i].header.name, pOAF->surfaces[i]->name );
g_data.surfData[i].header.numTriangles = pOAF->surfaces[i]->numtriangles;
g_data.surfData[i].header.numVerts = 0;
/*
if ( strstr( filename, gamedir + 1 ) )
{
strcpy( shaderName, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
}
else
{
strcpy( shaderName, filename );
}
if ( strrchr( shaderName, '/' ) )
*( strrchr( shaderName, '/' ) + 1 ) = 0;
strcpy( shaderName, pOAF->surfaces[i]->materialname );
*/
strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, pOAF->surfaces[i]->materialname );
g_data.surfData[i].header.numShaders++;
}
//
// compute unique vertices for each polyset
//
for ( i = 0; i < g_data.model.numSurfaces; i++ )
{
int t;
for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
{
bTri = &g_data.surfData[i].baseTriangles[t];
for (j=0 ; j<3 ; j++)
{
int k;
bVert = &bTri->v[j];
// get the xyz index
for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
{
if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
{
break; // this vertex is already in the base vertex list
}
}
if (k == g_data.surfData[i].header.numVerts) { // new index
g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
g_data.surfData[i].header.numVerts++;
}
bVert->index = k;
g_data.surfData[i].lodTriangles[t][j] = k;
}
}
}
//
// find tags
//
for ( i = 0; i < g_data.model.numSurfaces; i++ )
{
if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
{
if ( pOAF->surfaces[i]->numtriangles != 1 )
{
Error( "tag polysets must consist of only one triangle" );
}
if ( strstr( filename, "_flash.md3" ) && !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) )
continue;
printf( "found tag '%s'\n", pOAF->surfaces[i]->name );
g_data.model.numTags++;
}
}
}
static int LoadModelFile( const char *filename, polyset_t **psets, int *numpolysets )
{
int time1;
char file1[1024];
const char *frameFile;
printf ("---------------------\n");
if ( filename[1] != ':' )
{
frameFile = filename;
sprintf( file1, "%s/%s", g_cddir, frameFile );
}
else
{
strcpy( file1, filename );
}
time1 = FileTime (file1);
if (time1 == -1)
Error ("%s doesn't exist", file1);
//
// load the base triangles
//
*psets = Polyset_LoadSets( file1, numpolysets, g_data.maxSurfaceTris );
//
// snap polysets
//
Polyset_SnapSets( *psets, *numpolysets );
if ( strstr( file1, ".3ds" ) || strstr( file1, ".3DS" ) )
return MD3_TYPE_BASE3DS;
Error( "Unknown model file type" );
return MD3_TYPE_UNKNOWN;
}
/*
=================
Cmd_Base
=================
*/
void Cmd_Base( void )
{
char filename[1024];
GetToken( qfalse );
sprintf( filename, "%s/%s", g_cddir, token );
LoadBase( filename );
}
static void LoadBase( const char *filename )
{
int numpolysets;
polyset_t *psets;
int i;
ObjectAnimationFrame_t oaf;
// determine polyset splitting threshold
if ( TokenAvailable() )
{
GetToken( qfalse );
g_data.maxSurfaceTris = atoi( token );
}
else
{
g_data.maxSurfaceTris = MAX_SURFACE_TRIS - 1;
}
g_data.type = LoadModelFile( filename, &psets, &numpolysets );
Polyset_ComputeNormals( psets, numpolysets );
g_data.model.numSurfaces = numpolysets;
memset( &oaf, 0, sizeof( oaf ) );
for ( i = 0; i < numpolysets; i++ )
{
oaf.surfaces[i] = &psets[i];
oaf.numSurfaces = numpolysets;
}
BuildBaseFrame( filename, &oaf );
free( psets[0].triangles );
free( psets );
}
/*
=================
Cmd_SpriteBase
$spritebase xorg yorg width height
Generate a single square for the model
=================
*/
void Cmd_SpriteBase (void)
{
float xl, yl, width, height;
g_data.type = MD3_TYPE_SPRITE;
GetToken (qfalse);
xl = atof(token);
GetToken (qfalse);
yl = atof(token);
GetToken (qfalse);
width = atof(token);
GetToken (qfalse);
height = atof(token);
// if (g_skipmodel || g_release || g_archive)
// return;
printf ("---------------------\n");
g_data.surfData[0].verts[0] = ( float * ) calloc( 1, sizeof( float ) * 6 * 4 );
g_data.surfData[0].header.numVerts = 4;
g_data.surfData[0].verts[0][0+0] = 0;
g_data.surfData[0].verts[0][0+1] = -xl;
g_data.surfData[0].verts[0][0+2] = yl + height;
g_data.surfData[0].verts[0][0+3] = -1;
g_data.surfData[0].verts[0][0+4] = 0;
g_data.surfData[0].verts[0][0+5] = 0;
g_data.surfData[0].baseVertexes[0].st[0] = 0;
g_data.surfData[0].baseVertexes[0].st[1] = 0;
g_data.surfData[0].verts[0][6+0] = 0;
g_data.surfData[0].verts[0][6+1] = -xl - width;
g_data.surfData[0].verts[0][6+2] = yl + height;
g_data.surfData[0].verts[0][6+3] = -1;
g_data.surfData[0].verts[0][6+4] = 0;
g_data.surfData[0].verts[0][6+5] = 0;
g_data.surfData[0].baseVertexes[1].st[0] = 1;
g_data.surfData[0].baseVertexes[1].st[1] = 0;
g_data.surfData[0].verts[0][12+0] = 0;
g_data.surfData[0].verts[0][12+1] = -xl - width;
g_data.surfData[0].verts[0][12+2] = yl;
g_data.surfData[0].verts[0][12+3] = -1;
g_data.surfData[0].verts[0][12+4] = 0;
g_data.surfData[0].verts[0][12+5] = 0;
g_data.surfData[0].baseVertexes[2].st[0] = 1;
g_data.surfData[0].baseVertexes[2].st[1] = 1;
g_data.surfData[0].verts[0][18+0] = 0;
g_data.surfData[0].verts[0][18+1] = -xl;
g_data.surfData[0].verts[0][18+2] = yl;
g_data.surfData[0].verts[0][18+3] = -1;
g_data.surfData[0].verts[0][18+4] = 0;
g_data.surfData[0].verts[0][18+5] = 0;
g_data.surfData[0].baseVertexes[3].st[0] = 0;
g_data.surfData[0].baseVertexes[3].st[1] = 1;
g_data.surfData[0].lodTriangles[0][0] = 0;
g_data.surfData[0].lodTriangles[0][1] = 1;
g_data.surfData[0].lodTriangles[0][2] = 2;
g_data.surfData[0].lodTriangles[1][0] = 2;
g_data.surfData[0].lodTriangles[1][1] = 3;
g_data.surfData[0].lodTriangles[1][2] = 0;
g_data.model.numSurfaces = 1;
g_data.surfData[0].header.numTriangles = 2;
g_data.surfData[0].header.numVerts = 4;
g_data.model.numFrames = 1;
}
/*
===========================================================================
FRAME GRABBING
===========================================================================
*/
/*
===============
GrabFrame
===============
*/
void GrabFrame (const char *frame)
{
int i, j, k;
char file1[1024];
md3Frame_t *fr;
md3Tag_t tagParent;
float *frameXyz;
float *frameNormals;
const char *framefile;
polyset_t *psets;
qboolean parentTagExists = qfalse;
int numpolysets;
int numtags = 0;
int tagcount;
// the frame 'run1' will be looked for as either
// run.1 or run1.tri, so the new alias sequence save
// feature an be used
if ( frame[1] != ':' )
{
// framefile = FindFrameFile (frame);
framefile = frame;
sprintf (file1, "%s/%s",g_cddir, framefile);
}
else
{
strcpy( file1, frame );
}
printf ("grabbing %s\n", file1);
if (g_data.model.numFrames >= MD3_MAX_FRAMES)
Error ("model.numFrames >= MD3_MAX_FRAMES");
fr = &g_data.frames[g_data.model.numFrames];
strcpy (fr->name, frame);
psets = Polyset_LoadSets( file1, &numpolysets, g_data.maxSurfaceTris );
//
// snap polysets
//
Polyset_SnapSets( psets, numpolysets );
//
// compute vertex normals
//
Polyset_ComputeNormals( psets, numpolysets );
//
// flip everything to compensate for the alias coordinate system
// and perform global scale and adjust
//
for ( i = 0; i < g_data.model.numSurfaces; i++ )
{
triangle_t *ptri = psets[i].triangles;
int t;
for ( t = 0; t < psets[i].numtriangles; t++ )
{
for ( j = 0; j < 3; j++ )
{
// scale and adjust
for ( k = 0 ; k < 3 ; k++ ) {
ptri[t].verts[j][k] = ptri[t].verts[j][k] * g_data.scale_up +
g_data.adjust[k];
if ( ptri[t].verts[j][k] > 1023 ||
ptri[t].verts[j][k] < -1023 )
{
Error( "Model extents too large" );
}
}
}
}
}
//
// find and count tags, locate parent tag
//
for ( i = 0; i < numpolysets; i++ )
{
if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
{
if ( strstr( psets[i].name, "tag_parent" ) == psets[i].name )
{
if ( strstr( psets[i].name, "tag_parent" ) )
{
float tri[3][3];
if ( parentTagExists )
Error( "Multiple parent tags not allowed" );
memcpy( tri[0], psets[i].triangles[0].verts[0], sizeof( float ) * 3 );
memcpy( tri[1], psets[i].triangles[0].verts[1], sizeof( float ) * 3 );
memcpy( tri[2], psets[i].triangles[0].verts[2], sizeof( float ) * 3 );
MD3_ComputeTagFromTri( &tagParent, tri );
strcpy( tagParent.name, psets[i].name );
g_data.tags[g_data.model.numFrames][numtags] = tagParent;
parentTagExists = qtrue;
}
}
numtags++;
}
if ( strcmp( psets[i].name, g_data.surfData[i].header.name ) )
{
Error( "Mismatched surfaces from base('%s') to frame('%s') in model '%s'\n", g_data.surfData[i].header.name, psets[i].name, g_modelname );
}
}
if ( numtags != g_data.model.numTags )
{
Error( "mismatched number of tags in frame(%d) vs. base(%d)", numtags, g_data.model.numTags );
}
if ( numpolysets != g_data.model.numSurfaces )
{
Error( "mismatched number of surfaces in frame(%d) vs. base(%d)", numpolysets-numtags, g_data.model.numSurfaces );
}
//
// prepare to accumulate bounds and normals
//
ClearBounds( fr->bounds[0], fr->bounds[1] );
//
// store the frame's vertices in the same order as the base. This assumes the
// triangles and vertices in this frame are in exactly the same order as in the
// base
//
for ( i = 0, tagcount = 0; i < numpolysets; i++ )
{
int t;
triangle_t *pTris = psets[i].triangles;
strcpy( g_data.surfData[i].header.name, psets[i].name );
//
// parent tag adjust
//
if ( parentTagExists ) {
for ( t = 0; t < psets[i].numtriangles; t++ )
{
for ( j = 0; j < 3 ; j++ )
{
vec3_t tmp;
VectorSubtract( pTris[t].verts[j], tagParent.origin, tmp );
pTris[t].verts[j][0] = DotProduct( tmp, tagParent.axis[0] );
pTris[t].verts[j][1] = DotProduct( tmp, tagParent.axis[1] );
pTris[t].verts[j][2] = DotProduct( tmp, tagParent.axis[2] );
VectorCopy( pTris[t].normals[j], tmp );
pTris[t].normals[j][0] = DotProduct( tmp, tagParent.axis[0] );
pTris[t].normals[j][1] = DotProduct( tmp, tagParent.axis[1] );
pTris[t].normals[j][2] = DotProduct( tmp, tagParent.axis[2] );
}
}
}
//
// compute tag data
//
if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
{
md3Tag_t *pTag = &g_data.tags[g_data.model.numFrames][tagcount];
float tri[3][3];
strcpy( pTag->name, psets[i].name );
memcpy( tri[0], pTris[0].verts[0], sizeof( float ) * 3 );
memcpy( tri[1], pTris[0].verts[1], sizeof( float ) * 3 );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?