Generalize processing of air and ignore nodes

This commit is contained in:
Rogier 2014-05-22 18:57:08 +02:00
parent f832530bf8
commit 60b39e7d4b
4 changed files with 54 additions and 39 deletions

View File

@ -129,12 +129,14 @@ void PixelAttributes::renderShading(bool drawAlpha)
d = 3; d = 3;
} }
d = d * 12 / 255; d = d * 12 / 255;
#define pixel (m_pixelAttributes[y][x])
//PixelAttribute &pixel = m_pixelAttributes[y][x];
if (drawAlpha) if (drawAlpha)
d = d * (1 - m_pixelAttributes[y][x].t); d = d * (1 - pixel.t);
PixelAttribute &pixel = m_pixelAttributes[y][x];
pixel.r = colorSafeBounds(pixel.r + d); pixel.r = colorSafeBounds(pixel.r + d);
pixel.g = colorSafeBounds(pixel.g + d); pixel.g = colorSafeBounds(pixel.g + d);
pixel.b = colorSafeBounds(pixel.b + d); pixel.b = colorSafeBounds(pixel.b + d);
#undef pixel
} }
} }
m_firstUnshadedY = y - yCoord2Line(0); m_firstUnshadedY = y - yCoord2Line(0);
@ -142,7 +144,6 @@ void PixelAttributes::renderShading(bool drawAlpha)
void PixelAttribute::mixUnder(const PixelAttribute &p) void PixelAttribute::mixUnder(const PixelAttribute &p)
{ {
int prev_alpha = alpha();
if (!is_valid() || a == 0) { if (!is_valid() || a == 0) {
if (!is_valid() || p.a != 0) { if (!is_valid() || p.a != 0) {
r = p.r; r = p.r;
@ -154,6 +155,7 @@ void PixelAttribute::mixUnder(const PixelAttribute &p)
h = p.h; h = p.h;
} }
else { else {
int prev_alpha = alpha();
r = (a * r + p.a * (1 - a) * p.r); r = (a * r + p.a * (1 - a) * p.r);
g = (a * g + p.a * (1 - a) * p.g); g = (a * g + p.a * (1 - a) * p.g);
b = (a * b + p.a * (1 - a) * p.b); b = (a * b + p.a * (1 - a) * p.b);
@ -161,15 +163,15 @@ void PixelAttribute::mixUnder(const PixelAttribute &p)
if (p.a != 1) if (p.a != 1)
t = (t + p.t) / 2; t = (t + p.t) / 2;
h = p.h; h = p.h;
} if (prev_alpha >= 254 && p.alpha() < 255) {
if (prev_alpha >= 254 && p.alpha() < 255) { // Darken
// Darken // Parameters make deep water look good :-)
// Parameters make deep water look good :-) r = r * 0.95;
r = r * 0.95; g = g * 0.95;
g = g * 0.95; b = b * 0.95;
b = b * 0.95; if (p.a != 1)
if (p.a != 1) t = (t + p.t) / 2;
t = (t + p.t) / 2; }
} }
} }

View File

@ -116,6 +116,9 @@ static inline int readBlockContent(const unsigned char *mapData, int version, in
} }
} }
static const ColorEntry nodeColorNotDrawnObject;
const ColorEntry *TileGenerator::NodeColorNotDrawn = &nodeColorNotDrawnObject;
TileGenerator::TileGenerator(): TileGenerator::TileGenerator():
verboseCoordinates(0), verboseCoordinates(0),
verboseReadColors(0), verboseReadColors(0),
@ -806,7 +809,8 @@ void TileGenerator::pushPixelRows(int zPosLimit) {
for (int x = m_mapXStartNodeOffset; x < worldBlockX2StoredX(m_xMax + 1) + m_mapXEndNodeOffset; x++) { for (int x = m_mapXStartNodeOffset; x < worldBlockX2StoredX(m_xMax + 1) + m_mapXEndNodeOffset; x++) {
int mapX = x - m_mapXStartNodeOffset; int mapX = x - m_mapXStartNodeOffset;
int mapY = y - m_mapYStartNodeOffset; int mapY = y - m_mapYStartNodeOffset;
PixelAttribute &pixel = m_blockPixelAttributes.attribute(y, x); #define pixel m_blockPixelAttributes.attribute(y, x)
//PixelAttribute &pixel = m_blockPixelAttributes.attribute(y, x);
if (pixel.next16Empty) { if (pixel.next16Empty) {
x += 15; x += 15;
continue; continue;
@ -817,6 +821,7 @@ void TileGenerator::pushPixelRows(int zPosLimit) {
#endif #endif
if (pixel.is_valid() || pixel.color().to_uint()) if (pixel.is_valid() || pixel.color().to_uint())
m_image->tpixels[mapY2ImageY(mapY)][mapX2ImageX(mapX)] = pixel.color().to_libgd(); m_image->tpixels[mapY2ImageY(mapY)][mapX2ImageX(mapX)] = pixel.color().to_libgd();
#undef pixel
} }
} }
int yLimit = worldBlockZ2StoredY(zPosLimit); int yLimit = worldBlockZ2StoredY(zPosLimit);
@ -1079,8 +1084,6 @@ void TileGenerator::processMapBlock(const DB::Block &block)
} }
dataOffset += 4; // Skip timestamp dataOffset += 4; // Skip timestamp
m_blockAirId = -1;
m_blockIgnoreId = -1;
// Read mapping // Read mapping
if (version >= 22) { if (version >= 22) {
dataOffset++; // mapping version dataOffset++; // mapping version
@ -1093,17 +1096,24 @@ void TileGenerator::processMapBlock(const DB::Block &block)
dataOffset += 2; dataOffset += 2;
string name; string name;
readString(name, data, dataOffset, nameLen, length); readString(name, data, dataOffset, nameLen, length);
name = name.c_str(); // Truncate any trailing NUL bytes size_t end = name.find_first_of('\0');
if (name == "air") { if (end != std::string::npos)
ColorMap::const_iterator color = m_colors.find(name); name.erase(end);
if (!m_drawAir || color == m_colors.end()) ColorMap::const_iterator color = m_colors.find(name);
m_blockAirId = nodeId; if (name == "air" && !(m_drawAir && color != m_colors.end())) {
m_nodeIDColor[nodeId] = NodeColorNotDrawn;
} }
else if (name == "ignore") { else if (name == "ignore") {
m_blockIgnoreId = nodeId; m_nodeIDColor[nodeId] = NodeColorNotDrawn;
} }
else { else {
m_nameMap[nodeId] = name; if (color != m_colors.end()) {
m_nodeIDColor[nodeId] = &color->second;
}
else {
m_nameMap[nodeId] = name;
m_nodeIDColor[nodeId] = NULL;
}
} }
dataOffset += nameLen; dataOffset += nameLen;
} }
@ -1219,34 +1229,36 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
if (m_readedPixels[z] & (1 << x)) { if (m_readedPixels[z] & (1 << x)) {
continue; continue;
} }
if (m_blockDefaultColor.to_uint() && !m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin + x).color().to_uint()) { // The #define of pixel performs *significantly* *better* than the definition of PixelAttribute &pixel ...
PixelAttribute pixel = PixelAttribute(m_blockDefaultColor, NAN); #define pixel m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin + x)
m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin + x) = pixel; //PixelAttribute &pixel = m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin + x);
if (m_blockDefaultColor.to_uint() && !pixel.color().to_uint()) {
rowIsEmpty = false; rowIsEmpty = false;
pixel = PixelAttribute(m_blockDefaultColor, NAN);
} }
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);
int content = readBlockContent(mapData, version, position); int content = readBlockContent(mapData, version, position);
if (content == m_blockIgnoreId || content == m_blockAirId) { if (m_nodeIDColor[content] == NodeColorNotDrawn) {
continue; continue;
} }
NodeID2NameMap::iterator blockName = m_nameMap.find(content); if (m_nodeIDColor[content]) {
if (blockName == m_nameMap.end())
continue;
const string &name = blockName->second;
ColorMap::const_iterator color = m_colors.find(name);
if (color != m_colors.end()) {
rowIsEmpty = false; rowIsEmpty = false;
PixelAttribute pixel = PixelAttribute(color->second, pos.y * 16 + y); #define nodeColor (*m_nodeIDColor[content])
m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin + x).mixUnder(pixel); //const ColorEntry &nodeColor = *m_nodeIDColor[content];
if ((m_drawAlpha && pixel.alpha() == 0xff) || (!m_drawAlpha && pixel.alpha() != 0)) { pixel.mixUnder(PixelAttribute(nodeColor, pos.y * 16 + y));
if ((m_drawAlpha && nodeColor.a == 0xff) || (!m_drawAlpha && nodeColor.a != 0)) {
m_readedPixels[z] |= (1 << x); m_readedPixels[z] |= (1 << x);
break; break;
} }
#undef nodeColor
} else { } else {
m_unknownNodes.insert(name); NodeID2NameMap::iterator blockName = m_nameMap.find(content);
if (blockName != m_nameMap.end())
m_unknownNodes.insert(blockName->second);
} }
} }
#undef pixel
} }
if (!rowIsEmpty) if (!rowIsEmpty)
m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin).next16Empty = false; m_blockPixelAttributes.attribute(zBegin + 15 - z,xBegin).next16Empty = false;

