mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-11-21 15:03:49 +01:00
Add alpha transparency ability for blocks
This commit is contained in:
parent
6897ef85c7
commit
84d46ab8eb
@ -11,11 +11,13 @@
|
||||
#define PIXELATTRIBUTES_H_ADZ35GYF
|
||||
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
struct PixelAttribute {
|
||||
PixelAttribute(): height(std::numeric_limits<int>::min()) {};
|
||||
PixelAttribute(): height(std::numeric_limits<int>::min()), thicken(0) {};
|
||||
int height;
|
||||
uint8_t thicken;
|
||||
inline bool valid_height() {
|
||||
return height != std::numeric_limits<int>::min();
|
||||
}
|
||||
|
@ -53,6 +53,9 @@ drawplayers:
|
||||
draworigin:
|
||||
Draw origin indicator, `--draworigin`
|
||||
|
||||
drawalpha:
|
||||
Allow blocks to be drawn with transparency, `--drawalpha`
|
||||
|
||||
noshading:
|
||||
Don't draw shading on nodes, `--noshading`
|
||||
|
||||
|
@ -54,9 +54,14 @@ static inline uint16_t readU16(const unsigned char *data)
|
||||
return data[0] << 8 | data[1];
|
||||
}
|
||||
|
||||
static inline int rgb2int(uint8_t r, uint8_t g, uint8_t b)
|
||||
static inline int rgb2int(uint8_t r, uint8_t g, uint8_t b, uint8_t a=0xFF)
|
||||
{
|
||||
return (r << 16) + (g << 8) + b;
|
||||
return (a << 24) + (r << 16) + (g << 8) + b;
|
||||
}
|
||||
|
||||
static inline int color2int(Color c)
|
||||
{
|
||||
return rgb2int(c.r, c.g, c.b, c.a);
|
||||
}
|
||||
|
||||
static inline int readBlockContent(const unsigned char *mapData, int version, int datapos)
|
||||
@ -93,6 +98,19 @@ static inline int colorSafeBounds(int color)
|
||||
}
|
||||
}
|
||||
|
||||
static inline Color mixColors(Color a, Color b)
|
||||
{
|
||||
Color result;
|
||||
double a1 = a.a / 255.0;
|
||||
double a2 = b.a / 255.0;
|
||||
|
||||
result.r = (int) (a1 * a.r + a2 * (1 - a1) * b.r);
|
||||
result.g = (int) (a1 * a.g + a2 * (1 - a1) * b.g);
|
||||
result.b = (int) (a1 * a.b + a2 * (1 - a1) * b.b);
|
||||
result.a = (int) (255 * (a1 + a2 * (1 - a1)));
|
||||
return result;
|
||||
}
|
||||
|
||||
TileGenerator::TileGenerator():
|
||||
m_bgColor(255, 255, 255),
|
||||
m_scaleColor(0, 0, 0),
|
||||
@ -101,6 +119,7 @@ TileGenerator::TileGenerator():
|
||||
m_drawOrigin(false),
|
||||
m_drawPlayers(false),
|
||||
m_drawScale(false),
|
||||
m_drawAlpha(false),
|
||||
m_shading(true),
|
||||
m_border(0),
|
||||
m_backend("sqlite3"),
|
||||
@ -178,6 +197,11 @@ void TileGenerator::setDrawScale(bool drawScale)
|
||||
}
|
||||
}
|
||||
|
||||
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
||||
{
|
||||
m_drawAlpha = drawAlpha;
|
||||
}
|
||||
|
||||
void TileGenerator::setShading(bool shading)
|
||||
{
|
||||
m_shading = shading;
|
||||
@ -268,7 +292,7 @@ void TileGenerator::parseColorsStream(std::istream &in)
|
||||
{
|
||||
while (in.good()) {
|
||||
string name;
|
||||
Color color;
|
||||
ColorEntry color;
|
||||
in >> name;
|
||||
if (name[0] == '#') {
|
||||
in.ignore(65536, '\n');
|
||||
@ -277,14 +301,20 @@ void TileGenerator::parseColorsStream(std::istream &in)
|
||||
while (name == "\n" && in.good()) {
|
||||
in >> name;
|
||||
}
|
||||
int r, g, b;
|
||||
int r, g, b, a, t;
|
||||
in >> r;
|
||||
in >> g;
|
||||
in >> b;
|
||||
if(in.peek() != '\n') {
|
||||
in >> a;
|
||||
if(in.peek() != '\n')
|
||||
in >> t;
|
||||
else
|
||||
t = 0;
|
||||
} else
|
||||
a = 0xFF;
|
||||
if (in.good()) {
|
||||
color.r = r;
|
||||
color.g = g;
|
||||
color.b = b;
|
||||
color = ColorEntry(r,g,b,a,t);
|
||||
m_colors[name] = color;
|
||||
}
|
||||
}
|
||||
@ -352,7 +382,7 @@ void TileGenerator::createImage()
|
||||
m_image = gdImageCreateTrueColor(m_mapWidth + m_border, m_mapHeight + m_border);
|
||||
m_blockPixelAttributes.setWidth(m_mapWidth);
|
||||
// Background
|
||||
gdImageFilledRectangle(m_image, 0, 0, m_mapWidth + m_border - 1, m_mapHeight + m_border -1, rgb2int(m_bgColor.r, m_bgColor.g, m_bgColor.b));
|
||||
gdImageFilledRectangle(m_image, 0, 0, m_mapWidth + m_border - 1, m_mapHeight + m_border -1, color2int(m_bgColor));
|
||||
}
|
||||
|
||||
std::map<int, TileGenerator::BlockList> TileGenerator::getBlocksOnZ(int zPos)
|
||||
@ -496,6 +526,8 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
|
||||
const unsigned char *mapData = mapBlock.c_str();
|
||||
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16;
|
||||
int maxY = (pos.y * 16 < m_yMax) ? 15 : m_yMax - pos.y * 16;
|
||||
Color col;
|
||||
uint8_t th;
|
||||
for (int z = 0; z < 16; ++z) {
|
||||
int imageY = getImageY(zBegin + 15 - z);
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
@ -503,6 +535,10 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
|
||||
continue;
|
||||
}
|
||||
int imageX = getImageX(xBegin + x);
|
||||
if(m_drawAlpha) {
|
||||
col = Color(0,0,0,0);
|
||||
th = 0;
|
||||
}
|
||||
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
int position = x + (y << 4) + (z << 8);
|
||||
@ -511,20 +547,33 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
|
||||
continue;
|
||||
}
|
||||
std::map<int, std::string>::iterator blockName = m_nameMap.find(content);
|
||||
if (blockName != m_nameMap.end()) {
|
||||
const string &name = blockName->second;
|
||||
ColorMap::const_iterator color = m_colors.find(name);
|
||||
if (color != m_colors.end()) {
|
||||
const Color &c = color->second;
|
||||
m_image->tpixels[imageY][imageX] = rgb2int(c.r, c.g, c.b);
|
||||
m_readedPixels[z] |= (1 << x);
|
||||
m_blockPixelAttributes.attribute(15 - z, xBegin + x).height = pos.y * 16 + y;
|
||||
} else {
|
||||
m_unknownNodes.insert(name);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
if (blockName == m_nameMap.end())
|
||||
continue;
|
||||
const string &name = blockName->second;
|
||||
ColorMap::const_iterator color = m_colors.find(name);
|
||||
if (color != m_colors.end()) {
|
||||
const Color c = color->second.to_color();
|
||||
if (m_drawAlpha) {
|
||||
if (col.a == 0)
|
||||
col = c;
|
||||
else
|
||||
col = mixColors(col, c);
|
||||
if(col.a == 0xFF) {
|
||||
m_image->tpixels[imageY][imageX] = color2int(col);
|
||||
m_blockPixelAttributes.attribute(15 - z, xBegin + x).thicken = th;
|
||||
} else {
|
||||
th = (th + color->second.t) / 2.0;
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
m_image->tpixels[imageY][imageX] = color2int(c);
|
||||
m_readedPixels[z] |= (1 << x);
|
||||
m_blockPixelAttributes.attribute(15 - z, xBegin + x).height = pos.y * 16 + y;
|
||||
} else {
|
||||
m_unknownNodes.insert(name);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -550,13 +599,16 @@ inline void TileGenerator::renderShading(int zPos)
|
||||
if (d > 36) {
|
||||
d = 36;
|
||||
}
|
||||
if (m_drawAlpha)
|
||||
d = d * ((0xFF - m_blockPixelAttributes.attribute(z, x).thicken) / 255.0);
|
||||
int sourceColor = m_image->tpixels[imageY][getImageX(x)] & 0xffffff;
|
||||
int r = (sourceColor & 0xff0000) >> 16;
|
||||
int g = (sourceColor & 0x00ff00) >> 8;
|
||||
int b = (sourceColor & 0x0000ff);
|
||||
uint8_t r = (sourceColor & 0xff0000) >> 16;
|
||||
uint8_t g = (sourceColor & 0x00ff00) >> 8;
|
||||
uint8_t b = (sourceColor & 0x0000ff);
|
||||
r = colorSafeBounds(r + d);
|
||||
g = colorSafeBounds(g + d);
|
||||
b = colorSafeBounds(b + d);
|
||||
|
||||
m_image->tpixels[imageY][getImageX(x)] = rgb2int(r, g, b);
|
||||
}
|
||||
}
|
||||
@ -565,7 +617,7 @@ inline void TileGenerator::renderShading(int zPos)
|
||||
|
||||
void TileGenerator::renderScale()
|
||||
{
|
||||
int color = rgb2int(m_scaleColor.r, m_scaleColor.g, m_scaleColor.b);
|
||||
int color = color2int(m_scaleColor);
|
||||
gdImageString(m_image, gdFontGetMediumBold(), 24, 0, reinterpret_cast<unsigned char *>(const_cast<char *>("X")), color);
|
||||
gdImageString(m_image, gdFontGetMediumBold(), 2, 24, reinterpret_cast<unsigned char *>(const_cast<char *>("Z")), color);
|
||||
|
||||
@ -596,12 +648,12 @@ void TileGenerator::renderOrigin()
|
||||
{
|
||||
int imageX = -m_xMin * 16 + m_border;
|
||||
int imageY = m_mapHeight - m_zMin * -16 + m_border;
|
||||
gdImageArc(m_image, imageX, imageY, 12, 12, 0, 360, rgb2int(m_originColor.r, m_originColor.g, m_originColor.b));
|
||||
gdImageArc(m_image, imageX, imageY, 12, 12, 0, 360, color2int(m_originColor));
|
||||
}
|
||||
|
||||
void TileGenerator::renderPlayers(const std::string &inputPath)
|
||||
{
|
||||
int color = rgb2int(m_playerColor.r, m_playerColor.g, m_playerColor.b);
|
||||
int color = color2int(m_playerColor);
|
||||
|
||||
PlayerAttributes players(inputPath);
|
||||
for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) {
|
||||
|
@ -21,13 +21,27 @@
|
||||
#include "db.h"
|
||||
|
||||
struct Color {
|
||||
Color(): r(255), g(255), b(255) {};
|
||||
Color(uint8_t r, uint8_t g, uint8_t b): r(r), g(g), b(b) {};
|
||||
Color(): r(0xFF), g(0xFF), b(0xFF), a(0) {};
|
||||
Color(uint8_t r, uint8_t g, uint8_t b): r(r), g(g), b(b), a(0xFF) {};
|
||||
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a): r(r), g(g), b(b), a(a) {};
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
};
|
||||
|
||||
struct ColorEntry {
|
||||
ColorEntry(): r(0), g(0), b(0), a(0), t(0) {};
|
||||
ColorEntry(uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t t): r(r), g(g), b(b), a(a), t(t) {};
|
||||
inline Color to_color() const { return Color(r, g, b, a); }
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
uint8_t t;
|
||||
};
|
||||
|
||||
|
||||
struct BlockPos {
|
||||
int x;
|
||||
int y;
|
||||
@ -61,7 +75,7 @@ class TileGenerator
|
||||
{
|
||||
private:
|
||||
typedef std::basic_string<unsigned char> unsigned_string;
|
||||
typedef std::map<std::string, Color> ColorMap;
|
||||
typedef std::map<std::string, ColorEntry> ColorMap;
|
||||
typedef std::pair<BlockPos, unsigned_string> Block;
|
||||
typedef std::list<Block> BlockList;
|
||||
|
||||
@ -75,6 +89,7 @@ public:
|
||||
void setDrawOrigin(bool drawOrigin);
|
||||
void setDrawPlayers(bool drawPlayers);
|
||||
void setDrawScale(bool drawScale);
|
||||
void setDrawAlpha(bool drawAlpha);
|
||||
void setShading(bool shading);
|
||||
void setGeometry(int x, int y, int w, int h);
|
||||
void setMinY(int y);
|
||||
@ -110,6 +125,7 @@ private:
|
||||
bool m_drawOrigin;
|
||||
bool m_drawPlayers;
|
||||
bool m_drawScale;
|
||||
bool m_drawAlpha;
|
||||
bool m_shading;
|
||||
int m_border;
|
||||
std::string m_backend;
|
||||
|
@ -90,8 +90,9 @@ while read -r p; do
|
||||
fi
|
||||
done < nodes.txt > colors.txt
|
||||
# Use nicer colors for water and lava
|
||||
sed -re 's/^default:water_([a-z]+) [0-9 ]+$/default:water_\1 39 66 106/' < colors.txt > tmp$$ && mv tmp$$ colors.txt
|
||||
sed -re 's/^default:water_([a-z]+) [0-9 ]+$/default:water_\1 39 66 106 128 224/' < colors.txt > tmp$$ && mv tmp$$ colors.txt
|
||||
sed -re 's/^default:lava_([a-z]+) [0-9 ]+$/default:lava_\1 255 100 0/' < colors.txt > tmp$$ && mv tmp$$ colors.txt
|
||||
sed -re 's/^default:([a-z_]*)glass ([0-9 ]+)$/default:\1glass \2 64 16/' < colors.txt > tmp$$ && mv tmp$$ colors.txt
|
||||
==INSTRUCTIONS==
|
||||
1) Make sure avgcolors.py outputs the usage instructions
|
||||
2) Add the dumpnodes mod to Minetest
|
||||
|
@ -1466,15 +1466,15 @@ mesecons_lightstone:lightstone_yellow_off 222 220 72
|
||||
mesecons_walllever:wall_lever_on 136 136 136
|
||||
mesecons_walllever:wall_lever_off 136 136 136
|
||||
bones:bones 74 74 74
|
||||
default:glass 192 192 227
|
||||
default:water_flowing 39 66 106
|
||||
default:glass 192 192 227 64 16
|
||||
default:water_flowing 39 66 106 128 224
|
||||
default:junglesapling 37 34 14
|
||||
default:sandstonebrick 160 144 108
|
||||
default:furnace_active 97 93 91
|
||||
default:sign_wall 163 141 106
|
||||
default:lava_source 255 100 0
|
||||
default:goldblock 126 116 35
|
||||
default:obsidian_glass 16 17 17
|
||||
default:obsidian_glass 16 17 17 64 16
|
||||
default:stone_with_copper 91 88 87
|
||||
default:grass_1 72 109 32
|
||||
default:papyrus 98 173 32
|
||||
@ -1505,7 +1505,7 @@ default:desert_stone 122 74 57
|
||||
default:tree 66 52 35
|
||||
default:jungletree 120 106 78
|
||||
default:cactus 132 143 108
|
||||
default:water_source 39 66 106
|
||||
default:water_source 39 66 106 128 224
|
||||
default:mese 200 202 0
|
||||
default:stone_with_coal 91 88 87
|
||||
default:nyancat 38 16 66
|
||||
|
@ -30,6 +30,7 @@ void usage()
|
||||
" --drawscale\n"
|
||||
" --drawplayers\n"
|
||||
" --draworigin\n"
|
||||
" --drawalpha\n"
|
||||
" --noshading\n"
|
||||
" --min-y <y>\n"
|
||||
" --max-y <y>\n"
|
||||
@ -53,6 +54,7 @@ int main(int argc, char *argv[])
|
||||
{"draworigin", no_argument, 0, 'R'},
|
||||
{"drawplayers", no_argument, 0, 'P'},
|
||||
{"drawscale", no_argument, 0, 'S'},
|
||||
{"drawalpha", no_argument, 0, 'e'},
|
||||
{"noshading", no_argument, 0, 'H'},
|
||||
{"geometry", required_argument, 0, 'g'},
|
||||
{"min-y", required_argument, 0, 'a'},
|
||||
@ -108,6 +110,9 @@ int main(int argc, char *argv[])
|
||||
case 'S':
|
||||
generator.setDrawScale(true);
|
||||
break;
|
||||
case 'e':
|
||||
generator.setDrawAlpha(true);
|
||||
break;
|
||||
case 'H':
|
||||
generator.setShading(false);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user