3dslib.c

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

C
631
字号
	assert( numMeshMaterialGroups <= 1 );
}

static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO )
{
	long chunkLen;
	unsigned short chunkID;
	int i = 0;
	long bytesRead = 0;
	char name[100];
	_3DSTriObject_t triObj[MAX_TRI_OBJECTS];
	int numTriObjects = 0;

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

	bytesRead += ReadString( fp, name );

	if ( s_verbose )
		printf( "    >>> NAMED OBJECT '%s'\n", name );

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
		case _3DS_CHUNK_NAMED_TRI_OBJECT:
			LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );
			numTriObjects++;
			break;
		default:
			fread( s_buffer, chunkLen - 6, 1, fp );
			break;
		}

		bytesRead += chunkLen;

		if ( bytesRead >= thisChunkLen )
			break;
	}

	strcpy( pNO->name, name );
	pNO->pTriObjects = malloc( sizeof( _3DSTriObject_t ) * numTriObjects );
	memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );
	pNO->numTriObjects = numTriObjects;

	assert( numTriObjects <= 1 );
}

static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC )
{
	unsigned short chunkID;
	long chunkLen;
	long bytesRead = 0;
	_3DSEditChunk_t editChunk;

	_3DSMaterial_t mat[MAX_MATERIALS];
	_3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];

	int numMaterials = 0, numNamedObjects = 0;

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

	if ( s_verbose )
		printf( ">>> EDIT CHUNK\n" );

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
		case _3DS_CHUNK_MAT_LIST:
			LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );
			numMaterials++;
			break;
		case _3DS_CHUNK_NAMED_OBJECT:
			LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );
			if ( namedObjects[numNamedObjects].numTriObjects != 0 )
				++numNamedObjects;
			break;
		case _3DS_CHUNK_MESH_VERSION:
		default:
			fread( s_buffer, chunkLen - 6, 1, fp );
			break;
		}

		bytesRead += chunkLen;

		if ( bytesRead >= thisChunkLen )
			break;
	}

	if ( numMaterials == 0 )
	{
		numMaterials = 1;
		strcpy( mat[0].name, "(null)" );
		printf( "Warning: no material definitions found\n" );
	}

	pEC->numNamedObjects = numNamedObjects;

	pEC->pMaterials = malloc( sizeof( _3DSMaterial_t ) * numMaterials );
	pEC->pNamedObjects = malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );

	memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );
	memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );
}

static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose )
{
	FILE *fp;
	unsigned short chunkID;
	long  chunkLen;
	_3DSEditChunk_t editChunk;

	s_verbose = verbose;

	if ( ( fp = fopen( filename, "rb" ) ) == 0 )
		Error( "Unable to open '%s'", filename );

	// read magic number
	if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||
		 ( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) )
	{
		Error( "Missing or incorrect magic number in '%s'", filename );
	}
	if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 )
		Error( "Unexpected EOF encountered in '%s'", filename );
	// version number
	if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
		Error( "Missing version number in '%s'", filename );
	if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 )
		Error( "Unexpected EOF encountered in '%s'", filename );

	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
	{
		switch ( chunkID )
		{
			case _3DS_CHUNK_EDIT:
				LoadEditChunk( fp, chunkLen - 6, &editChunk );
				break;
			case _3DS_CHUNK_KEYFRAME_DATA:
				fread( s_buffer, chunkLen - 6, 1, fp );
				break;
			default:
				fread( s_buffer, chunkLen - 6, 1, fp );
				break;
		}
	}

	fclose( fp );

	p3DS->editChunk = editChunk;
}

