⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tiledb.cpp

📁 空战游戏flacon源码
💻 CPP
字号:
/*******************************************************************************\
	TileDB.cpp
	Provides an interface to the tile database written by the tile tool.  At 
	present this is only used by the TexGen tool.

	Scott Randolph
	Spectrum HoloByte
	October 8, 1996
\*******************************************************************************/
#include <stdio.h>
#include <math.h>
#include "TileDB.h"


// Terrain and feature types defined in the the visual basic tile tool
// (Not all are features, but we have the whole list here for completeness sake)
const int COVERAGE_WATER		= 1;
const int COVERAGE_RIVER		= 2;
const int COVERAGE_SWAMP		= 3;
const int COVERAGE_PLAINS		= 4;
const int COVERAGE_BRUSH		= 5;
const int COVERAGE_THINFOREST	= 6;
const int COVERAGE_THICKFOREST	= 7;
const int COVERAGE_ROCKY		= 8;
const int COVERAGE_URBAN		= 9;
const int COVERAGE_ROAD			= 10;
const int COVERAGE_RAIL			= 11;
const int COVERAGE_BRIDGE		= 12;
const int COVERAGE_RUNWAY		= 13;
const int COVERAGE_STATION		= 14;


void TileDatabase::Load( char *filename ) {
	HANDLE		inputFile;
	DWORD		bytes;
	char		message[80];
	int			tile;


	// Open the texture tile database for reading
	inputFile = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
	if (inputFile == INVALID_HANDLE_VALUE) {
		PutErrorString( message );
		strcat( message, ":  Failed tile database open" );
		ShiError( message );
	}


	// Read the file header
	ReadFile( inputFile, &header, 29, &bytes, NULL );
	if ( bytes != 29 ) {
		PutErrorString( message );
		strcat( message, ":  Failed file header read" );
		ShiError( message );
	}


	// Verify the file header
	if ( strncmp( header.title, "TILE DATABASE O", sizeof(header.title) ) != 0 ) {
		ShiError( "Unrecognized file header" );
	}
	if ( strncmp( header.version, "1.1     ", sizeof(header.version) ) != 0 ) {
		ShiError( "Unrecognized file version" );
	}


	// Allocate memory for the tile list
	header.tiles = (TileRecord*)malloc( header.numTiles * sizeof(*header.tiles) );


	// Loop for each tile
	for (tile = 0; tile < header.numTiles; tile++ ) {
		ReadTile( inputFile, &header.tiles[tile] );
	}


	// Close the tile database
	CloseHandle( inputFile );
}


void TileDatabase::Free( void )
{
	int tile, feature;

	for ( tile = 0; tile < header.numTiles; tile++ ) {
		for ( feature = 0; feature < header.tiles[tile].numFeatures; feature++ ) {
			free ( header.tiles[tile].features[feature].points );
			header.tiles[tile].features[feature].points = NULL;
		}
		free ( header.tiles[tile].colors );
		free ( header.tiles[tile].elevations );
		free ( header.tiles[tile].features );
		free ( header.tiles[tile].paths );
		free ( header.tiles[tile].areas );
		header.tiles[tile].colors = NULL;
		header.tiles[tile].elevations = NULL;
		header.tiles[tile].features = NULL;
		header.tiles[tile].areas = NULL;
		header.tiles[tile].paths = NULL;
	}
	free ( header.tiles );
	header.tiles = NULL;

	memset ( &header, 0, sizeof(header) );
}


