Improve memory use of BlockPos

master
Rogier 2015-02-26 10:02:49 +01:00
parent fd92db0ced
commit 7c8a99599f
4 changed files with 127 additions and 126 deletions

View File

@ -23,13 +23,12 @@ struct BlockPos {
AXYZ, // Freeminer
};
int dimension[3];
// Unfortunately, static member references are not supported (even though static member pointers are...)
// I'd like to have:
// static int BlockPos::&x = dimension[0];
// (which would avoid the extra object size associated with non-static members)
int &x = dimension[0];
int &y = dimension[1];
int &z = dimension[2];
int &x(void) { return dimension[0]; }
int &y(void) { return dimension[1]; }
int &z(void) { return dimension[2]; }
const int &x(void) const { return dimension[0]; }
const int &y(void) const { return dimension[1]; }
const int &z(void) const { return dimension[2]; }
//#if SIZE_MAX > (1LL << 36)
// std::size_t hash(void) const { return databasePosI64(); }
//#else
@ -37,7 +36,7 @@ struct BlockPos {
//#endif
BlockPos() : dimension{0, 0, 0}, m_strFormat(Unknown) {}
BlockPos(int _x, int _y, int _z) : dimension{_x, _y, _z}, m_strFormat(Unknown) {}
BlockPos(const BlockPos &pos) : dimension{pos.x, pos.y, pos.z}, m_strFormat(pos.m_strFormat) {}
BlockPos(const BlockPos &pos) : dimension{pos.x(), pos.y(), pos.z()}, m_strFormat(pos.m_strFormat) {}
BlockPos(int64_t i) { operator=(i); }
BlockPos(const std::string &s) { operator=(s); }
int64_t databasePosI64(void) const { return getDBPos(); }
@ -46,7 +45,7 @@ struct BlockPos {
bool operator<(const BlockPos& p) const;
bool operator==(const BlockPos& p) const;
void operator=(const BlockPos &p) { x = p.x; y = p.y; z = p.z; m_strFormat = p.m_strFormat; }
void operator=(const BlockPos &p) { x() = p.x(); y() = p.y(); z() = p.z(); m_strFormat = p.m_strFormat; }
void operator=(int64_t i) { setFromDBPos(i); m_strFormat = I64; }
void operator=(const std::string &s);
@ -69,22 +68,24 @@ private:
struct NodeCoord : BlockPos
{
bool isBlock[3];
// Unfortunately, static member references are not supported (even though static member pointers are...)
bool &xBlock = isBlock[0];
bool &yBlock = isBlock[1];
bool &zBlock = isBlock[2];
bool &xBlock(void) { return isBlock[0]; }
bool &yBlock(void) { return isBlock[1]; }
bool &zBlock(void) { return isBlock[2]; }
const bool &xBlock(void) const { return isBlock[0]; }
const bool &yBlock(void) const { return isBlock[1]; }
const bool &zBlock(void) const { return isBlock[2]; }
NodeCoord() : BlockPos(), isBlock{false, false, false} {}
NodeCoord(int _x, int _y, int _z) : BlockPos(_x, _y, _z), isBlock{false, false, false} {}
NodeCoord(const BlockPos &pos, bool node = false) : BlockPos(pos), isBlock{pos.x == Any ? false : !node, pos.y == Any ? false : !node, pos.z == Any ? false : !node} {}
NodeCoord(const NodeCoord &coord) : BlockPos(coord), isBlock{coord.xBlock, coord.yBlock, coord.zBlock} {}
NodeCoord(const BlockPos &pos, bool node = false) : BlockPos(pos), isBlock{pos.x() == Any ? false : !node, pos.y() == Any ? false : !node, pos.z() == Any ? false : !node} {}
NodeCoord(const NodeCoord &coord) : BlockPos(coord), isBlock{coord.xBlock(), coord.yBlock(), coord.zBlock()} {}
NodeCoord(int64_t i) : isBlock{true, true, true} { setFromDBPos(i); }
size_t hash(void) const;
bool operator==(const NodeCoord &coord) const;
void operator=(const BlockPos &coord) { x = coord.x; y = coord.y; z = coord.z; xBlock = true; yBlock = true; zBlock = true; }
void operator=(const NodeCoord &coord) { x = coord.x; y = coord.y; z = coord.z; xBlock = coord.xBlock; yBlock = coord.yBlock; zBlock = coord.zBlock; }
void operator=(const BlockPos &coord) { x() = coord.x(); y() = coord.y(); z() = coord.z(); xBlock() = true; yBlock() = true; zBlock() = true; }
void operator=(const NodeCoord &coord) { x() = coord.x(); y() = coord.y(); z() = coord.z(); xBlock() = coord.xBlock(); yBlock() = coord.yBlock(); zBlock() = coord.zBlock(); }
};
// Use this for map or set storage only...
@ -130,11 +131,11 @@ inline void BlockPos::operator=(const std::string &s)
// Freeminer new format (a<x>,<y>,<z>)
char c1, c2;
is >> c1;
is >> x;
is >> x();
is >> c1;
is >> y;
is >> y();
is >> c2;
is >> z;
is >> z();
if (is.bad() || !is.eof() || c1 != ',' || c2 != ',') {
throw std::runtime_error(std::string("Failed to decode axyz (freeminer) coordinate string from database (") + s + ")" );
}
@ -165,10 +166,10 @@ inline std::string BlockPos::databasePosStrFmt(StrFormat format) const
os << databasePosI64();
break;
case XYZ:
os << x << ',' << y << ',' << z;
os << x() << ',' << y() << ',' << z();
break;
case AXYZ:
os << 'a' << x << ',' << y << ',' << z;
os << 'a' << x() << ',' << y() << ',' << z();
break;
}
return os.str();
@ -181,28 +182,28 @@ inline std::string BlockPos::databasePosStrFmt(StrFormat format) const
// Last (least significant): y coordinate, descending (i.e. reversed)
inline bool BlockPos::operator<(const BlockPos& p) const
{
if (z > p.z)
if (z() > p.z())
return true;
if (z < p.z)
if (z() < p.z())
return false;
if (x < p.x)
if (x() < p.x())
return true;
if (x > p.x)
if (x() > p.x())
return false;
if (y > p.y)
if (y() > p.y())
return true;
if (y < p.y)
if (y() < p.y())
return false;
return false;
}
inline bool BlockPos::operator==(const BlockPos &p) const
{
if (z != p.z)
if (z() != p.z())
return false;
if (y != p.y)
if (y() != p.y())
return false;
if (x != p.x)
if (x() != p.x())
return false;
return true;
}
@ -218,17 +219,17 @@ inline size_t NodeCoord::hash(void) const
inline bool NodeCoord::operator==(const NodeCoord &coord) const
{
if (z != coord.z)
if (z() != coord.z())
return false;
if (y != coord.y)
if (y() != coord.y())
return false;
if (x != coord.x)
if (x() != coord.x())
return false;
if (zBlock != coord.zBlock)
if (zBlock() != coord.zBlock())
return false;
if (yBlock != coord.yBlock)
if (yBlock() != coord.yBlock())
return false;
if (xBlock != coord.xBlock)
if (xBlock() != coord.xBlock())
return false;
return true;
}

View File

@ -357,35 +357,35 @@ void TileGenerator::enableProgressIndicator(void)
void TileGenerator::setGeometry(const NodeCoord &corner1, const NodeCoord &corner2)
{
if (corner1.x > 0) {
m_reqXMin = corner1.x / 16;
if (corner1.x() > 0) {
m_reqXMin = corner1.x() / 16;
}
else {
m_reqXMin = (corner1.x - 15) / 16;
m_reqXMin = (corner1.x() - 15) / 16;
}
if (corner1.y > 0) {
m_reqZMin = corner1.y / 16;
if (corner1.y() > 0) {
m_reqZMin = corner1.y() / 16;
}
else {
m_reqZMin = (corner1.y - 15) / 16;
m_reqZMin = (corner1.y() - 15) / 16;
}
m_mapXStartNodeOffsetOrig = m_mapXStartNodeOffset = corner1.x - m_reqXMin * 16;
m_mapYEndNodeOffsetOrig = m_mapYEndNodeOffset = m_reqZMin * 16 - corner1.y;
m_mapXStartNodeOffsetOrig = m_mapXStartNodeOffset = corner1.x() - m_reqXMin * 16;
m_mapYEndNodeOffsetOrig = m_mapYEndNodeOffset = m_reqZMin * 16 - corner1.y();
if (corner2.x > 0) {
m_reqXMax = corner2.x / 16;
if (corner2.x() > 0) {
m_reqXMax = corner2.x() / 16;
}
else {
m_reqXMax = (corner2.x - 15) / 16;
m_reqXMax = (corner2.x() - 15) / 16;
}
if (corner2.y > 0) {
m_reqZMax = corner2.y / 16;
if (corner2.y() > 0) {
m_reqZMax = corner2.y() / 16;
}
else {
m_reqZMax = (corner2.y - 15) / 16;
m_reqZMax = (corner2.y() - 15) / 16;
}
m_mapXEndNodeOffsetOrig = m_mapXEndNodeOffset = corner2.x - (m_reqXMax * 16 + 15);
m_mapYStartNodeOffsetOrig = m_mapYStartNodeOffset = (m_reqZMax * 16 + 15) - corner2.y;
m_mapXEndNodeOffsetOrig = m_mapXEndNodeOffset = corner2.x() - (m_reqXMax * 16 + 15);
m_mapYStartNodeOffsetOrig = m_mapYStartNodeOffset = (m_reqZMax * 16 + 15) - corner2.y();
}
void TileGenerator::setMinY(int y)
@ -922,54 +922,54 @@ void TileGenerator::loadBlocks()
for(DB::BlockPosList::const_iterator it = blocks.begin(); it != blocks.end(); ++it) {
world_blocks ++;
const BlockPos &pos = *it;
if (pos.x < mapXMin) {
mapXMin = pos.x;
if (pos.x() < mapXMin) {
mapXMin = pos.x();
}
if (pos.x > mapXMax) {
mapXMax = pos.x;
if (pos.x() > mapXMax) {
mapXMax = pos.x();
}
if (pos.y < mapYMin) {
mapYMin = pos.y;
if (pos.y() < mapYMin) {
mapYMin = pos.y();
}
if (pos.y > mapYMax) {
mapYMax = pos.y;
if (pos.y() > mapYMax) {
mapYMax = pos.y();
}
if (pos.z < mapZMin) {
mapZMin = pos.z;
if (pos.z() < mapZMin) {
mapZMin = pos.z();
}
if (pos.z > mapZMax) {
mapZMax = pos.z;
if (pos.z() > mapZMax) {
mapZMax = pos.z();
}
if (pos.x < m_reqXMin || pos.x > m_reqXMax || pos.z < m_reqZMin || pos.z > m_reqZMax) {
if (pos.x() < m_reqXMin || pos.x() > m_reqXMax || pos.z() < m_reqZMin || pos.z() > m_reqZMax) {
continue;
}
if (pos.y < geomYMin) {
geomYMin = pos.y;
if (pos.y() < geomYMin) {
geomYMin = pos.y();
}
if (pos.y > geomYMax) {
geomYMax = pos.y;
if (pos.y() > geomYMax) {
geomYMax = pos.y();
}
if (pos.y < m_reqYMin || pos.y > m_reqYMax) {
if (pos.y() < m_reqYMin || pos.y() > m_reqYMax) {
continue;
}
map_blocks++;
if (pos.y < m_yMin) {
m_yMin = pos.y;
if (pos.y() < m_yMin) {
m_yMin = pos.y();
}
if (pos.y > m_yMax) {
m_yMax = pos.y;
if (pos.y() > m_yMax) {
m_yMax = pos.y();
}
if (pos.x < m_xMin) {
m_xMin = pos.x;
if (pos.x() < m_xMin) {
m_xMin = pos.x();
}
if (pos.x > m_xMax) {
m_xMax = pos.x;
if (pos.x() > m_xMax) {
m_xMax = pos.x();
}
if (pos.z < m_zMin) {
m_zMin = pos.z;
if (pos.z() < m_zMin) {
m_zMin = pos.z();
}
if (pos.z > m_zMax) {
m_zMax = pos.z;
if (pos.z() > m_zMax) {
m_zMax = pos.z();
}
m_positions.push_back(pos);
}
@ -1480,27 +1480,27 @@ void TileGenerator::renderMap()
int blocks_rendered = 0;
int area_rendered = 0;
BlockPos currentPos;
currentPos.x = INT_MIN;
currentPos.y = 0;
currentPos.z = INT_MIN;
currentPos.x() = INT_MIN;
currentPos.y() = 0;
currentPos.z() = INT_MIN;
bool allReaded = false;
for (std::list<BlockPos>::const_iterator position = m_positions.begin(); position != m_positions.end(); ++position) {
const BlockPos &pos = *position;
if (currentPos.x != pos.x || currentPos.z != pos.z) {
if (currentPos.x() != pos.x() || currentPos.z() != pos.z()) {
area_rendered++;
if (currentPos.z != pos.z) {
if (currentPos.z() != pos.z()) {
if (m_scaleFactor > 1) {
scalePixelRows(m_blockPixelAttributes, m_blockPixelAttributesScaled, pos.z);
pushPixelRows(m_blockPixelAttributesScaled, pos.z);
m_blockPixelAttributesScaled.setLastY(((m_zMax - pos.z) * 16 + 15) / m_scaleFactor);
scalePixelRows(m_blockPixelAttributes, m_blockPixelAttributesScaled, pos.z());
pushPixelRows(m_blockPixelAttributesScaled, pos.z());
m_blockPixelAttributesScaled.setLastY(((m_zMax - pos.z()) * 16 + 15) / m_scaleFactor);
}
else {
pushPixelRows(m_blockPixelAttributes, pos.z);
pushPixelRows(m_blockPixelAttributes, pos.z());
}
m_blockPixelAttributes.setLastY((m_zMax - pos.z) * 16 + 15);
m_blockPixelAttributes.setLastY((m_zMax - pos.z()) * 16 + 15);
if (progressIndicator)
cout << "Processing Z-coordinate: " << std::setw(6) << pos.z*16
<< " (" << std::fixed << std::setprecision(0) << 100.0 * (m_zMax - pos.z) / (m_zMax - m_zMin)
cout << "Processing Z-coordinate: " << std::setw(6) << pos.z()*16
<< " (" << std::fixed << std::setprecision(0) << 100.0 * (m_zMax - pos.z()) / (m_zMax - m_zMin)
<< "%) \r" << std::flush;
}
for (int i = 0; i < 16; ++i) {
@ -1527,19 +1527,19 @@ void TileGenerator::renderMap()
}
}
catch (UnpackError &e) {
std::cerr << "Failed to unpack map block " << pos.x << "," << pos.y << "," << pos.z
std::cerr << "Failed to unpack map block " << pos.x() << "," << pos.y() << "," << pos.z()
<< " (id: " << pos.databasePosStr(BlockPos::I64) << "). Block corrupt ?"
<< std::endl
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
<< "\tCoordinates: " << pos.x()*16 << "," << pos.y()*16 << "," << pos.z()*16 << "+16+16+16"
<< "; Data: " << e.type << " at: " << e.offset << "(+" << e.length << ")/" << e.dataLength
<< std::endl;
unpackErrors++;
}
catch (ZlibDecompressor::DecompressError &e) {
std::cerr << "Failed to decompress data in map block " << pos.x << "," << pos.y << "," << pos.z
std::cerr << "Failed to decompress data in map block " << pos.x() << "," << pos.y() << "," << pos.z()
<< " (id: " << pos.databasePosStr(BlockPos::I64) << "). Block corrupt ?"
<< std::endl
<< "\tCoordinates: " << pos.x*16 << "," << pos.y*16 << "," << pos.z*16 << "+16+16+16"
<< "\tCoordinates: " << pos.x()*16 << "," << pos.y()*16 << "," << pos.z()*16 << "+16+16+16"
<< "; Cause: " << e.message
<< std::endl;
unpackErrors++;
@ -1549,13 +1549,13 @@ void TileGenerator::renderMap()
throw(std::runtime_error("Too many block unpacking errors - bailing out"));
}
}
if (currentPos.z != INT_MIN) {
if (currentPos.z() != INT_MIN) {
if (m_scaleFactor > 1) {
scalePixelRows(m_blockPixelAttributes, m_blockPixelAttributesScaled, currentPos.z - 1);
pushPixelRows(m_blockPixelAttributesScaled, currentPos.z - 1);
scalePixelRows(m_blockPixelAttributes, m_blockPixelAttributesScaled, currentPos.z() - 1);
pushPixelRows(m_blockPixelAttributesScaled, currentPos.z() - 1);
}
else {
pushPixelRows(m_blockPixelAttributes, currentPos.z - 1);
pushPixelRows(m_blockPixelAttributes, currentPos.z() - 1);
}
}
if (verboseStatistics) {
@ -1601,11 +1601,11 @@ Color TileGenerator::computeMapHeightColor(int height)
inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPos &pos, int version)
{
checkBlockNodeDataLimit(version, mapBlock.length());
int xBegin = worldBlockX2StoredX(pos.x);
int zBegin = worldBlockZ2StoredY(pos.z);
int xBegin = worldBlockX2StoredX(pos.x());
int zBegin = worldBlockZ2StoredY(pos.z());
const unsigned char *mapData = mapBlock.c_str();
int minY = (pos.y < m_reqYMin) ? 16 : (pos.y > m_reqYMin) ? 0 : m_reqYMinNode;
int maxY = (pos.y > m_reqYMax) ? -1 : (pos.y < m_reqYMax) ? 15 : m_reqYMaxNode;
int minY = (pos.y() < m_reqYMin) ? 16 : (pos.y() > m_reqYMin) ? 0 : m_reqYMinNode;
int maxY = (pos.y() > m_reqYMax) ? -1 : (pos.y() < m_reqYMax) ? 15 : m_reqYMaxNode;
for (int z = 0; z < 16; ++z) {
bool rowIsEmpty = true;
for (int x = 0; x < 16; ++x) {
@ -1627,7 +1627,7 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
if (m_nodeIDColor[content] == NodeColorNotDrawn) {
continue;
}
int height = pos.y * 16 + y;
int height = pos.y() * 16 + y;
if (m_heightMap) {
if (m_nodeIDColor[content] && nodeColor.a != 0) {
if (!(m_readedPixels[z] & (1 << x))) {
@ -1942,19 +1942,19 @@ void TileGenerator::renderDrawObjects(void)
}
switch(o->type) {
case DrawObject::Point:
gdImageSetPixel(m_image, o->center.x, o->center.y, o->color.to_libgd());
gdImageSetPixel(m_image, o->center.x(), o->center.y(), o->color.to_libgd());
break;
case DrawObject::Line:
gdImageLine(m_image, o->corner1.x, o->corner1.y, o->corner2.x, o->corner2.y, o->color.to_libgd());
gdImageLine(m_image, o->corner1.x(), o->corner1.y(), o->corner2.x(), o->corner2.y(), o->color.to_libgd());
break;
case DrawObject::Ellipse:
gdImageArc(m_image, o->center.x, o->center.y, o->dimensions.x, o->dimensions.y, 0, 360, o->color.to_libgd());
gdImageArc(m_image, o->center.x(), o->center.y(), o->dimensions.x(), o->dimensions.y(), 0, 360, o->color.to_libgd());
break;
case DrawObject::Rectangle:
gdImageRectangle(m_image, o->corner1.x, o->corner1.y, o->corner2.x, o->corner2.y, o->color.to_libgd());
gdImageRectangle(m_image, o->corner1.x(), o->corner1.y(), o->corner2.x(), o->corner2.y(), o->color.to_libgd());
break;
case DrawObject::Text:
gdImageString(m_image, gdFontGetMediumBold(), o->center.x, o->center.y, reinterpret_cast<unsigned char *>(const_cast<char *>(o->text.c_str())), o->color.to_libgd());
gdImageString(m_image, gdFontGetMediumBold(), o->center.x(), o->center.y(), reinterpret_cast<unsigned char *>(const_cast<char *>(o->text.c_str())), o->color.to_libgd());
break;
default:
#ifdef DEBUG
@ -1969,7 +1969,7 @@ inline std::list<int> TileGenerator::getZValueList() const
{
std::list<int> zlist;
for (std::list<BlockPos>::const_iterator position = m_positions.begin(); position != m_positions.end(); ++position) {
zlist.push_back(position->z);
zlist.push_back(position->z());
}
zlist.sort();
zlist.unique();

View File

@ -430,7 +430,7 @@ static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, Nod
is.clear();
is.seekg(pos);
if (wildcard) {
coord1.x = coord1.y = coord1.z = 0;
coord1.x() = coord1.y() = coord1.z() = 0;
}
if (parseCoordinates(is, coord1, n, wildcard, ',')) {
if (expectDimensions == FuzzyBool::No || (expectDimensions == FuzzyBool::Maybe && (is.eof() || is.peek() == ' ' || is.peek() == '\t'))) {
@ -438,7 +438,7 @@ static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, Nod
centered = false;
return (is.eof() || is.peek() == ' ' || is.peek() == '\t');
}
else if (wildcard && (coord1.x == wildcard || coord1.y == wildcard || coord1.z == wildcard)) {
else if (wildcard && (coord1.x() == wildcard || coord1.y() == wildcard || coord1.z() == wildcard)) {
// wildcards are only allowed for plain coordinates (i.e. no dimensions)
return false;
}
@ -959,11 +959,11 @@ int main(int argc, char *argv[])
if (result) {
if (origin) {
convertBlockToNodeCoordinates(coord, 0, 2);
generator.setTileOrigin(coord.x, coord.y);
generator.setTileOrigin(coord.x(), coord.y());
}
else {
convertBlockToNodeCoordinates(coord, 8, 2);
generator.setTileCenter(coord.x, coord.y);
generator.setTileCenter(coord.x(), coord.y());
}
}
else {

View File

@ -52,18 +52,18 @@ static inline int64_t pythonmodulo(int64_t i, int16_t mod)
inline int64_t getDBPos(void) const
{
return (uint64_t) z * 0x1000000 +
(uint64_t) y * 0x1000 +
(uint64_t) x;
return (uint64_t) z() * 0x1000000 +
(uint64_t) y() * 0x1000 +
(uint64_t) x();
}
inline void setFromDBPos(int64_t i)
{
x = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
i = (i - x) / 4096;
y = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
i = (i - y) / 4096;
z = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
x() = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
i = (i - x()) / 4096;
y() = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
i = (i - y()) / 4096;
z() = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
}