Skip to content

Commit

Permalink
migration from STRING to HASH to handle Blocks internally
Browse files Browse the repository at this point in the history
Accessing a QMap and searching Blocks is very very slow because of the QString handling. Compared to the old code before 1.13 it has a penalty of 2x .. 3x rendering time for a map.

Using qHash to convert all QStrings into numbers and using this hached ID (hid) brings back the speed. I measured also 2x .. 3x performance gain and old maps render as fast as before.
  • Loading branch information
EtlamGit committed Aug 11, 2018
1 parent 9e2107b commit 5f0bf4f
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 36 deletions.
1 change: 1 addition & 0 deletions blockdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class BlockData {
public:
uint hid; // we use hashed name as ID
QString name;
QMap<QString, QVariant> properties;
};
Expand Down
28 changes: 22 additions & 6 deletions blockidentifier.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** Copyright (c) 2013, Sean Kasun */

#include <QDebug>
#include <QtWidgets/QMessageBox>
#include <assert.h>
#include <cmath>

Expand Down Expand Up @@ -83,7 +84,7 @@ BlockIdentifier::BlockIdentifier() {
for (int i = 0; i < 16; i++)
unknownBlock.colors[i] = 0xff00ff;
unknownBlock.alpha = 1.0;
unknownBlock.setName("Unknown");
unknownBlock.setName("Unknown Block");
}

BlockIdentifier::~BlockIdentifier() {
Expand All @@ -93,10 +94,10 @@ BlockIdentifier::~BlockIdentifier() {
}
}

