Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract all mesh grid maths into a dedicated class #1

Merged
merged 1 commit into from Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/client/client.cpp
Expand Up @@ -143,7 +143,7 @@ Client::Client(
}

m_cache_save_interval = g_settings->getU16("server_map_save_interval");
m_mesh_chunk = g_settings->getU16("client_mesh_chunk");
m_mesh_grid = { g_settings->getU16("client_mesh_chunk") };
}

void Client::migrateModStorage()
Expand Down Expand Up @@ -608,10 +608,10 @@ void Client::step(float dtime)
v3s16 ofs;

// See also mapblock_mesh.cpp for the code that creates the array of minimap blocks.
for (ofs.Z = 0; ofs.Z < m_mesh_chunk; ofs.Z++)
for (ofs.Y = 0; ofs.Y < m_mesh_chunk; ofs.Y++)
for (ofs.X = 0; ofs.X < m_mesh_chunk; ofs.X++) {
size_t i = ofs.Z * m_mesh_chunk * m_mesh_chunk + ofs.Y * m_mesh_chunk + ofs.X;
for (ofs.Z = 0; ofs.Z < m_mesh_grid.cell_size; ofs.Z++)
for (ofs.Y = 0; ofs.Y < m_mesh_grid.cell_size; ofs.Y++)
for (ofs.X = 0; ofs.X < m_mesh_grid.cell_size; ofs.X++) {
size_t i = m_mesh_grid.getOffsetIndex(ofs);
if (i < minimap_mapblocks.size() && minimap_mapblocks[i])
m_minimap->addBlock(r.p + ofs, minimap_mapblocks[i]);
}
Expand Down
15 changes: 6 additions & 9 deletions src/client/client.h
Expand Up @@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "network/peerhandler.h"
#include "gameparams.h"
#include <fstream>
#include "util/numeric.h"

#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f

Expand Down Expand Up @@ -437,15 +438,11 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
{
return m_env.getLocalPlayer()->formspec_prepend;
}
inline u16 getMeshChunk() {
return m_mesh_chunk;
}
inline s16 getMeshPos(s16 p) {
return ((p - (p < 0) * (m_mesh_chunk - 1)) / m_mesh_chunk * m_mesh_chunk);
}
inline bool checkMeshPos(v3s16 &p) {
return ((p.X + p.Y + p.Z) % m_mesh_chunk) == 0;
inline MeshGrid getMeshGrid()
{
return m_mesh_grid;
}

private:
void loadMods();

Expand Down Expand Up @@ -613,5 +610,5 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
std::unique_ptr<ModChannelMgr> m_modchannel_mgr;

// The number of blocks the client will combine for mesh generation.
u16 m_mesh_chunk;
MeshGrid m_mesh_grid;
};
15 changes: 7 additions & 8 deletions src/client/clientmap.cpp
Expand Up @@ -304,6 +304,7 @@ void ClientMap::updateDrawList()
blocks_seen.getChunk(camera_block).getBits(camera_block) = 0x07; // mark all sides as visible

std::set<v3s16> shortlist;
MeshGrid mesh_grid = m_client->getMeshGrid();

// Recursively walk the space and pick mapblocks for drawing
while (blocks_to_consider.size() > 0) {
Expand Down Expand Up @@ -375,11 +376,11 @@ void ClientMap::updateDrawList()
continue;
}

if (m_client->getMeshChunk() > 1) {
if (mesh_grid.cell_size > 1) {
// Block meshes are stored in the corner block of a chunk
// (where all coordinate are divisible by the chunk size)
// Add them to the de-dup set.
shortlist.emplace(m_client->getMeshPos(block_coord.X), m_client->getMeshPos(block_coord.Y), m_client->getMeshPos(block_coord.Z));
shortlist.emplace(mesh_grid.getMeshPos(block_coord.X), mesh_grid.getMeshPos(block_coord.Y), mesh_grid.getMeshPos(block_coord.Z));
// All other blocks we can grab and add to the keeplist right away.
if (block) {
m_keeplist.push_back(block);
Expand Down Expand Up @@ -619,8 +620,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)

auto is_frustum_culled = m_client->getCamera()->getFrustumCuller();

const u16 mesh_chunk = m_client->getMeshChunk();
const u16 mesh_chunk_vol = mesh_chunk * mesh_chunk * mesh_chunk;
const MeshGrid mesh_grid = m_client->getMeshGrid();
for (auto &i : m_drawlist) {
v3s16 block_pos = i.first;
MapBlock *block = i.second;
Expand Down Expand Up @@ -749,7 +749,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
material.TextureLayer[ShadowRenderer::TEXTURE_LAYER_SHADOW].Texture = nullptr;
}

v3f block_wpos = intToFloat(descriptor.m_pos / mesh_chunk_vol * mesh_chunk_vol * MAP_BLOCKSIZE, BS);
v3f block_wpos = intToFloat(mesh_grid.getMeshPos(descriptor.m_pos) * MAP_BLOCKSIZE, BS);
m.setTranslation(block_wpos - offset);

driver->setTransform(video::ETS_WORLD, m);
Expand Down Expand Up @@ -987,8 +987,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
return;
}

const u16 mesh_chunk = m_client->getMeshChunk();
const u16 mesh_chunk_vol = mesh_chunk * mesh_chunk * mesh_chunk;
const MeshGrid mesh_grid = m_client->getMeshGrid();
for (const auto &i : m_drawlist_shadow) {
// only process specific part of the list & break early
++count;
Expand Down Expand Up @@ -1077,7 +1076,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
++material_swaps;
}

v3f block_wpos = intToFloat(descriptor.m_pos / mesh_chunk_vol * mesh_chunk_vol * MAP_BLOCKSIZE, BS);
v3f block_wpos = intToFloat(mesh_grid.getMeshPos(descriptor.m_pos) * MAP_BLOCKSIZE, BS);
x2048 marked this conversation as resolved.
Show resolved Hide resolved
m.setTranslation(block_wpos - offset);

driver->setTransform(video::ETS_WORLD, m);
Expand Down
20 changes: 10 additions & 10 deletions src/client/mapblock_mesh.cpp
Expand Up @@ -38,7 +38,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,

MeshMakeData::MeshMakeData(Client *client, bool use_shaders):
m_client(client),
m_use_shaders(use_shaders)
m_use_shaders(use_shaders),
m_mesh_grid(client->getMeshGrid()),
side_length(MAP_BLOCKSIZE * m_mesh_grid.cell_size)
{}

void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
Expand Down Expand Up @@ -1176,22 +1178,20 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
m_enable_shaders = data->m_use_shaders;
m_enable_vbo = g_settings->getBool("enable_vbo");

const u16 mesh_chunk = data->side_length / MAP_BLOCKSIZE;
const u16 mesh_chunk_vol = mesh_chunk * mesh_chunk * mesh_chunk;
v3s16 bp = data->m_blockpos;
// Only generate minimap mapblocks at even coordinates.
if (data->m_client->checkMeshPos(bp) && data->m_client->getMinimap()) {
m_minimap_mapblocks.resize(mesh_chunk_vol, nullptr);
if (data->m_mesh_grid.isMeshPos(bp) && data->m_client->getMinimap()) {
m_minimap_mapblocks.resize(data->m_mesh_grid.getCellVolume(), nullptr);
v3s16 ofs;

// See also client.cpp for the code that reads the array of minimap blocks.
for (ofs.Z = 0; ofs.Z < mesh_chunk; ofs.Z++)
for (ofs.Y = 0; ofs.Y < mesh_chunk; ofs.Y++)
for (ofs.X = 0; ofs.X < mesh_chunk; ofs.X++) {
for (ofs.Z = 0; ofs.Z < data->m_mesh_grid.cell_size; ofs.Z++)
for (ofs.Y = 0; ofs.Y < data->m_mesh_grid.cell_size; ofs.Y++)
for (ofs.X = 0; ofs.X < data->m_mesh_grid.cell_size; ofs.X++) {
v3s16 p = (bp + ofs) * MAP_BLOCKSIZE;
if (data->m_vmanip.getNodeNoEx(p).getContent() != CONTENT_IGNORE) {
MinimapMapblock *block = new MinimapMapblock;
m_minimap_mapblocks[ofs.Z * mesh_chunk * mesh_chunk + ofs.Y * mesh_chunk + ofs.X] = block;
m_minimap_mapblocks[data->m_mesh_grid.getOffsetIndex(ofs)] = block;
block->getMinimapNodes(&data->m_vmanip, p);
}
}
Expand Down Expand Up @@ -1222,7 +1222,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
Convert FastFaces to MeshCollector
*/

v3f offset = intToFloat((data->m_blockpos - data->m_blockpos / mesh_chunk_vol * mesh_chunk_vol ) * MAP_BLOCKSIZE, BS);
v3f offset = intToFloat((data->m_blockpos - data->m_mesh_grid.getMeshPos(data->m_blockpos)) * MAP_BLOCKSIZE, BS);
MeshCollector collector(m_bounding_sphere_center, offset);

{
Expand Down
1 change: 1 addition & 0 deletions src/client/mapblock_mesh.h
Expand Up @@ -43,6 +43,7 @@ struct MeshMakeData
v3s16 m_blockpos = v3s16(-1337,-1337,-1337);
v3s16 m_crack_pos_relative = v3s16(-1337,-1337,-1337);
bool m_smooth_lighting = false;
MeshGrid m_mesh_grid;
u16 side_length = MAP_BLOCKSIZE;

Client *m_client;
Expand Down
27 changes: 13 additions & 14 deletions src/client/mesh_generator_thread.cpp
Expand Up @@ -77,9 +77,11 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool

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(m_client->getMeshPos(p.X), m_client->getMeshPos(p.Y), m_client->getMeshPos(p.Z));
v3s16 mesh_position(mesh_grid.getMeshPos(p));
/*
Mark the block as urgent if requested
*/
Expand All @@ -90,7 +92,6 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool
Find if block is already in queue.
If it is, update the data and quit.
*/
const u16 mesh_chunk = m_client->getMeshChunk();
for (QueuedMeshUpdate *q : m_queue) {
if (q->p == mesh_position) {
// NOTE: We are not adding a new position to the queue, thus
Expand All @@ -102,9 +103,9 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool
q->urgent |= urgent;
v3s16 pos;
int i = 0;
for (pos.X = q->p.X - 1; pos.X <= q->p.X + mesh_chunk; pos.X++)
for (pos.Z = q->p.Z - 1; pos.Z <= q->p.Z + mesh_chunk; pos.Z++)
for (pos.Y = q->p.Y - 1; pos.Y <= q->p.Y + mesh_chunk; pos.Y++) {
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) {
Expand All @@ -122,11 +123,11 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool
Make a list of blocks necessary for mesh generation and lock the blocks in memory.
*/
std::vector<MapBlock *> map_blocks;
map_blocks.reserve((mesh_chunk+2)*(mesh_chunk+2)*(mesh_chunk+2));
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_chunk; pos.X++)
for (pos.Z = mesh_position.Z - 1; pos.Z <= mesh_position.Z + mesh_chunk; pos.Z++)
for (pos.Y = mesh_position.Y - 1; pos.Y <= mesh_position.Y + mesh_chunk; pos.Y++) {
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)
Expand Down Expand Up @@ -189,18 +190,16 @@ void MeshUpdateQueue::done(v3s16 pos)

void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q)
{
const u16 mesh_chunk = m_client->getMeshChunk();
MeshMakeData *data = new MeshMakeData(m_client, m_cache_enable_shaders);
q->data = data;
data->side_length = mesh_chunk * MAP_BLOCKSIZE;

data->fillBlockDataBegin(q->p);

v3s16 pos;
int i = 0;
for (pos.X = q->p.X - 1; pos.X <= q->p.X + mesh_chunk; pos.X++)
for (pos.Z = q->p.Z - 1; pos.Z <= q->p.Z + mesh_chunk; pos.Z++)
for (pos.Y = q->p.Y - 1; pos.Y <= q->p.Y + mesh_chunk; pos.Y++) {
for (pos.X = q->p.X - 1; pos.X <= q->p.X + data->m_mesh_grid.cell_size; pos.X++)
for (pos.Z = q->p.Z - 1; pos.Z <= q->p.Z + data->m_mesh_grid.cell_size; pos.Z++)
for (pos.Y = q->p.Y - 1; pos.Y <= q->p.Y + data->m_mesh_grid.cell_size; pos.Y++) {
MapBlock *block = q->map_blocks[i++];
data->fillBlockData(pos, block ? block->getData() : block_placeholder.data);
}
Expand Down
31 changes: 31 additions & 0 deletions src/util/numeric.h
Expand Up @@ -145,6 +145,37 @@ inline v3s16 componentwise_max(const v3s16 &a, const v3s16 &b)
return v3s16(MYMAX(a.X, b.X), MYMAX(a.Y, b.Y), MYMAX(a.Z, b.Z));
}

/// @brief Describes a grid with given step, oirginating at (0,0,0)
struct MeshGrid {
u16 cell_size;

u32 getCellVolume() const { return cell_size * cell_size * cell_size; }

/// @brief returns closest step of the grid smaller than p
s16 getMeshPos(s16 p) const
{
return ((p - (p < 0) * (cell_size - 1)) / cell_size * cell_size);
}

/// @brief Returns coordinates of the origin of the grid cell containing p
v3s16 getMeshPos(v3s16 p) const
{
return v3s16(getMeshPos(p.X), getMeshPos(p.Y), getMeshPos(p.Z));
}

/// @brief Returns true if p is an origin of a cell in the grid.
bool isMeshPos(v3s16 &p) const
{
return ((p.X + p.Y + p.Z) % cell_size) == 0;
}

/// @brief Returns index of the given offset in a grid cell
/// All offset coordinates must be smaller than the size of the cell
u16 getOffsetIndex(v3s16 offset) const
{
return (offset.Z * cell_size + offset.Y) * cell_size + offset.X;
}
};

/** Returns \p f wrapped to the range [-360, 360]
*
Expand Down