Allow reading heightmap colors from file, and use separate option for nodes file

This commit is contained in:
Rogier 2015-02-15 08:45:28 +01:00
parent 3812e31fc9
commit 4476de429d
7 changed files with 1443 additions and 1270 deletions

View File

@ -296,7 +296,8 @@ if(WIN32)
install(FILES ${META_FILES} DESTINATION ".") install(FILES ${META_FILES} DESTINATION ".")
install(FILES "colors.txt" DESTINATION ".") install(FILES "colors.txt" DESTINATION ".")
install(FILES "colors-heightmap.txt" DESTINATION ".") install(FILES "heightmap-nodes.txt" DESTINATION ".")
install(FILES "heightmap-colors.txt" DESTINATION ".")
install(FILES "colors-average-alpha.txt" DESTINATION ".") install(FILES "colors-average-alpha.txt" DESTINATION ".")
install(FILES "colors-cumulative-alpha.txt" DESTINATION ".") install(FILES "colors-cumulative-alpha.txt" DESTINATION ".")
install(PROGRAMS "${PROJECT_BINARY_DIR}/minetestmapper.exe" DESTINATION ".") install(PROGRAMS "${PROJECT_BINARY_DIR}/minetestmapper.exe" DESTINATION ".")
@ -319,7 +320,8 @@ elseif(CREATE_FLAT_PACKAGE)
install(FILES ${META_FILES} DESTINATION ".") install(FILES ${META_FILES} DESTINATION ".")
install(FILES "colors.txt" DESTINATION ".") install(FILES "colors.txt" DESTINATION ".")
install(FILES "colors-heightmap.txt" DESTINATION ".") install(FILES "heightmap-nodes.txt" DESTINATION ".")
install(FILES "heightmap-colors.txt" DESTINATION ".")
install(FILES "colors-average-alpha.txt" DESTINATION ".") install(FILES "colors-average-alpha.txt" DESTINATION ".")
install(FILES "colors-cumulative-alpha.txt" DESTINATION ".") install(FILES "colors-cumulative-alpha.txt" DESTINATION ".")
install(PROGRAMS "${PROJECT_BINARY_DIR}/minetestmapper" DESTINATION ".") install(PROGRAMS "${PROJECT_BINARY_DIR}/minetestmapper" DESTINATION ".")
@ -354,7 +356,8 @@ else(WIN32)
install(FILES ${META_FILES} DESTINATION "share/doc/${PROJECT_NAME}" COMPONENT mapper) install(FILES ${META_FILES} DESTINATION "share/doc/${PROJECT_NAME}" COMPONENT mapper)
install(FILES colors.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper) install(FILES colors.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper)
install(FILES colors-heightmap.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper) install(FILES heightmap-nodes.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper)
install(FILES heightmap-colors.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper)
install(FILES colors-average-alpha.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper) install(FILES colors-average-alpha.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper)
install(FILES colors-cumulative-alpha.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper) install(FILES colors-cumulative-alpha.txt DESTINATION "share/games/${PROJECT_NAME}" COMPONENT mapper)
install(TARGETS minetestmapper RUNTIME DESTINATION bin COMPONENT mapper) install(TARGETS minetestmapper RUNTIME DESTINATION bin COMPONENT mapper)

View File

