This commit is contained in:
sfence 2024-05-16 10:55:33 +10:00 committed by GitHub
commit 280acfc7c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 136 additions and 14 deletions

View File

@ -617,6 +617,7 @@ void Client::step(float dtime)
else {
// Replace with the new mesh
block->mesh = r.mesh;
getEnv().getClientMap().updateMesh(block->mesh);
if (r.urgent)
force_update_shadows = true;
}

View File

@ -137,7 +137,8 @@ ClientMap::~ClientMap()
void ClientMap::updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SColor light_color)
{
v3s16 previous_node = floatToInt(m_camera_position, BS) + m_camera_offset;
v3s16 prev_pos = floatToInt(m_camera_position, BS);
v3s16 previous_node = prev_pos + m_camera_offset;
v3s16 previous_block = getContainerPos(previous_node, MAP_BLOCKSIZE);
m_camera_position = pos;
@ -146,7 +147,8 @@ void ClientMap::updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SCo
m_camera_offset = offset;
m_camera_light_color = light_color;
v3s16 current_node = floatToInt(m_camera_position, BS) + m_camera_offset;
v3s16 curr_pos = floatToInt(m_camera_position, BS);
v3s16 current_node = curr_pos + m_camera_offset;
v3s16 current_block = getContainerPos(current_node, MAP_BLOCKSIZE);
// reorder the blocks when camera crosses block boundary
@ -156,6 +158,33 @@ void ClientMap::updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SCo
// reorder transparent meshes when camera crosses node boundary
if (previous_node != current_node)
m_needs_update_transparent_meshes = true;
/* update liquid hideable sides materials if neccessary
* This is used to hide specific liquid sides on a liquid-glass boundary
* if the player is in the specific liquid.
*/
if (prev_pos != curr_pos) {
MapNode prev_node = getNode(prev_pos);
MapNode curr_node = getNode(curr_pos);
const NodeDefManager *ndef = m_client->getNodeDefManager();
const ContentFeatures &prev_f = ndef->get(prev_node.getContent());
const ContentFeatures &curr_f = ndef->get(curr_node.getContent());
if ( (prev_f.liquid_alternative_source_id != curr_f.liquid_alternative_source_id) ||
(prev_f.liquid_alternative_flowing_id != curr_f.liquid_alternative_flowing_id)) {
m_camera_liquid_source_id = curr_f.liquid_alternative_source_id;
m_camera_liquid_flowing_id = curr_f.liquid_alternative_flowing_id;
for (auto &i : m_drawlist) {
i.second->mesh->updateHideable(m_camera_liquid_source_id, m_camera_liquid_flowing_id);
}
}
}
}
void ClientMap::updateMesh(MapBlockMesh *mesh)
{
mesh->updateHideable(m_camera_liquid_source_id, m_camera_liquid_flowing_id);
}
MapSector * ClientMap::emergeSector(v2s16 p2d)
@ -263,6 +292,13 @@ private:
v3s16 volume;
};
void ClientMap::addBlockToDrawList(v3s16 pos, MapBlock *block)
{
block->refGrab();
block->mesh->updateHideable(m_camera_liquid_source_id, m_camera_liquid_flowing_id);
m_drawlist.emplace(pos, block);
}
void ClientMap::updateDrawList()
{
ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG);
@ -398,8 +434,7 @@ void ClientMap::updateDrawList()
block->refGrab();
} else if (mesh) {
// without mesh chunking we can add the block to the drawlist
block->refGrab();
m_drawlist.emplace(block->getPos(), block);
addBlockToDrawList(block->getPos(), block);
}
}
}
@ -506,8 +541,7 @@ void ClientMap::updateDrawList()
}
} else if (mesh) {
// without mesh chunking we can add the block to the drawlist
block->refGrab();
m_drawlist.emplace(block_coord, block);
addBlockToDrawList(block_coord, block);
}
// Decide which sides to traverse next or to block away
@ -618,8 +652,7 @@ void ClientMap::updateDrawList()
for (auto pos : shortlist) {
MapBlock *block = getBlockNoCreateNoEx(pos);
if (block) {
block->refGrab();
m_drawlist.emplace(pos, block);
addBlockToDrawList(pos, block);
}
}

View File

