Skip to content

Commit 6ada090

Browse files
committedAug 23, 2019
Occlusion: Check for light_propagates and do mapblock bounds checks
1 parent 7d016b4 commit 6ada090

File tree

3 files changed

+60
-34
lines changed

3 files changed

+60
-34
lines changed
 

Diff for: ‎src/client/clientmap.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ void ClientMap::updateDrawList()
151151
occlusion_culling_enabled = false;
152152
}
153153

154+
// Uncomment to debug occluded blocks in the wireframe mode
155+
// TODO: Include this as a flag for an extended debugging setting
156+
//if (occlusion_culling_enabled && m_control.show_wireframe)
157+
// occlusion_culling_enabled = porting::getTimeS() & 1;
158+
154159
for (const auto &sector_it : m_sectors) {
155160
MapSector *sector = sector_it.second;
156161
v2s16 sp = sector->getPos();

Diff for: ‎src/map.cpp

+52-32
Original file line numberDiff line numberDiff line change
@@ -1032,21 +1032,46 @@ void Map::removeNodeTimer(v3s16 p)
10321032
block->m_node_timers.remove(p_rel);
10331033
}
10341034

1035-
bool Map::isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
1036-
float stepfac, float offset, float end_offset, u32 needed_count)
1035+
bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
1036+
const core::aabbox3d<s16> &block_bounds, float step, float stepfac, float offset,
1037+
u32 needed_count)
10371038
{
1038-
float distance = BS * pos_origin.getDistanceFrom(pos_blockcenter);
1039-
v3f direction = intToFloat(pos_blockcenter - pos_origin, BS);
1040-
direction.normalize();
1041-
v3f pos_origin_f = intToFloat(pos_origin, BS);
1039+
// Worst-case safety distance to keep to the target position
1040+
// Anything smaller than the mapblock diagonal could result in in self-occlusion
1041+
// Diagonal = sqrt(1*1 + 1*1 + 1*1)
1042+
const static float BLOCK_DIAGONAL = BS * MAP_BLOCKSIZE * 1.732f;
10421043

1044+
v3f direction = intToFloat(pos_target - pos_camera, BS);
1045+
float distance = direction.getLength();
1046+
1047+
// Disable occlusion culling for near mapblocks in underground
1048+
if (distance < BLOCK_DIAGONAL)
1049+
return false;
1050+
1051+
// Normalize direction vector
1052+
if (distance > 0.0f)
1053+
direction /= distance;
1054+
1055+
v3f pos_origin_f = intToFloat(pos_camera, BS);
10431056
u32 count = 0;
1044-
for (; offset < distance + end_offset; offset += step){
1045-
v3f pf = pos_origin_f + direction * offset;
1046-
v3s16 pos_node = floatToInt(pf, BS);
1047-
MapNode node = getNode(pos_node);
1048-
if (m_nodedef->get(node).drawtype == NDT_NORMAL) {
1049-
// not transparent, see ContentFeature::updateTextures
1057+
bool is_valid_position;
1058+
1059+
for (; offset < distance; offset += step) {
1060+
v3f pos_node_f = pos_origin_f + direction * offset;
1061+
v3s16 pos_node = floatToInt(pos_node_f, BS);
1062+
1063+
if (offset > distance - BLOCK_DIAGONAL) {
1064+
// Do accurate position checks:
1065+
// Check whether the node is inside the current mapblock
1066+
if (block_bounds.isPointInside(pos_node))
1067+
return false;
1068+
}
1069+
1070+
MapNode node = getNode(pos_node, &is_valid_position);
1071+
1072+
if (is_valid_position &&
1073+
!m_nodedef->get(node).light_propagates) {
1074+
// Cannot see through light-blocking nodes --> occluded
10501075
count++;
10511076
if (count >= needed_count)
10521077
return true;
@@ -1058,8 +1083,11 @@ bool Map::isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
10581083

10591084
bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
10601085
{
1086+
// Check occlusion for center and all 8 corners of the mapblock
1087+
// Overshoot a little for less flickering
10611088
static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
1062-
static const v3s16 dir8[8] = {
1089+
static const v3s16 dir9[9] = {
1090+
v3s16( 0, 0, 0),
10631091
v3s16( 1, 1, 1) * bs2,
10641092
v3s16( 1, 1, -1) * bs2,
10651093
v3s16( 1, -1, 1) * bs2,
@@ -1070,34 +1098,26 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
10701098
v3s16(-1, -1, -1) * bs2,
10711099
};
10721100

1073-
v3s16 pos_blockcenter = block->getPos() * MAP_BLOCKSIZE;
1074-
pos_blockcenter += v3s16(MAP_BLOCKSIZE) / 2;
1101+
// Minimal and maximal positions in the mapblock
1102+
core::aabbox3d<s16> block_bounds = block->getBox();
10751103

1076-
float step = BS * 1;
1104+
v3s16 pos_blockcenter = block_bounds.MinEdge + (MAP_BLOCKSIZE / 2);
1105+
1106+
// Starting step size, value between 1m and sqrt(3)m
1107+
float step = BS * 1.2f;
10771108
// Multiply step by each iteraction by 'stepfac' to reduce checks in distance
1078-
float stepfac = 1.1;
1109+
float stepfac = 1.05f;
10791110

1080-
float start_offset = BS * 1;
1081-
// The occlusion search of 'isOccluded()' must stop short of the target
1082-
// point by distance 'end_offset' (end offset) to not enter the target mapblock.
1083-
// For the 8 mapblock corners 'end_offset' must therefore be the maximum diagonal
1084-
// of a mapblock, because we must consider all view angles.
1085-
// sqrt(1^2 + 1^2 + 1^2) = 1.732
1086-
float end_offset = -BS * MAP_BLOCKSIZE * 1.7321;
1111+
float start_offset = BS * 1.0f;
10871112

10881113
// to reduce the likelihood of falsely occluded blocks
10891114
// require at least two solid blocks
10901115
// this is a HACK, we should think of a more precise algorithm
10911116
u32 needed_count = 2;
10921117

1093-
// For the central point of the mapblock 'end_offset' can be halved
1094-
if (!isOccluded(cam_pos_nodes, pos_blockcenter,
1095-
step, stepfac, start_offset, end_offset / 2.0f, needed_count))
1096-
return false;
1097-
1098-
for (const v3s16 &dir : dir8) {
1099-
if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir,
1100-
step, stepfac, start_offset, end_offset, needed_count))
1118+
for (const v3s16 &dir : dir9) {
1119+
if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir, block_bounds,
1120+
step, stepfac, start_offset, needed_count))
11011121
return false;
11021122
}
11031123
return true;

Diff for: ‎src/map.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,9 @@ class Map /*: public NodeContainer*/
310310
// This stores the properties of the nodes on the map.
311311
const NodeDefManager *m_nodedef;
312312

313-
bool isOccluded(v3s16 pos_origin, v3s16 pos_blockcenter, float step,
314-
float stepfac, float start_offset, float end_offset, u32 needed_count);
313+
bool isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
314+
const core::aabbox3d<s16> &block_bounds, float step, float stepfac,
315+
float offset, u32 needed_count);
315316

316317
private:
317318
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;

0 commit comments

Comments
 (0)
Please sign in to comment.