void TileDatabase::ReadTile( HANDLE inputFile, TileRecord *tile )
{
	DWORD	bytes;
	char	string[8];
	char	message[80];
	char	codeString[8];
	int		feature;
	DWORD	arraySize;


	// Read the tile record header
	ReadFile( inputFile, tile, 17, &bytes, NULL );
	if ( bytes != 17 ) {
		PutErrorString( message );
		strcat( message, ":  Failed the tile header read" );
		ShiError( message );
	}


	// Extract the original tile code from the file name
	strcpy( codeString, "0x" );
	strncpy( &codeString[2], &tile->basename[5], 3 );
	sscanf( codeString, "%hx", &tile->code );


	// Read and verify the color record header
	ReadFile( inputFile, &string, 4, &bytes, NULL );
	if (strncmp( string, "CLR ", 4 ) != 0) {
		PutErrorString( message );
		strcat( message, ":  Failed the color tag read/verify" );
		ShiError( message );
	}

	// Allocate the memory for the color array
	arraySize = header.gridXsize * header.gridYsize * 4;
	tile->colors = (colorRecord*)malloc( arraySize );
	ShiAssert( tile->colors );

	// Read the color array
	ReadFile( inputFile, tile->colors, arraySize, &bytes, NULL );
	if ( bytes != arraySize ) {
		PutErrorString( message );
		strcat( message, ":  Failed the color read" );
		ShiError( message );
	}


	// Read and verify the elevation record header
	ReadFile( inputFile, &string, 4, &bytes, NULL );
	if (strncmp( string, "ELEV", 4 ) != 0) {
		PutErrorString( message );
		strcat( message, ":  Failed the color tag read/verify" );
		ShiError( message );
	}

	// Allocate the memory for the elevation array
	arraySize = header.gridXsize * header.gridYsize * 3;
	tile->elevations = (elevationRecord*)malloc( arraySize );
	ShiAssert( tile->elevations );

	// Read the elevation array
	ReadFile( inputFile, tile->elevations, arraySize, &bytes, NULL );
	if ( bytes != arraySize ) {
		PutErrorString( message );
		strcat( message, ":  Failed the elevation read" );
		ShiError( message );
	}


	// Read and verify the feature record header
	ReadFile( inputFile, &string, 4, &bytes, NULL );
	if (strncmp( string, "FEAT", 4 ) != 0) {
		PutErrorString( message );
		strcat( message, ":  Failed the feature group tag read/verify" );
		ShiError( message );
	}


	// Allocate memory for the features in this tile
	tile->features = (FeatureRecord*)malloc( tile->numFeatures * sizeof( *tile->features ) );
	tile->sortedFeatures = (FeatureRecord**)malloc( tile->numFeatures * sizeof(void*) );
	tile->nareas = 0;
	tile->npaths = 0;

	
	// Read each feature description and count types
	for( feature = 0; feature < tile->numFeatures; feature++ ) {
		ReadFeature( inputFile, &tile->features[feature] );
		tile->sortedFeatures[feature] = &tile->features[feature];

		if ( typeIsPath( tile->features[feature].type ) ) {

			// Make sure each path has at least two defining points
			ShiAssert( tile->features[feature].numPoints >= 2 );
			tile->npaths += tile->features[feature].numPoints - 1;

		} else {

			// Make sure each area has exactly one center point
			ShiAssert( tile->features[feature].numPoints == 1 );
			tile->nareas++;

		}
	}

	
	// Sort the feature descriptions by type
	SortArray( tile->sortedFeatures, tile->numFeatures );


	// Build the path and area records as appropriate for each feature
	tile->areas = (AreaRecord*)malloc( tile->nareas * sizeof( AreaRecord ) );
	tile->paths = (PathRecord*)malloc( tile->npaths * sizeof( PathRecord ) );
	ShiAssert( tile->areas );
	ShiAssert( tile->paths );
	int areaIndex = 0;
	int pathIndex = 0;

	for( feature = 0; feature < tile->numFeatures; feature++ ) {

		if ( typeIsPath( tile->features[feature].type ) ) {
			int pntIndex = 1;

			while ( pntIndex < tile->features[feature].numPoints ) {
				ShiAssert( pathIndex < tile->npaths );
				tile->paths[pathIndex].type = tile->features[feature].type;
				tile->paths[pathIndex].size = tile->features[feature].size;
				tile->paths[pathIndex].x1 = tile->features[feature].points[pntIndex-1].x;
				tile->paths[pathIndex].y1 = tile->features[feature].points[pntIndex-1].y;
				tile->paths[pathIndex].x2 = tile->features[feature].points[pntIndex].x;
				tile->paths[pathIndex].y2 = tile->features[feature].points[pntIndex].y;
				pathIndex++;
				pntIndex++;
			}

		} else {
			ShiAssert( areaIndex < tile->nareas );
			tile->areas[areaIndex].type = tile->features[feature].type;
			tile->areas[areaIndex].size = tile->features[feature].size;
			tile->areas[areaIndex].x = tile->features[feature].points[0].x;
			tile->areas[areaIndex].y = tile->features[feature].points[0].y;
			areaIndex++;
		}
	}
}


void TileDatabase::ReadFeature( HANDLE inputFile, FeatureRecord *feature )
{
	DWORD	bytes;
	char	message[80];


	// Read the feature record header
	ReadFile( inputFile, feature, 13, &bytes, NULL );
	if (bytes != 13) {
		PutErrorString( message );
		strcat( message, ":  Failed feature record read" );
		ShiError( message );
	}

	// Verify the feature tag
	if ( strncmp( feature->tag, "1FTR", 4 ) != 0 ) {
		ShiError( "Failed feature tag check" );
	}


	// Allocate memory for the list of points
	feature->points = (PointRecord*)malloc( feature->numPoints * sizeof( *feature->points ) );
	ShiAssert( feature->points );

	// Read the point records
	ReadFile( inputFile, feature->points, 8*feature->numPoints, &bytes, NULL );
	if (bytes != (DWORD)8*feature->numPoints) {
		PutErrorString( message );
		strcat( message, ":  Failed read of a point record" );
		ShiError( message );
	}
}


void TileDatabase::SortArray( FeatureRecord **array, int numElements )
{
	int				i, j, k;
	FeatureRecord	*p;


	for (i=1; i<numElements; i++) {

		// Decide where to place this element in the list
		j = i;
		while ((j>0) && (array[j-1]->type > array[i]->type)) {
			j--;
		}

		// Only adjust the list if we need to
		if ( j != i ) {

			// Remove the element under consideration (i) from its current location
			p = array[i];
			for (k=i; k<numElements-1; k++) {
				array[k] = array[k+1];
			}

			// Insert the element under consideration in front of the identified element
			for (k=numElements-1; k>j; k--) {
				array[k] = array[k-1];
			}
			array[j] = p;
		}
	}
}


TileRecord* TileDatabase::GetTileRecord( WORD code )
{
	int tile;

	for ( tile = 0; tile < header.numTiles; tile++ ) {

		if (header.tiles[tile].code == code) {
			return &header.tiles[tile];
		}
	}

	// We didn't find a match
	return NULL;
}


AreaRecord* TileDatabase::GetArea( TileRecord *pTile, int area )
{
	if (pTile == NULL) {
		return NULL;
	}

	ShiAssert( area < pTile->nareas );

	return &pTile->areas[area];
}


PathRecord* TileDatabase::GetPath( TileRecord *pTile, int path )
{
	if (pTile == NULL) {
		return NULL;
	}

	ShiAssert( path < pTile->npaths );

	return &pTile->paths[path];
}


BOOL TileDatabase::typeIsPath( BYTE featureType )
{
	return ( (featureType == COVERAGE_RIVER) ||
			 (featureType == COVERAGE_ROAD)  ||
		     (featureType == COVERAGE_RAIL)  ||
		     (featureType == COVERAGE_BRIDGE)||
		     (featureType == COVERAGE_RUNWAY) );
}

⌨️ 快捷键说明

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