3dslib.c

来自「quake3工具源码。包括生成bsp文件」· C语言 代码 · 共 631 行 · 第 1/2 页

C
631
字号
#include <assert.h>
#include "q3data.h"

static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose );

static qboolean s_verbose;

#define MAX_MATERIALS 100
#define MAX_NAMED_OBJECTS 100
#define MAX_MESH_MATERIAL_GROUPS 100
#define MAX_TRI_OBJECTS 512

static char s_buffer[1000000];

static int ReadString( FILE *fp, char *buffer )
{
	int i = 0;
	int bytesRead = 0;

	do
	{
		fread( &buffer[i], 1, sizeof( char ), fp );
		bytesRead++;
	} while ( buffer[i++] != 0 );
	buffer[i] = 0;

	return bytesRead;
}

static int ReadChunkAndLength( FILE *fp, short *chunk, long *len )
{
	if ( fread( chunk, sizeof( short ), 1, fp ) != 1 )
		return 0;
	if ( fread( len, sizeof( long ), 1, fp ) != 1 )
		Error( "Unexpected EOF found" );
	return 1;
}

static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen )
{
	unsigned short chunkID;
	long chunkLen;
	long bytesRead = 0;

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
		case _3DS_CHUNK_MAT_MAPNAME:
			fread( buffer, chunkLen - 6, 1, fp );
			break;
		default:
			fread( s_buffer, chunkLen - 6, 1, fp );
			break;
		}
		bytesRead += chunkLen;
		if ( bytesRead >= thisChunkLen )
			return;
	}
}

static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat )
{
	long chunkLen;
	unsigned short chunkID;
	long bytesRead = 0;
	_3DSMaterial_t mat;
	char curdir[1024];
	char buffer[2048];

	memset( &mat, 0, sizeof( mat ) );

	if ( s_verbose )
		printf( "    >>> MATERIAL LIST\n" );

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
			case _3DS_CHUNK_MAT_NAME:
				fread( mat.name, chunkLen - 6, 1, fp );
				if ( s_verbose )
					printf( "        found mat name '%s'\n", mat.name );
				break;
			case _3DS_CHUNK_TEXMAP:
				LoadMapName( fp, mat.texture, chunkLen - 6 );
				if ( s_verbose )
					printf( "        found texture '%s'\n", mat.texture );
				break;
			case _3DS_CHUNK_SPECMAP:
				LoadMapName( fp, mat.specular, chunkLen - 6 );
				if ( s_verbose )
					printf( "        found specular map '%s'\n", mat.specular );
				break;
			case _3DS_CHUNK_OPACMAP:
				LoadMapName( fp, mat.opacity, chunkLen - 6 );
				if ( s_verbose )
					printf( "        found opacity map '%s'\n", mat.opacity );
				break;
			case _3DS_CHUNK_REFLMAP:
				LoadMapName( fp, mat.reflection, chunkLen - 6 );
				if ( s_verbose )
					printf( "        found reflection map '%s'\n", mat.reflection );
				break;
			case _3DS_CHUNK_BUMPMAP:
				LoadMapName( fp, mat.bump, chunkLen - 6 );
				if ( s_verbose )
					printf( "        found bump map '%s'\n", mat.bump );
				break;
			default:
				fread( s_buffer, chunkLen - 6, 1, fp );
				break;
		}

		bytesRead += chunkLen;

		if ( bytesRead >= thisChunkLen )
			break;
	}

	Q_getwd( curdir );

	if ( mat.texture[0] )
	{
		sprintf( buffer, "%s%s", curdir, mat.texture );
		if ( strstr( buffer, gamedir + 1 ) )
			strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
		else
			strcpy( mat.texture, buffer );
	}

	if ( mat.specular[0] )
	{
		sprintf( buffer, "%s%s", curdir, mat.specular );
		if ( strstr( buffer, gamedir + 1 ) )
			strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
		else
			strcpy( mat.specular, buffer );
	}

	if ( mat.bump[0] )
	{
		sprintf( buffer, "%s%s", curdir, mat.bump );
		if ( strstr( buffer, gamedir + 1 ) )
			strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
		else
			strcpy( mat.bump, buffer );
	}

	if ( mat.reflection[0] )
	{
		sprintf( buffer, "%s%s", curdir, mat.reflection );
		if ( strstr( buffer, gamedir + 1 ) )
			strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
		else
			strcpy( mat.reflection, buffer );
	}

	if ( mat.opacity[0] )
	{
		sprintf( buffer, "%s%s", curdir, mat.opacity );
		if ( strstr( buffer, gamedir + 1 ) )
			strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
		else
			strcpy( mat.opacity, buffer );
	}

	*pMat = mat;
}

