forked from Mirrorlandia_minetest/minetest
Mapgen: Performance improvement and fixes for updateLiquid (#4065)
- Adds only ~100 nodes per chunk to trans_liquid with similar processing time - Adds liquid nodes themselves instead of potential solid nodes below them - CONTENT_IGNORE nodes are interpreted as if they continue their neighborhood - This allows liquid columns to span multiple chunks without being interrupted - NOTE: Expects an one-node border in generation chunk without liquid changes
This commit is contained in:
parent
109c7e3349
commit
7841f1c509
@ -213,27 +213,86 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
|
||||
//printf("updateHeightmap: %dus\n", t.stop());
|
||||
}
|
||||
|
||||
inline bool Mapgen::isLiquidHorizontallyFlowable(u32 vi, v3s16 em)
|
||||
{
|
||||
u32 vi_neg_x = vi;
|
||||
vm->m_area.add_x(em, vi_neg_x, -1);
|
||||
if (vm->m_data[vi_neg_x].getContent() != CONTENT_IGNORE) {
|
||||
const ContentFeatures &c_nx = ndef->get(vm->m_data[vi_neg_x]);
|
||||
if (c_nx.floodable && !c_nx.isLiquid())
|
||||
return true;
|
||||
}
|
||||
u32 vi_pos_x = vi;
|
||||
vm->m_area.add_x(em, vi_pos_x, +1);
|
||||
if (vm->m_data[vi_pos_x].getContent() != CONTENT_IGNORE) {
|
||||
const ContentFeatures &c_px = ndef->get(vm->m_data[vi_pos_x]);
|
||||
if (c_px.floodable && !c_px.isLiquid())
|
||||
return true;
|
||||
}
|
||||
u32 vi_neg_z = vi;
|
||||
vm->m_area.add_z(em, vi_neg_z, -1);
|
||||
if (vm->m_data[vi_neg_z].getContent() != CONTENT_IGNORE) {
|
||||
const ContentFeatures &c_nz = ndef->get(vm->m_data[vi_neg_z]);
|
||||
if (c_nz.floodable && !c_nz.isLiquid())
|
||||
return true;
|
||||
}
|
||||
u32 vi_pos_z = vi;
|
||||
vm->m_area.add_z(em, vi_pos_z, +1);
|
||||
if (vm->m_data[vi_pos_z].getContent() != CONTENT_IGNORE) {
|
||||
const ContentFeatures &c_pz = ndef->get(vm->m_data[vi_pos_z]);
|
||||
if (c_pz.floodable && !c_pz.isLiquid())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax)
|
||||
{
|
||||
bool isliquid, wasliquid;
|
||||
bool isignored, isliquid, wasignored, wasliquid, waschecked, waspushed;
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
|
||||
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
|
||||
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
||||
wasliquid = true;
|
||||
for (s16 z = nmin.Z + 1; z <= nmax.Z - 1; z++)
|
||||
for (s16 x = nmin.X + 1; x <= nmax.X - 1; x++) {
|
||||
wasignored = true;
|
||||
wasliquid = false;
|
||||
waschecked = false;
|
||||
waspushed = false;
|
||||
|
||||
u32 i = vm->m_area.index(x, nmax.Y, z);
|
||||
for (s16 y = nmax.Y; y >= nmin.Y; y--) {
|
||||
isliquid = ndef->get(vm->m_data[i]).isLiquid();
|
||||
u32 vi = vm->m_area.index(x, nmax.Y, z);
|
||||
for (s16 y = nmax.Y; y >= nmin.Y; y--) {
|
||||
isignored = vm->m_data[vi].getContent() == CONTENT_IGNORE;
|
||||
isliquid = ndef->get(vm->m_data[vi]).isLiquid();
|
||||
|
||||
// there was a change between liquid and nonliquid, add to queue.
|
||||
if (isliquid != wasliquid)
|
||||
if (isignored || wasignored || isliquid == wasliquid) {
|
||||
// Neither topmost node of liquid column nor topmost node below column
|
||||
waschecked = false;
|
||||
waspushed = false;
|
||||
} else if (isliquid) {
|
||||
// This is the topmost node in the column
|
||||
bool ispushed = false;
|
||||
if (isLiquidHorizontallyFlowable(vi, em)) {
|
||||
trans_liquid->push_back(v3s16(x, y, z));
|
||||
|
||||
wasliquid = isliquid;
|
||||
vm->m_area.add_y(em, i, -1);
|
||||
ispushed = true;
|
||||
}
|
||||
// Remember waschecked and waspushed to avoid repeated
|
||||
// checks/pushes in case the column consists of only this node
|
||||
waschecked = true;
|
||||
waspushed = ispushed;
|
||||
} else {
|
||||
// This is the topmost node below a liquid column
|
||||
u32 vi_above = vi;
|
||||
vm->m_area.add_y(em, vi_above, 1);
|
||||
if (!waspushed && (ndef->get(vm->m_data[vi]).floodable ||
|
||||
(!waschecked && isLiquidHorizontallyFlowable(vi_above, em)))) {
|
||||
// Push back the lowest node in the column which is one
|
||||
// node above this one
|
||||
trans_liquid->push_back(v3s16(x, y + 1, z));
|
||||
}
|
||||
}
|
||||
|
||||
wasliquid = isliquid;
|
||||
wasignored = isignored;
|
||||
vm->m_area.add_y(em, vi, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,6 +199,10 @@ public:
|
||||
virtual int getSpawnLevelAtPoint(v2s16 p) { return 0; }
|
||||
|
||||
private:
|
||||
// isLiquidHorizontallyFlowable() is a helper function for updateLiquid()
|
||||
// that checks whether there are floodable nodes without liquid beneath
|
||||
// the node at index vi.
|
||||
inline bool isLiquidHorizontallyFlowable(u32 vi, v3s16 em);
|
||||
DISABLE_CLASS_COPY(Mapgen);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user