As an amateur writer, I was looking for world-building aids. I wanted something realistic yet different enough to offer inspiration for a fantasy/sci-fiction setting. Searching the web for utilities in this vein led me to WinStarGen, Celestia, and Torben's Mogensen's Planet Generator. The planet generator offered something close to what I had in mind and I really enjoyed the power of Celestia and the possibility of displaying my "universe" with it's engine.
I monkeyed with the generator for a while and found a world I thought suitable. It wasn't long before I realized, however, that true utility wouldn't come from my newly made world without significant detail (resolution). After stumbling through efforts to manage unwieldly large images, I discovered Celestia's virtual textures. By carefully manipulating longitude, latitude, resolution, and magnification, I was able to use Torben's generator to create tiles. Doing this by hand quickly become onerous as I considered the 128 tiles necessary for level3.
A few days and a fair amount of teaching myself C++ and this program was born. Here's the source code. Sorry for the complete lack of comments. It's really not too complicated and function and variable names are descriptive so it shouldn't be difficult to makes sense of it.
If there's any interest in it or if there's a better place or way to post this, please let me know. I'd be glad to help make it useful to anyone.
Code: Select all
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <math.h>
using namespace std;
long double checkRange(long double interval, long double degrees) {
int degreesTruncated;
if(degrees>=0.0){
degreesTruncated=ceil(degrees/interval);
}
else {
degreesTruncated=floor(degrees/interval);
}
degrees=interval*degreesTruncated;
return degrees;
}
long double correctLatitude(long double degreesLatitude) {
return (degreesLatitude/2.0);
}
void fileError() {
cout << "Proper formatting requires a 'VTMaker.txt' file which contains the following:\n";
cout << " - one value each for the Ice, Bump Shading, and alternate color scheme options. These are each a '1' (one) if you wish them to be applied, '0' (zero) if not.\n";
cout << " - an integer value defining the BaseSplit value in your .ctx file.\n";
cout << " - integer values for the Lowest Level (e.g. '0') and the Highest Level (e.g. '12') you wish to render.\n";
cout << " - an integer value defining the Tile Resolution you wish to use (a power of 2 is required for Celesitia, e.g. '512').\n";
cout << "All of the following values MUST have a decimal component (e.g. '180.0', '.00012'):\n";
cout << " - an Alititude Contribution number (generally around '.4'). See planet.exe's Manual.txt for more details.\n";
cout << " - an Distance Contribution number (generally around '.03'). See planet.exe's Manual.txt for more details.\n";
cout << " - a Random Number Seed (between '.0' and '1.0').\n";
cout << " - the West-most Longitude of the area you wish to render (between '-180.0' and '180.0').\n";
cout << " - the East-most Longitude of the area you wish to render (between '-180.0' and '180.0').\n";
cout << " - the North-most Latitude of the area you wish to render (between '90.0' and '-90.0').\n";
cout << " - the South-most Latitude of the area you wish to render (between '90.0' and '-90.0').\n\n";
cout << "All values are numberic and are to be separated by white space (spaces, tabs, or new lines).\n\n";
cout << "EXAMPLE VTMaker.txt file:\n";
cout << "0 0 0\n";
cout << "0\n";
cout << "0 3\n";
cout << "512\n";
cout << ".58 .031\n";
cout << ".00021\n";
cout << "-135.0 45.0\n";
cout << "0.0 -45.0\n";
}
int parameterFileStatus (bool properFormatting) {
int fileError;
if (!properFormatting) {
fileError = 1;
}
else fileError = 0;
return fileError;
}
int main () {
int parameterFileError = 0;
ifstream parameterFile;
parameterFile.open (".\\VTMaker.txt", ios::binary);
bool ICE = 0,
BUMP = 0,
ALTERNATE_COLOR = 0;
int BASE_SPLIT = 0,
PARAMETER_START_LEVEL = 0,
PARAMETER_END_LEVEL = 0,
TILE_RESOLUTION = 32;
long double ALTITUDE_CONTRIBUTION = 0.0,
DISTANCE_CONTRIBUTION = 0.0,
RANDOM_SEED = 0.0,
PARAMETER_LEFT_LONGITUDE = -180.0,
PARAMETER_RIGHT_LONGITUDE = 180.0,
PARAMETER_TOP_LATITUDE = 90.0,
PARAMETER_BOTTOM_LATITUDE = -90.0;
if (parameterFile.is_open()) {
parameterFile >> ICE;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> BUMP;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> ALTERNATE_COLOR;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> BASE_SPLIT;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_START_LEVEL;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_END_LEVEL;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> TILE_RESOLUTION;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> ALTITUDE_CONTRIBUTION;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> DISTANCE_CONTRIBUTION;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> RANDOM_SEED;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_LEFT_LONGITUDE;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_RIGHT_LONGITUDE;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_TOP_LATITUDE;
parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
parameterFile >> PARAMETER_BOTTOM_LATITUDE;
if (!parameterFile.eof()) parameterFileError = parameterFileError + parameterFileStatus (parameterFile.good());
if (parameterFileError == 0) {
ofstream batchFile[5];
batchFile[0].open (".\\planet0.bat", ios::binary);
batchFile[1].open (".\\planet1.bat", ios::binary);
batchFile[2].open (".\\planet2.bat", ios::binary);
batchFile[3].open (".\\planet3.bat", ios::binary);
batchFile[4].open (".\\VTinfo.txt", ios::binary);
string options = "";
if (ICE) options = options + "-c ";
if (BUMP) options = options + "-B ";
if (ALTERNATE_COLOR) options = options + "-a ";
int numberOfColumns = 0,
firstColumn = 0,
column = 0,
numberOfRows = 0,
firstRow = 0,
row = 0,
startLevel = PARAMETER_START_LEVEL,
endLevel = PARAMETER_END_LEVEL,
level = 0,
magnitude = 0,
fileNumber = 0,
counter = 0,
tileTotal = 0;
long double longitude = 0.0,
latitude = 0.0,
leftLongitude = 0.0,
rightLongitude = 0.0,
topLatitude = 0.0,
bottomLatitude = 0.0,
rangeLongitude = 0.0,
rangeLatitude = 0.0,
levelInterval[13];
for(level=PARAMETER_START_LEVEL;level<=PARAMETER_END_LEVEL;level++) {
levelInterval[level]=(360.0/pow(2.0,(level+BASE_SPLIT+1.0)));
}
for(fileNumber=0;fileNumber<=3;fileNumber++) {
batchFile[fileNumber] << "@echo off\n";
}
fileNumber=0;
if (startLevel==0&&BASE_SPLIT==0) {
batchFile[fileNumber] << "mkdir level" << startLevel << "\n";
batchFile[fileNumber] << "echo LEVEL: " << startLevel << " TILE: tx_0_0.bmp RESOLUTION: " << TILE_RESOLUTION << ".\n";
batchFile[fileNumber] << "planet -w " << TILE_RESOLUTION << " -h " << TILE_RESOLUTION << " -v " << ALTITUDE_CONTRIBUTION << " -V "
<< DISTANCE_CONTRIBUTION << " -s " << RANDOM_SEED << " -p q " << options << "-o .\\level0\\tx_0_0.bmp -m 2 -l -90 -L 0\n";
batchFile[fileNumber] << "echo Completed.\n";
batchFile[fileNumber] << "echo LEVEL: " << startLevel << " TILE: tx_1_0.bmp RESOLUTION: " << TILE_RESOLUTION << ".\n";
batchFile[fileNumber] << "planet -w " << TILE_RESOLUTION << " -h " << TILE_RESOLUTION << " -v " << ALTITUDE_CONTRIBUTION << " -V "
<< DISTANCE_CONTRIBUTION << " -s " << RANDOM_SEED << " -p q " << options << "-o .\\level0\\tx_1_0.bmp -m 2 -l 90 -L 0\n";
batchFile[fileNumber] << "echo Completed.\n";
batchFile[4] << "Level 0 will have 2 columns and 1 row for a total of 2 tiles.\n";
startLevel=1;
tileTotal=2;
}
for(level=startLevel; level<=endLevel; level++) {
batchFile[0] << "mkdir level" << level << "\n";
batchFile[1] << "mkdir level" << level << "\n";
batchFile[2] << "mkdir level" << level << "\n";
batchFile[3] << "mkdir level" << level << "\n";
leftLongitude = checkRange(levelInterval[level],PARAMETER_LEFT_LONGITUDE);
rightLongitude = checkRange(levelInterval[level],PARAMETER_RIGHT_LONGITUDE);
rangeLongitude = rightLongitude - leftLongitude;
topLatitude = checkRange(levelInterval[level],PARAMETER_TOP_LATITUDE);
bottomLatitude = checkRange(levelInterval[level],PARAMETER_BOTTOM_LATITUDE);
rangeLatitude = topLatitude - bottomLatitude;
magnitude = pow(2,level+BASE_SPLIT+1);
numberOfColumns=rangeLongitude/levelInterval[level];
if(numberOfColumns==0) {numberOfColumns=1;}
numberOfRows=rangeLatitude/levelInterval[level];
if(numberOfRows==0) {numberOfRows=1;}
firstColumn=(180+leftLongitude)/levelInterval[level];
firstRow=(90-topLatitude)/levelInterval[level];
batchFile[4] << "Level " << level << " will have " << numberOfColumns << " columns and "
<< numberOfRows << " rows for a total of " << (numberOfRows*numberOfColumns) << " tiles.\n";
tileTotal=(numberOfColumns*numberOfRows)+tileTotal;
latitude = topLatitude - (levelInterval[level]/2.0);
numberOfColumns--;
numberOfRows--;
for(row=0;row<=numberOfRows;row++) {
longitude = leftLongitude + (levelInterval[level]/2.0);
for(column=0;column<=numberOfColumns;column++) {
batchFile[fileNumber] << "echo LEVEL: " << level << " TILE: tx_" << (column+firstColumn) << "_" << (row+firstRow)
<< ".bmp RESOLUTION: " << TILE_RESOLUTION << " TILE NUMBER: " << (counter/4)+1 << ".\n";
batchFile[fileNumber] << setprecision(16) << "planet -w " << TILE_RESOLUTION << " -h " << TILE_RESOLUTION << " -v "
<< ALTITUDE_CONTRIBUTION << " -V " << DISTANCE_CONTRIBUTION << " -s " << RANDOM_SEED << " -p q " << options
<< "-o .\\level" << level << "\\tx_" << (column+firstColumn) << "_" << (row+firstRow) << ".bmp -m " << magnitude
<< " -l " << longitude << " -L " << correctLatitude(latitude) << "\n";
batchFile[fileNumber] << "echo Completed.\n";
longitude = longitude + levelInterval[level];
counter++;
fileNumber++;
if (fileNumber==4) {
fileNumber=0;
}
}
latitude = latitude - levelInterval[level];
}
}
batchFile[4] << "TOTAL NUMBER OF TILES: " << tileTotal << "\n";
batchFile[4] << "RESOLUTION: " << TILE_RESOLUTION << "\n";
if (ICE||BUMP||ALTERNATE_COLOR)
{
batchFile[4] << "OPTIONS APPLIED:\n";
if(ICE) batchFile[4] << " Ice Coloring\n";
if(BUMP) batchFile[4] << " Bump Shading\n";
if(ALTERNATE_COLOR) batchFile[4] << " Alternate Color Scheme\n";
}
batchFile[4] << "WEST-MOST LONGITUDE: " << PARAMETER_LEFT_LONGITUDE << "\n";
batchFile[4] << "EAST-MOST LONGITUDE: " << PARAMETER_RIGHT_LONGITUDE << "\n";
batchFile[4] << "NORTH-MOST LATITUDE: " << PARAMETER_TOP_LATITUDE << "\n";
batchFile[4] << "SOUTH-MOST LATITUDE: " << PARAMETER_BOTTOM_LATITUDE << "\n";
for (fileNumber=0; fileNumber<=4; fileNumber++) {
batchFile[fileNumber].close();
}
} else {
cout << "Error: Improper formatting in Paramter File.\n\n";
fileError();
}
} else {
cout << "Error: Unable to open Parameter file.\n\n";
fileError();
}
parameterFile.close();
return 0;
}