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
#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();
}

View File

@ -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`

View File

@ -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) {

View File

@ -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;

View File

@ -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

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_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

View File

@ -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;