mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Reorganize ClientMap rendering code for a bit more performance
- Don't select blocks for drawing in every frame - Sort meshbuffers by material before drawing
This commit is contained in:
parent
0e6f7a21c6
commit
ee2d9d973a
@ -157,43 +157,21 @@ static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||||
{
|
{
|
||||||
|
ScopeProfiler sp(g_profiler, "CM::updateDrawList()", SPT_AVG);
|
||||||
|
g_profiler->add("CM::updateDrawList() count", 1);
|
||||||
|
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
|
||||||
//m_dout<<DTIME<<"Rendering map..."<<std::endl;
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
DSTACK(__FUNCTION_NAME);
|
i = m_drawlist.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
|
||||||
|
|
||||||
std::string prefix;
|
|
||||||
if(pass == scene::ESNRP_SOLID)
|
|
||||||
prefix = "CM: solid: ";
|
|
||||||
else
|
|
||||||
prefix = "CM: transparent: ";
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is called two times per frame, reset on the non-transparent one
|
|
||||||
*/
|
|
||||||
if(pass == scene::ESNRP_SOLID)
|
|
||||||
{
|
{
|
||||||
m_last_drawn_sectors.clear();
|
MapBlock *block = i.getNode()->getValue();
|
||||||
|
block->refDrop();
|
||||||
}
|
}
|
||||||
|
m_drawlist.clear();
|
||||||
/*
|
|
||||||
Get time for measuring timeout.
|
|
||||||
|
|
||||||
Measuring time is very useful for long delays when the
|
|
||||||
machine is swapping a lot.
|
|
||||||
*/
|
|
||||||
int time1 = time(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get animation parameters
|
|
||||||
*/
|
|
||||||
float animation_time = m_client->getAnimationTime();
|
|
||||||
int crack = m_client->getCrackLevel();
|
|
||||||
u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
|
|
||||||
|
|
||||||
m_camera_mutex.Lock();
|
m_camera_mutex.Lock();
|
||||||
v3f camera_position = m_camera_position;
|
v3f camera_position = m_camera_position;
|
||||||
@ -201,17 +179,15 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
f32 camera_fov = m_camera_fov;
|
f32 camera_fov = m_camera_fov;
|
||||||
m_camera_mutex.Unlock();
|
m_camera_mutex.Unlock();
|
||||||
|
|
||||||
/*
|
// Use a higher fov to accomodate faster camera movements.
|
||||||
Get all blocks and draw all visible ones
|
// Blocks are cropped better when they are drawn.
|
||||||
*/
|
// Or maybe they aren't? Well whatever.
|
||||||
|
camera_fov *= 1.2;
|
||||||
|
|
||||||
v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
|
v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
|
||||||
|
|
||||||
v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
|
v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
|
||||||
|
|
||||||
v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
|
v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
|
||||||
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
|
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
|
||||||
|
|
||||||
// Take a fair amount as we will be dropping more out later
|
// Take a fair amount as we will be dropping more out later
|
||||||
// Umm... these additions are a bit strange but they are needed.
|
// Umm... these additions are a bit strange but they are needed.
|
||||||
v3s16 p_blocks_min(
|
v3s16 p_blocks_min(
|
||||||
@ -223,13 +199,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
||||||
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
||||||
|
|
||||||
u32 vertex_count = 0;
|
|
||||||
u32 meshbuffer_count = 0;
|
|
||||||
|
|
||||||
// For limiting number of mesh animations per frame
|
|
||||||
u32 mesh_animate_count = 0;
|
|
||||||
u32 mesh_animate_count_far = 0;
|
|
||||||
|
|
||||||
// Number of blocks in rendering range
|
// Number of blocks in rendering range
|
||||||
u32 blocks_in_range = 0;
|
u32 blocks_in_range = 0;
|
||||||
// Number of blocks occlusion culled
|
// Number of blocks occlusion culled
|
||||||
@ -242,18 +211,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
// Blocks that were drawn and had a mesh
|
// Blocks that were drawn and had a mesh
|
||||||
u32 blocks_drawn = 0;
|
u32 blocks_drawn = 0;
|
||||||
// Blocks which had a corresponding meshbuffer for this pass
|
// Blocks which had a corresponding meshbuffer for this pass
|
||||||
u32 blocks_had_pass_meshbuf = 0;
|
//u32 blocks_had_pass_meshbuf = 0;
|
||||||
// Blocks from which stuff was actually drawn
|
// Blocks from which stuff was actually drawn
|
||||||
u32 blocks_without_stuff = 0;
|
//u32 blocks_without_stuff = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
Collect a set of blocks for drawing
|
|
||||||
*/
|
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> drawset;
|
|
||||||
|
|
||||||
{
|
|
||||||
ScopeProfiler sp(g_profiler, prefix+"collecting blocks for drawing", SPT_AVG);
|
|
||||||
|
|
||||||
for(core::map<v2s16, MapSector*>::Iterator
|
for(core::map<v2s16, MapSector*>::Iterator
|
||||||
si = m_sectors.getIterator();
|
si = m_sectors.getIterator();
|
||||||
@ -380,10 +340,171 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
&& d > m_control.wanted_min_range * BS)
|
&& d > m_control.wanted_min_range * BS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Add to set
|
||||||
|
block->refGrab();
|
||||||
|
m_drawlist[block->getPos()] = block;
|
||||||
|
|
||||||
|
sector_blocks_drawn++;
|
||||||
|
blocks_drawn++;
|
||||||
|
|
||||||
|
} // foreach sectorblocks
|
||||||
|
|
||||||
|
if(sector_blocks_drawn != 0)
|
||||||
|
m_last_drawn_sectors[sp] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
g_profiler->avg("CM: blocks drawn", blocks_drawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MeshBufList
|
||||||
|
{
|
||||||
|
video::SMaterial m;
|
||||||
|
core::list<scene::IMeshBuffer*> bufs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshBufListList
|
||||||
|
{
|
||||||
|
core::list<MeshBufList> lists;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
lists.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(scene::IMeshBuffer *buf)
|
||||||
|
{
|
||||||
|
for(core::list<MeshBufList>::Iterator i = lists.begin();
|
||||||
|
i != lists.end(); i++){
|
||||||
|
MeshBufList &l = *i;
|
||||||
|
if(l.m == buf->getMaterial()){
|
||||||
|
l.bufs.push_back(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MeshBufList l;
|
||||||
|
l.m = buf->getMaterial();
|
||||||
|
l.bufs.push_back(buf);
|
||||||
|
lists.push_back(l);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
||||||
|
|
||||||
|
std::string prefix;
|
||||||
|
if(pass == scene::ESNRP_SOLID)
|
||||||
|
prefix = "CM: solid: ";
|
||||||
|
else
|
||||||
|
prefix = "CM: transparent: ";
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is called two times per frame, reset on the non-transparent one
|
||||||
|
*/
|
||||||
|
if(pass == scene::ESNRP_SOLID)
|
||||||
|
{
|
||||||
|
m_last_drawn_sectors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get time for measuring timeout.
|
||||||
|
|
||||||
|
Measuring time is very useful for long delays when the
|
||||||
|
machine is swapping a lot.
|
||||||
|
*/
|
||||||
|
int time1 = time(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get animation parameters
|
||||||
|
*/
|
||||||
|
float animation_time = m_client->getAnimationTime();
|
||||||
|
int crack = m_client->getCrackLevel();
|
||||||
|
u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
|
||||||
|
|
||||||
|
m_camera_mutex.Lock();
|
||||||
|
v3f camera_position = m_camera_position;
|
||||||
|
v3f camera_direction = m_camera_direction;
|
||||||
|
f32 camera_fov = m_camera_fov;
|
||||||
|
m_camera_mutex.Unlock();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get all blocks and draw all visible ones
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
|
||||||
|
|
||||||
|
// Take a fair amount as we will be dropping more out later
|
||||||
|
// Umm... these additions are a bit strange but they are needed.
|
||||||
|
v3s16 p_blocks_min(
|
||||||
|
p_nodes_min.X / MAP_BLOCKSIZE - 3,
|
||||||
|
p_nodes_min.Y / MAP_BLOCKSIZE - 3,
|
||||||
|
p_nodes_min.Z / MAP_BLOCKSIZE - 3);
|
||||||
|
v3s16 p_blocks_max(
|
||||||
|
p_nodes_max.X / MAP_BLOCKSIZE + 1,
|
||||||
|
p_nodes_max.Y / MAP_BLOCKSIZE + 1,
|
||||||
|
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
|
||||||
|
|
||||||
|
u32 vertex_count = 0;
|
||||||
|
u32 meshbuffer_count = 0;
|
||||||
|
|
||||||
|
// For limiting number of mesh animations per frame
|
||||||
|
u32 mesh_animate_count = 0;
|
||||||
|
u32 mesh_animate_count_far = 0;
|
||||||
|
|
||||||
|
// Blocks that had mesh that would have been drawn according to
|
||||||
|
// rendering range (if max blocks limit didn't kick in)
|
||||||
|
u32 blocks_would_have_drawn = 0;
|
||||||
|
// Blocks that were drawn and had a mesh
|
||||||
|
u32 blocks_drawn = 0;
|
||||||
|
// Blocks which had a corresponding meshbuffer for this pass
|
||||||
|
u32 blocks_had_pass_meshbuf = 0;
|
||||||
|
// Blocks from which stuff was actually drawn
|
||||||
|
u32 blocks_without_stuff = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draw the selected MapBlocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
ScopeProfiler sp(g_profiler, prefix+"drawing blocks", SPT_AVG);
|
||||||
|
|
||||||
|
MeshBufListList drawbufs;
|
||||||
|
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = m_drawlist.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
MapBlock *block = i.getNode()->getValue();
|
||||||
|
|
||||||
|
// If the mesh of the block happened to get deleted, ignore it
|
||||||
|
if(block->mesh == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float d = 0.0;
|
||||||
|
if(isBlockInSight(block->getPos(), camera_position,
|
||||||
|
camera_direction, camera_fov,
|
||||||
|
100000*BS, &d) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Mesh animation
|
// Mesh animation
|
||||||
{
|
{
|
||||||
//JMutexAutoLock lock(block->mesh_mutex);
|
//JMutexAutoLock lock(block->mesh_mutex);
|
||||||
MapBlockMesh *mapBlockMesh = block->mesh;
|
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;
|
||||||
//bool faraway = d >= m_control.wanted_range * BS;
|
//bool faraway = d >= m_control.wanted_range * BS;
|
||||||
@ -407,30 +528,42 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to set
|
|
||||||
drawset[block->getPos()] = block;
|
|
||||||
|
|
||||||
sector_blocks_drawn++;
|
|
||||||
blocks_drawn++;
|
|
||||||
|
|
||||||
} // foreach sectorblocks
|
|
||||||
|
|
||||||
if(sector_blocks_drawn != 0)
|
|
||||||
m_last_drawn_sectors[sp] = true;
|
|
||||||
}
|
|
||||||
} // ScopeProfiler
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Draw the selected MapBlocks
|
Get the meshbuffers of the block
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, prefix+"drawing blocks", SPT_AVG);
|
//JMutexAutoLock lock(block->mesh_mutex);
|
||||||
|
|
||||||
|
MapBlockMesh *mapBlockMesh = block->mesh;
|
||||||
|
assert(mapBlockMesh);
|
||||||
|
|
||||||
|
scene::SMesh *mesh = mapBlockMesh->getMesh();
|
||||||
|
assert(mesh);
|
||||||
|
|
||||||
|
u32 c = mesh->getMeshBufferCount();
|
||||||
|
for(u32 i=0; i<c; i++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||||
|
const video::SMaterial& material = buf->getMaterial();
|
||||||
|
video::IMaterialRenderer* rnd =
|
||||||
|
driver->getMaterialRenderer(material.MaterialType);
|
||||||
|
bool transparent = (rnd && rnd->isTransparent());
|
||||||
|
if(transparent == is_transparent_pass)
|
||||||
|
{
|
||||||
|
if(buf->getVertexCount() == 0)
|
||||||
|
errorstream<<"Block ["<<analyze_block(block)
|
||||||
|
<<"] contains an empty meshbuf"<<std::endl;
|
||||||
|
drawbufs.add(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core::list<MeshBufList> &lists = drawbufs.lists;
|
||||||
|
|
||||||
int timecheck_counter = 0;
|
int timecheck_counter = 0;
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
for(core::list<MeshBufList>::Iterator i = lists.begin();
|
||||||
i = drawset.getIterator();
|
i != lists.end(); i++)
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
timecheck_counter++;
|
timecheck_counter++;
|
||||||
@ -448,8 +581,19 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock *block = i.getNode()->getValue();
|
MeshBufList &list = *i;
|
||||||
|
|
||||||
|
driver->setMaterial(list.m);
|
||||||
|
|
||||||
|
for(core::list<scene::IMeshBuffer*>::Iterator j = list.bufs.begin();
|
||||||
|
j != list.bufs.end(); j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = *j;
|
||||||
|
driver->drawMeshBuffer(buf);
|
||||||
|
vertex_count += buf->getVertexCount();
|
||||||
|
meshbuffer_count++;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Draw the faces of the block
|
Draw the faces of the block
|
||||||
*/
|
*/
|
||||||
@ -494,17 +638,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
else
|
else
|
||||||
blocks_without_stuff++;
|
blocks_without_stuff++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} // ScopeProfiler
|
} // ScopeProfiler
|
||||||
|
|
||||||
// Log only on solid pass because values are the same
|
// Log only on solid pass because values are the same
|
||||||
if(pass == scene::ESNRP_SOLID){
|
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);
|
|
||||||
g_profiler->avg("CM: blocks drawn", blocks_drawn);
|
|
||||||
g_profiler->avg("CM: animated meshes", mesh_animate_count);
|
g_profiler->avg("CM: animated meshes", mesh_animate_count);
|
||||||
g_profiler->avg("CM: animated meshes (far)", mesh_animate_count_far);
|
g_profiler->avg("CM: animated meshes (far)", mesh_animate_count_far);
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ public:
|
|||||||
return m_box;
|
return m_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateDrawList(video::IVideoDriver* driver);
|
||||||
void renderMap(video::IVideoDriver* driver, s32 pass);
|
void renderMap(video::IVideoDriver* driver, s32 pass);
|
||||||
|
|
||||||
int getBackgroundBrightness(float max_d, u32 daylight_factor,
|
int getBackgroundBrightness(float max_d, u32 daylight_factor,
|
||||||
@ -142,6 +143,8 @@ private:
|
|||||||
f32 m_camera_fov;
|
f32 m_camera_fov;
|
||||||
JMutex m_camera_mutex;
|
JMutex m_camera_mutex;
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> m_drawlist;
|
||||||
|
|
||||||
core::map<v2s16, bool> m_last_drawn_sectors;
|
core::map<v2s16, bool> m_last_drawn_sectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
15
src/game.cpp
15
src/game.cpp
@ -1235,6 +1235,9 @@ void the_game(
|
|||||||
float object_hit_delay_timer = 0.0;
|
float object_hit_delay_timer = 0.0;
|
||||||
float time_from_last_punch = 10;
|
float time_from_last_punch = 10;
|
||||||
|
|
||||||
|
float update_draw_list_timer = 0.0;
|
||||||
|
v3f update_draw_list_last_cam_dir;
|
||||||
|
|
||||||
bool invert_mouse = g_settings->getBool("invert_mouse");
|
bool invert_mouse = g_settings->getBool("invert_mouse");
|
||||||
|
|
||||||
bool respawn_menu_active = false;
|
bool respawn_menu_active = false;
|
||||||
@ -2698,6 +2701,18 @@ void the_game(
|
|||||||
camera.wield(item);
|
camera.wield(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update block draw list every 200ms or when camera direction has
|
||||||
|
changed much
|
||||||
|
*/
|
||||||
|
update_draw_list_timer += dtime;
|
||||||
|
if(update_draw_list_timer >= 0.2 ||
|
||||||
|
update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2){
|
||||||
|
update_draw_list_timer = 0;
|
||||||
|
client.getEnv().getClientMap().updateDrawList(driver);
|
||||||
|
update_draw_list_last_cam_dir = camera_direction;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Drawing begins
|
Drawing begins
|
||||||
*/
|
*/
|
||||||
|
@ -1469,7 +1469,7 @@ void Map::timerUpdate(float dtime, float unload_timeout,
|
|||||||
|
|
||||||
block->incrementUsageTimer(dtime);
|
block->incrementUsageTimer(dtime);
|
||||||
|
|
||||||
if(block->getUsageTimer() > unload_timeout)
|
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout)
|
||||||
{
|
{
|
||||||
v3s16 p = block->getPos();
|
v3s16 p = block->getPos();
|
||||||
|
|
||||||
|
@ -56,7 +56,8 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
|
|||||||
m_generated(false),
|
m_generated(false),
|
||||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_disk_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_disk_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_usage_timer(0)
|
m_usage_timer(0),
|
||||||
|
m_refcount(0)
|
||||||
{
|
{
|
||||||
data = NULL;
|
data = NULL;
|
||||||
if(dummy == false)
|
if(dummy == false)
|
||||||
|
@ -431,6 +431,22 @@ public:
|
|||||||
return m_usage_timer;
|
return m_usage_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See m_refcount
|
||||||
|
*/
|
||||||
|
void refGrab()
|
||||||
|
{
|
||||||
|
m_refcount++;
|
||||||
|
}
|
||||||
|
void refDrop()
|
||||||
|
{
|
||||||
|
m_refcount--;
|
||||||
|
}
|
||||||
|
int refGet()
|
||||||
|
{
|
||||||
|
return m_refcount;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Node Timers
|
Node Timers
|
||||||
*/
|
*/
|
||||||
@ -566,6 +582,12 @@ private:
|
|||||||
Map will unload the block when this reaches a timeout.
|
Map will unload the block when this reaches a timeout.
|
||||||
*/
|
*/
|
||||||
float m_usage_timer;
|
float m_usage_timer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reference count; currently used for determining if this block is in
|
||||||
|
the list of blocks to be drawn.
|
||||||
|
*/
|
||||||
|
int m_refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool blockpos_over_limit(v3s16 p)
|
inline bool blockpos_over_limit(v3s16 p)
|
||||||
|
Loading…
Reference in New Issue
Block a user