static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG )
{
	_3DSMeshMaterialGroup_t mmg;

	memset( &mmg, 0, sizeof( mmg ) );

	ReadString( fp, mmg.name );

	fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );
	mmg.pFaces = malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );
	fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );

	if ( s_verbose )
	{
		printf( "    >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );

		{
			int i;

			for ( i = 0; i < mmg.numFaces; i++ )
			{
				printf( "        %d\n", mmg.pFaces[i] );
			}
		}
	}

	*pMMG = mmg;
}

static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO )
{
	long chunkLen;
	unsigned short chunkID;
	int i = 0;
	long bytesRead = 0;
	_3DSTriObject_t triObj;
	_3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];
	int numMeshMaterialGroups = 0;

	memset( &triObj, 0, sizeof( triObj ) );

	if ( s_verbose )
		printf( "        >>> NAMED TRI OBJECT\n" );

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
		case _3DS_CHUNK_MSH_MAT_GROUP:
			LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );
			bytesRead += chunkLen;
			numMeshMaterialGroups++;
			break;
		case _3DS_CHUNK_FACE_ARRAY:
			fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );
			assert( triObj.pFaces == 0 );

			triObj.pFaces = malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );
			fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );
			bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;

			if ( s_verbose )
			{
				printf( "            found face array with %d faces\n", triObj.numFaces );
				for ( i = 0; i < triObj.numFaces; i++ )
				{
					printf( "                %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );
				}
			}

			break;
		case _3DS_CHUNK_POINT_ARRAY:
			fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );
			triObj.pPoints = malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );
			fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );
			bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;

			// flip points around into our coordinate system
			for ( i = 0; i < triObj.numPoints; i++ )
			{
				float x, y, z;

				x = triObj.pPoints[i].x;
				y = triObj.pPoints[i].y;
				z = triObj.pPoints[i].z;

				triObj.pPoints[i].x = -y;
				triObj.pPoints[i].y = x;
				triObj.pPoints[i].z = z;
			}

			if ( s_verbose )
			{
				printf( "            found point array with %d points\n", triObj.numPoints );
				for ( i = 0; i < triObj.numPoints; i++ )
				{
					printf( "                %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );
				}
			}
			break;
		case _3DS_CHUNK_TEX_VERTS:
			fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );
			triObj.pTexVerts = malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );
			fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );
			bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;

			if ( s_verbose )
			{
				printf( "            found tex vert array with %d tex verts\n", triObj.numTexVerts );
				for ( i = 0; i < triObj.numTexVerts; i++ )
				{
					printf( "                %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );
				}
			}
			break;
		default:
			fread( s_buffer, chunkLen - 6, 1, fp );
			bytesRead += chunkLen;
			break;
		}

		if ( bytesRead >= thisChunkLen )
			break;
	}
	*pTO = triObj;

	if ( numMeshMaterialGroups == 0 )
	{
		numMeshMaterialGroups = 1;
		strcpy( meshMaterialGroups[0].name, "(null)" );
		if ( pTO->numTexVerts ) {
			printf( "Warning: assigning (null) skin to tri object\n" );
		}
	}
	else
	{
		assert( pTO->numFaces == meshMaterialGroups[0].numFaces );
	}

	pTO->pMeshMaterialGroups = malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );
	memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );
	pTO->numMeshMaterialGroups = numMeshMaterialGroups;

	//
	// sanity checks
	//

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?