View File

@ -217,13 +217,12 @@ private:
int m_pictHeight; int m_pictHeight;
std::list<BlockPos> m_positions; std::list<BlockPos> m_positions;
NodeID2NameMap m_nameMap; NodeID2NameMap m_nameMap;
static const ColorEntry *NodeColorNotDrawn;
const ColorEntry *m_nodeIDColor[MAPBLOCK_MAXCOLORS];
ColorMap m_colors; ColorMap m_colors;
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;
int m_blockAirId;
int m_blockIgnoreId;
}; /* ----- end of class TileGenerator ----- */ }; /* ----- end of class TileGenerator ----- */
#endif /* end of include guard: TILEGENERATOR_H_JJNUCARH */ #endif /* end of include guard: TILEGENERATOR_H_JJNUCARH */

View File

@ -17,6 +17,8 @@
#define MAPBLOCK_MIN (-2048) #define MAPBLOCK_MIN (-2048)
#define MAPBLOCK_MAX 2047 #define MAPBLOCK_MAX 2047
// Max number of node name -> color mappings stored in a mapblock
#define MAPBLOCK_MAXCOLORS 65536
#ifdef USE_CMAKE_CONFIG_H #ifdef USE_CMAKE_CONFIG_H
#include "cmake_config.h" #include "cmake_config.h"