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

📄 mapdice.cpp

📁 空战游戏flacon源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************\
	Map Converter from BMP color and RAW elevation to Falcon 4.0 LOD format

	Scott Randolph
	Spectrum HoloByte
	November 14, 1995
\*******************************************************************************/
#include <stdio.h>
#include <math.h>
#include "..\..\Terrain\Ttypes.h"
#include "..\..\Terrain\TPost.h"
#include "..\..\Terrain\TDskPost.h"
#include "..\..\3Dlib\Image.h"


#define 		MAX_LEVELS				6		// How many levels of detail to generate
#define			LAST_TEX_LEVEL			2		// What is the number of the last level to be textured

const float		altScale	= 8.0f * FEET_PER_METER;	// Must match units in *-E.RAW file

float			FeetPerPost = (FEET_PER_KM / 4.0f);		// I've got 250m posts at the moment
const int		MEA_DOWNSAMPLE_SHIFT = 5;				// From 250m to 8km
const float		FeetToMEAcell = 1.0f / (FeetPerPost * (1<<MEA_DOWNSAMPLE_SHIFT));


static const WORD	INVALID_TEXID	= 0xFFFF;


int main(int argc, char* argv[]) {

	BYTE		*ColorIndexBuffer	= NULL;
	DWORD		*ColorPaletteBuffer	= NULL;
	BYTE		*ElevationBuffer	= NULL;
	WORD		*TexIDBuffer		= NULL;
	WORD		*FarFieldBuffer		= NULL;
	WORD		*NormalBuffer		= NULL;
	TdiskPost	*postBuffer			= NULL;
	TdiskPost	*postBufferPrev		= NULL;

	DWORD		ElevationBufferSize;
	DWORD		TexIDBufferSize;
	DWORD		FarFieldBufferSize;
	DWORD		NormalBufferSize;
	DWORD		postBufferSize;

	CImageFileMemory	colorFile;

	HANDLE		elevationFile;
	HANDLE		textureFile;
	HANDLE		farFieldFile;
	HANDLE		headerFile;
	HANDLE		postFile;
	HANDLE		offsetFile;

	int			bufferWidth;
	int			bufferHeight;

	Int16		MEAvalue;
	int			MEAwidth;
	int			MEAheight;

	int			texMapWidth;
	int			texMapHeight;

	int			farMapWidth;
	int			farMapHeight;

	OPENFILENAME dialogInfo;
	char		filename[256];
	char		dataRootDir[256];
	char		dataSet[256];
	char		texPath[256];

	int			row;
	int			col;
	int			r;
	int			c;

	int			top;
	int			left;
	int			bottom;
	int			right;

	int			LOD;
	int			blockRow;
	int			blockCol;
	DWORD		dataOffset;

	int			LastFarTexLevel;
	DWORD		fileOffset = 0xFFFFFFFF;
	DWORD		bytes;
	int			result;


	// See if we got a filename on the command line
	if ( argc == 2) {
		result = GetFullPathName( argv[1], sizeof( filename ), filename, NULL );
	} else {
		result = 0;
	}

	// If we didn't get it on the command line, ask the user
	// for the name of the BMP color file
	if (!result) {
		filename[0] = NULL;
		dialogInfo.lStructSize = sizeof( dialogInfo );
		dialogInfo.hwndOwner = NULL;
		dialogInfo.hInstance = NULL;
		dialogInfo.lpstrFilter = "24 Bit BMP\0*-C.GIF\0\0";
		dialogInfo.lpstrCustomFilter = NULL;
		dialogInfo.nMaxCustFilter = 0;
		dialogInfo.nFilterIndex = 1;
		dialogInfo.lpstrFile = filename;
		dialogInfo.nMaxFile = sizeof( filename );
		dialogInfo.lpstrFileTitle = NULL;
		dialogInfo.nMaxFileTitle = 0;
		dialogInfo.lpstrInitialDir = "J:\\TerrData";
		dialogInfo.lpstrTitle = "Select a base GIF file (*-C.GIF)";
		dialogInfo.Flags = OFN_FILEMUSTEXIST;
		dialogInfo.lpstrDefExt = "GIF";

 		if ( !GetOpenFileName( &dialogInfo ) ) {
			return -1;
		}
	}


	// Extract the path to the directory ONE above the one containing the selected file
	// (the "root" of the data tree)
	char *p = &filename[ strlen(filename)-1 ];
	while ( (*p != ':') && (*p != '\\') && (p != filename) ) {
		if (*p == '.')  *p = '\0';
		p--;
	}
	*p = '\0';
	char *base = p+1;
	char *dir = filename;
	while ( (*p != ':') && (*p != '\\') && (p != filename) ) {
		p--;
	}
	*p = '\0';
	strcpy( dataRootDir, dir );
	strcpy( dataSet, base );
	dataSet[strlen(dataSet)-2] = '\0';	// Get rid of the "-C"
	strcpy( texPath, dir );
	strcat( texPath, "\\texture\\" );


/************************************************************************************\
	Got all input args -- Begin Setup
\************************************************************************************/


	// Open the color input file
	sprintf( filename, "%s\\terrain\\%s-C.GIF", dataRootDir, dataSet );
	printf( "Reading COLOR file %s\n", filename );
	colorFile.imageType = CheckImageType( filename );
	ShiAssert( colorFile.imageType != IMAGE_TYPE_UNKNOWN );
	result = colorFile.glOpenFileMem( filename );
	if ( result != 1 ) {
		char	message[256];
		sprintf( message, "Failed to open %s", filename );
		ShiError( message );
	}

	// Read the image data (note that ReadTextureImage will close texFile for us)
	colorFile.glReadFileMem();
	result = ReadTextureImage( &colorFile );
	if (result != GOOD_READ) {
		ShiError( "Failed to read terrain texture.  CD Error?" );
	}
	ShiAssert(colorFile.image.image);
	ShiAssert(colorFile.image.palette);

	// Store the image data
	bufferWidth			= colorFile.image.width;
	bufferHeight		= colorFile.image.height;
	ColorIndexBuffer	= colorFile.image.image;
	ColorPaletteBuffer	= (DWORD*)colorFile.image.palette;

	
	// Allocate space for the elevation buffer
	ElevationBufferSize = bufferWidth*bufferHeight*sizeof(*ElevationBuffer);
	ElevationBuffer = (BYTE*)malloc( ElevationBufferSize );
	ShiAssert( ElevationBuffer );

	// Open the elevation information file
	sprintf( filename, "%s\\terrain\\%s-E.RAW", dataRootDir, dataSet );
	printf( "Reading ELEVATION file %s\n", filename );
    elevationFile = CreateFile( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
	if ( elevationFile == INVALID_HANDLE_VALUE ) {
		char string[256];
		PutErrorString( string );
		strcat( string, "Failed to open elevation file." );
		ShiError( string );
	}

	// Read in the data
	if ( !ReadFile( elevationFile, ElevationBuffer, ElevationBufferSize, &bytes, NULL ) )  bytes=0xFFFFFFFF;
	if ( bytes != ElevationBufferSize ) {
		char string[256];
		PutErrorString( string );
		strcat( string, "Couldn't read required elevation data." );
		ShiError( string );
	}
	CloseHandle( elevationFile );



	// Store the size of the MEA table we're going to build
	MEAwidth	= bufferWidth  >> MEA_DOWNSAMPLE_SHIFT;
	MEAheight	= bufferHeight >> MEA_DOWNSAMPLE_SHIFT;

	// Open the MEA table output file
	sprintf( filename, "%s\\terrain\\Theater.MEA", dataRootDir );
	printf( "Writing the MEA table %s\n", filename );
	headerFile = CreateFile( filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	if( headerFile == INVALID_HANDLE_VALUE ) {
		char string[256];
		PutErrorString( string );
		strcat( string, "Failed to open MEA table output file." );
		ShiError( string );
	}

	// Store the maximum height encountered in each MEA cell on the map
	for (row=0; row < MEAheight; row++) {

		for (col=0; col < MEAwidth; col++) {
			MEAvalue = -32000;

			top		= row<<MEA_DOWNSAMPLE_SHIFT;
			left	= col<<MEA_DOWNSAMPLE_SHIFT;
			bottom	= ((row+1)<<MEA_DOWNSAMPLE_SHIFT) - 1;
			right	= ((col+1)<<MEA_DOWNSAMPLE_SHIFT) - 1;


			// Search for the maximum height within this MEA cell
			for (r = top; r <= bottom; r++) {
				for (c = left; c <= right; c++) {
		 			dataOffset = r*bufferWidth + c;
					MEAvalue = max( MEAvalue, (Int16)(ElevationBuffer[dataOffset] * altScale) );
				}
			}

			// Now we look one post outward (if we're not at an edge)
			if ((row>0) && (row<MEAheight-1) && (col>0) && (col<MEAwidth-1)) {
				for (c = left-1; c <= right+1; c++) {
		 			dataOffset = (top-1)*bufferWidth + c;
					MEAvalue = max( MEAvalue, (Int16)(ElevationBuffer[dataOffset] * altScale) );
		 			dataOffset = (top+1)*bufferWidth + c;
					MEAvalue = max( MEAvalue, (Int16)(ElevationBuffer[dataOffset] * altScale) );
				}
				for (r = top; r <= bottom; r++) {
	 				dataOffset = r*bufferWidth + (left-1);
					MEAvalue = max( MEAvalue, (Int16)(ElevationBuffer[dataOffset] * altScale) );
	 				dataOffset = r*bufferWidth + (left+1);
					MEAvalue = max( MEAvalue, (Int16)(ElevationBuffer[dataOffset] * altScale) );
				}
			}

			// Write out this element of the MEA table
			WriteFile( headerFile, &MEAvalue, sizeof(MEAvalue), &bytes, NULL );
			ShiAssert( bytes == sizeof(MEAvalue) );
		}
	}

	// Close the MEA table file
	CloseHandle( headerFile );



	// Allocate space for the surface normal buffer
	NormalBufferSize = bufferWidth*bufferHeight*sizeof(*NormalBuffer);
	NormalBuffer = (WORD*)malloc( NormalBufferSize );
	ShiAssert( NormalBuffer );

	// Compute the normal at each post based on its neighbors
	printf("Computing the surface normal at each post\n");
	for (r=0; r < bufferHeight; r++) {
		for (c=0; c < bufferWidth; c++) {

 			dataOffset = r*bufferWidth + c;
			ShiAssert( dataOffset < (DWORD)bufferWidth*bufferHeight );
			ShiAssert( dataOffset >= 0 );


			// Compute the cartesian components of the surface normal based on
			// the known post spacing and the height changes between the neighbors
			double Nx, Ny, Nz;
			double normalizer;

			// Start with the height changes (rise) in x direction and in the y direction
			// At the edges of the map, just use a normal pointing straight up for now.
			if ( (r == 0) || (c == 0) || (r == bufferHeight-1) || (c == bufferWidth-1) ) {
				Nx = 0.0f;
				Ny = 0.0f;
			} else {
				ShiAssert( dataOffset+bufferWidth < (DWORD)bufferWidth*bufferHeight );
				ShiAssert( dataOffset-bufferWidth >= 0 );
				Nx = altScale * (ElevationBuffer[dataOffset+bufferWidth] - ElevationBuffer[dataOffset-bufferWidth]);
				Ny = altScale * (ElevationBuffer[dataOffset-1]           - ElevationBuffer[dataOffset+1]);
			}
			Nz = GLOBAL_POST_TO_WORLD( 2 );

			// Now normalize the vector
			normalizer = 1.0 / sqrt(Nx*Nx + Ny*Ny + Nz*Nz);
			Nx *= normalizer;
			Ny *= normalizer;
			Nz *= normalizer;

	
			// Now store the normal in spherical coordinates (unit vector, so rho = 1)			
			double theta;
			double phi;

			// Convert from catesian to spherical coordinates
			phi		= asin( Nz );
			ShiAssert( phi <= PI/2.0 );
			ShiAssert( phi >= 0.0 );

			// BUG IN ATAN2 -- fails when both args are 0.0, therefore...
			if ( fabs(Nx) < 0.000001 ) {
				if ( Ny < 0.0 ) {
					theta = -PI / 2.0;
				} else {
					theta =  PI / 2.0;
				}
			} else {
				theta	= atan2( Ny, Nx );
			}
			if (theta < 0.0)  theta += PI*2.0;
			ShiAssert( theta < PI*2.0 );
			ShiAssert( theta >= 0.0 );

			// Scale theta from 0 - 2 PI (360 degrees) to 0 - 255
			static const double thetaInStart	= 0.0;
			static const double thetaInStop		= PI*2.0;
			static const double thetaInRange	= thetaInStop - thetaInStart;
			static const double thetaOutScale	= 255.99;
			theta = thetaOutScale * (theta - thetaInStart) / thetaInRange;

			// Scale phi from 1.3 - PI/2 to 0 - 63
			static const double phiInStart	= 1.3;
			static const double phiInStop	= PI/2.0;
			static const double phiInRange	= phiInStop - phiInStart;
			static const double phiOutScale	= 63.99;

⌨️ 快捷键说明

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