BlockInfo &BlockIdentifier::getBlock(QString name) {
BlockInfo &BlockIdentifier::getBlockInfo(uint hid) {
// first apply the mask
if (blocks.contains(name)) {
return *blocks[name];
if (blocks.contains(hid)) {
return *blocks[hid];
}
// data &= blocks[name].first()->mask;
//
Expand Down Expand Up @@ -126,8 +127,8 @@ BlockInfo &BlockIdentifier::getBlock(QString name) {
// }
// }
// }

// no blocks at all found.. dammit
unknownBlock.setName(name);
return unknownBlock;
}

Expand Down Expand Up @@ -272,6 +273,21 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent,
parseDefinition(dynamic_cast<JSONObject *>(variants->at(j)), block, pack);
}

blocks.insert(name, block);
uint hid = qHash(name);
if (blocks.contains(hid)) {
// this will only trigger during development of vanilla_blocks.json
// and prevents generating a wrong definition file
QMessageBox::warning((QWidget*)(NULL),
"Error hashing Block",
name,
QMessageBox::Cancel, QMessageBox::Cancel);
}
blocks.insert(hid, block);
packs[pack].append(block);

// we need this ugly code to allow mob spawn detection
// todo: rework mob spawn highlight
if (block->getName() == "minecraft:air") {
blocks.insert(0, block);
}
}
4 changes: 2 additions & 2 deletions blockidentifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ class BlockIdentifier {
int addDefinitions(JSONArray *, int pack = -1);
void enableDefinitions(int id);
void disableDefinitions(int id);
BlockInfo &getBlock(QString name);
BlockInfo &getBlockInfo(uint hid);
private:
void parseDefinition(JSONObject *block, BlockInfo *parent, int pack);
QMap<QString, BlockInfo*> blocks;
QMap<uint, BlockInfo*> blocks;
QList<QList<BlockInfo*> > packs;
};

Expand Down
15 changes: 8 additions & 7 deletions chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void Chunk::loadSection1519(ChunkSection *cs, const Tag *section) {
cs->palette = new BlockData[cs->paletteLength];
for (int j = 0; j < rawPalette->length(); j++) {
cs->palette[j].name = rawPalette->at(j)->at("Name")->toString();
cs->palette[j].hid = qHash(cs->palette[j].name);
if (rawPalette->at(j)->has("Properties"))
cs->palette[j].properties = rawPalette->at(j)->at("Properties")->getData().toMap();
}
Expand All @@ -173,27 +174,27 @@ Chunk::~Chunk() {
if (sections[i]) {
if (sections[i]->paletteLength > 0) {
delete[] sections[i]->palette;
sections[i]->paletteLength = 0;
} else {
sections[i]->palette = NULL;
}
sections[i]->paletteLength = 0;
sections[i]->palette = NULL;

delete sections[i];
sections[i] = NULL;
}
}
}


QString ChunkSection::getBlock(int x, int y, int z) {
uint ChunkSection::getBlock(int x, int y, int z) {
int xoffset = x;
int yoffset = (y & 0x0f) << 8;
int zoffset = z << 4;
return palette[blocks[xoffset + yoffset + zoffset]].name;
return palette[blocks[xoffset + yoffset + zoffset]].hid;
}

QString ChunkSection::getBlock(int offset, int y) {
uint ChunkSection::getBlock(int offset, int y) {
int yoffset = (y & 0x0f) << 8;
return palette[blocks[offset + yoffset]].name;
return palette[blocks[offset + yoffset]].hid;
}

quint8 ChunkSection::getSkyLight(int x, int y, int z) {
Expand Down
17 changes: 8 additions & 9 deletions chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
#include "./entity.h"
#include "./blockdata.h"

class BlockIdentifier;


class ChunkSection {
public:
QString getBlock(int x, int y, int z);
QString getBlock(int offset, int y);
quint8 getSkyLight(int x, int y, int z);
quint8 getSkyLight(int offset, int y);
quint8 getBlockLight(int x, int y, int z);
quint8 getBlockLight(int offset, int y);
uint getBlock(int x, int y, int z);
uint getBlock(int offset, int y);
quint8 getSkyLight(int x, int y, int z);
quint8 getSkyLight(int offset, int y);
quint8 getBlockLight(int x, int y, int z);
quint8 getBlockLight(int offset, int y);

BlockData *palette;
int paletteLength;
int paletteLength;

quint16 blocks[16*16*16];
quint8 skyLight[16*16*16/2];
quint8 blockLight[16*16*16/2];
Expand Down
6 changes: 5 additions & 1 deletion flatteningconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ void FlatteningConverter::parseDefinition(
flatname = b->at("flatname")->asString();

palette[bid].name = flatname;
palette[bid].hid = qHash(palette[bid].name);
if ((parentID == NULL) && (data == 0)) {
// spread main block type for data == 0
for (int d=1; d<16; d++) {
palette[bid | (d<<8)].name = flatname;
int sid = bid | (d<<8);
palette[sid].name = flatname;
palette[sid].hid = palette[bid].hid;
}
}
// packs[pack].append(block);
Expand All @@ -106,6 +109,7 @@ void FlatteningConverter::parseDefinition(
int id = bid | (j << 8);
int mid = bid | ((j & mask) << 8);
palette[id].name = palette[mid].name;
palette[id].hid = palette[mid].hid;
}
}
}
18 changes: 7 additions & 11 deletions mapview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ void MapView::renderChunk(Chunk *chunk) {
//int data = section->getData(offset, y);

// get BlockInfo from block value
BlockInfo &block = blocks->getBlock(section->getBlock(offset, y));
BlockInfo &block = blocks->getBlockInfo(section->getBlock(offset, y));
if (block.alpha == 0.0) continue;

// get light value from one block above
Expand Down Expand Up @@ -504,8 +504,7 @@ void MapView::renderChunk(Chunk *chunk) {
}
if (flags & flgMobSpawn) {
// get block info from 1 and 2 above and 1 below
QString blid1(""), blid2(""), blidB(""); // default to air
int data1(0), data2(0), dataB(0); // default variant
uint blid1(0), blid2(0), blidB(0); // default to legacy air (todo: better handling of block above)
ChunkSection *section2 = NULL;
ChunkSection *sectionB = NULL;
if (y < 254)
Expand All @@ -514,20 +513,17 @@ void MapView::renderChunk(Chunk *chunk) {
sectionB = chunk->sections[(y-1) >> 4];
if (section1) {
blid1 = section1->getBlock(offset, y+1);
// data1 = section1->getData(offset, y+1);
}
if (section2) {
blid2 = section2->getBlock(offset, y+2);
// data2 = section2->getData(offset, y+2);
}
if (sectionB) {
blidB = sectionB->getBlock(offset, y-1);
// dataB = sectionB->getData(offset, y-1);
}
BlockInfo &block2 = blocks->getBlock(blid2);
BlockInfo &block1 = blocks->getBlock(blid1);
BlockInfo &block2 = blocks->getBlockInfo(blid2);
BlockInfo &block1 = blocks->getBlockInfo(blid1);
BlockInfo &block0 = block;
BlockInfo &blockB = blocks->getBlock(blidB);
BlockInfo &blockB = blocks->getBlockInfo(blidB);
int light0 = section->getBlockLight(offset, y);

// spawn check #1: on top of solid block
Expand Down Expand Up @@ -589,7 +585,7 @@ void MapView::renderChunk(Chunk *chunk) {
// get data value
// int data = section->getData(offset, y);
// get BlockInfo from block value
BlockInfo &block = blocks->getBlock(section->getBlock(offset, y));
BlockInfo &block = blocks->getBlockInfo(section->getBlock(offset, y));
if (block.transparent) {
cave_factor -= caveshade[cave_test];
}
Expand Down Expand Up @@ -635,7 +631,7 @@ void MapView::getToolTip(int x, int z) {
int yoffset = (y & 0xf) << 8;
//int data = section->data[(offset + yoffset) / 2];
//if (x & 1) data >>= 4;
auto &block = blocks->getBlock(section->getBlock(offset, y));
auto &block = blocks->getBlockInfo(section->getBlock(offset, y));
if (block.alpha == 0.0) continue;
// found block
name = block.getName();
Expand Down

0 comments on commit 5f0bf4f

Please sign in to comment.