static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris )
{
	vec3_t faceNormals[POLYSET_MAXTRIANGLES];
	vec3_t vertexNormals[POLYSET_MAXTRIANGLES*3];
	vec3_t side0, side1, facenormal;
	int f, v;

	memset( faceNormals, 0, sizeof( faceNormals ) );
	memset( vertexNormals, 0, sizeof( vertexNormals ) );

	//
	// compute face normals
	//
	for ( f = 0; f < pTO->numFaces; f++ )
	{
		VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );
		VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );

		CrossProduct( side0, side1, facenormal );
		VectorNormalize( facenormal, faceNormals[f] );
	}

	//
	// sum vertex normals
	//
	for ( v = 0; v < pTO->numPoints; v++ )
	{
		for ( f = 0; f < pTO->numFaces; f++ )
		{
			if ( ( pTO->pFaces[f].a == v ) ||
				 ( pTO->pFaces[f].b == v ) ||
				 ( pTO->pFaces[f].c == v ) )
			{
				vertexNormals[v][0] += faceNormals[f][0];
				vertexNormals[v][1] += faceNormals[f][1];
				vertexNormals[v][2] += faceNormals[f][2];
			}
		}

		VectorNormalize( vertexNormals[v], vertexNormals[v] );
	}

	//
	// copy vertex normals into triangles
	//
	for ( f = 0; f < pTO->numFaces; f++ )
	{
		int i0 = pTO->pFaces[f].c;
		int i1 = pTO->pFaces[f].b;
		int i2 = pTO->pFaces[f].a;

		VectorCopy( vertexNormals[i0], pTris[f].normals[0] );
		VectorCopy( vertexNormals[i1], pTris[f].normals[1] );
		VectorCopy( vertexNormals[i2], pTris[f].normals[2] );
	}
}

/*
** void _3DS_LoadPolysets
*/
void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose )
{
	_3DS_t _3ds;
	int numPolysets;
	polyset_t *pPSET;
	triangle_t *ptri, *triangles;
	int i;

	// load the 3DS
	memset( &_3ds, 0, sizeof( _3ds ) );
	Load3DS( filename, &_3ds, verbose );

	// compute information
	numPolysets = _3ds.editChunk.numNamedObjects;

	// allocate memory
	pPSET = calloc( 1, numPolysets * sizeof( polyset_t ) );
	triangles = ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );

	// copy the data over
	for ( i = 0; i < numPolysets; i++ )
	{
		char matnamebuf[1024];
		int j;
		triangle_t *tri;
		_3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];

		pPSET[i].triangles = ptri;
		pPSET[i].numtriangles = pTO->numFaces;
		strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );

		strcpy( matnamebuf, filename );
		if ( strrchr( matnamebuf, '/' ) )
			*( strrchr( matnamebuf, '/' ) + 1 )= 0;
		strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );

		if ( strstr( matnamebuf, gamedir ) )
			strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );
		else
			strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );

		assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );

		for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )
		{
			int i0 = pTO->pFaces[j].c;
			int i1 = pTO->pFaces[j].b;
			int i2 = pTO->pFaces[j].a;

			tri->verts[0][0] = pTO->pPoints[i0].x;
			tri->verts[0][1] = pTO->pPoints[i0].y;
			tri->verts[0][2] = pTO->pPoints[i0].z;

			tri->verts[1][0] = pTO->pPoints[i1].x;
			tri->verts[1][1] = pTO->pPoints[i1].y;
			tri->verts[1][2] = pTO->pPoints[i1].z;

			tri->verts[2][0] = pTO->pPoints[i2].x;
			tri->verts[2][1] = pTO->pPoints[i2].y;
			tri->verts[2][2] = pTO->pPoints[i2].z;
/*
			for ( k = 0; k < 3; k++ )
			{
				tri->colors[0][k] = 1;
				tri->colors[1][k] = 1;
				tri->colors[2][k] = 1;
			}
*/

			if ( pTO->pTexVerts )
			{
				tri->texcoords[0][0] = pTO->pTexVerts[i0].s;
				tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;
				tri->texcoords[1][0] = pTO->pTexVerts[i1].s;
				tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;
				tri->texcoords[2][0] = pTO->pTexVerts[i2].s;
				tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;
			}

			tri++;
		}

		ptri += pPSET[i].numtriangles;
		assert( ptri - triangles < POLYSET_MAXTRIANGLES );
	}

	// compute normal data
#if 0
	for ( i = 0; i < numPolysets; i++ )
	{
		// unique vertices based solely on vertex position
		ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],
						 pPSET[i].triangles );
	}
#endif

	free( _3ds.editChunk.pMaterials );
	free( _3ds.editChunk.pNamedObjects );

	*ppPSET = pPSET;
	*numpsets = numPolysets;
}

⌨️ 快捷键说明

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