@ -63,6 +63,7 @@ public:
}
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SColor light_color);
void updateMesh(MapBlockMesh *mesh);
/*
Forcefully get a sector from somewhere
@ -125,6 +126,8 @@ private:
// update the vertex order in transparent mesh buffers
void updateTransparentMeshBuffers();
// help method for updateDrawList
void addBlockToDrawList(v3s16 pos, MapBlock *block);
// Orders blocks by distance to the camera
class MapBlockComparer
@ -181,6 +184,9 @@ private:
video::SColor m_camera_light_color = video::SColor(0xFFFFFFFF);
bool m_needs_update_transparent_meshes = true;
content_t m_camera_liquid_source_id = CONTENT_IGNORE;
content_t m_camera_liquid_flowing_id = CONTENT_IGNORE;
std::map<v3s16, MapBlock*, MapBlockComparer> m_drawlist;
std::vector<MapBlock*> m_keeplist;
std::map<v3s16, MapBlock*> m_drawlist_shadow;

View File

@ -83,6 +83,7 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
enable_mesh_cache(g_settings->getBool("enable_mesh_cache") &&
!data->m_smooth_lighting) // Mesh cache is not supported with smooth lighting
{
cam_f = &nodedef->get(data->m_cameranode);
}
void MapblockMeshGenerator::useTile(int index, u8 set_flags, u8 reset_flags, bool special)
@ -425,6 +426,7 @@ void MapblockMeshGenerator::drawSolidNode()
MapNode neighbor = data->m_vmanip.getNodeNoEx(p2);
content_t n2 = neighbor.getContent();
bool backface_culling = cur_node.f->drawtype == NDT_NORMAL;
bool is_hideable = false;
if (n2 == n1)
continue;
if (n2 == CONTENT_IGNORE)
@ -436,6 +438,9 @@ void MapblockMeshGenerator::drawSolidNode()
if (cur_node.f->drawtype == NDT_LIQUID) {
if (cur_node.f->sameLiquidRender(f2))
continue;
if (f2.drawtype == NDT_GLASSLIKE) {
is_hideable = true;
}
backface_culling = f2.solidness || f2.visual_solidness;
}
}
@ -446,6 +451,11 @@ void MapblockMeshGenerator::drawSolidNode()
layer.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
layer.material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;
layer.material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
if (is_hideable) {
layer.material_flags |= MATERIAL_FLAG_HIDDABLE;
layer.liquid_source_id = cur_node.f->liquid_alternative_source_id;
layer.liquid_flowing_id = cur_node.f->liquid_alternative_flowing_id;
}
}
if (!data->m_smooth_lighting) {
lights[face] = getFaceLight(cur_node.n, neighbor, nodedef);

View File

@ -91,6 +91,9 @@ private:
f32 scale;
} cur_node;
// camera node
const ContentFeatures *cam_f;
// lighting
void getSmoothLightFrame();
LightInfo blendLight(const v3f &vertex_pos);

View File

@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock_mesh.h"
#include "client.h"
#include "camera.h"
#include "mapblock.h"
#include "map.h"
#include "noise.h"
@ -39,11 +40,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
MeshMakeData
*/
MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders):
MeshMakeData::MeshMakeData(Client *client, u16 side_length, bool use_shaders):
side_length(side_length),
nodedef(client->getNodeDefManager()),
m_use_shaders(use_shaders)
{
v3s16 pos = floatToInt(client->getCamera()->getPosition(), BS);
m_cameranode = client->getEnv().getMap().getNode(pos);
}
MeshMakeData::MeshMakeData(const NodeDefManager *ndef, MapNode &cameranode, u16 side_length, bool use_shaders):
side_length(side_length),
nodedef(ndef),
m_cameranode(cameranode),
m_use_shaders(use_shaders)
{}
{
}
void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
{
@ -617,6 +628,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
m_last_crack(-1),
m_last_daynight_ratio((u32) -1)
{
m_texture_blank = m_tsrc->getTextureForMesh("blank.png", &m_texture_blank_id);
for (auto &m : m_mesh)
m = new scene::SMesh();
m_enable_shaders = data->m_use_shaders;
@ -713,6 +725,16 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
p.layer.texture = (*p.layer.frames)[0].texture;
}
// - Texture hideable
if (p.layer.material_flags & MATERIAL_FLAG_HIDDABLE) {
// Add to MapBlockMesh to hideable
auto &info = m_hideable_info[{layer, i}];
info.hidden = false;
info.liquid_source_id = p.layer.liquid_source_id;
info.liquid_flowing_id = p.layer.liquid_flowing_id;
info.tile = p.layer;
}
if (!m_enable_shaders) {
// Extract colors for day-night animation
// Dummy sunlight to handle non-sunlit areas
@ -888,6 +910,28 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
return true;
}
void MapBlockMesh::updateHideable(content_t liquid_source_id, content_t liquid_flowing_id)
{
// Texture animation
for (auto &it : m_hideable_info) {
const TileLayer &tile = it.second.tile;
scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second);
bool hide = (it.second.liquid_source_id == liquid_source_id) &&
(it.second.liquid_flowing_id == liquid_flowing_id);
if (it.second.hidden != hide) {
buf->getMaterial().setTexture(0, hide ? m_texture_blank : tile.texture);
if (m_enable_shaders) {
if (tile.normal_texture)
buf->getMaterial().setTexture(1, hide ? m_texture_blank : tile.normal_texture);
buf->getMaterial().setTexture(2, hide ? m_texture_blank : tile.flags_texture);
}
it.second.hidden = hide;
}
}
}
void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
{
// nothing to do if the entire block is opaque

View File

@ -49,9 +49,11 @@ struct MeshMakeData
u16 side_length;
const NodeDefManager *nodedef;
MapNode m_cameranode;
bool m_use_shaders;
MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders);
MeshMakeData(Client *client, u16 side_length, bool use_shaders);
MeshMakeData(const NodeDefManager *ndef, MapNode &cameranode, u16 side_length, bool use_shaders);
/*
Copy block data manually (to allow optimizations by the caller)
@ -192,6 +194,8 @@ public:
// Returns true if anything has been changed.
bool animate(bool faraway, float time, int crack, u32 daynight_ratio);
void updateHideable(content_t liquid_source_id, content_t liquid_flowing_id);
scene::IMesh *getMesh()
{
return m_mesh[0];
@ -242,11 +246,19 @@ private:
int frame_offset;
TileLayer tile;
};
struct HideableInfo {
bool hidden;
content_t liquid_source_id;
content_t liquid_flowing_id;
TileLayer tile;
};
scene::IMesh *m_mesh[MAX_TILE_LAYERS];
std::vector<MinimapMapblock*> m_minimap_mapblocks;
ITextureSource *m_tsrc;
IShaderSource *m_shdrsrc;
video::ITexture *m_texture_blank;
u32 m_texture_blank_id;
f32 m_bounding_radius;
v3f m_bounding_sphere_center;
@ -268,6 +280,10 @@ private:
// Keys are pairs of (mesh index, buffer index in the mesh)
std::map<std::pair<u8, u32>, AnimationInfo> m_animation_info;
// Hideable info: hideable textures
// Used for better rendering under liquids
std::map<std::pair<u8, u32>, HideableInfo> m_hideable_info;
// Animation info: day/night transitions
// Last daynight_ratio value passed to animate()
u32 m_last_daynight_ratio;

View File

@ -190,7 +190,7 @@ void MeshUpdateQueue::done(v3s16 pos)
void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q)
{
auto mesh_grid = m_client->getMeshGrid();
MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders);
MeshMakeData *data = new MeshMakeData(m_client, MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders);
q->data = data;
data->fillBlockDataBegin(q->p);

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <ITexture.h>
#include <vector>
#include <SMaterial.h>
#include "mapnode.h"
enum MaterialType{
TILE_MATERIAL_BASIC,
@ -51,6 +52,7 @@ enum MaterialType{
//#define MATERIAL_FLAG_HIGHLIGHTED 0x10
#define MATERIAL_FLAG_TILEABLE_HORIZONTAL 0x20
#define MATERIAL_FLAG_TILEABLE_VERTICAL 0x40
#define MATERIAL_FLAG_HIDDABLE 0x80
/*
This fully defines the looks of a tile.
@ -121,6 +123,9 @@ struct TileLayer
u32 texture_id = 0;
content_t liquid_source_id;
content_t liquid_flowing_id;
u16 animation_frame_length_ms = 0;
u16 animation_frame_count = 1;
@ -167,4 +172,7 @@ struct TileSpec
u8 emissive_light = 0;
//! The first is base texture, the second is overlay.
TileLayer layers[MAX_TILE_LAYERS];
//Specify liquid for hide
content_t liquid_source_id = CONTENT_IGNORE;
content_t liquid_flowing_id = CONTENT_IGNORE;
};

View File

@ -315,7 +315,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
std::vector<ItemPartColor> *colors, const ContentFeatures &f)
{
MeshMakeData mesh_make_data(client->ndef(), 1, false);
MeshMakeData mesh_make_data(client, 1, false);
MeshCollector collector(v3f(0.0f * BS), v3f());
mesh_make_data.setSmoothLighting(false);
MapblockMeshGenerator gen(&mesh_make_data, &collector,

View File

@ -53,7 +53,8 @@ public:
MeshMakeData makeSingleNodeMMD(bool smooth_lighting = true, bool for_shaders = true)
{
MeshMakeData data{ndef(), 1, for_shaders};
MapNode cameranode(CONTENT_AIR);
MeshMakeData data{ndef(), cameranode, 1, for_shaders};
data.setSmoothLighting(smooth_lighting);
data.m_blockpos = {0, 0, 0};
for (s16 x = -1; x <= 1; x++)