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())
|
||||
do_mapper_update = false;
|
||||
|
||||
bool is_empty = true;
|
||||
for (int l = 0; l < MAX_TILE_LAYERS; l++)
|
||||
if (r.mesh->getMesh(l)->getMeshBufferCount() != 0)
|
||||
is_empty = false;
|
||||
|
||||
if (is_empty) {
|
||||
if (r.mesh->isEmpty()) {
|
||||
delete r.mesh;
|
||||
} else {
|
||||
// Replace with the new mesh
|
||||
|
|
|
@ -472,7 +472,6 @@ void MapblockMeshGenerator::drawSolidNode()
|
|||
if (!faces)
|
||||
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.
|
||||
cur_node.origin = intToFloat(cur_node.p, BS);
|
||||
auto box = aabb3f(v3f(-0.5 * BS), v3f(0.5 * BS));
|
||||
box.MinEdge += cur_node.origin;
|
||||
box.MaxEdge += cur_node.origin;
|
||||
|
@ -1773,6 +1772,7 @@ void MapblockMeshGenerator::errorUnknownDrawtype()
|
|||
|
||||
void MapblockMeshGenerator::drawNode()
|
||||
{
|
||||
cur_node.origin = intToFloat(cur_node.p, BS);
|
||||
switch (cur_node.f->drawtype) {
|
||||
case NDT_AIRLIKE: // Not drawn at all
|
||||
return;
|
||||
|
@ -1783,7 +1783,6 @@ void MapblockMeshGenerator::drawNode()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
cur_node.origin = intToFloat(cur_node.p, BS);
|
||||
if (data->m_smooth_lighting) {
|
||||
getSmoothLightFrame();
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@ struct LightInfo {
|
|||
float light_night;
|
||||
float light_boosted;
|
||||
|
||||
LightPair getPair(float sunlight_boost = 0.0) const
|
||||
LightPair getPair(float sunlight_boost = 0.0f) const
|
||||
{
|
||||
return LightPair(
|
||||
(1 - sunlight_boost) * light_day
|
||||
|
|
|
@ -212,6 +212,20 @@ public:
|
|||
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
|
||||
{
|
||||
return m_animation_force_timer == 0;
|
||||
|
@ -242,7 +256,7 @@ public:
|
|||
/// get the list of transparent buffers
|
||||
const std::vector<PartialMeshBuffer> &getTransparentBuffers() const
|
||||
{
|
||||
return this->m_transparent_buffers;
|
||||
return m_transparent_buffers;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -20,6 +20,38 @@ QueuedMeshUpdate::~QueuedMeshUpdate()
|
|||
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
|
||||
*/
|
||||
|
@ -36,26 +68,28 @@ MeshUpdateQueue::~MeshUpdateQueue()
|
|||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
for (QueuedMeshUpdate *q : m_queue) {
|
||||
for (auto block : q->map_blocks)
|
||||
if (block)
|
||||
block->refDrop();
|
||||
q->dropBlocks();
|
||||
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);
|
||||
if (!main_block)
|
||||
return false;
|
||||
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
MeshGrid mesh_grid = m_client->getMeshGrid();
|
||||
|
||||
// Mesh is placed at the corner block of a chunk
|
||||
// (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
|
||||
*/
|
||||
|
@ -68,57 +102,27 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool
|
|||
*/
|
||||
for (QueuedMeshUpdate *q : m_queue) {
|
||||
if (q->p == mesh_position) {
|
||||
// NOTE: We are not adding a new position to the queue, thus
|
||||
// refcount_from_queue stays the same.
|
||||
if(ack_block_to_server)
|
||||
if (ack_block_to_server)
|
||||
q->ack_list.push_back(p);
|
||||
q->crack_level = m_client->getCrackLevel();
|
||||
q->crack_pos = m_client->getCrackPos();
|
||||
q->urgent |= urgent;
|
||||
v3s16 pos;
|
||||
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++;
|
||||
}
|
||||
q->retrieveBlocks(map, mesh_grid.cell_size);
|
||||
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
|
||||
*/
|
||||
QueuedMeshUpdate *q = new QueuedMeshUpdate;
|
||||
q->p = mesh_position;
|
||||
if(ack_block_to_server)
|
||||
if (ack_block_to_server)
|
||||
q->ack_list.push_back(p);
|
||||
q->crack_level = m_client->getCrackLevel();
|
||||
q->crack_pos = m_client->getCrackPos();
|
||||
q->urgent = urgent;
|
||||
q->map_blocks = std::move(map_blocks);
|
||||
q->retrieveBlocks(map, mesh_grid.cell_size);
|
||||
m_queue.push_back(q);
|
||||
|
||||
return true;
|
||||
|
@ -208,6 +212,7 @@ void MeshUpdateWorkerThread::doUpdate()
|
|||
|
||||
ScopeProfiler sp(g_profiler, "Client: Mesh making (sum)");
|
||||
|
||||
// This generates the mesh:
|
||||
MapBlockMesh *mesh_new = new MapBlockMesh(m_client, q->data);
|
||||
|
||||
MeshUpdateResult r;
|
||||
|
@ -216,7 +221,7 @@ void MeshUpdateWorkerThread::doUpdate()
|
|||
r.solid_sides = get_solid_sides(q->data);
|
||||
r.ack_list = std::move(q->ack_list);
|
||||
r.urgent = q->urgent;
|
||||
r.map_blocks = q->map_blocks;
|
||||
r.map_blocks = std::move(q->map_blocks);
|
||||
|
||||
m_manager->putResult(r);
|
||||
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 =
|
||||
g_settings->getBool("smooth_lighting")
|
||||
&& !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 "
|
||||
<< p << std::endl;
|
||||
return;
|
||||
|
@ -259,10 +264,10 @@ void MeshUpdateManager::updateBlock(Map *map, v3s16 p, bool ack_block_to_server,
|
|||
if (update_neighbors) {
|
||||
if (many_neighbors) {
|
||||
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 {
|
||||
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();
|
||||
|
|
|
@ -22,11 +22,24 @@ struct QueuedMeshUpdate
|
|||
int crack_level = -1;
|
||||
v3s16 crack_pos;
|
||||
MeshMakeData *data = nullptr; // This is generated in MeshUpdateQueue::pop()
|
||||
std::vector<MapBlock *> map_blocks;
|
||||
std::vector<MapBlock*> map_blocks;
|
||||
bool urgent = false;
|
||||
|
||||
QueuedMeshUpdate() = default;
|
||||
~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();
|
||||
|
||||
// Caches the block at p and its neighbors (if needed) and queues a mesh
|
||||
// update for the block at p
|
||||
bool addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent);
|
||||
/**
|
||||
* Caches the block at p and its neighbors (if needed) and queues a mesh
|
||||
* 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
|
||||
// Returns NULL if queue is empty
|
||||
|
@ -56,7 +76,7 @@ public:
|
|||
// Marks a position as finished, unblocking the next update
|
||||
void done(v3s16 pos);
|
||||
|
||||
u32 size()
|
||||
size_t size()
|
||||
{
|
||||
MutexAutoLock lock(m_mutex);
|
||||
return m_queue.size();
|
||||
|
@ -83,7 +103,7 @@ struct MeshUpdateResult
|
|||
u8 solid_sides;
|
||||
std::vector<v3s16> ack_list;
|
||||
bool urgent = false;
|
||||
std::vector<MapBlock *> map_blocks;
|
||||
std::vector<MapBlock*> map_blocks;
|
||||
|
||||
MeshUpdateResult() = default;
|
||||
};
|
||||
|
@ -117,6 +137,7 @@ public:
|
|||
void updateBlock(Map *map, v3s16 p, bool ack_block_to_server, bool urgent,
|
||||
bool update_neighbors = false);
|
||||
void putResult(const MeshUpdateResult &r);
|
||||
/// @note caller needs to refDrop() the affected map_blocks
|
||||
bool getNextResult(MeshUpdateResult &r);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue