forked from Mirrorlandia_minetest/minetest
Client map: do frustum culling via planes (#12710)
This commit is contained in:
parent
a428a0cf37
commit
c9ed059d91
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
#include "script/scripting_client.h"
|
#include "script/scripting_client.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
#include <SViewFrustum.h>
|
||||||
|
|
||||||
#define CAMERA_OFFSET_STEP 200
|
#define CAMERA_OFFSET_STEP 200
|
||||||
#define WIELDMESH_OFFSET_X 55.0f
|
#define WIELDMESH_OFFSET_X 55.0f
|
||||||
@ -318,6 +319,9 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||||||
v3f old_player_position = m_playernode->getPosition();
|
v3f old_player_position = m_playernode->getPosition();
|
||||||
v3f player_position = player->getPosition();
|
v3f player_position = player->getPosition();
|
||||||
|
|
||||||
|
f32 yaw = player->getYaw();
|
||||||
|
f32 pitch = player->getPitch();
|
||||||
|
|
||||||
// This is worse than `LocalPlayer::getPosition()` but
|
// This is worse than `LocalPlayer::getPosition()` but
|
||||||
// mods expect the player head to be at the parent's position
|
// mods expect the player head to be at the parent's position
|
||||||
// plus eye height.
|
// plus eye height.
|
||||||
@ -342,7 +346,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||||||
|
|
||||||
// Set player node transformation
|
// Set player node transformation
|
||||||
m_playernode->setPosition(player_position);
|
m_playernode->setPosition(player_position);
|
||||||
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
|
m_playernode->setRotation(v3f(0, -1 * yaw, 0));
|
||||||
m_playernode->updateAbsolutePosition();
|
m_playernode->updateAbsolutePosition();
|
||||||
|
|
||||||
// Get camera tilt timer (hurt animation)
|
// Get camera tilt timer (hurt animation)
|
||||||
@ -379,7 +383,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||||||
// Set head node transformation
|
// Set head node transformation
|
||||||
eye_offset.Y += cameratilt * -player->hurt_tilt_strength + fall_bobbing;
|
eye_offset.Y += cameratilt * -player->hurt_tilt_strength + fall_bobbing;
|
||||||
m_headnode->setPosition(eye_offset);
|
m_headnode->setPosition(eye_offset);
|
||||||
m_headnode->setRotation(v3f(player->getPitch(), 0,
|
m_headnode->setRotation(v3f(pitch, 0,
|
||||||
cameratilt * player->hurt_tilt_strength));
|
cameratilt * player->hurt_tilt_strength));
|
||||||
m_headnode->updateAbsolutePosition();
|
m_headnode->updateAbsolutePosition();
|
||||||
}
|
}
|
||||||
@ -463,6 +467,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||||||
|
|
||||||
// Set camera node transformation
|
// Set camera node transformation
|
||||||
m_cameranode->setPosition(my_cp-intToFloat(m_camera_offset, BS));
|
m_cameranode->setPosition(my_cp-intToFloat(m_camera_offset, BS));
|
||||||
|
m_cameranode->updateAbsolutePosition();
|
||||||
m_cameranode->setUpVector(abs_cam_up);
|
m_cameranode->setUpVector(abs_cam_up);
|
||||||
// *100.0 helps in large map coordinates
|
// *100.0 helps in large map coordinates
|
||||||
m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
||||||
@ -511,8 +516,11 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
|
|||||||
m_cameranode->setAspectRatio(m_aspect);
|
m_cameranode->setAspectRatio(m_aspect);
|
||||||
m_cameranode->setFOV(m_fov_y);
|
m_cameranode->setFOV(m_fov_y);
|
||||||
|
|
||||||
|
// Make new matrices and frustum
|
||||||
|
m_cameranode->updateMatrices();
|
||||||
|
|
||||||
if (m_arm_inertia)
|
if (m_arm_inertia)
|
||||||
addArmInertia(player->getYaw());
|
addArmInertia(yaw);
|
||||||
|
|
||||||
// Position the wielded item
|
// Position the wielded item
|
||||||
//v3f wield_position = v3f(45, -35, 65);
|
//v3f wield_position = v3f(45, -35, 65);
|
||||||
@ -643,6 +651,7 @@ void Camera::drawWieldedTool(irr::core::matrix4* translation)
|
|||||||
irr::core::vector3df camera_pos =
|
irr::core::vector3df camera_pos =
|
||||||
(startMatrix * *translation).getTranslation();
|
(startMatrix * *translation).getTranslation();
|
||||||
cam->setPosition(camera_pos);
|
cam->setPosition(camera_pos);
|
||||||
|
cam->updateAbsolutePosition();
|
||||||
cam->setTarget(focusPoint);
|
cam->setTarget(focusPoint);
|
||||||
}
|
}
|
||||||
m_wieldmgr->drawAll();
|
m_wieldmgr->drawAll();
|
||||||
@ -704,3 +713,15 @@ void Camera::removeNametag(Nametag *nametag)
|
|||||||
m_nametags.remove(nametag);
|
m_nametags.remove(nametag);
|
||||||
delete nametag;
|
delete nametag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<core::plane3d<f32>, 4> Camera::getFrustumCullPlanes() const
|
||||||
|
{
|
||||||
|
using irr::scene::SViewFrustum;
|
||||||
|
const auto &frustum_planes = m_cameranode->getViewFrustum()->planes;
|
||||||
|
return {
|
||||||
|
frustum_planes[SViewFrustum::VF_LEFT_PLANE],
|
||||||
|
frustum_planes[SViewFrustum::VF_RIGHT_PLANE],
|
||||||
|
frustum_planes[SViewFrustum::VF_BOTTOM_PLANE],
|
||||||
|
frustum_planes[SViewFrustum::VF_TOP_PLANE],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "client/tile.h"
|
#include "client/tile.h"
|
||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
#include <ISceneNode.h>
|
#include <ISceneNode.h>
|
||||||
|
#include <plane3d.h>
|
||||||
|
#include <array>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "util/Optional.h"
|
#include "util/Optional.h"
|
||||||
|
|
||||||
@ -133,6 +135,23 @@ public:
|
|||||||
return MYMAX(m_fov_x, m_fov_y);
|
return MYMAX(m_fov_x, m_fov_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a lambda that when called with an object's position and bounding-sphere
|
||||||
|
// radius (both in BS space) returns true if, and only if the object should be
|
||||||
|
// frustum-culled.
|
||||||
|
auto getFrustumCuller() const
|
||||||
|
{
|
||||||
|
return [planes = getFrustumCullPlanes(),
|
||||||
|
camera_offset = intToFloat(m_camera_offset, BS)
|
||||||
|
](v3f position, f32 radius) {
|
||||||
|
v3f pos_camspace = position - camera_offset;
|
||||||
|
for (auto &plane : planes) {
|
||||||
|
if (plane.getDistanceTo(pos_camspace) > radius)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Notify about new server-sent FOV and initialize smooth FOV transition
|
// Notify about new server-sent FOV and initialize smooth FOV transition
|
||||||
void notifyFovChange();
|
void notifyFovChange();
|
||||||
|
|
||||||
@ -190,6 +209,10 @@ public:
|
|||||||
inline void addArmInertia(f32 player_yaw);
|
inline void addArmInertia(f32 player_yaw);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Use getFrustumCuller().
|
||||||
|
// This helper just exists to decrease the header's number of includes.
|
||||||
|
std::array<core::plane3d<f32>, 4> getFrustumCullPlanes() const;
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
scene::ISceneNode *m_playernode = nullptr;
|
scene::ISceneNode *m_playernode = nullptr;
|
||||||
scene::ISceneNode *m_headnode = nullptr;
|
scene::ISceneNode *m_headnode = nullptr;
|
||||||
|
@ -196,22 +196,12 @@ void ClientMap::updateDrawList()
|
|||||||
}
|
}
|
||||||
m_drawlist.clear();
|
m_drawlist.clear();
|
||||||
|
|
||||||
const v3f camera_position = m_camera_position;
|
v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS);
|
||||||
const v3f camera_direction = m_camera_direction;
|
|
||||||
|
|
||||||
// Use a higher fov to accomodate faster camera movements.
|
|
||||||
// Blocks are cropped better when they are drawn.
|
|
||||||
const f32 camera_fov = m_camera_fov * 1.1f;
|
|
||||||
|
|
||||||
v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
|
|
||||||
|
|
||||||
v3s16 p_blocks_min;
|
v3s16 p_blocks_min;
|
||||||
v3s16 p_blocks_max;
|
v3s16 p_blocks_max;
|
||||||
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
|
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
|
||||||
|
|
||||||
// Read the vision range, unless unlimited range is enabled.
|
|
||||||
float range = m_control.range_all ? 1e7 : m_control.wanted_range;
|
|
||||||
|
|
||||||
// Number of blocks currently loaded by the client
|
// Number of blocks currently loaded by the client
|
||||||
u32 blocks_loaded = 0;
|
u32 blocks_loaded = 0;
|
||||||
// Number of blocks with mesh in rendering range
|
// Number of blocks with mesh in rendering range
|
||||||
@ -230,6 +220,8 @@ void ClientMap::updateDrawList()
|
|||||||
v3s16 camera_block = getContainerPos(cam_pos_nodes, MAP_BLOCKSIZE);
|
v3s16 camera_block = getContainerPos(cam_pos_nodes, MAP_BLOCKSIZE);
|
||||||
m_drawlist = std::map<v3s16, MapBlock*, MapBlockComparer>(MapBlockComparer(camera_block));
|
m_drawlist = std::map<v3s16, MapBlock*, MapBlockComparer>(MapBlockComparer(camera_block));
|
||||||
|
|
||||||
|
auto is_frustum_culled = m_client->getCamera()->getFrustumCuller();
|
||||||
|
|
||||||
// Uncomment to debug occluded blocks in the wireframe mode
|
// Uncomment to debug occluded blocks in the wireframe mode
|
||||||
// TODO: Include this as a flag for an extended debugging setting
|
// TODO: Include this as a flag for an extended debugging setting
|
||||||
//if (occlusion_culling_enabled && m_control.show_wireframe)
|
//if (occlusion_culling_enabled && m_control.show_wireframe)
|
||||||
@ -271,7 +263,7 @@ void ClientMap::updateDrawList()
|
|||||||
|
|
||||||
// First, perform a simple distance check, with a padding of one extra block.
|
// First, perform a simple distance check, with a padding of one extra block.
|
||||||
if (!m_control.range_all &&
|
if (!m_control.range_all &&
|
||||||
block_position.getDistanceFrom(cam_pos_nodes) > range + MAP_BLOCKSIZE)
|
block_position.getDistanceFrom(cam_pos_nodes) > m_control.wanted_range)
|
||||||
continue; // Out of range, skip.
|
continue; // Out of range, skip.
|
||||||
|
|
||||||
// Keep the block alive as long as it is in range.
|
// Keep the block alive as long as it is in range.
|
||||||
@ -279,14 +271,18 @@ void ClientMap::updateDrawList()
|
|||||||
blocks_in_range_with_mesh++;
|
blocks_in_range_with_mesh++;
|
||||||
|
|
||||||
// Frustum culling
|
// Frustum culling
|
||||||
float d = 0.0;
|
// Only do coarse culling here, to account for fast camera movement.
|
||||||
if (!isBlockInSight(block_coord, camera_position,
|
// This is needed because this function is not called every frame.
|
||||||
camera_direction, camera_fov, range * BS, &d))
|
constexpr float frustum_cull_extra_radius = 300.0f;
|
||||||
|
v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
|
||||||
|
+ block->mesh->getBoundingSphereCenter();
|
||||||
|
f32 mesh_sphere_radius = block->mesh->getBoundingRadius();
|
||||||
|
if (is_frustum_culled(mesh_sphere_center,
|
||||||
|
mesh_sphere_radius + frustum_cull_extra_radius))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Occlusion culling
|
// Occlusion culling
|
||||||
if ((!m_control.range_all && d > m_control.wanted_range * BS) ||
|
if (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes)) {
|
||||||
(occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes))) {
|
|
||||||
blocks_occlusion_culled++;
|
blocks_occlusion_culled++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -358,33 +354,43 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
std::vector<DrawDescriptor> draw_order;
|
std::vector<DrawDescriptor> draw_order;
|
||||||
video::SMaterial previous_material;
|
video::SMaterial previous_material;
|
||||||
|
|
||||||
|
auto is_frustum_culled = m_client->getCamera()->getFrustumCuller();
|
||||||
|
|
||||||
for (auto &i : m_drawlist) {
|
for (auto &i : m_drawlist) {
|
||||||
v3s16 block_pos = i.first;
|
v3s16 block_pos = i.first;
|
||||||
MapBlock *block = i.second;
|
MapBlock *block = i.second;
|
||||||
|
MapBlockMesh *block_mesh = block->mesh;
|
||||||
|
|
||||||
// If the mesh of the block happened to get deleted, ignore it
|
// If the mesh of the block happened to get deleted, ignore it
|
||||||
if (!block->mesh)
|
if (!block_mesh)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Do exact frustum culling
|
||||||
|
// (The one in updateDrawList is only coarse.)
|
||||||
|
v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
|
||||||
|
+ block_mesh->getBoundingSphereCenter();
|
||||||
|
f32 mesh_sphere_radius = block_mesh->getBoundingRadius();
|
||||||
|
if (is_frustum_culled(mesh_sphere_center, mesh_sphere_radius))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS);
|
v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS);
|
||||||
|
|
||||||
float d = camera_position.getDistanceFrom(block_pos_r);
|
float d = camera_position.getDistanceFrom(block_pos_r);
|
||||||
d = MYMAX(0,d - BLOCK_MAX_RADIUS);
|
d = MYMAX(0,d - BLOCK_MAX_RADIUS);
|
||||||
|
|
||||||
// Mesh animation
|
// Mesh animation
|
||||||
if (pass == scene::ESNRP_SOLID) {
|
if (pass == scene::ESNRP_SOLID) {
|
||||||
MapBlockMesh *mapBlockMesh = block->mesh;
|
|
||||||
assert(mapBlockMesh);
|
|
||||||
// Pretty random but this should work somewhat nicely
|
// Pretty random but this should work somewhat nicely
|
||||||
bool faraway = d >= BS * 50;
|
bool faraway = d >= BS * 50;
|
||||||
if (mapBlockMesh->isAnimationForced() || !faraway ||
|
if (block_mesh->isAnimationForced() || !faraway ||
|
||||||
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
|
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
|
||||||
|
|
||||||
bool animated = mapBlockMesh->animate(faraway, animation_time,
|
bool animated = block_mesh->animate(faraway, animation_time,
|
||||||
crack, daynight_ratio);
|
crack, daynight_ratio);
|
||||||
if (animated)
|
if (animated)
|
||||||
mesh_animate_count++;
|
mesh_animate_count++;
|
||||||
} else {
|
} else {
|
||||||
mapBlockMesh->decreaseAnimationForceTimer();
|
block_mesh->decreaseAnimationForceTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,17 +400,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
if (is_transparent_pass) {
|
if (is_transparent_pass) {
|
||||||
// In transparent pass, the mesh will give us
|
// In transparent pass, the mesh will give us
|
||||||
// the partial buffers in the correct order
|
// the partial buffers in the correct order
|
||||||
for (auto &buffer : block->mesh->getTransparentBuffers())
|
for (auto &buffer : block_mesh->getTransparentBuffers())
|
||||||
draw_order.emplace_back(block_pos, &buffer);
|
draw_order.emplace_back(block_pos, &buffer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// otherwise, group buffers across meshes
|
// otherwise, group buffers across meshes
|
||||||
// using MeshBufListList
|
// using MeshBufListList
|
||||||
MapBlockMesh *mapBlockMesh = block->mesh;
|
|
||||||
assert(mapBlockMesh);
|
|
||||||
|
|
||||||
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
||||||
scene::IMesh *mesh = mapBlockMesh->getMesh(layer);
|
scene::IMesh *mesh = block_mesh->getMesh(layer);
|
||||||
assert(mesh);
|
assert(mesh);
|
||||||
|
|
||||||
u32 c = mesh->getMeshBufferCount();
|
u32 c = mesh->getMeshBufferCount();
|
||||||
@ -772,9 +775,9 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
|
|||||||
for (auto &lists : grouped_buffers.lists)
|
for (auto &lists : grouped_buffers.lists)
|
||||||
for (MeshBufList &list : lists)
|
for (MeshBufList &list : lists)
|
||||||
buffer_count += list.bufs.size();
|
buffer_count += list.bufs.size();
|
||||||
|
|
||||||
draw_order.reserve(draw_order.size() + buffer_count);
|
draw_order.reserve(draw_order.size() + buffer_count);
|
||||||
|
|
||||||
// Capture draw order for all solid meshes
|
// Capture draw order for all solid meshes
|
||||||
for (auto &lists : grouped_buffers.lists) {
|
for (auto &lists : grouped_buffers.lists) {
|
||||||
for (MeshBufList &list : lists) {
|
for (MeshBufList &list : lists) {
|
||||||
@ -908,8 +911,8 @@ void ClientMap::updateTransparentMeshBuffers()
|
|||||||
MapBlock* block = it->second;
|
MapBlock* block = it->second;
|
||||||
if (!block->mesh)
|
if (!block->mesh)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m_needs_update_transparent_meshes ||
|
if (m_needs_update_transparent_meshes ||
|
||||||
block->mesh->getTransparentBuffers().size() == 0) {
|
block->mesh->getTransparentBuffers().size() == 0) {
|
||||||
|
|
||||||
v3s16 block_pos = block->getPos();
|
v3s16 block_pos = block->getPos();
|
||||||
|
@ -1031,9 +1031,9 @@ void MapBlockBspTree::buildTree(const std::vector<MeshTriangle> *triangles)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Find a candidate plane to split a set of triangles in two
|
* @brief Find a candidate plane to split a set of triangles in two
|
||||||
*
|
*
|
||||||
* The candidate plane is represented by one of the triangles from the set.
|
* The candidate plane is represented by one of the triangles from the set.
|
||||||
*
|
*
|
||||||
* @param list Vector of indexes of the triangles in the set
|
* @param list Vector of indexes of the triangles in the set
|
||||||
* @param triangles Vector of all triangles in the BSP tree
|
* @param triangles Vector of all triangles in the BSP tree
|
||||||
* @return Address of the triangle that represents the proposed split plane
|
* @return Address of the triangle that represents the proposed split plane
|
||||||
@ -1225,7 +1225,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
|||||||
Convert FastFaces to MeshCollector
|
Convert FastFaces to MeshCollector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MeshCollector collector;
|
MeshCollector collector(m_bounding_sphere_center);
|
||||||
|
|
||||||
{
|
{
|
||||||
// avg 0ms (100ms spikes when loading textures the first time)
|
// avg 0ms (100ms spikes when loading textures the first time)
|
||||||
@ -1261,6 +1261,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
|||||||
const bool desync_animations = g_settings->getBool(
|
const bool desync_animations = g_settings->getBool(
|
||||||
"desynchronize_mapblock_texture_animation");
|
"desynchronize_mapblock_texture_animation");
|
||||||
|
|
||||||
|
m_bounding_radius = std::sqrt(collector.m_bounding_radius_sq);
|
||||||
|
|
||||||
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
||||||
for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
|
for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements a binary space partitioning tree
|
* Implements a binary space partitioning tree
|
||||||
* See also: https://en.wikipedia.org/wiki/Binary_space_partitioning
|
* See also: https://en.wikipedia.org/wiki/Binary_space_partitioning
|
||||||
*/
|
*/
|
||||||
class MapBlockBspTree
|
class MapBlockBspTree
|
||||||
@ -221,6 +221,12 @@ public:
|
|||||||
m_animation_force_timer--;
|
m_animation_force_timer--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Radius of the bounding-sphere, in BS-space.
|
||||||
|
f32 getBoundingRadius() const { return m_bounding_radius; }
|
||||||
|
|
||||||
|
/// Center of the bounding-sphere, in BS-space, relative to block pos.
|
||||||
|
v3f getBoundingSphereCenter() const { return m_bounding_sphere_center; }
|
||||||
|
|
||||||
/// update transparent buffers to render towards the camera
|
/// update transparent buffers to render towards the camera
|
||||||
void updateTransparentBuffers(v3f camera_pos, v3s16 block_pos);
|
void updateTransparentBuffers(v3f camera_pos, v3s16 block_pos);
|
||||||
void consolidateTransparentBuffers();
|
void consolidateTransparentBuffers();
|
||||||
@ -243,6 +249,10 @@ private:
|
|||||||
ITextureSource *m_tsrc;
|
ITextureSource *m_tsrc;
|
||||||
IShaderSource *m_shdrsrc;
|
IShaderSource *m_shdrsrc;
|
||||||
|
|
||||||
|
f32 m_bounding_radius;
|
||||||
|
// MapblockMeshGenerator uses the same as mapblock center
|
||||||
|
v3f m_bounding_sphere_center = v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
|
||||||
|
|
||||||
bool m_enable_shaders;
|
bool m_enable_shaders;
|
||||||
bool m_enable_vbo;
|
bool m_enable_vbo;
|
||||||
|
|
||||||
|
@ -45,9 +45,12 @@ void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *verti
|
|||||||
scale = 1.0f / layer.scale;
|
scale = 1.0f / layer.scale;
|
||||||
|
|
||||||
u32 vertex_count = p.vertices.size();
|
u32 vertex_count = p.vertices.size();
|
||||||
for (u32 i = 0; i < numVertices; i++)
|
for (u32 i = 0; i < numVertices; i++) {
|
||||||
p.vertices.emplace_back(vertices[i].Pos, vertices[i].Normal,
|
p.vertices.emplace_back(vertices[i].Pos, vertices[i].Normal,
|
||||||
vertices[i].Color, scale * vertices[i].TCoords);
|
vertices[i].Color, scale * vertices[i].TCoords);
|
||||||
|
m_bounding_radius_sq = std::max(m_bounding_radius_sq,
|
||||||
|
(vertices[i].Pos - m_center_pos).getLengthSQ());
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < numIndices; i++)
|
for (u32 i = 0; i < numIndices; i++)
|
||||||
p.indices.push_back(indices[i] + vertex_count);
|
p.indices.push_back(indices[i] + vertex_count);
|
||||||
@ -81,8 +84,11 @@ void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *verti
|
|||||||
video::SColor color = c;
|
video::SColor color = c;
|
||||||
if (!light_source)
|
if (!light_source)
|
||||||
applyFacesShading(color, vertices[i].Normal);
|
applyFacesShading(color, vertices[i].Normal);
|
||||||
p.vertices.emplace_back(vertices[i].Pos + pos, vertices[i].Normal, color,
|
auto vpos = vertices[i].Pos + pos;
|
||||||
|
p.vertices.emplace_back(vpos, vertices[i].Normal, color,
|
||||||
scale * vertices[i].TCoords);
|
scale * vertices[i].TCoords);
|
||||||
|
m_bounding_radius_sq = std::max(m_bounding_radius_sq,
|
||||||
|
(vpos - m_center_pos).getLengthSQ());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < numIndices; i++)
|
for (u32 i = 0; i < numIndices; i++)
|
||||||
|
@ -37,6 +37,12 @@ struct PreMeshBuffer
|
|||||||
struct MeshCollector
|
struct MeshCollector
|
||||||
{
|
{
|
||||||
std::array<std::vector<PreMeshBuffer>, MAX_TILE_LAYERS> prebuffers;
|
std::array<std::vector<PreMeshBuffer>, MAX_TILE_LAYERS> prebuffers;
|
||||||
|
// bounding sphere radius and center
|
||||||
|
f32 m_bounding_radius_sq = 0.0f;
|
||||||
|
v3f m_center_pos;
|
||||||
|
|
||||||
|
// center_pos: pos to use for bounding-sphere, in BS-space
|
||||||
|
MeshCollector(const v3f center_pos) : m_center_pos(center_pos) {}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
void append(const TileSpec &material,
|
void append(const TileSpec &material,
|
||||||
|
@ -313,7 +313,7 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
|
|||||||
std::vector<ItemPartColor> *colors, const ContentFeatures &f)
|
std::vector<ItemPartColor> *colors, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
MeshMakeData mesh_make_data(client, false);
|
MeshMakeData mesh_make_data(client, false);
|
||||||
MeshCollector collector;
|
MeshCollector collector(v3f(0.0f * BS));
|
||||||
mesh_make_data.setSmoothLighting(false);
|
mesh_make_data.setSmoothLighting(false);
|
||||||
MapblockMeshGenerator gen(&mesh_make_data, &collector,
|
MapblockMeshGenerator gen(&mesh_make_data, &collector,
|
||||||
client->getSceneManager()->getMeshManipulator());
|
client->getSceneManager()->getMeshManipulator());
|
||||||
|
Loading…
Reference in New Issue
Block a user