forked from Mirrorlandia_minetest/minetest
Occlusion: Check for light_propagates and do mapblock bounds checks
This commit is contained in:
parent
7d016b4efd
commit
6ada090bb0
@ -151,6 +151,11 @@ void ClientMap::updateDrawList()
|
|||||||
occlusion_culling_enabled = false;
|
occlusion_culling_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uncomment to debug occluded blocks in the wireframe mode
|
||||||
|
// TODO: Include this as a flag for an extended debugging setting
|
||||||
|
//if (occlusion_culling_enabled && m_control.show_wireframe)
|
||||||
|
// occlusion_culling_enabled = porting::getTimeS() & 1;
|
||||||
|
|
||||||
for (const auto §or_it : m_sectors) {
|
for (const auto §or_it : m_sectors) {
|
||||||
MapSector *sector = sector_it.second;
|
MapSector *sector = sector_it.second;
|
||||||
v2s16 sp = sector->getPos();
|
v2s16 sp = sector->getPos();
|
||||||
|
84
src/map.cpp
84
src/map.cpp
@ -1032,21 +1032,46 @@ void Map::removeNodeTimer(v3s16 p)
|
|||||||
block->m_node_timers.remove(p_rel);
|
block->m_node_timers.remove(p_rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Map::isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
|
bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
|
||||||
float stepfac, float offset, float end_offset, u32 needed_count)
|
const core::aabbox3d<s16> &block_bounds, float step, float stepfac, float offset,
|
||||||
|
u32 needed_count)
|
||||||
{
|
{
|
||||||
float distance = BS * pos_origin.getDistanceFrom(pos_blockcenter);
|
// Worst-case safety distance to keep to the target position
|
||||||
v3f direction = intToFloat(pos_blockcenter - pos_origin, BS);
|
// Anything smaller than the mapblock diagonal could result in in self-occlusion
|
||||||
direction.normalize();
|
// Diagonal = sqrt(1*1 + 1*1 + 1*1)
|
||||||
v3f pos_origin_f = intToFloat(pos_origin, BS);
|
const static float BLOCK_DIAGONAL = BS * MAP_BLOCKSIZE * 1.732f;
|
||||||
|
|
||||||
|
v3f direction = intToFloat(pos_target - pos_camera, BS);
|
||||||
|
float distance = direction.getLength();
|
||||||
|
|
||||||
|
// Disable occlusion culling for near mapblocks in underground
|
||||||
|
if (distance < BLOCK_DIAGONAL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Normalize direction vector
|
||||||
|
if (distance > 0.0f)
|
||||||
|
direction /= distance;
|
||||||
|
|
||||||
|
v3f pos_origin_f = intToFloat(pos_camera, BS);
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
for (; offset < distance + end_offset; offset += step){
|
bool is_valid_position;
|
||||||
v3f pf = pos_origin_f + direction * offset;
|
|
||||||
v3s16 pos_node = floatToInt(pf, BS);
|
for (; offset < distance; offset += step) {
|
||||||
MapNode node = getNode(pos_node);
|
v3f pos_node_f = pos_origin_f + direction * offset;
|
||||||
if (m_nodedef->get(node).drawtype == NDT_NORMAL) {
|
v3s16 pos_node = floatToInt(pos_node_f, BS);
|
||||||
// not transparent, see ContentFeature::updateTextures
|
|
||||||
|
if (offset > distance - BLOCK_DIAGONAL) {
|
||||||
|
// Do accurate position checks:
|
||||||
|
// Check whether the node is inside the current mapblock
|
||||||
|
if (block_bounds.isPointInside(pos_node))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapNode node = getNode(pos_node, &is_valid_position);
|
||||||
|
|
||||||
|
if (is_valid_position &&
|
||||||
|
!m_nodedef->get(node).light_propagates) {
|
||||||
|
// Cannot see through light-blocking nodes --> occluded
|
||||||
count++;
|
count++;
|
||||||
if (count >= needed_count)
|
if (count >= needed_count)
|
||||||
return true;
|
return true;
|
||||||
@ -1058,8 +1083,11 @@ bool Map::isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
|
|||||||
|
|
||||||
bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
|
bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
|
||||||
{
|
{
|
||||||
|
// Check occlusion for center and all 8 corners of the mapblock
|
||||||
|
// Overshoot a little for less flickering
|
||||||
static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
|
static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
|
||||||
static const v3s16 dir8[8] = {
|
static const v3s16 dir9[9] = {
|
||||||
|
v3s16( 0, 0, 0),
|
||||||
v3s16( 1, 1, 1) * bs2,
|
v3s16( 1, 1, 1) * bs2,
|
||||||
v3s16( 1, 1, -1) * bs2,
|
v3s16( 1, 1, -1) * bs2,
|
||||||
v3s16( 1, -1, 1) * bs2,
|
v3s16( 1, -1, 1) * bs2,
|
||||||
@ -1070,34 +1098,26 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
|
|||||||
v3s16(-1, -1, -1) * bs2,
|
v3s16(-1, -1, -1) * bs2,
|
||||||
};
|
};
|
||||||
|
|
||||||
v3s16 pos_blockcenter = block->getPos() * MAP_BLOCKSIZE;
|
// Minimal and maximal positions in the mapblock
|
||||||
pos_blockcenter += v3s16(MAP_BLOCKSIZE) / 2;
|
core::aabbox3d<s16> block_bounds = block->getBox();
|
||||||
|
|
||||||
float step = BS * 1;
|
v3s16 pos_blockcenter = block_bounds.MinEdge + (MAP_BLOCKSIZE / 2);
|
||||||
|
|
||||||
|
// Starting step size, value between 1m and sqrt(3)m
|
||||||
|
float step = BS * 1.2f;
|
||||||
// Multiply step by each iteraction by 'stepfac' to reduce checks in distance
|
// Multiply step by each iteraction by 'stepfac' to reduce checks in distance
|
||||||
float stepfac = 1.1;
|
float stepfac = 1.05f;
|
||||||
|
|
||||||
float start_offset = BS * 1;
|
float start_offset = BS * 1.0f;
|
||||||
// The occlusion search of 'isOccluded()' must stop short of the target
|
|
||||||
// point by distance 'end_offset' (end offset) to not enter the target mapblock.
|
|
||||||
// For the 8 mapblock corners 'end_offset' must therefore be the maximum diagonal
|
|
||||||
// of a mapblock, because we must consider all view angles.
|
|
||||||
// sqrt(1^2 + 1^2 + 1^2) = 1.732
|
|
||||||
float end_offset = -BS * MAP_BLOCKSIZE * 1.7321;
|
|
||||||
|
|
||||||
// to reduce the likelihood of falsely occluded blocks
|
// to reduce the likelihood of falsely occluded blocks
|
||||||
// require at least two solid blocks
|
// require at least two solid blocks
|
||||||
// this is a HACK, we should think of a more precise algorithm
|
// this is a HACK, we should think of a more precise algorithm
|
||||||
u32 needed_count = 2;
|
u32 needed_count = 2;
|
||||||
|
|
||||||
// For the central point of the mapblock 'end_offset' can be halved
|
for (const v3s16 &dir : dir9) {
|
||||||
if (!isOccluded(cam_pos_nodes, pos_blockcenter,
|
if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir, block_bounds,
|
||||||
step, stepfac, start_offset, end_offset / 2.0f, needed_count))
|
step, stepfac, start_offset, needed_count))
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const v3s16 &dir : dir8) {
|
|
||||||
if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir,
|
|
||||||
step, stepfac, start_offset, end_offset, needed_count))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -310,8 +310,9 @@ protected:
|
|||||||
// This stores the properties of the nodes on the map.
|
// This stores the properties of the nodes on the map.
|
||||||
const NodeDefManager *m_nodedef;
|
const NodeDefManager *m_nodedef;
|
||||||
|
|
||||||
bool isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
|
bool isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
|
||||||
float stepfac, float start_offset, float end_offset, u32 needed_count);
|
const core::aabbox3d<s16> &block_bounds, float step, float stepfac,
|
||||||
|
float offset, u32 needed_count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
|
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
|
||||||
|
Loading…
Reference in New Issue
Block a user