📄 mapdice.cpp
字号:
/*******************************************************************************\
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 <crtdbg.h>
#include <ShiError.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 TDSKPOST.CPP
float FeetPerPost = (FEET_PER_KM / 4.0f); // I've got 250m posts at the moment
void main(int argc, char* argv[]) {
BYTE *ColorBuffer;
BYTE *ElevationBuffer;
WORD *TexIDBuffer;
WORD *NormalBuffer;
TdiskPost *postBuffer;
DWORD ColorBufferSize;
DWORD ElevationBufferSize;
DWORD TexIDBufferSize;
DWORD NormalBufferSize;
DWORD postBufferSize;
HANDLE colorFile;
HANDLE elevationFile;
HANDLE textureFile;
HANDLE headerFile;
HANDLE postFile;
HANDLE offsetFile;
int bufferWidth;
int bufferHeight;
int texMapWidth;
int texMapHeight;
OPENFILENAME dialogInfo;
char filename[256];
char basename[256];
int row;
int col;
int LOD;
int blockRow;
int blockCol;
DWORD fileOffset;
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.BMP\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 BMP file (*-C.BMP)";
dialogInfo.Flags = OFN_FILEMUSTEXIST;
dialogInfo.lpstrDefExt = "BMP";
if ( !GetOpenFileName( &dialogInfo ) ) {
return;
}
}
// Construct the base map name assuming the source file name ends in "-c.bmp"
strcpy( basename, filename );
basename[ strlen(filename)-6 ] = 0;
// Open the color input file
printf( "Reading COLOR file %s\n", filename );
colorFile = CreateFile( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( colorFile == INVALID_HANDLE_VALUE ) {
char string[256];
PutErrorString( string );
strcat( string, "Failed to open color file." );
ShiError( string );
}
#if 0
HANDLE colorMapping;
// Create a memory mapped file object for the color buffer
printf( "(Creating memory mapped file object for COLOR file)\n", filename );
colorMapping = CreateFileMapping( colorFile, NULL, PAGE_READONLY, 0, 0, NULL );
ShiAssert( colorMapping );
ColorBuffer = (BYTE*)MapViewOfFile( colorMapping, FILE_MAP_READ, 0, 0, 0 );
ShiAssert( ColorBuffer );
// Release the memory mapped file object
UnmapViewOfFile( ColorBuffer );
CloseHandle( colorMapping );
#endif
// Read the image header
#pragma pack (1) // Force tightly packed structure to match the file format
struct {
BITMAPFILEHEADER header;
BITMAPINFOHEADER info;
} bm;
#pragma pack () // Go back to the default structure alignment scheme
if ( !ReadFile( colorFile, &bm, sizeof(bm), &bytes, NULL ) ) bytes=0xFFFFFFFF;
if ( bytes != sizeof(bm) ) {
char string[256];
PutErrorString( string );
strcat( string, "Couldn't read required color BMP header." );
ShiError( string );
}
if (( bm.header.bfType != 0x4D42 ) ||
( bm.info.biCompression != BI_RGB ) ||
( bm.info.biPlanes != 1 ) ||
( bm.info.biBitCount != 24 )) {
ShiError( "Invalid or unsupported BMP format" );
}
// Store the image size
bufferWidth = bm.info.biWidth;
bufferHeight = bm.info.biHeight;
// Allocate space for the color buffer
ColorBufferSize = bufferWidth * bufferHeight * 3 * sizeof( BYTE );
ColorBuffer = (BYTE*)malloc( ColorBufferSize );
ShiAssert( ColorBuffer );
// Read the color data a row at a time to flip it into conventional orientation
// (ie: undo the bottom up storage that is used in BMP files)
for (row=bufferHeight-1; row>=0; row--) {
DWORD rowSize = bufferWidth * 3 * sizeof( BYTE );
BYTE *color = ColorBuffer + row*rowSize;
if ( !ReadFile( colorFile, color, rowSize, &bytes, NULL ) ) bytes=0xFFFFFFFF;
if ( bytes != rowSize ) {
char string[256];
PutErrorString( string );
strcat( string, "Couldn't read required color data." );
ShiError( string );
}
}
CloseHandle( colorFile );
// Allocate space for the elevation buffer
ElevationBufferSize = bufferWidth*bufferHeight*sizeof(*ElevationBuffer);
ElevationBuffer = (BYTE*)malloc( ElevationBufferSize );
ShiAssert( ElevationBuffer );
// Open the elevation information file
strcpy( filename, basename );
strcat( filename, "-E.RAW" );
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 );
// 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 (int r=0; r < bufferHeight; r++) {
for (int c=0; c < bufferWidth; c++) {
DWORD dataOffset = r*bufferWidth + c;
ShiAssert( dataOffset < (DWORD)bufferWidth*bufferHeight );
ShiAssert( dataOffset >= 0 );
// 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) ) {
NormalBuffer[dataOffset] = 0xFF00;
continue;
}
ShiAssert( dataOffset+bufferWidth < (DWORD)bufferWidth*bufferHeight );
ShiAssert( dataOffset-bufferWidth >= 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
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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -