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 + -
显示快捷键?