Add alpha transparency ability for blocks

This commit is contained in:
Sfan5 2014-04-03 20:32:48 +02:00
parent 6897ef85c7
commit 84d46ab8eb
7 changed files with 115 additions and 36 deletions

View File

@ -11,11 +11,13 @@
#define PIXELATTRIBUTES_H_ADZ35GYF #define PIXELATTRIBUTES_H_ADZ35GYF
#include <limits> #include <limits>
#include <stdint.h>
#include "config.h" #include "config.h"
struct PixelAttribute { struct PixelAttribute {
PixelAttribute(): height(std::numeric_limits<int>::min()) {}; PixelAttribute(): height(std::numeric_limits<int>::min()), thicken(0) {};
int height; int height;
uint8_t thicken;
inline bool valid_height() { inline bool valid_height() {
return height != std::numeric_limits<int>::min(); return height != std::numeric_limits<int>::min();
} }

View File

@ -53,6 +53,9 @@ drawplayers:
draworigin: draworigin:
Draw origin indicator, `--draworigin` Draw origin indicator, `--draworigin`
drawalpha:
Allow blocks to be drawn with transparency, `--drawalpha`
noshading: noshading:
Don't draw shading on nodes, `--noshading` Don't draw shading on nodes, `--noshading`

View File

@ -54,9 +54,14 @@ static inline uint16_t readU16(const unsigned char *data)
return data[0] << 8 | data[1]; 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) 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(): TileGenerator::TileGenerator():
m_bgColor(255, 255, 255), m_bgColor(255, 255, 255),
m_scaleColor(0, 0, 0), m_scaleColor(0, 0, 0),
@ -101,6 +119,7 @@ TileGenerator::TileGenerator():
m_drawOrigin(false), m_drawOrigin(false),
m_drawPlayers(false), m_drawPlayers(false),
m_drawScale(false), m_drawScale(false),
m_drawAlpha(false),
m_shading(true), m_shading(true),
m_border(0), m_border(0),
m_backend("sqlite3"), 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) void TileGenerator::setShading(bool shading)
{ {
m_shading = shading; m_shading = shading;
@ -268,7 +292,7 @@ void TileGenerator::parseColorsStream(std::istream &in)
{ {
while (in.good()) { while (in.good()) {
string name; string name;
Color color; ColorEntry color;
in >> name; in >> name;
if (name[0] == '#') { if (name[0] == '#') {
in.ignore(65536, '\n'); in.ignore(65536, '\n');
@ -277,14 +301,20 @@ void TileGenerator::parseColorsStream(std::istream &in)
while (name == "\n" && in.good()) { while (name == "\n" && in.good()) {
in >> name; in >> name;
} }
int r, g, b; int r, g, b, a, t;
in >> r; in >> r;
in >> g; in >> g;
in >> b; in >> b;
if(in.peek() != '\n') {
in >> a;
if(in.peek() != '\n')
in >> t;
else
t = 0;
} else
a = 0xFF;
if (in.good()) { if (in.good()) {
color.r = r; color = ColorEntry(r,g,b,a,t);
color.g = g;
color.b = b;
m_colors[name] = color; m_colors[name] = color;
} }
} }
@ -352,7 +382,7 @@ void TileGenerator::createImage()
m_image = gdImageCreateTrueColor(m_mapWidth + m_border, m_mapHeight + m_border); m_image = gdImageCreateTrueColor(m_mapWidth + m_border, m_mapHeight + m_border);
m_blockPixelAttributes.setWidth(m_mapWidth); m_blockPixelAttributes.setWidth(m_mapWidth);
// Background // 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) 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(); const unsigned char *mapData = mapBlock.c_str();
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16; 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; 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) { for (int z = 0; z < 16; ++z) {
int imageY = getImageY(zBegin + 15 - z); int imageY = getImageY(zBegin + 15 - z);
for (int x = 0; x < 16; ++x) { for (int x = 0; x < 16; ++x) {
@ -503,6 +535,10 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
continue; continue;
} }
int imageX = getImageX(xBegin + x); int imageX = getImageX(xBegin + x);
if(m_drawAlpha) {
col = Color(0,0,0,0);
th = 0;
}
for (int y = maxY; y >= minY; --y) { for (int y = maxY; y >= minY; --y) {
int position = x + (y << 4) + (z << 8); int position = x + (y << 4) + (z << 8);
@ -511,12 +547,26 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
continue; continue;
} }
std::map<int, std::string>::iterator blockName = m_nameMap.find(content); std::map<int, std::string>::iterator blockName = m_nameMap.find(content);
if (blockName != m_nameMap.end()) { if (blockName == m_nameMap.end())
continue;
const string &name = blockName->second; const string &name = blockName->second;
ColorMap::const_iterator color = m_colors.find(name); ColorMap::const_iterator color = m_colors.find(name);
if (color != m_colors.end()) { if (color != m_colors.end()) {
const Color &c = color->second; const Color c = color->second.to_color();
m_image->tpixels[imageY][imageX] = rgb2int(c.r, c.g, c.b); 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_readedPixels[z] |= (1 << x);
m_blockPixelAttributes.attribute(15 - z, xBegin + x).height = pos.y * 16 + y; m_blockPixelAttributes.attribute(15 - z, xBegin + x).height = pos.y * 16 + y;
} else { } else {
@ -527,7 +577,6 @@ inline void TileGenerator::renderMapBlock(const unsigned_string &mapBlock, const
} }
} }
} }
}
} }
inline void TileGenerator::renderShading(int zPos) inline void TileGenerator::renderShading(int zPos)
@ -550,13 +599,16 @@ inline void TileGenerator::renderShading(int zPos)
if (d > 36) { if (d > 36) {
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 sourceColor = m_image->tpixels[imageY][getImageX(x)] & 0xffffff;
int r = (sourceColor & 0xff0000) >> 16; uint8_t r = (sourceColor & 0xff0000) >> 16;
int g = (sourceColor & 0x00ff00) >> 8; uint8_t g = (sourceColor & 0x00ff00) >> 8;
int b = (sourceColor & 0x0000ff); uint8_t b = (sourceColor & 0x0000ff);
r = colorSafeBounds(r + d); r = colorSafeBounds(r + d);
g = colorSafeBounds(g + d); g = colorSafeBounds(g + d);
b = colorSafeBounds(b + d); b = colorSafeBounds(b + d);
m_image->tpixels[imageY][getImageX(x)] = rgb2int(r, g, b); m_image->tpixels[imageY][getImageX(x)] = rgb2int(r, g, b);
} }
} }
@ -565,7 +617,7 @@ inline void TileGenerator::renderShading(int zPos)
void TileGenerator::renderScale() 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(), 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); 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 imageX = -m_xMin * 16 + m_border;
int imageY = m_mapHeight - m_zMin * -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) 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); PlayerAttributes players(inputPath);
for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) { for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) {

View File

@ -21,13 +21,27 @@
#include "db.h" #include "db.h"
struct Color { struct Color {
Color(): r(255), g(255), b(255) {}; 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) {}; 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 r;
uint8_t g; uint8_t g;
uint8_t b; 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 { struct BlockPos {
int x; int x;
int y; int y;
@ -61,7 +75,7 @@ class TileGenerator
{ {
private: private:
typedef std::basic_string<unsigned char> unsigned_string; 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::pair<BlockPos, unsigned_string> Block;
typedef std::list<Block> BlockList; typedef std::list<Block> BlockList;
@ -75,6 +89,7 @@ public:
void setDrawOrigin(bool drawOrigin); void setDrawOrigin(bool drawOrigin);
void setDrawPlayers(bool drawPlayers); void setDrawPlayers(bool drawPlayers);
void setDrawScale(bool drawScale); void setDrawScale(bool drawScale);
void setDrawAlpha(bool drawAlpha);
void setShading(bool shading); void setShading(bool shading);
void setGeometry(int x, int y, int w, int h); void setGeometry(int x, int y, int w, int h);
void setMinY(int y); void setMinY(int y);
@ -110,6 +125,7 @@ private:
bool m_drawOrigin; bool m_drawOrigin;
bool m_drawPlayers; bool m_drawPlayers;
bool m_drawScale; bool m_drawScale;
bool m_drawAlpha;
bool m_shading; bool m_shading;
int m_border; int m_border;
std::string m_backend; std::string m_backend;

View File

@ -90,8 +90,9 @@ while read -r p; do
fi fi
done < nodes.txt > colors.txt done < nodes.txt > colors.txt
# Use nicer colors for water and lava # 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: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== ==INSTRUCTIONS==
1) Make sure avgcolors.py outputs the usage instructions 1) Make sure avgcolors.py outputs the usage instructions
2) Add the dumpnodes mod to Minetest 2) Add the dumpnodes mod to Minetest

View File

@ -1466,15 +1466,15 @@ mesecons_lightstone:lightstone_yellow_off 222 220 72
mesecons_walllever:wall_lever_on 136 136 136 mesecons_walllever:wall_lever_on 136 136 136
mesecons_walllever:wall_lever_off 136 136 136 mesecons_walllever:wall_lever_off 136 136 136
bones:bones 74 74 74 bones:bones 74 74 74
default:glass 192 192 227 default:glass 192 192 227 64 16
default:water_flowing 39 66 106 default:water_flowing 39 66 106 128 224
default:junglesapling 37 34 14 default:junglesapling 37 34 14
default:sandstonebrick 160 144 108 default:sandstonebrick 160 144 108
default:furnace_active 97 93 91 default:furnace_active 97 93 91
default:sign_wall 163 141 106 default:sign_wall 163 141 106
default:lava_source 255 100 0 default:lava_source 255 100 0
default:goldblock 126 116 35 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:stone_with_copper 91 88 87
default:grass_1 72 109 32 default:grass_1 72 109 32
default:papyrus 98 173 32 default:papyrus 98 173 32
@ -1505,7 +1505,7 @@ default:desert_stone 122 74 57
default:tree 66 52 35 default:tree 66 52 35
default:jungletree 120 106 78 default:jungletree 120 106 78
default:cactus 132 143 108 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:mese 200 202 0
default:stone_with_coal 91 88 87 default:stone_with_coal 91 88 87
default:nyancat 38 16 66 default:nyancat 38 16 66

View File

@ -30,6 +30,7 @@ void usage()
" --drawscale\n" " --drawscale\n"
" --drawplayers\n" " --drawplayers\n"
" --draworigin\n" " --draworigin\n"
" --drawalpha\n"
" --noshading\n" " --noshading\n"
" --min-y <y>\n" " --min-y <y>\n"
" --max-y <y>\n" " --max-y <y>\n"
@ -53,6 +54,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", no_argument, 0, 'S'}, {"drawscale", no_argument, 0, 'S'},
{"drawalpha", no_argument, 0, 'e'},
{"noshading", no_argument, 0, 'H'}, {"noshading", no_argument, 0, 'H'},
{"geometry", required_argument, 0, 'g'}, {"geometry", required_argument, 0, 'g'},
{"min-y", required_argument, 0, 'a'}, {"min-y", required_argument, 0, 'a'},
@ -108,6 +110,9 @@ int main(int argc, char *argv[])
case 'S': case 'S':
generator.setDrawScale(true); generator.setDrawScale(true);
break; break;
case 'e':
generator.setDrawAlpha(true);
break;
case 'H': case 'H':
generator.setShading(false); generator.setShading(false);
break; break;