@ -133,7 +133,6 @@ TileGenerator::TileGenerator():
verboseStatistics(false), verboseStatistics(false),
progressIndicator(false), progressIndicator(false),
m_heightMap(false), m_heightMap(false),
m_heightMapGrey(false),
m_heightMapYScale(1), m_heightMapYScale(1),
m_seaLevel(0), m_seaLevel(0),
m_bgColor(255, 255, 255), m_bgColor(255, 255, 255),
@ -180,39 +179,19 @@ TileGenerator::TileGenerator():
m_tileMapXOffset(0), m_tileMapXOffset(0),
m_tileMapYOffset(0) m_tileMapYOffset(0)
{ {
// Load default grey colors.
m_heightMapColors.push_back(HeightMapColor(INT_MIN, Color(0,0,0), -129, Color(0,0,0)));
m_heightMapColors.push_back(HeightMapColor(-128, Color(0,0,0), 127, Color(255,255,255)));
m_heightMapColors.push_back(HeightMapColor(128, Color(255,255,255), INT_MAX, Color(255,255,255)));
} }
TileGenerator::~TileGenerator() TileGenerator::~TileGenerator()
{ {
} }
void TileGenerator::setHeightMap(bool enable, bool grey) void TileGenerator::setHeightMap(bool enable)
{ {
m_heightMap = enable; m_heightMap = enable;
m_heightMapGrey = grey;
m_heightMapColors.clear();
if (m_heightMapGrey) {
m_heightMapColors.push_back(HeightMapColor(INT_MIN, Color(0,0,0), -1, Color(0,0,0)));
m_heightMapColors.push_back(HeightMapColor(0, Color(0,0,0), 255, Color(255,255,255)));
m_heightMapColors.push_back(HeightMapColor(256, Color(255,255,255), INT_MAX, Color(255,255,255)));
}
else {
m_heightMapColors.push_back(HeightMapColor(INT_MIN, Color(4,4,4), -60, Color(4,4,4)));
m_heightMapColors.push_back(HeightMapColor(-60, Color(4,4,4), -45, Color(16,16,16)));
m_heightMapColors.push_back(HeightMapColor(-45, Color(16,16,16), -30, Color(16,32,64)));
m_heightMapColors.push_back(HeightMapColor(-30, Color(16,32,64), 0, Color(32,64,255)));
m_heightMapColors.push_back(HeightMapColor(1, Color(32,128,32), 10, Color(64,192,64))); // Green
m_heightMapColors.push_back(HeightMapColor(10, Color(64,192,64), 20, Color(192,192,64))); // Green -> Yellow
m_heightMapColors.push_back(HeightMapColor(20, Color(192,192,64), 40, Color(128,128,64))); // Yellow
m_heightMapColors.push_back(HeightMapColor(40, Color(128,128,64), 50, Color(128,64,64))); // Yellow -> Red
m_heightMapColors.push_back(HeightMapColor(50, Color(128,64,64), 70, Color(64,32,32))); // Red
m_heightMapColors.push_back(HeightMapColor(70, Color(64,32,32), 80, Color(48,48,48))); // Red -> Grey
m_heightMapColors.push_back(HeightMapColor(80, Color(48,48,48), 140, Color(96,96,96))); // Grey
// Above 100, white suggests snowy :-)
m_heightMapColors.push_back(HeightMapColor(141, Color(160,160,160), 250, Color(250,250,250))); // Grey -> White
m_heightMapColors.push_back(HeightMapColor(250, Color(250,250,250), INT_MAX, Color(250,250,250)));
}
} }
void TileGenerator::setHeightMapYScale(float scale) void TileGenerator::setHeightMapYScale(float scale)
@ -267,6 +246,14 @@ void TileGenerator::setPlayerColor(const Color &playerColor)
m_playerColor = playerColor; m_playerColor = playerColor;
} }
void TileGenerator::setHeightMapColor(const Color &color0, const Color &color1)
{
m_heightMapColors.clear();
m_heightMapColors.push_back(HeightMapColor(INT_MIN, color0, -129, color0));
m_heightMapColors.push_back(HeightMapColor(-128, color0, 127, color1));
m_heightMapColors.push_back(HeightMapColor(128, color1, INT_MAX, color1));
}
void TileGenerator::setTileBorderColor(const Color &tileBorderColor) void TileGenerator::setTileBorderColor(const Color &tileBorderColor)
{ {
m_tileBorderColor = tileBorderColor; m_tileBorderColor = tileBorderColor;
@ -389,21 +376,41 @@ void TileGenerator::setMaxY(int y)
m_reqYMaxNode = y - 16 * m_reqYMax; m_reqYMaxNode = y - 16 * m_reqYMax;
} }
void TileGenerator::parseColorsFile(const std::string &fileName, int depth) void TileGenerator::parseNodeColorsFile(const std::string &fileName)
{
m_nodeColors.clear();
parseDataFile(fileName, 0, "map colors", &TileGenerator::parseNodeColorsLine);
}
void TileGenerator::parseHeightMapNodesFile(const std::string &fileName)
{
m_nodeColors.clear();
parseDataFile(fileName, 0, "heightmap nodes", &TileGenerator::parseHeightMapNodesLine);
}
void TileGenerator::parseHeightMapColorsFile(const std::string &fileName)
{
m_heightMapColors.clear();
parseDataFile(fileName, 0, "heightmap colors", &TileGenerator::parseHeightMapColorsLine);
}
void TileGenerator::parseDataFile(const std::string &fileName, int depth, const char *type,
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
istringstream &iline, int linenr, const std::string &filename))
{ {
if (depth > 100) if (depth > 100)
throw std::runtime_error(std::string("Excessive inclusion depth of colors files - suspected recursion (i.e. cycle); current file: '") + fileName + "'"); throw std::runtime_error(std::string("Excessive inclusion depth of ") + type + " files - suspected recursion (i.e. cycle); current file: '" + fileName + "'");
if (depth == 0 && verboseReadColors >= 2) if (depth == 0 && verboseReadColors >= 2)
cout << "Checking for colors file: " << fileName << std::endl; cout << "Checking for " << type << " file: " << fileName << std::endl;
ifstream in; ifstream in;
in.open(fileName.c_str(), ifstream::in); in.open(fileName.c_str(), ifstream::in);
if (!in.is_open()) { if (!in.is_open()) {
throw std::runtime_error(std::string("Failed to open colors file '") + fileName + "'"); throw std::runtime_error(std::string("Failed to open ") + type + " file '" + fileName + "'");
return; return;
} }
if (verboseReadColors >= 1) if (verboseReadColors >= 1)
cout << "Reading colors file: " << fileName << std::endl; cout << "Reading " << type << " file: " << fileName << std::endl;
parseColorsStream(in, fileName.c_str(), depth); parseDataStream(in, fileName, depth, type, parseLine);
in.close(); in.close();
} }
@ -449,7 +456,9 @@ void TileGenerator::generate(const std::string &input, const std::string &output
printUnknown(); printUnknown();
} }
void TileGenerator::parseColorsStream(std::istream &in, const std::string &filename, int depth) void TileGenerator::parseDataStream(std::istream &in, const std::string &filename, int depth, const char *type,
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
istringstream &iline, int linenr, const std::string &filename))
{ {
string line; string line;
int linenr = 0; int linenr = 0;
@ -462,7 +471,6 @@ void TileGenerator::parseColorsStream(std::istream &in, const std::string &filen
iline.str(line); iline.str(line);
iline >> std::skipws; iline >> std::skipws;
string name; string name;
ColorEntry color;
iline >> name >> std::ws; iline >> name >> std::ws;
if (name.length() == 0) if (name.length() == 0)
continue; continue;
@ -487,54 +495,10 @@ void TileGenerator::parseColorsStream(std::istream &in, const std::string &filen
} }
} }
#endif #endif
parseColorsFile(includeFile, depth + 1); parseDataFile(includeFile, depth + 1, type, parseLine);
}
else if (iline.good() && iline.peek() == '-') {
char c;
iline >> c >> std::ws;
if (iline.bad() || !iline.eof()) {
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
continue;
}
m_colors.erase(name);
} }
else { else {
int r, g, b, a, t; (this->*parseLine)(line, name, iline, linenr, filename);
iline >> r;
iline >> g;
iline >> b;
if (iline.fail()) {
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
continue;
}
a = 0xff;
iline >> a;
t = 0;
iline >> t;
color = ColorEntry(r,g,b,a,t);
if ((m_drawAlpha && a == 0xff) || (!m_drawAlpha && a != 0xff)) {
// If drawing alpha, and the colors file contains both
// an opaque entry and a non-opaque entry for a name, prefer
// the non-opaque entry
// If not drawing alpha, and the colors file contains both
// an opaque entry and a non-opaque entry for a name, prefer
// the opaque entry
// Otherwise, any later entry overrides any previous entry
ColorMap::iterator it = m_colors.find(name);
if (it != m_colors.end()) {
if (m_drawAlpha && (a == 0xff && it->second.a != 0xff)) {
// drawing alpha: don't use opaque color to override
// non-opaque color
continue;
}
if (!m_drawAlpha && (a != 0xff && it->second.a == 0xff)) {
// not drawing alpha: don't use non-opaque color to
// override opaque color
continue;
}
}
}
m_colors[name] = color;
} }
} }
if (!in.eof()) { if (!in.eof()) {
@ -542,6 +506,128 @@ void TileGenerator::parseColorsStream(std::istream &in, const std::string &filen
} }
} }
void TileGenerator::parseNodeColorsLine(const std::string &line, std::string name, istringstream &iline, int linenr, const std::string &filename)
{
if (iline.good() && iline.peek() == '-') {
char c;
iline >> c >> std::ws;
if (iline.bad() || !iline.eof()) {
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
return;
}
m_nodeColors.erase(name);
}
else {
int r, g, b, a, t;
ColorEntry color;
iline >> r;
iline >> g;
iline >> b;
if (iline.fail()) {
std::cerr << filename << ":" << linenr << ": bad line in colors file (" << line << ")" << std::endl;
return;
}
a = 0xff;
iline >> a;
t = 0;
iline >> t;
color = ColorEntry(r,g,b,a,t);
if ((m_drawAlpha && a == 0xff) || (!m_drawAlpha && a != 0xff)) {
// If drawing alpha, and the colors file contains both
// an opaque entry and a non-opaque entry for a name, prefer
// the non-opaque entry
// If not drawing alpha, and the colors file contains both
// an opaque entry and a non-opaque entry for a name, prefer
// the opaque entry
// Otherwise, any later entry overrides any previous entry
NodeColorMap::iterator it = m_nodeColors.find(name);
if (it != m_nodeColors.end()) {
if (m_drawAlpha && (a == 0xff && it->second.a != 0xff)) {
// drawing alpha: don't use opaque color to override
// non-opaque color
return;
}
if (!m_drawAlpha && (a != 0xff && it->second.a == 0xff)) {
// not drawing alpha: don't use non-opaque color to
// override opaque color
return;
}
}
}
m_nodeColors[name] = color;
}
}
void TileGenerator::parseHeightMapColorsLine(const std::string &line, std::string name, istringstream &iline, int linenr, const std::string &filename)
{
(void) name;
int height[2];
Color color[2];
iline.str(line); // Reset
for (int i = 0; i < 2; i++) {
iline >> std::ws;
char c = iline.peek();
iline >> height[i];
if (iline.fail()) {
std::string value;
iline.clear();
iline >> std::ws;
iline >> value >> std::ws;
if (iline.good()) {
if (value == "-oo" || (c == '-' && value=="oo"))
height[i] = INT_MIN;
else if (value == "oo" || value == "+oo")
height[i] = INT_MAX;
else {
iline.clear(ios::failbit); // Set to failed
break;
}
}
}
}
for (int i = 0; i < 2; i++) {
int r, g, b;
iline >> r;
iline >> g;
iline >> b;
color[i] = Color(r,g,b);
}
if (height[0] > height[1]) {
{
int tmp = height[0];
height[0] = height[1];
height[1] = tmp;
}
{
Color tmp = color[0];
color[0] = color[1];
color[1] = tmp;
}
}
iline >> std::ws;
if (iline.fail() || !iline.eof()) {
std::cerr << filename << ":" << linenr << ": bad line in heightmap colors file (" << line << ")" << std::endl;
return;
}
m_heightMapColors.push_back(HeightMapColor(height[0], color[0], height[1], color[1]));
}
void TileGenerator::parseHeightMapNodesLine(const std::string &line, std::string name, istringstream &iline, int linenr, const std::string &filename)
{
if (name == "-") {
iline >> std::ws >> name >> std::ws;
m_nodeColors.erase(name);
}
else {
m_nodeColors[name] = ColorEntry(0,0,0,255,1); // Dummy entry - but must not be transparent
}
// Don't care if not at eof (== really eol). We might be reading a colors.txt file...
if (iline.bad()) {
std::cerr << filename << ":" << linenr << ": bad line in heightmap nodes file (" << line << ")" << std::endl;
return;
}
}
std::string TileGenerator::getWorldDatabaseBackend(const std::string &input) std::string TileGenerator::getWorldDatabaseBackend(const std::string &input)
{ {
string backend; string backend;
@ -1201,15 +1287,16 @@ void TileGenerator::processMapBlock(const DB::Block &block)
size_t end = name.find_first_of('\0'); size_t end = name.find_first_of('\0');
if (end != std::string::npos) if (end != std::string::npos)
name.erase(end); name.erase(end);
ColorMap::const_iterator color = m_colors.find(name); // In case of a height map, it stores just dummy colors...
if (name == "air" && !(m_drawAir && color != m_colors.end())) { NodeColorMap::const_iterator color = m_nodeColors.find(name);
if (name == "air" && !(m_drawAir && color != m_nodeColors.end())) {
m_nodeIDColor[nodeId] = NodeColorNotDrawn; m_nodeIDColor[nodeId] = NodeColorNotDrawn;
} }
else if (name == "ignore") { else if (name == "ignore") {
m_nodeIDColor[nodeId] = NodeColorNotDrawn; m_nodeIDColor[nodeId] = NodeColorNotDrawn;
} }
else { else {
if (color != m_colors.end()) { if (color != m_nodeColors.end()) {
m_nodeIDColor[nodeId] = &color->second; m_nodeIDColor[nodeId] = &color->second;
} }
else { else {
@ -1306,7 +1393,7 @@ void TileGenerator::renderMap()
cout << "Statistics" cout << "Statistics"
<< ": blocks read: " << m_db->getBlocksReadCount() << ": blocks read: " << m_db->getBlocksReadCount()
<< " (" << m_db->getBlocksCachedCount() << " cached + " << " (" << m_db->getBlocksCachedCount() << " cached + "
<< m_db->getBlocksUnCachedCount() << " uncached)" << m_db->getBlocksUnCachedCount() << " uncached)"
<< "; blocks rendered: " << blocks_rendered << "; blocks rendered: " << blocks_rendered
<< "; area rendered: " << area_rendered << "; area rendered: " << area_rendered
<< "/" << (m_xMax-m_xMin+1) * (m_zMax-m_zMin+1) << "/" << (m_xMax-m_xMin+1) * (m_zMax-m_zMin+1)
@ -1357,7 +1444,7 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
float g = 0; float g = 0;
float b = 0; float b = 0;
int n = 0; int n = 0;
for (std::list<HeightMapColor>::iterator i = m_heightMapColors.begin(); i != m_heightMapColors.end(); i++) { for (HeightMapColorList::iterator i = m_heightMapColors.begin(); i != m_heightMapColors.end(); i++) {
HeightMapColor &colorSpec = *i; HeightMapColor &colorSpec = *i;
if (adjustedHeight >= colorSpec.height[0] && adjustedHeight <= colorSpec.height[1]) { if (adjustedHeight >= colorSpec.height[0] && adjustedHeight <= colorSpec.height[1]) {
float weight = (float) (colorSpec.height[1] - adjustedHeight + 1) / (colorSpec.height[1] - colorSpec.height[0] + 1); float weight = (float) (colorSpec.height[1] - adjustedHeight + 1) / (colorSpec.height[1] - colorSpec.height[0] + 1);

View File

@ -23,7 +23,8 @@
#include <list> #include <list>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <string> #include <iostream>
#include <sstream>
#include "types.h" #include "types.h"
#include "PixelAttributes.h" #include "PixelAttributes.h"
#include "BlockPos.h" #include "BlockPos.h"
@ -51,10 +52,10 @@ class TileGenerator
{ {
private: private:
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
typedef std::unordered_map<std::string, ColorEntry> ColorMap; typedef std::unordered_map<std::string, ColorEntry> NodeColorMap;
typedef std::unordered_map<int, std::string> NodeID2NameMap; typedef std::unordered_map<int, std::string> NodeID2NameMap;
#else #else
typedef std::map<std::string, ColorEntry> ColorMap; typedef std::map<std::string, ColorEntry> NodeColorMap;
typedef std::map<int, std::string> NodeID2NameMap; typedef std::map<int, std::string> NodeID2NameMap;
#endif #endif
public: public:
@ -64,6 +65,7 @@ public:
int height[2]; int height[2];
Color color[2]; Color color[2];
}; };
typedef std::list<HeightMapColor> HeightMapColorList;
struct DrawObject { struct DrawObject {
void setCenter(const NodeCoord &c) { haveCenter = true; center = c; } void setCenter(const NodeCoord &c) { haveCenter = true; center = c; }
void setCorner1(const NodeCoord &c) { haveCenter = false; corner1 = c; } void setCorner1(const NodeCoord &c) { haveCenter = false; corner1 = c; }
@ -101,7 +103,7 @@ public:
TileGenerator(); TileGenerator();
~TileGenerator(); ~TileGenerator();
void setHeightMap(bool enable, bool grey); void setHeightMap(bool enable);
void setHeightMapYScale(float scale); void setHeightMapYScale(float scale);
void setSeaLevel(int level); void setSeaLevel(int level);
void setBgColor(const Color &bgColor); void setBgColor(const Color &bgColor);
@ -109,6 +111,7 @@ public:
void setScaleColor(const Color &scaleColor); void setScaleColor(const Color &scaleColor);
void setOriginColor(const Color &originColor); void setOriginColor(const Color &originColor);
void setPlayerColor(const Color &playerColor); void setPlayerColor(const Color &playerColor);
void setHeightMapColor(const Color &color0, const Color &color1);
Color parseColor(const Color &color); Color parseColor(const Color &color);
void setDrawOrigin(bool drawOrigin); void setDrawOrigin(bool drawOrigin);
void setDrawPlayers(bool drawPlayers); void setDrawPlayers(bool drawPlayers);
@ -129,13 +132,14 @@ public:
void setTileOrigin(int x, int y); void setTileOrigin(int x, int y);
void setTileCenter(int x, int y); void setTileCenter(int x, int y);
void enableProgressIndicator(void); void enableProgressIndicator(void);
void parseColorsFile(const std::string &fileName, int depth = 0); void parseNodeColorsFile(const std::string &fileName);
void parseHeightMapNodesFile(const std::string &fileName);
void parseHeightMapColorsFile(const std::string &fileName);
void setBackend(std::string backend); void setBackend(std::string backend);
void setChunkSize(int size); void setChunkSize(int size);
void generate(const std::string &input, const std::string &output); void generate(const std::string &input, const std::string &output);
private: private:
void parseColorsStream(std::istream &in, const std::string &filename, int depth);
std::string getWorldDatabaseBackend(const std::string &input); std::string getWorldDatabaseBackend(const std::string &input);
int getMapChunkSize(const std::string &input); int getMapChunkSize(const std::string &input);
void openDb(const std::string &input); void openDb(const std::string &input);
@ -143,21 +147,21 @@ private:
void createImage(); void createImage();
void computeMapParameters(const std::string &input); void computeMapParameters(const std::string &input);
void computeTileParameters( void computeTileParameters(
// Input parameters // Input parameters
int minPos, int minPos,
int maxPos, int maxPos,
int mapStartNodeOffset, int mapStartNodeOffset,
int mapEndNodeOffset, int mapEndNodeOffset,
int tileOrigin, int tileOrigin,
int tileSize, int tileSize,
// Input / Output parameters // Input / Output parameters
int &pictSize, int &pictSize,
// Output parameters // Output parameters
int &tileBorderCount, int &tileBorderCount,
int &tileMapOffset, int &tileMapOffset,
int &tileMapExcess, int &tileMapExcess,
// Behavior selection // Behavior selection
bool ascending); bool ascending);
void renderMap(); void renderMap();
std::list<int> getZValueList() const; std::list<int> getZValueList() const;
void pushPixelRows(int zPosLimit); void pushPixelRows(int zPosLimit);
@ -180,6 +184,19 @@ private:
int borderLeft() const { return ((m_drawScale & DRAWSCALE_LEFT) ? SCALESIZE_VERT : 0); } int borderLeft() const { return ((m_drawScale & DRAWSCALE_LEFT) ? SCALESIZE_VERT : 0); }
int borderRight() const { return ((m_drawScale & DRAWSCALE_RIGHT) ? SCALESIZE_VERT : 0); } int borderRight() const { return ((m_drawScale & DRAWSCALE_RIGHT) ? SCALESIZE_VERT : 0); }
void parseDataFile(const std::string &fileName, int depth, const char *type,
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
std::istringstream &iline, int linenr, const std::string &filename));
void parseDataStream(std::istream &in, const std::string &filename, int depth, const char *type,
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
std::istringstream &iline, int linenr, const std::string &filename));
void parseNodeColorsLine(const std::string &line, std::string name, std::istringstream &iline,
int linenr, const std::string &filename);
void parseHeightMapNodesLine(const std::string &line, std::string name, std::istringstream &iline,
int linenr, const std::string &filename);
void parseHeightMapColorsLine(const std::string &line, std::string name, std::istringstream &iline,
int linenr, const std::string &filename);
public: public:
int verboseCoordinates; int verboseCoordinates;
int verboseReadColors; int verboseReadColors;
@ -188,10 +205,8 @@ public:
private: private:
bool m_heightMap; bool m_heightMap;
bool m_heightMapGrey;
float m_heightMapYScale; float m_heightMapYScale;
int m_seaLevel; int m_seaLevel;
std::list<HeightMapColor> m_heightMapColors;
Color m_bgColor; Color m_bgColor;
Color m_blockDefaultColor; Color m_blockDefaultColor;
Color m_scaleColor; Color m_scaleColor;
@ -250,7 +265,8 @@ private:
NodeID2NameMap m_nameMap; NodeID2NameMap m_nameMap;
static const ColorEntry *NodeColorNotDrawn; static const ColorEntry *NodeColorNotDrawn;
const ColorEntry *m_nodeIDColor[MAPBLOCK_MAXCOLORS]; const ColorEntry *m_nodeIDColor[MAPBLOCK_MAXCOLORS];
ColorMap m_colors; NodeColorMap m_nodeColors;
HeightMapColorList m_heightMapColors;
uint16_t m_readedPixels[16]; uint16_t m_readedPixels[16];
std::set<std::string> m_unknownNodes; std::set<std::string> m_unknownNodes;
std::vector<DrawObject> m_drawObjects; std::vector<DrawObject> m_drawObjects;

File diff suppressed because it is too large Load Diff

25
heightmap-colors.txt Normal file
View File

@ -0,0 +1,25 @@
# The colors in this file were primarily chosen so that they make a standard
# minetest world look good.
# Secondarily, they were chosen to span as large a height-range as possible.
-oo -150 4 4 4 4 4 4 # Almost black
-150 -90 4 4 4 48 16 48 # Dark purple -> almost black
-90 -60 48 16 48 16 32 64 # Dark blue -> dark purple
-60 0 16 32 64 32 64 255 # Light blue -> dark blue
# The green, yellow and red-ish colors could be spread over a much
# greater height range, but using these parameters, a map of a regular
# world contains some yellow, and even red-ish as well
# See below
1 10 32 128 32 64 192 64 # Green -> Yellow-ish
10 20 64 192 64 192 192 64 # Yellow-ish -> Yellow
20 40 192 192 64 128 128 64 # Yellow -> dark yellow
40 50 128 128 64 128 64 64 # Dark yellow -> red-ish
50 70 128 64 64 64 32 32 # Red-ish -> dark red-ish
70 80 64 32 32 48 48 48 # Dark red-ish -> dark grey
80 140 48 48 48 96 96 96 # Dark grey -> less dark gray
# Above 140, white suggests snowy :-)
141 250 160 160 160 250 250 250 # Light gray -> almost white
250 oo 250 250 250 250 250 250 # Almost white

1130
heightmap-nodes.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -32,15 +32,17 @@ using namespace std;
#define OPT_VERBOSE_SEARCH_COLORS 0x86 #define OPT_VERBOSE_SEARCH_COLORS 0x86
#define OPT_CHUNKSIZE 0x87 #define OPT_CHUNKSIZE 0x87
#define OPT_HEIGHTMAP 0x88 #define OPT_HEIGHTMAP 0x88
#define OPT_HEIGHTMAPGREY 0x89 #define OPT_HEIGHTMAPYSCALE 0x89
#define OPT_HEIGHTMAPYSCALE 0x8a #define OPT_HEIGHT_LEVEL0 0x8a
#define OPT_HEIGHT_LEVEL0 0x8b #define OPT_HEIGHTMAPNODESFILE 0x8b
#define OPT_HEIGHTMAPCOLORSFILE 0x8c
// Will be replaced with the actual name and location of the executable (if found) // Will be replaced with the actual name and location of the executable (if found)
string executableName = "minetestmapper"; string executableName = "minetestmapper";
string installPrefix = INSTALL_PREFIX; string installPrefix = INSTALL_PREFIX;
string colorsDefaultName = "colors.txt"; string nodeColorsDefaultFile = "colors.txt";
string heightMapNodesDefaultFile = "heightmap-nodes.txt";
string heightMapColorsDefaultFile = "heightmap-colors.txt";
class FuzzyBool { class FuzzyBool {
private: private:
@ -71,9 +73,11 @@ void usage()
" -i/--input <world_path>\n" " -i/--input <world_path>\n"
" -o/--output <output_image.png>\n" " -o/--output <output_image.png>\n"
" --colors <file>\n" " --colors <file>\n"
" --heightmap[-grey]\n" " --heightmap-nodes <file>\n"
" --heightmap-scale <scale>\n" " --heightmap-colors[=<file>]\n"
" --height-level-0 <level>\n" " --height-level-0 <level>\n"
" --heightmap[=<color>]\n"
" --heightmap-yscale <scale>\n"
" --bgcolor <color>\n" " --bgcolor <color>\n"
" --blockcolor <color>\n" " --blockcolor <color>\n"
" --scalecolor <color>\n" " --scalecolor <color>\n"
@ -139,9 +143,11 @@ void usage()
std::cout << executableName << ' ' << options_text; std::cout << executableName << ' ' << options_text;
} }
void parseColorsFile(TileGenerator &generator, const string &input, string colorsFile) { void parseDataFile(TileGenerator &generator, const string &input, string dataFile, string defaultFile,
if (!colorsFile.empty()) { void (TileGenerator::*parseFile)(const std::string &fileName))
generator.parseColorsFile(colorsFile); {
if (!dataFile.empty()) {
(generator.*parseFile)(dataFile);
return; return;
} }
@ -170,17 +176,17 @@ void parseColorsFile(TileGenerator &generator, const string &input, string color
} }
colorPaths.push_back(""); colorPaths.push_back("");
std::vector<std::string> colorFileNames; std::vector<std::string> fileNames;
colorFileNames.push_back(colorsDefaultName); fileNames.push_back(defaultFile);
for (std::vector<std::string>::iterator path = colorPaths.begin(); path != colorPaths.end(); path++) { for (std::vector<std::string>::iterator path = colorPaths.begin(); path != colorPaths.end(); path++) {
for (std::vector<std::string>::iterator name = colorFileNames.begin(); name != colorFileNames.end(); name++) { for (std::vector<std::string>::iterator name = fileNames.begin(); name != fileNames.end(); name++) {
if (path->empty()) if (path->empty())
colorsFile = *name; dataFile = *name;
else else
colorsFile = *path + PATH_SEPARATOR + *name; dataFile = *path + PATH_SEPARATOR + *name;
try { try {
generator.parseColorsFile(colorsFile); (generator.*parseFile)(dataFile);
if (path->empty()) { if (path->empty()) {
// I hope this is not obnoxious to windows users ? // I hope this is not obnoxious to windows users ?
cerr << "Warning: Using " << *name << " in current directory as a last resort." << std::endl cerr << "Warning: Using " << *name << " in current directory as a last resort." << std::endl
@ -199,7 +205,9 @@ void parseColorsFile(TileGenerator &generator, const string &input, string color
} }
} }
throw std::runtime_error("Failed to find or failed to open a colors.txt file."); ostringstream oss;
oss << "Failed to find or failed to open a " << defaultFile << " file.";
throw std::runtime_error(oss.str().c_str());
} }
// is: stream to read from // is: stream to read from
@ -530,10 +538,10 @@ int main(int argc, char *argv[])
{"input", required_argument, 0, 'i'}, {"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'}, {"output", required_argument, 0, 'o'},
{"colors", required_argument, 0, 'C'}, {"colors", required_argument, 0, 'C'},
{"heightmap", no_argument, 0, OPT_HEIGHTMAP}, {"heightmap-nodes", required_argument, 0, OPT_HEIGHTMAPNODESFILE},
{"heightmap-grey", no_argument, 0, OPT_HEIGHTMAPGREY}, {"heightmap-colors", required_argument, 0, OPT_HEIGHTMAPCOLORSFILE},
{"heightmap-gray", no_argument, 0, OPT_HEIGHTMAPGREY}, {"heightmap", optional_argument, 0, OPT_HEIGHTMAP},
{"heightmap-scale", required_argument, 0, OPT_HEIGHTMAPYSCALE}, {"heightmap-yscale", required_argument, 0, OPT_HEIGHTMAPYSCALE},
{"height-level-0", required_argument, 0, OPT_HEIGHT_LEVEL0}, {"height-level-0", required_argument, 0, OPT_HEIGHT_LEVEL0},
{"bgcolor", required_argument, 0, 'b'}, {"bgcolor", required_argument, 0, 'b'},
{"blockcolor", required_argument, 0, OPT_BLOCKCOLOR}, {"blockcolor", required_argument, 0, OPT_BLOCKCOLOR},
@ -580,7 +588,11 @@ int main(int argc, char *argv[])
string input; string input;
string output; string output;
string colorsFile; bool heightMap = false;
bool loadHeightMapColorsFile = false;
string nodeColorsFile;
string heightMapColorsFile;
string heightMapNodesFile;
bool foundGeometrySpec = false; bool foundGeometrySpec = false;
bool setFixedOrShrinkGeometry = false; bool setFixedOrShrinkGeometry = false;
@ -614,16 +626,39 @@ int main(int argc, char *argv[])
output = optarg; output = optarg;
break; break;
case 'C': case 'C':
colorsFile = optarg; nodeColorsFile = optarg;
break;
case OPT_HEIGHTMAPNODESFILE:
heightMapNodesFile = optarg;
break;
case OPT_HEIGHTMAPCOLORSFILE:
heightMapColorsFile = optarg;
break; break;
case 'b': case 'b':
generator.setBgColor(Color(optarg, 0)); generator.setBgColor(Color(optarg, 0));
break; break;
case OPT_HEIGHTMAP: case OPT_HEIGHTMAP:
generator.setHeightMap(true, false); generator.setHeightMap(true);
break; heightMap = true;
case OPT_HEIGHTMAPGREY: if (optarg && *optarg) {
generator.setHeightMap(true, true); loadHeightMapColorsFile = false;
std::string color = optarg;
int l = color.length();
for (int i = 0; i < l; i++)
color[i] = tolower(color[i]);
if (color == "grey" || color == "gray")
generator.setHeightMapColor(Color(0, 0, 0), Color(255, 255, 255));
else if (color == "black")
generator.setHeightMapColor(Color(0, 0, 0), Color(0, 0, 0));
else if (color == "white")
generator.setHeightMapColor(Color(255, 255, 255), Color(255, 255, 255));
else
generator.setHeightMapColor(Color(0, 0, 0), Color(color, 0));
break;
}
else {
loadHeightMapColorsFile = true;
}
break; break;
case OPT_HEIGHTMAPYSCALE: case OPT_HEIGHTMAPYSCALE:
if (isdigit(optarg[0]) || ((optarg[0]=='-' || optarg[0]=='+') && isdigit(optarg[1]))) { if (isdigit(optarg[0]) || ((optarg[0]=='-' || optarg[0]=='+') && isdigit(optarg[1]))) {
@ -1053,7 +1088,14 @@ int main(int argc, char *argv[])
} }
try { try {
parseColorsFile(generator, input, colorsFile); if (heightMap) {
parseDataFile(generator, input, heightMapNodesFile, heightMapNodesDefaultFile, &TileGenerator::parseHeightMapNodesFile);
if (loadHeightMapColorsFile)
parseDataFile(generator, input, heightMapColorsFile, heightMapColorsDefaultFile, &TileGenerator::parseHeightMapColorsFile);
}
else {
parseDataFile(generator, input, nodeColorsFile, nodeColorsDefaultFile, &TileGenerator::parseNodeColorsFile);
}
generator.generate(input, output); generator.generate(input, output);
} catch(std::runtime_error e) { } catch(std::runtime_error e) {
std::cout<<"Exception: "<<e.what()<<std::endl; std::cout<<"Exception: "<<e.what()<<std::endl;