drawing range updater update and myrand() (but not usage of it)

This commit is contained in:
Perttu Ahola 2010-12-26 13:33:20 +02:00
parent 582af0cb21
commit 4ba5cd580d
8 changed files with 131 additions and 107 deletions

@ -66,14 +66,9 @@ void * ClientUpdateThread::Thread()
Client::Client( Client::Client(
IrrlichtDevice *device, IrrlichtDevice *device,
const char *playername, const char *playername,
JMutex &range_mutex, MapDrawControl &control):
float &viewing_range_nodes,
bool &viewing_range_all):
m_thread(this), m_thread(this),
m_env(new ClientMap(this, m_env(new ClientMap(this, control,
range_mutex,
viewing_range_nodes,
viewing_range_all,
device->getSceneManager()->getRootSceneNode(), device->getSceneManager()->getRootSceneNode(),
device->getSceneManager(), 666), device->getSceneManager(), 666),
dout_client), dout_client),

@ -110,9 +110,7 @@ public:
Client( Client(
IrrlichtDevice *device, IrrlichtDevice *device,
const char *playername, const char *playername,
JMutex &range_mutex, MapDrawControl &control
float &viewing_range_nodes,
bool &viewing_range_all
); );
~Client(); ~Client();

@ -253,25 +253,7 @@ TODO: Fix viewing range updater's oscillation when there is large non-
IrrlichtWrapper *g_irrlicht; IrrlichtWrapper *g_irrlicht;
// All range-related stuff below is locked behind this MapDrawControl draw_control;
JMutex g_range_mutex;
// Blocks are viewed in this range from the player
float g_viewing_range_nodes = 60;
//s16 g_viewing_range_nodes = 0;
// This is updated by the client's fetchBlocks routine
//s16 g_actual_viewing_range_nodes = VIEWING_RANGE_NODES_DEFAULT;
// If true, the preceding value has no meaning and all blocks
// already existing in memory are drawn
bool g_viewing_range_all = false;
// This is the freetime ratio imposed by the dynamic viewing
// range changing code.
// It is controlled by the main loop to the smallest value that
// inhibits glitches (dtime jitter) in the main loop.
//float g_freetime_ratio = FREETIME_RATIO_MAX;
/* /*
Settings. Settings.
@ -455,15 +437,14 @@ public:
// Viewing range selection // Viewing range selection
if(event.KeyInput.Key == irr::KEY_KEY_R) if(event.KeyInput.Key == irr::KEY_KEY_R)
{ {
JMutexAutoLock lock(g_range_mutex); if(draw_control.range_all)
if(g_viewing_range_all)
{ {
g_viewing_range_all = false; draw_control.range_all = false;
dstream<<DTIME<<"Disabled full viewing range"<<std::endl; dstream<<DTIME<<"Disabled full viewing range"<<std::endl;
} }
else else
{ {
g_viewing_range_all = true; draw_control.range_all = true;
dstream<<DTIME<<"Enabled full viewing range"<<std::endl; dstream<<DTIME<<"Enabled full viewing range"<<std::endl;
} }
} }
@ -853,7 +834,7 @@ private:
void updateViewingRange(f32 frametime, Client *client) void updateViewingRange(f32 frametime, Client *client)
{ {
// Range_all messes up frametime_avg // Range_all messes up frametime_avg
if(g_viewing_range_all == true) if(draw_control.range_all == true)
return; return;
float wanted_fps = g_settings.getFloat("wanted_fps"); float wanted_fps = g_settings.getFloat("wanted_fps");
@ -887,7 +868,7 @@ void updateViewingRange(f32 frametime, Client *client)
float fraction_unbiased = frametime_avg / frametime_wanted; float fraction_unbiased = frametime_avg / frametime_wanted;
float fraction = pow(fraction_unbiased, 20./(float)g_viewing_range_nodes); float fraction = pow(fraction_unbiased, 20./(float)draw_control.wanted_range);
/*float fraction = 1.0; /*float fraction = 1.0;
// If frametime is too high // If frametime is too high
@ -948,7 +929,7 @@ void updateViewingRange(f32 frametime, Client *client)
s16 viewing_range_nodes_min = g_settings.getS16("viewing_range_nodes_min"); s16 viewing_range_nodes_min = g_settings.getS16("viewing_range_nodes_min");
s16 viewing_range_nodes_max = g_settings.getS16("viewing_range_nodes_max"); s16 viewing_range_nodes_max = g_settings.getS16("viewing_range_nodes_max");
s16 n = (float)g_viewing_range_nodes / fraction; s16 n = (float)draw_control.wanted_range / fraction;
if(n < viewing_range_nodes_min) if(n < viewing_range_nodes_min)
n = viewing_range_nodes_min; n = viewing_range_nodes_min;
if(n > viewing_range_nodes_max) if(n > viewing_range_nodes_max)
@ -956,20 +937,20 @@ void updateViewingRange(f32 frametime, Client *client)
bool can_change = true; bool can_change = true;
if(client->isFetchingBlocks() == true && n > g_viewing_range_nodes) if(client->isFetchingBlocks() == true && n > draw_control.wanted_range)
can_change = false; can_change = false;
if(can_change) if(can_change)
g_viewing_range_nodes = n; draw_control.wanted_range = n;
/*dstream<<"g_viewing_range_nodes = " /*dstream<<"draw_control.wanted_range = "
<<g_viewing_range_nodes<<std::endl;*/ <<draw_control.wanted_range<<std::endl;*/
} }
#endif #endif
void updateViewingRange(f32 frametime_in, Client *client) void updateViewingRange(f32 frametime_in, Client *client)
{ {
if(g_viewing_range_all == true) if(draw_control.range_all == true)
return; return;
static f32 added_frametime = 0; static f32 added_frametime = 0;
@ -990,7 +971,29 @@ void updateViewingRange(f32 frametime_in, Client *client)
<<": Collected "<<added_frames<<" frames, total of " <<": Collected "<<added_frames<<" frames, total of "
<<added_frametime<<"s."<<std::endl; <<added_frametime<<"s."<<std::endl;
f32 frametime = added_frametime / added_frames; dstream<<"draw_control.blocks_drawn="
<<draw_control.blocks_drawn
<<", draw_control.blocks_would_have_drawn="
<<draw_control.blocks_would_have_drawn
<<std::endl;
float range_min = g_settings.getS16("viewing_range_nodes_min");
float range_max = g_settings.getS16("viewing_range_nodes_max");
draw_control.wanted_min_range = range_min;
draw_control.wanted_max_blocks = (1.2*draw_control.blocks_drawn)+1;
float block_draw_ratio = 1.0;
if(draw_control.blocks_would_have_drawn != 0)
{
block_draw_ratio = (float)draw_control.blocks_drawn
/ (float)draw_control.blocks_would_have_drawn;
}
// Calculate the average frametime in the case that all wanted
// blocks had been drawn
f32 frametime = added_frametime / added_frames / block_draw_ratio;
added_frametime = 0.0; added_frametime = 0.0;
added_frames = 0; added_frames = 0;
@ -1007,7 +1010,7 @@ void updateViewingRange(f32 frametime_in, Client *client)
return; return;
} }
float range = g_viewing_range_nodes; float range = draw_control.wanted_range;
float new_range = range; float new_range = range;
static s16 range_old = 0; static s16 range_old = 0;
@ -1029,16 +1032,24 @@ void updateViewingRange(f32 frametime_in, Client *client)
// A high value here results in slow changing range (0.0025) // A high value here results in slow changing range (0.0025)
// SUGG: This could be dynamically adjusted so that when // SUGG: This could be dynamically adjusted so that when
// the camera is turning, this is lower // the camera is turning, this is lower
float min_time_per_range = 0.001; //float min_time_per_range = 0.0015;
float min_time_per_range = 0.0010;
//float min_time_per_range = 0.05 / range;
if(time_per_range < min_time_per_range) if(time_per_range < min_time_per_range)
{
time_per_range = min_time_per_range; time_per_range = min_time_per_range;
dstream<<"time_per_range="<<time_per_range<<" (min)"<<std::endl;
dstream<<"time_per_range="<<time_per_range<<std::endl; }
else
{
dstream<<"time_per_range="<<time_per_range<<std::endl;
}
f32 wanted_range_change = wanted_frametime_change / time_per_range; f32 wanted_range_change = wanted_frametime_change / time_per_range;
// Dampen the change a bit to kill oscillations // Dampen the change a bit to kill oscillations
//wanted_range_change *= 0.9; //wanted_range_change *= 0.9;
wanted_range_change *= 0.75; //wanted_range_change *= 0.75;
wanted_range_change *= 0.5;
dstream<<"wanted_range_change="<<wanted_range_change<<std::endl; dstream<<"wanted_range_change="<<wanted_range_change<<std::endl;
// If needed range change is very small, just return // If needed range change is very small, just return
@ -1051,9 +1062,6 @@ void updateViewingRange(f32 frametime_in, Client *client)
new_range += wanted_range_change; new_range += wanted_range_change;
dstream<<"new_range="<<new_range/*<<std::endl*/; dstream<<"new_range="<<new_range/*<<std::endl*/;
float range_min = g_settings.getS16("viewing_range_nodes_min");
float range_max = g_settings.getS16("viewing_range_nodes_max");
float new_range_unclamped = new_range; float new_range_unclamped = new_range;
if(new_range < range_min) if(new_range < range_min)
new_range = range_min; new_range = range_min;
@ -1065,9 +1073,7 @@ void updateViewingRange(f32 frametime_in, Client *client)
else else
dstream<<std::endl; dstream<<std::endl;
JMutexAutoLock lock(g_range_mutex); draw_control.wanted_range = new_range;
g_viewing_range_nodes = new_range;
range_old = new_range; range_old = new_range;
frametime_old = frametime; frametime_old = frametime;
@ -1324,6 +1330,7 @@ int main(int argc, char *argv[])
// Initialize random seed // Initialize random seed
srand(time(0)); srand(time(0));
mysrand(time(0));
/* /*
Run unit tests Run unit tests
@ -1334,12 +1341,6 @@ int main(int argc, char *argv[])
run_tests(); run_tests();
} }
/*
Global range mutex
*/
g_range_mutex.Init();
assert(g_range_mutex.IsInitialized());
// Read map parameters from settings // Read map parameters from settings
HMParams hm_params; HMParams hm_params;
@ -1584,10 +1585,7 @@ int main(int argc, char *argv[])
Create client Create client
*/ */
Client client(device, playername, Client client(device, playername, draw_control);
g_range_mutex,
g_viewing_range_nodes,
g_viewing_range_all);
g_client = &client; g_client = &client;
@ -2409,8 +2407,8 @@ int main(int argc, char *argv[])
if(g_settings.getBool("enable_fog") == true) if(g_settings.getBool("enable_fog") == true)
{ {
f32 range = g_viewing_range_nodes * BS; f32 range = draw_control.wanted_range * BS;
if(g_viewing_range_all) if(draw_control.range_all)
range = 100000*BS; range = 100000*BS;
driver->setFog( driver->setFog(
@ -2435,13 +2433,13 @@ int main(int argc, char *argv[])
wchar_t temptext[150]; wchar_t temptext[150];
static float drawtime_avg = 0; static float drawtime_avg = 0;
drawtime_avg = drawtime_avg * 0.98 + (float)drawtime*0.02; drawtime_avg = drawtime_avg * 0.95 + (float)drawtime*0.05;
static float beginscenetime_avg = 0; static float beginscenetime_avg = 0;
beginscenetime_avg = beginscenetime_avg * 0.98 + (float)beginscenetime*0.02; beginscenetime_avg = beginscenetime_avg * 0.95 + (float)beginscenetime*0.05;
static float scenetime_avg = 0; static float scenetime_avg = 0;
scenetime_avg = scenetime_avg * 0.98 + (float)scenetime*0.02; scenetime_avg = scenetime_avg * 0.95 + (float)scenetime*0.05;
static float endscenetime_avg = 0; static float endscenetime_avg = 0;
endscenetime_avg = endscenetime_avg * 0.98 + (float)endscenetime*0.02; endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;
swprintf(temptext, 150, L"Minetest-c55 (" swprintf(temptext, 150, L"Minetest-c55 ("
L"F: item=%i" L"F: item=%i"
@ -2449,7 +2447,7 @@ int main(int argc, char *argv[])
L")" L")"
L" drawtime=%.0f, beginscenetime=%.0f, scenetime=%.0f, endscenetime=%.0f", L" drawtime=%.0f, beginscenetime=%.0f, scenetime=%.0f, endscenetime=%.0f",
g_selected_item, g_selected_item,
g_viewing_range_all, draw_control.range_all,
drawtime_avg, drawtime_avg,
beginscenetime_avg, beginscenetime_avg,
scenetime_avg, scenetime_avg,
@ -2472,7 +2470,7 @@ int main(int argc, char *argv[])
busytime_jitter1_min_sample, busytime_jitter1_min_sample,
busytime_jitter1_max_sample, busytime_jitter1_max_sample,
dtime_jitter1_max_fraction * 100.0, dtime_jitter1_max_fraction * 100.0,
g_viewing_range_nodes draw_control.wanted_range
); );
guitext2->setText(temptext); guitext2->setText(temptext);

@ -2889,9 +2889,7 @@ void ServerMap::PrintInfo(std::ostream &out)
ClientMap::ClientMap( ClientMap::ClientMap(
Client *client, Client *client,
JMutex &range_mutex, MapDrawControl &control,
float &viewing_range_nodes,
bool &viewing_range_all,
scene::ISceneNode* parent, scene::ISceneNode* parent,
scene::ISceneManager* mgr, scene::ISceneManager* mgr,
s32 id s32 id
@ -2900,9 +2898,7 @@ ClientMap::ClientMap(
scene::ISceneNode(parent, mgr, id), scene::ISceneNode(parent, mgr, id),
m_client(client), m_client(client),
mesh(NULL), mesh(NULL),
m_range_mutex(range_mutex), m_control(control)
m_viewing_range_nodes(viewing_range_nodes),
m_viewing_range_all(viewing_range_all)
{ {
mesh_mutex.Init(); mesh_mutex.Init();
@ -3003,24 +2999,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
*/ */
int time1 = time(0); int time1 = time(0);
//s32 daynight_i = m_client->getDayNightIndex();
u32 daynight_ratio = m_client->getDayNightRatio(); u32 daynight_ratio = m_client->getDayNightRatio();
/*
Collect all blocks that are in the view range
Should not optimize more here as we want to auto-update
all changed nodes in viewing range at the next step.
*/
float viewing_range_nodes;
bool viewing_range_all;
{
JMutexAutoLock lock(m_range_mutex);
viewing_range_nodes = m_viewing_range_nodes;
viewing_range_all = m_viewing_range_all;
}
m_camera_mutex.Lock(); m_camera_mutex.Lock();
v3f camera_position = m_camera_position; v3f camera_position = m_camera_position;
v3f camera_direction = m_camera_direction; v3f camera_direction = m_camera_direction;
@ -3035,7 +3015,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
camera_position.Y / BS, camera_position.Y / BS,
camera_position.Z / BS); camera_position.Z / BS);
v3s16 box_nodes_d = viewing_range_nodes * 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;
@ -3055,11 +3035,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
// For limiting number of mesh updates per frame // For limiting number of mesh updates per frame
u32 mesh_update_count = 0; u32 mesh_update_count = 0;
u32 blocks_would_have_drawn = 0;
u32 blocks_drawn = 0;
//NOTE: The sectors map should be locked but we're not doing it //NOTE: The sectors map should be locked but we're not doing it
// because it'd cause too much delays // because it'd cause too much delays
int timecheck_counter = 0; int timecheck_counter = 0;
core::map<v2s16, MapSector*>::Iterator si; core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator(); si = m_sectors.getIterator();
for(; si.atEnd() == false; si++) for(; si.atEnd() == false; si++)
@ -3082,7 +3064,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
MapSector *sector = si.getNode()->getValue(); MapSector *sector = si.getNode()->getValue();
v2s16 sp = sector->getPos(); v2s16 sp = sector->getPos();
if(viewing_range_all == false) if(m_control.range_all == false)
{ {
if(sp.X < p_blocks_min.X if(sp.X < p_blocks_min.X
|| sp.X > p_blocks_max.X || sp.X > p_blocks_max.X
@ -3126,12 +3108,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
// Total distance // Total distance
f32 d = blockpos_relative.getLength(); f32 d = blockpos_relative.getLength();
if(viewing_range_all == false) if(m_control.range_all == false)
{ {
// If block is far away, don't draw it // If block is far away, don't draw it
if(d > viewing_range_nodes * BS) if(d > m_control.wanted_range * BS)
// This is nicer when fog is used // This is nicer when fog is used
//if((dforward+d)/2 > viewing_range_nodes * BS) //if((dforward+d)/2 > m_control.wanted_range * BS)
continue; continue;
} }
@ -3175,7 +3157,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
} }
f32 faraway = BS*50; f32 faraway = BS*50;
//f32 faraway = viewing_range_nodes * BS; //f32 faraway = m_control.wanted_range * BS;
/* /*
This has to be done with the mesh_mutex unlocked This has to be done with the mesh_mutex unlocked
@ -3218,6 +3200,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
if(mesh == NULL) if(mesh == NULL)
continue; 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;
blocks_drawn++;
u32 c = mesh->getMeshBufferCount(); u32 c = mesh->getMeshBufferCount();
for(u32 i=0; i<c; i++) for(u32 i=0; i<c; i++)
@ -3239,6 +3228,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
} // foreach sectorblocks } // foreach sectorblocks
} }
m_control.blocks_drawn = blocks_drawn;
m_control.blocks_would_have_drawn = blocks_would_have_drawn;
/*dstream<<"renderMap(): is_transparent_pass="<<is_transparent_pass /*dstream<<"renderMap(): is_transparent_pass="<<is_transparent_pass
<<", rendered "<<vertex_count<<" vertices."<<std::endl;*/ <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
} }

@ -543,6 +543,31 @@ private:
#ifndef SERVER #ifndef SERVER
struct MapDrawControl
{
MapDrawControl():
range_all(false),
wanted_range(50),
wanted_max_blocks(0),
wanted_min_range(0),
blocks_drawn(0),
blocks_would_have_drawn(0)
{
}
// Overrides limits by drawing everything
bool range_all;
// Wanted drawing range
float wanted_range;
// Maximum number of blocks to draw
u32 wanted_max_blocks;
// Blocks in this range are drawn regardless of number of blocks drawn
float wanted_min_range;
// Number of blocks rendered is written here by the renderer
u32 blocks_drawn;
// Number of blocks that would have been drawn in wanted_range
u32 blocks_would_have_drawn;
};
class Client; class Client;
class ClientMap : public Map, public scene::ISceneNode class ClientMap : public Map, public scene::ISceneNode
@ -550,9 +575,7 @@ class ClientMap : public Map, public scene::ISceneNode
public: public:
ClientMap( ClientMap(
Client *client, Client *client,
JMutex &range_mutex, MapDrawControl &control,
float &viewing_range_nodes,
bool &viewing_range_all,
scene::ISceneNode* parent, scene::ISceneNode* parent,
scene::ISceneManager* mgr, scene::ISceneManager* mgr,
s32 id s32 id
@ -619,9 +642,7 @@ private:
scene::SMesh *mesh; scene::SMesh *mesh;
JMutex mesh_mutex; JMutex mesh_mutex;
JMutex &m_range_mutex; MapDrawControl &m_control;
float &m_viewing_range_nodes;
bool &m_viewing_range_all;
}; };
#endif #endif

@ -239,6 +239,7 @@ int main(int argc, char *argv[])
// Initialize random seed // Initialize random seed
srand(time(0)); srand(time(0));
mysrand(time(0));
/* /*
Run unit tests Run unit tests

@ -88,4 +88,18 @@ const v3s16 g_26dirs[26] =
// 26 // 26
}; };
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void)
{
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed)
{
next = seed;
}

@ -1323,5 +1323,10 @@ private:
MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue; MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
}; };
// Pseudo-random (VC++ rand() sucks)
int myrand(void);
void mysrand(unsigned seed);
#define MYRAND_MAX 32767
#endif #endif