mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Refactor meshgen-related code
This commit is contained in:
parent
0ea89d4112
commit
6545710c8e
6 changed files with 95 additions and 61 deletions
|
@ -612,12 +612,7 @@ void Client::step(float dtime)
|
||||||
if (minimap_mapblocks.empty())
|
if (minimap_mapblocks.empty())
|
||||||
do_mapper_update = false;
|
do_mapper_update = false;
|
||||||
|
|
||||||
bool is_empty = true;
|
if (r.mesh->isEmpty()) {
|
||||||
for (int l = 0; l < MAX_TILE_LAYERS; l++)
|
|
||||||
if (r.mesh->getMesh(l)->getMeshBufferCount() != 0)
|
|
||||||
is_empty = false;
|
|
||||||
|
|
||||||
if (is_empty) {
|
|
||||||
delete r.mesh;
|
delete r.mesh;
|
||||||
} else {
|
} else {
|
||||||
// Replace with the new mesh
|
// Replace with the new mesh
|
||||||
|
|
|
@ -472,7 +472,6 @@ void MapblockMeshGenerator::drawSolidNode()
|
||||||
if (!faces)
|
if (!faces)
|
||||||
return;
|
return;
|
||||||
u8 mask = faces ^ 0b0011'1111; // k-th bit is set if k-th face is to be *omitted*, as expected by cuboid drawing functions.
|
u8 mask = faces ^ 0b0011'1111; // k-th bit is set if k-th face is to be *omitted*, as expected by cuboid drawing functions.
|
||||||
cur_node.origin = intToFloat(cur_node.p, BS);
|
|
||||||
auto box = aabb3f(v3f(-0.5 * BS), v3f(0.5 * BS));
|
auto box = aabb3f(v3f(-0.5 * BS), v3f(0.5 * BS));
|
||||||
box.MinEdge += cur_node.origin;
|
box.MinEdge += cur_node.origin;
|
||||||
box.MaxEdge += cur_node.origin;
|
box.MaxEdge += cur_node.origin;
|
||||||
|
@ -1773,6 +1772,7 @@ void MapblockMeshGenerator::errorUnknownDrawtype()
|
||||||
|
|
||||||
void MapblockMeshGenerator::drawNode()
|
void MapblockMeshGenerator::drawNode()
|
||||||
{
|
{
|
||||||
|
cur_node.origin = intToFloat(cur_node.p, BS);
|
||||||
switch (cur_node.f->drawtype) {
|
switch (cur_node.f->drawtype) {
|
||||||
case NDT_AIRLIKE: // Not drawn at all
|
case NDT_AIRLIKE: // Not drawn at all
|
||||||
return;
|
return;
|
||||||
|
@ -1783,7 +1783,6 @@ void MapblockMeshGenerator::drawNode()
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cur_node.origin = intToFloat(cur_node.p, BS);
|
|
||||||
if (data->m_smooth_lighting) {
|
if (data->m_smooth_lighting) {
|
||||||
getSmoothLightFrame();
|
getSmoothLightFrame();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct LightInfo {
|
||||||
float light_night;
|
float light_night;
|
||||||
float light_boosted;
|
float light_boosted;
|
||||||
|
|
||||||
LightPair getPair(float sunlight_boost = 0.0) const
|
LightPair getPair(float sunlight_boost = 0.0f) const
|
||||||
{
|
{
|
||||||
return LightPair(
|
return LightPair(
|
||||||
(1 - sunlight_boost) * light_day
|
(1 - sunlight_boost) * light_day
|
||||||
|
|
|
@ -212,6 +212,20 @@ public:
|
||||||
return minimap_mapblocks;
|
return minimap_mapblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return true if the mesh contains nothing to draw
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
if (!m_transparent_triangles.empty())
|
||||||
|
return false;
|
||||||
|
for (auto &mesh : m_mesh) {
|
||||||
|
for (u32 i = 0; i < mesh->getMeshBufferCount(); i++) {
|
||||||
|
if (mesh->getMeshBuffer(i)->getIndexCount() != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool isAnimationForced() const
|
bool isAnimationForced() const
|
||||||
{
|
{
|
||||||
return m_animation_force_timer == 0;
|
return m_animation_force_timer == 0;
|
||||||
|
@ -242,7 +256,7 @@ public:
|
||||||
/// get the list of transparent buffers
|
/// get the list of transparent buffers
|
||||||
const std::vector<PartialMeshBuffer> &getTransparentBuffers() const
|
const std::vector<PartialMeshBuffer> &getTransparentBuffers() const
|
||||||
{
|
{
|
||||||
return this->m_transparent_buffers;
|
return m_transparent_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -20,6 +20,38 @@ QueuedMeshUpdate::~QueuedMeshUpdate()
|
||||||
delete data;
|
delete data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QueuedMeshUpdate::retrieveBlocks(Map *map, u16 cell_size)
|
||||||
|
{
|
||||||
|
const size_t total = (cell_size+2)*(cell_size+2)*(cell_size+2);
|
||||||
|
if (map_blocks.empty())
|
||||||
|
map_blocks.resize(total);
|
||||||
|
else
|
||||||
|
assert(map_blocks.size() == total); // must not change
|
||||||
|
size_t i = 0;
|
||||||
|
v3s16 pos;
|
||||||
|
for (pos.X = p.X - 1; pos.X <= p.X + cell_size; pos.X++)
|
||||||
|
for (pos.Z = p.Z - 1; pos.Z <= p.Z + cell_size; pos.Z++)
|
||||||
|
for (pos.Y = p.Y - 1; pos.Y <= p.Y + cell_size; pos.Y++) {
|
||||||
|
if (!map_blocks[i]) {
|
||||||
|
MapBlock *block = map->getBlockNoCreateNoEx(pos);
|
||||||
|
if (block) {
|
||||||
|
block->refGrab();
|
||||||
|
map_blocks[i] = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueuedMeshUpdate::dropBlocks()
|
||||||
|
{
|
||||||
|
for (auto *block : map_blocks) {
|
||||||
|
if (block)
|
||||||
|
block->refDrop();
|
||||||
|
}
|
||||||
|
map_blocks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MeshUpdateQueue
|
MeshUpdateQueue
|
||||||
*/
|
*/
|
||||||
|
@ -36,26 +68,28 @@ MeshUpdateQueue::~MeshUpdateQueue()
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
for (QueuedMeshUpdate *q : m_queue) {
|
for (QueuedMeshUpdate *q : m_queue) {
|
||||||
for (auto block : q->map_blocks)
|
q->dropBlocks();
|
||||||
if (block)
|
|
||||||
block->refDrop();
|
|
||||||
delete q;
|
delete q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent)
|
bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server,
|
||||||
|
bool urgent, bool from_neighbor)
|
||||||
{
|
{
|
||||||
|
// FIXME: with cell_size > 1 there isn't a "main block" and this check is
|
||||||
|
// probably incorrect and broken
|
||||||
MapBlock *main_block = map->getBlockNoCreateNoEx(p);
|
MapBlock *main_block = map->getBlockNoCreateNoEx(p);
|
||||||
if (!main_block)
|
if (!main_block)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
MeshGrid mesh_grid = m_client->getMeshGrid();
|
MeshGrid mesh_grid = m_client->getMeshGrid();
|
||||||
|
|
||||||
// Mesh is placed at the corner block of a chunk
|
// Mesh is placed at the corner block of a chunk
|
||||||
// (where all coordinate are divisible by the chunk size)
|
// (where all coordinate are divisible by the chunk size)
|
||||||
v3s16 mesh_position(mesh_grid.getMeshPos(p));
|
v3s16 mesh_position = mesh_grid.getMeshPos(p);
|
||||||
|
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mark the block as urgent if requested
|
Mark the block as urgent if requested
|
||||||
*/
|
*/
|
||||||
|
@ -68,57 +102,27 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool
|
||||||
*/
|
*/
|
||||||
for (QueuedMeshUpdate *q : m_queue) {
|
for (QueuedMeshUpdate *q : m_queue) {
|
||||||
if (q->p == mesh_position) {
|
if (q->p == mesh_position) {
|
||||||
// NOTE: We are not adding a new position to the queue, thus
|
if (ack_block_to_server)
|
||||||
// refcount_from_queue stays the same.
|
|
||||||
if(ack_block_to_server)
|
|
||||||
q->ack_list.push_back(p);
|
q->ack_list.push_back(p);
|
||||||
q->crack_level = m_client->getCrackLevel();
|
q->crack_level = m_client->getCrackLevel();
|
||||||
q->crack_pos = m_client->getCrackPos();
|
q->crack_pos = m_client->getCrackPos();
|
||||||
q->urgent |= urgent;
|
q->urgent |= urgent;
|
||||||
v3s16 pos;
|
q->retrieveBlocks(map, mesh_grid.cell_size);
|
||||||
int i = 0;
|
|
||||||
for (pos.X = q->p.X - 1; pos.X <= q->p.X + mesh_grid.cell_size; pos.X++)
|
|
||||||
for (pos.Z = q->p.Z - 1; pos.Z <= q->p.Z + mesh_grid.cell_size; pos.Z++)
|
|
||||||
for (pos.Y = q->p.Y - 1; pos.Y <= q->p.Y + mesh_grid.cell_size; pos.Y++) {
|
|
||||||
if (!q->map_blocks[i]) {
|
|
||||||
MapBlock *block = map->getBlockNoCreateNoEx(pos);
|
|
||||||
if (block) {
|
|
||||||
block->refGrab();
|
|
||||||
q->map_blocks[i] = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Make a list of blocks necessary for mesh generation and lock the blocks in memory.
|
|
||||||
*/
|
|
||||||
std::vector<MapBlock *> map_blocks;
|
|
||||||
map_blocks.reserve((mesh_grid.cell_size+2)*(mesh_grid.cell_size+2)*(mesh_grid.cell_size+2));
|
|
||||||
v3s16 pos;
|
|
||||||
for (pos.X = mesh_position.X - 1; pos.X <= mesh_position.X + mesh_grid.cell_size; pos.X++)
|
|
||||||
for (pos.Z = mesh_position.Z - 1; pos.Z <= mesh_position.Z + mesh_grid.cell_size; pos.Z++)
|
|
||||||
for (pos.Y = mesh_position.Y - 1; pos.Y <= mesh_position.Y + mesh_grid.cell_size; pos.Y++) {
|
|
||||||
MapBlock *block = map->getBlockNoCreateNoEx(pos);
|
|
||||||
map_blocks.push_back(block);
|
|
||||||
if (block)
|
|
||||||
block->refGrab();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add the block
|
Add the block
|
||||||
*/
|
*/
|
||||||
QueuedMeshUpdate *q = new QueuedMeshUpdate;
|
QueuedMeshUpdate *q = new QueuedMeshUpdate;
|
||||||
q->p = mesh_position;
|
q->p = mesh_position;
|
||||||
if(ack_block_to_server)
|
if (ack_block_to_server)
|
||||||
q->ack_list.push_back(p);
|
q->ack_list.push_back(p);
|
||||||
q->crack_level = m_client->getCrackLevel();
|
q->crack_level = m_client->getCrackLevel();
|
||||||
q->crack_pos = m_client->getCrackPos();
|
q->crack_pos = m_client->getCrackPos();
|
||||||
q->urgent = urgent;
|
q->urgent = urgent;
|
||||||
q->map_blocks = std::move(map_blocks);
|
q->retrieveBlocks(map, mesh_grid.cell_size);
|
||||||
m_queue.push_back(q);
|
m_queue.push_back(q);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -208,6 +212,7 @@ void MeshUpdateWorkerThread::doUpdate()
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "Client: Mesh making (sum)");
|
ScopeProfiler sp(g_profiler, "Client: Mesh making (sum)");
|
||||||
|
|
||||||
|
// This generates the mesh:
|
||||||
MapBlockMesh *mesh_new = new MapBlockMesh(m_client, q->data);
|
MapBlockMesh *mesh_new = new MapBlockMesh(m_client, q->data);
|
||||||
|
|
||||||
MeshUpdateResult r;
|
MeshUpdateResult r;
|
||||||
|
@ -216,7 +221,7 @@ void MeshUpdateWorkerThread::doUpdate()
|
||||||
r.solid_sides = get_solid_sides(q->data);
|
r.solid_sides = get_solid_sides(q->data);
|
||||||
r.ack_list = std::move(q->ack_list);
|
r.ack_list = std::move(q->ack_list);
|
||||||
r.urgent = q->urgent;
|
r.urgent = q->urgent;
|
||||||
r.map_blocks = q->map_blocks;
|
r.map_blocks = std::move(q->map_blocks);
|
||||||
|
|
||||||
m_manager->putResult(r);
|
m_manager->putResult(r);
|
||||||
m_queue_in->done(q->p);
|
m_queue_in->done(q->p);
|
||||||
|
@ -251,7 +256,7 @@ void MeshUpdateManager::updateBlock(Map *map, v3s16 p, bool ack_block_to_server,
|
||||||
static thread_local const bool many_neighbors =
|
static thread_local const bool many_neighbors =
|
||||||
g_settings->getBool("smooth_lighting")
|
g_settings->getBool("smooth_lighting")
|
||||||
&& !g_settings->getFlag("performance_tradeoffs");
|
&& !g_settings->getFlag("performance_tradeoffs");
|
||||||
if (!m_queue_in.addBlock(map, p, ack_block_to_server, urgent)) {
|
if (!m_queue_in.addBlock(map, p, ack_block_to_server, urgent, false)) {
|
||||||
warningstream << "Update requested for non-existent block at "
|
warningstream << "Update requested for non-existent block at "
|
||||||
<< p << std::endl;
|
<< p << std::endl;
|
||||||
return;
|
return;
|
||||||
|
@ -259,10 +264,10 @@ void MeshUpdateManager::updateBlock(Map *map, v3s16 p, bool ack_block_to_server,
|
||||||
if (update_neighbors) {
|
if (update_neighbors) {
|
||||||
if (many_neighbors) {
|
if (many_neighbors) {
|
||||||
for (v3s16 dp : g_26dirs)
|
for (v3s16 dp : g_26dirs)
|
||||||
m_queue_in.addBlock(map, p + dp, false, urgent);
|
m_queue_in.addBlock(map, p + dp, false, urgent, true);
|
||||||
} else {
|
} else {
|
||||||
for (v3s16 dp : g_6dirs)
|
for (v3s16 dp : g_6dirs)
|
||||||
m_queue_in.addBlock(map, p + dp, false, urgent);
|
m_queue_in.addBlock(map, p + dp, false, urgent, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deferUpdate();
|
deferUpdate();
|
||||||
|
|
|
@ -22,11 +22,24 @@ struct QueuedMeshUpdate
|
||||||
int crack_level = -1;
|
int crack_level = -1;
|
||||||
v3s16 crack_pos;
|
v3s16 crack_pos;
|
||||||
MeshMakeData *data = nullptr; // This is generated in MeshUpdateQueue::pop()
|
MeshMakeData *data = nullptr; // This is generated in MeshUpdateQueue::pop()
|
||||||
std::vector<MapBlock *> map_blocks;
|
std::vector<MapBlock*> map_blocks;
|
||||||
bool urgent = false;
|
bool urgent = false;
|
||||||
|
|
||||||
QueuedMeshUpdate() = default;
|
QueuedMeshUpdate() = default;
|
||||||
~QueuedMeshUpdate();
|
~QueuedMeshUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get blocks needed for this mesh update from the map.
|
||||||
|
* Blocks that were already loaded are skipped.
|
||||||
|
* @param map Map
|
||||||
|
* @param cell_size mesh grid cell size
|
||||||
|
*/
|
||||||
|
void retrieveBlocks(Map *map, u16 cell_size);
|
||||||
|
/**
|
||||||
|
* Drop block references.
|
||||||
|
* @note not done by destructor, since this is only safe on main thread
|
||||||
|
*/
|
||||||
|
void dropBlocks();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -45,9 +58,16 @@ public:
|
||||||
|
|
||||||
~MeshUpdateQueue();
|
~MeshUpdateQueue();
|
||||||
|
|
||||||
// Caches the block at p and its neighbors (if needed) and queues a mesh
|
/**
|
||||||
// update for the block at p
|
* Caches the block at p and its neighbors (if needed) and queues a mesh
|
||||||
bool addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent);
|
* update for the block p.
|
||||||
|
* @param map Map
|
||||||
|
* @param p block position
|
||||||
|
* @param ack_to_server Should be acked to server when done?
|
||||||
|
* @param urget High-priority?
|
||||||
|
* @param from_neighbor was this update only necessary due to a neighbor change?
|
||||||
|
*/
|
||||||
|
bool addBlock(Map *map, v3s16 p, bool ack_to_server, bool urgent, bool from_neighbor);
|
||||||
|
|
||||||
// Returned pointer must be deleted
|
// Returned pointer must be deleted
|
||||||
// Returns NULL if queue is empty
|
// Returns NULL if queue is empty
|
||||||
|
@ -56,7 +76,7 @@ public:
|
||||||
// Marks a position as finished, unblocking the next update
|
// Marks a position as finished, unblocking the next update
|
||||||
void done(v3s16 pos);
|
void done(v3s16 pos);
|
||||||
|
|
||||||
u32 size()
|
size_t size()
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
return m_queue.size();
|
return m_queue.size();
|
||||||
|
@ -83,7 +103,7 @@ struct MeshUpdateResult
|
||||||
u8 solid_sides;
|
u8 solid_sides;
|
||||||
std::vector<v3s16> ack_list;
|
std::vector<v3s16> ack_list;
|
||||||
bool urgent = false;
|
bool urgent = false;
|
||||||
std::vector<MapBlock *> map_blocks;
|
std::vector<MapBlock*> map_blocks;
|
||||||
|
|
||||||
MeshUpdateResult() = default;
|
MeshUpdateResult() = default;
|
||||||
};
|
};
|
||||||
|
@ -117,6 +137,7 @@ public:
|
||||||
void updateBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent,
|
void updateBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent,
|
||||||
bool update_neighbors = false);
|
bool update_neighbors = false);
|
||||||
void putResult(const MeshUpdateResult &r);
|
void putResult(const MeshUpdateResult &r);
|
||||||
|
/// @note caller needs to refDrop() the affected map_blocks
|
||||||
bool getNextResult(MeshUpdateResult &r);
|
bool getNextResult(MeshUpdateResult &r);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue