Add the option to draw a height scale for the height map
This commit is contained in:
parent
4476de429d
commit
994e9d7171
@ -177,7 +177,9 @@ TileGenerator::TileGenerator():
|
|||||||
m_tileHeight(0),
|
m_tileHeight(0),
|
||||||
m_tileBorderSize(1),
|
m_tileBorderSize(1),
|
||||||
m_tileMapXOffset(0),
|
m_tileMapXOffset(0),
|
||||||
m_tileMapYOffset(0)
|
m_tileMapYOffset(0),
|
||||||
|
m_surfaceHeight(INT_MIN),
|
||||||
|
m_surfaceDepth(INT_MAX)
|
||||||
{
|
{
|
||||||
// Load default grey colors.
|
// 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(INT_MIN, Color(0,0,0), -129, Color(0,0,0)));
|
||||||
@ -298,7 +300,18 @@ void TileGenerator::setDrawPlayers(bool drawPlayers)
|
|||||||
|
|
||||||
void TileGenerator::setDrawScale(int scale)
|
void TileGenerator::setDrawScale(int scale)
|
||||||
{
|
{
|
||||||
m_drawScale = (scale & DRAWSCALE_MASK);
|
m_drawScale = (scale & DRAWSCALE_MASK) | (m_drawScale & DRAWHEIGHTSCALE_MASK & ((~scale & DRAWSCALE_MASK) << 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileGenerator::setDrawHeightScale(int scale)
|
||||||
|
{
|
||||||
|
unsigned s = scale;
|
||||||
|
int bits = 0;
|
||||||
|
for (; s; s >>= 1)
|
||||||
|
if ((s & 0x1)) bits++;
|
||||||
|
if (bits > 1)
|
||||||
|
throw std::runtime_error(std::string("Multiple height scale positions requested"));
|
||||||
|
m_drawScale = (scale & DRAWHEIGHTSCALE_MASK) | (m_drawScale & DRAWSCALE_MASK & ((~scale & DRAWHEIGHTSCALE_MASK) >> 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
||||||
@ -436,9 +449,12 @@ void TileGenerator::generate(const std::string &input, const std::string &output
|
|||||||
computeMapParameters(input);
|
computeMapParameters(input);
|
||||||
createImage();
|
createImage();
|
||||||
renderMap();
|
renderMap();
|
||||||
if (m_drawScale) {
|
if ((m_drawScale & DRAWSCALE_MASK)) {
|
||||||
renderScale();
|
renderScale();
|
||||||
}
|
}
|
||||||
|
if (m_heightMap && (m_drawScale & DRAWHEIGHTSCALE_MASK)) {
|
||||||
|
renderHeightScale();
|
||||||
|
}
|
||||||
if (m_drawOrigin) {
|
if (m_drawOrigin) {
|
||||||
renderOrigin();
|
renderOrigin();
|
||||||
}
|
}
|
||||||
@ -1406,6 +1422,29 @@ void TileGenerator::renderMap()
|
|||||||
cout << std::setw(50) << "" << "\r";
|
cout << std::setw(50) << "" << "\r";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color TileGenerator::computeMapHeightColor(int height)
|
||||||
|
{
|
||||||
|
int adjustedHeight = int((height - m_seaLevel) * m_heightMapYScale + 0.5);
|
||||||
|
float r = 0;
|
||||||
|
float g = 0;
|
||||||
|
float b = 0;
|
||||||
|
int n = 0;
|
||||||
|
for (HeightMapColorList::iterator i = m_heightMapColors.begin(); i != m_heightMapColors.end(); i++) {
|
||||||
|
HeightMapColor &colorSpec = *i;
|
||||||
|
if (adjustedHeight >= colorSpec.height[0] && adjustedHeight <= colorSpec.height[1]) {
|
||||||
|
float weight = (float) (colorSpec.height[1] - adjustedHeight + 1) / (colorSpec.height[1] - colorSpec.height[0] + 1);
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
r += colorSpec.color[j].r * weight;
|
||||||
|
g += colorSpec.color[j].g * weight;
|
||||||
|
b += colorSpec.color[j].b * weight;
|
||||||
|
weight = 1 - weight;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Color(int(r / n + 0.5), int(g / n + 0.5), int(b / n + 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version)
|
inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version)
|
||||||
{
|
{
|
||||||
checkBlockNodeDataLimit(version, mapBlock.length());
|
checkBlockNodeDataLimit(version, mapBlock.length());
|
||||||
@ -1438,26 +1477,12 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
|
|||||||
int height = pos.y * 16 + y;
|
int height = pos.y * 16 + y;
|
||||||
if (m_heightMap) {
|
if (m_heightMap) {
|
||||||
if (m_nodeIDColor[content] && nodeColor.a != 0) {
|
if (m_nodeIDColor[content] && nodeColor.a != 0) {
|
||||||
int adjustedHeight = int((height - m_seaLevel) * m_heightMapYScale + 0.5);
|
if (!(m_readedPixels[z] & (1 << x))) {
|
||||||
|
if (height > m_surfaceHeight) m_surfaceHeight = height;
|
||||||
|
if (height < m_surfaceDepth) m_surfaceDepth = height;
|
||||||
|
}
|
||||||
rowIsEmpty = false;
|
rowIsEmpty = false;
|
||||||
float r = 0;
|
pixel = PixelAttribute(computeMapHeightColor(height), height);
|
||||||
float g = 0;
|
|
||||||
float b = 0;
|
|
||||||
int n = 0;
|
|
||||||
for (HeightMapColorList::iterator i = m_heightMapColors.begin(); i != m_heightMapColors.end(); i++) {
|
|
||||||
HeightMapColor &colorSpec = *i;
|
|
||||||
if (adjustedHeight >= colorSpec.height[0] && adjustedHeight <= colorSpec.height[1]) {
|
|
||||||
float weight = (float) (colorSpec.height[1] - adjustedHeight + 1) / (colorSpec.height[1] - colorSpec.height[0] + 1);
|
|
||||||
for (int j = 0; j < 2; j++) {
|
|
||||||
r += colorSpec.color[j].r * weight;
|
|
||||||
g += colorSpec.color[j].g * weight;
|
|
||||||
b += colorSpec.color[j].b * weight;
|
|
||||||
weight = 1 - weight;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pixel = PixelAttribute(Color(int(r / n + 0.5), int(g / n + 0.5), int(b / n + 0.5)), height);
|
|
||||||
m_readedPixels[z] |= (1 << x);
|
m_readedPixels[z] |= (1 << x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1526,6 +1551,48 @@ void TileGenerator::renderScale()
|
|||||||
// DRAWSCALE_RIGHT and DRAWSCALE_BOTTOM not implemented - getting the text positioned right seems not trivial (??)
|
// DRAWSCALE_RIGHT and DRAWSCALE_BOTTOM not implemented - getting the text positioned right seems not trivial (??)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileGenerator::renderHeightScale()
|
||||||
|
{
|
||||||
|
|
||||||
|
int scaleColor = m_scaleColor.to_libgd();
|
||||||
|
int height_min = m_surfaceDepth - 16;
|
||||||
|
int height_limit = m_surfaceHeight + 16;
|
||||||
|
int xBorderOffset = borderLeft();
|
||||||
|
int yBorderOffset = borderTop() + m_pictHeight;
|
||||||
|
double height_step = (double)(height_limit - height_min) / m_pictWidth;
|
||||||
|
if (height_step < 1.0 / 16) {
|
||||||
|
height_step = 1.0 / 16;
|
||||||
|
}
|
||||||
|
double number_step = 64;
|
||||||
|
while (number_step / height_step < 48)
|
||||||
|
number_step *= 2;
|
||||||
|
while (number_step / height_step > 96)
|
||||||
|
number_step /= 2;
|
||||||
|
|
||||||
|
double height = height_min;
|
||||||
|
for (int x = 0; height < height_limit; x++, height += height_step) {
|
||||||
|
Color color = computeMapHeightColor(int(height + 0.5));
|
||||||
|
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + 8, xBorderOffset + x, yBorderOffset + borderBottom() - 20, color.to_libgd());
|
||||||
|
|
||||||
|
int iheight = int(height + (height > 0 ? 0.5 : -0.5));
|
||||||
|
int iheight64 = int(iheight / number_step + (height > 0 ? 0.5 : -0.5)) * number_step;
|
||||||
|
if (fabs(height - iheight64) <= height_step / 2 && (height - iheight64) > -height_step / 2) {
|
||||||
|
if (iheight64 / int(number_step) % 2 == 1 && fabs(height) > 9999 && number_step / height_step < 56) {
|
||||||
|
// Maybe not enough room for the number. Draw a tick mark instead
|
||||||
|
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 16, scaleColor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stringstream buf;
|
||||||
|
buf << iheight64;
|
||||||
|
string scaleText = buf.str();
|
||||||
|
gdImageString(m_image, gdFontGetMediumBold(), xBorderOffset + x + 2, yBorderOffset + borderBottom() - 16,
|
||||||
|
reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), scaleColor);
|
||||||
|
gdImageLine(m_image, xBorderOffset + x, yBorderOffset + borderBottom() - 19, xBorderOffset + x, yBorderOffset + borderBottom() - 1, scaleColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TileGenerator::renderOrigin()
|
void TileGenerator::renderOrigin()
|
||||||
{
|
{
|
||||||
int imageX = worldX2ImageX(0);
|
int imageX = worldX2ImageX(0);
|
||||||
|
@ -44,9 +44,15 @@
|
|||||||
#define DRAWSCALE_RIGHT 0x02
|
#define DRAWSCALE_RIGHT 0x02
|
||||||
#define DRAWSCALE_TOP 0x04
|
#define DRAWSCALE_TOP 0x04
|
||||||
#define DRAWSCALE_BOTTOM 0x08
|
#define DRAWSCALE_BOTTOM 0x08
|
||||||
|
#define DRAWHEIGHTSCALE_MASK 0xf0
|
||||||
|
#define DRAWHEIGHTSCALE_LEFT 0x10
|
||||||
|
#define DRAWHEIGHTSCALE_RIGHT 0x20
|
||||||
|
#define DRAWHEIGHTSCALE_TOP 0x40
|
||||||
|
#define DRAWHEIGHTSCALE_BOTTOM 0x80
|
||||||
|
|
||||||
#define SCALESIZE_HOR 40
|
#define SCALESIZE_HOR 40
|
||||||
#define SCALESIZE_VERT 50
|
#define SCALESIZE_VERT 50
|
||||||
|
#define HEIGHTSCALESIZE 60
|
||||||
|
|
||||||
class TileGenerator
|
class TileGenerator
|
||||||
{
|
{
|
||||||
@ -116,6 +122,7 @@ public:
|
|||||||
void setDrawOrigin(bool drawOrigin);
|
void setDrawOrigin(bool drawOrigin);
|
||||||
void setDrawPlayers(bool drawPlayers);
|
void setDrawPlayers(bool drawPlayers);
|
||||||
void setDrawScale(int scale);
|
void setDrawScale(int scale);
|
||||||
|
void setDrawHeightScale(int scale);
|
||||||
void setDrawAlpha(bool drawAlpha);
|
void setDrawAlpha(bool drawAlpha);
|
||||||
void setDrawAir(bool drawAir);
|
void setDrawAir(bool drawAir);
|
||||||
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
|
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
|
||||||
@ -138,6 +145,7 @@ public:
|
|||||||
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);
|
||||||
|
Color computeMapHeightColor(int height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getWorldDatabaseBackend(const std::string &input);
|
std::string getWorldDatabaseBackend(const std::string &input);
|
||||||
@ -168,6 +176,7 @@ private:
|
|||||||
void processMapBlock(const DB::Block &block);
|
void processMapBlock(const DB::Block &block);
|
||||||
void renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version);
|
void renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version);
|
||||||
void renderScale();
|
void renderScale();
|
||||||
|
void renderHeightScale();
|
||||||
void renderOrigin();
|
void renderOrigin();
|
||||||
void renderPlayers(const std::string &inputPath);
|
void renderPlayers(const std::string &inputPath);
|
||||||
void renderDrawObjects();
|
void renderDrawObjects();
|
||||||
@ -179,10 +188,10 @@ private:
|
|||||||
int worldZ2ImageY(int val) const;
|
int worldZ2ImageY(int val) const;
|
||||||
int worldBlockX2StoredX(int xPos) const { return (xPos - m_xMin) * 16; }
|
int worldBlockX2StoredX(int xPos) const { return (xPos - m_xMin) * 16; }
|
||||||
int worldBlockZ2StoredY(int zPos) const { return (m_zMax - zPos) * 16; }
|
int worldBlockZ2StoredY(int zPos) const { return (m_zMax - zPos) * 16; }
|
||||||
int borderTop() const { return ((m_drawScale & DRAWSCALE_TOP) ? SCALESIZE_HOR : 0); }
|
int borderTop() const { return ((m_drawScale & DRAWSCALE_TOP) ? SCALESIZE_HOR : 0) + (m_heightMap && (m_drawScale & DRAWHEIGHTSCALE_TOP) ? HEIGHTSCALESIZE : 0); }
|
||||||
int borderBottom() const { return ((m_drawScale & DRAWSCALE_BOTTOM) ? SCALESIZE_HOR : 0); }
|
int borderBottom() const { return ((m_drawScale & DRAWSCALE_BOTTOM) ? SCALESIZE_HOR : 0) + (m_heightMap && (m_drawScale & DRAWHEIGHTSCALE_BOTTOM) ? HEIGHTSCALESIZE : 0); }
|
||||||
int borderLeft() const { return ((m_drawScale & DRAWSCALE_LEFT) ? SCALESIZE_VERT : 0); }
|
int borderLeft() const { return ((m_drawScale & DRAWSCALE_LEFT) ? SCALESIZE_VERT : 0) + (m_heightMap && (m_drawScale & DRAWHEIGHTSCALE_LEFT) ? HEIGHTSCALESIZE : 0); }
|
||||||
int borderRight() const { return ((m_drawScale & DRAWSCALE_RIGHT) ? SCALESIZE_VERT : 0); }
|
int borderRight() const { return ((m_drawScale & DRAWSCALE_RIGHT) ? SCALESIZE_VERT : 0) + (m_heightMap && (m_drawScale & DRAWHEIGHTSCALE_RIGHT) ? HEIGHTSCALESIZE : 0); }
|
||||||
|
|
||||||
void parseDataFile(const std::string &fileName, int depth, const char *type,
|
void parseDataFile(const std::string &fileName, int depth, const char *type,
|
||||||
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
|
void (TileGenerator::*parseLine)(const std::string &line, std::string name,
|
||||||
@ -261,6 +270,8 @@ private:
|
|||||||
int m_tileBorderYCount;
|
int m_tileBorderYCount;
|
||||||
int m_pictWidth;
|
int m_pictWidth;
|
||||||
int m_pictHeight;
|
int m_pictHeight;
|
||||||
|
int m_surfaceHeight;
|
||||||
|
int m_surfaceDepth;
|
||||||
std::list<BlockPos> m_positions;
|
std::list<BlockPos> m_positions;
|
||||||
NodeID2NameMap m_nameMap;
|
NodeID2NameMap m_nameMap;
|
||||||
static const ColorEntry *NodeColorNotDrawn;
|
static const ColorEntry *NodeColorNotDrawn;
|
||||||
|
@ -36,6 +36,7 @@ using namespace std;
|
|||||||
#define OPT_HEIGHT_LEVEL0 0x8a
|
#define OPT_HEIGHT_LEVEL0 0x8a
|
||||||
#define OPT_HEIGHTMAPNODESFILE 0x8b
|
#define OPT_HEIGHTMAPNODESFILE 0x8b
|
||||||
#define OPT_HEIGHTMAPCOLORSFILE 0x8c
|
#define OPT_HEIGHTMAPCOLORSFILE 0x8c
|
||||||
|
#define OPT_DRAWHEIGHTSCALE 0x8d
|
||||||
|
|
||||||
// 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";
|
||||||
@ -85,6 +86,7 @@ void usage()
|
|||||||
" --origincolor <color>\n"
|
" --origincolor <color>\n"
|
||||||
" --tilebordercolor <color>\n"
|
" --tilebordercolor <color>\n"
|
||||||
" --drawscale[=left,top]\n"
|
" --drawscale[=left,top]\n"
|
||||||
|
" --drawheightscale\n"
|
||||||
" --drawplayers\n"
|
" --drawplayers\n"
|
||||||
" --draworigin\n"
|
" --draworigin\n"
|
||||||
" --drawalpha[=cumulative|cumulative-darken|average|none]\n"
|
" --drawalpha[=cumulative|cumulative-darken|average|none]\n"
|
||||||
@ -551,6 +553,7 @@ int main(int argc, char *argv[])
|
|||||||
{"draworigin", no_argument, 0, 'R'},
|
{"draworigin", no_argument, 0, 'R'},
|
||||||
{"drawplayers", no_argument, 0, 'P'},
|
{"drawplayers", no_argument, 0, 'P'},
|
||||||
{"drawscale", optional_argument, 0, 'S'},
|
{"drawscale", optional_argument, 0, 'S'},
|
||||||
|
{"drawheightscale", no_argument, 0, OPT_DRAWHEIGHTSCALE},
|
||||||
{"drawalpha", optional_argument, 0, 'e'},
|
{"drawalpha", optional_argument, 0, 'e'},
|
||||||
{"drawair", no_argument, 0, OPT_DRAWAIR},
|
{"drawair", no_argument, 0, OPT_DRAWAIR},
|
||||||
{"drawpoint", required_argument, 0, OPT_DRAW_OBJECT},
|
{"drawpoint", required_argument, 0, OPT_DRAW_OBJECT},
|
||||||
@ -724,6 +727,9 @@ int main(int argc, char *argv[])
|
|||||||
generator.setDrawScale(DRAWSCALE_LEFT | DRAWSCALE_TOP);
|
generator.setDrawScale(DRAWSCALE_LEFT | DRAWSCALE_TOP);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPT_DRAWHEIGHTSCALE :
|
||||||
|
generator.setDrawHeightScale(DRAWHEIGHTSCALE_BOTTOM);
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
|
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
|
||||||
if (optarg[0] == '0')
|
if (optarg[0] == '0')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user