#include "settings.h"
#include "log.h"
#include "profiler.h"
+#include "mapnode_contentfeatures.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
/*
update the current node
*/
- bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
+ //bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
if (content_features(new_node_content).liquid_type == LIQUID_FLOWING) {
// set level to last 3 bits, flowing down bit to 4th bit
n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
<<std::endl;
return NULL;
}
- NodeMetadata *meta = block->m_node_metadata.get(p_rel);
+ NodeMetadata *meta = block->m_node_metadata->get(p_rel);
return meta;
}
<<std::endl;
return;
}
- block->m_node_metadata.set(p_rel, meta);
+ block->m_node_metadata->set(p_rel, meta);
}
void Map::removeNodeMetadata(v3s16 p)
<<std::endl;
return;
}
- block->m_node_metadata.remove(p_rel);
+ block->m_node_metadata->remove(p_rel);
}
void Map::nodeMetadataStep(float dtime,
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
{
MapBlock *block = *i;
- bool changed = block->m_node_metadata.step(dtime);
+ bool changed = block->m_node_metadata->step(dtime);
if(changed)
changed_blocks[block->getPos()] = block;
}
ISceneNode::OnRegisterSceneNode();
}
+static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
+ float start_off, float end_off, u32 needed_count)
+{
+ float d0 = (float)BS * p0.getDistanceFrom(p1);
+ v3s16 u0 = p1 - p0;
+ v3f uf = v3f(u0.X, u0.Y, u0.Z) * BS;
+ uf.normalize();
+ v3f p0f = v3f(p0.X, p0.Y, p0.Z) * BS;
+ u32 count = 0;
+ for(float s=start_off; s<d0+end_off; s+=step){
+ v3f pf = p0f + uf * s;
+ v3s16 p = floatToInt(pf, BS);
+ MapNode n = map->getNodeNoEx(p);
+ bool is_transparent = false;
+ ContentFeatures &f = content_features(n);
+ if(f.solidness == 0)
+ is_transparent = (f.visual_solidness != 2);
+ else
+ is_transparent = (f.solidness != 2);
+ if(!is_transparent){
+ count++;
+ if(count >= needed_count)
+ return true;
+ }
+ step *= stepfac;
+ }
+ return false;
+}
+
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
{
//m_dout<<DTIME<<"Rendering map..."<<std::endl;
Get all blocks and draw all visible ones
*/
- v3s16 cam_pos_nodes(
- camera_position.X / BS,
- camera_position.Y / BS,
- camera_position.Z / BS);
-
+ v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
+
v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
// Number of blocks in rendering range
u32 blocks_in_range = 0;
+ // Number of blocks occlusion culled
+ u32 blocks_occlusion_culled = 0;
// Number of blocks in rendering range but don't have a mesh
u32 blocks_in_range_without_mesh = 0;
// Blocks that had mesh that would have been drawn according to
/*if(m_control.range_all == false &&
d - 0.5*BS*MAP_BLOCKSIZE > range)
continue;*/
-
- // This block is in range. Reset usage timer.
- block->resetUsageTimer();
blocks_in_range++;
}
#endif
+ /*
+ Occlusion culling
+ */
+
+ v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
+ cpn += v3s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2);
+ float step = BS*1;
+ float stepfac = 1.1;
+ float startoff = BS*1;
+ float endoff = -BS*MAP_BLOCKSIZE*1.42*1.42;
+ v3s16 spn = cam_pos_nodes + v3s16(0,0,0);
+ s16 bs2 = MAP_BLOCKSIZE/2 + 1;
+ u32 needed_count = 1;
+ if(
+ isOccluded(this, spn, cpn + v3s16(0,0,0),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(bs2,bs2,-bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(bs2,-bs2,bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(bs2,-bs2,-bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(-bs2,bs2,bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(-bs2,bs2,-bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,bs2),
+ step, stepfac, startoff, endoff, needed_count) &&
+ isOccluded(this, spn, cpn + v3s16(-bs2,-bs2,-bs2),
+ step, stepfac, startoff, endoff, needed_count)
+ )
+ {
+ blocks_occlusion_culled++;
+ continue;
+ }
+
+ // This block is in range. Reset usage timer.
+ block->resetUsageTimer();
+
+ /*
+ Ignore if mesh doesn't exist
+ */
{
JMutexAutoLock lock(block->mesh_mutex);
blocks_in_range_without_mesh++;
continue;
}
-
- blocks_would_have_drawn++;
- if(blocks_drawn >= m_control.wanted_max_blocks
- && m_control.range_all == false
- && d > m_control.wanted_min_range * BS)
- continue;
}
-
+
+ // Limit block count in case of a sudden increase
+ blocks_would_have_drawn++;
+ if(blocks_drawn >= m_control.wanted_max_blocks
+ && m_control.range_all == false
+ && d > m_control.wanted_min_range * BS)
+ continue;
+
+ // Add to set
drawset[block->getPos()] = block;
sector_blocks_drawn++;
// Log only on solid pass because values are the same
if(pass == scene::ESNRP_SOLID){
g_profiler->avg("CM: blocks in range", blocks_in_range);
+ g_profiler->avg("CM: blocks occlusion culled", blocks_occlusion_culled);
if(blocks_in_range != 0)
g_profiler->avg("CM: blocks in range without mesh (frac)",
(float)blocks_in_range_without_mesh/blocks_in_range);