diff options
author | Perttu Ahola <celeron55@gmail.com> | 2011-01-17 02:40:53 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-01-17 02:40:53 +0200 |
commit | 3891bc43e084b9bd1c345638dfbbffa9d71658c9 (patch) | |
tree | 1a32921c26409c735c062bfc8131b0c71728fadb | |
parent | 7068bc90af1f452359a1fcfe20fa01fc88f3d70a (diff) | |
download | minetest-3891bc43e084b9bd1c345638dfbbffa9d71658c9.tar.gz minetest-3891bc43e084b9bd1c345638dfbbffa9d71658c9.tar.bz2 minetest-3891bc43e084b9bd1c345638dfbbffa9d71658c9.zip |
fine-tuning of map generator and server and stuff.
-rw-r--r-- | src/defaultsettings.cpp | 5 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/map.cpp | 241 | ||||
-rw-r--r-- | src/map.h | 2 | ||||
-rw-r--r-- | src/materials.cpp | 4 | ||||
-rw-r--r-- | src/player.cpp | 21 | ||||
-rw-r--r-- | src/server.cpp | 55 | ||||
-rw-r--r-- | src/server.h | 14 | ||||
-rw-r--r-- | src/test.cpp | 2 | ||||
-rw-r--r-- | src/utility.cpp | 55 | ||||
-rw-r--r-- | src/utility.h | 7 |
11 files changed, 298 insertions, 113 deletions
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index dd4a7b2ef..d3e193f9e 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -61,10 +61,11 @@ void set_default_settings() g_settings.setDefault("active_object_range", "2"); g_settings.setDefault("max_simultaneous_block_sends_per_client", "1"); g_settings.setDefault("max_simultaneous_block_sends_server_total", "4"); + g_settings.setDefault("water_moves", "true"); g_settings.setDefault("disable_water_climb", "true"); g_settings.setDefault("endless_water", "true"); - g_settings.setDefault("max_block_send_distance", "5"); - g_settings.setDefault("max_block_generate_distance", "5"); + g_settings.setDefault("max_block_send_distance", "6"); + g_settings.setDefault("max_block_generate_distance", "6"); g_settings.setDefault("time_send_interval", "20"); g_settings.setDefault("time_speed", "96"); g_settings.setDefault("server_unload_unused_sectors_timeout", "60"); diff --git a/src/main.cpp b/src/main.cpp index f36f17a1d..51d94aba4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -168,6 +168,8 @@ TODO: Check what goes wrong with caching map to disk (Kray) TODO: When server sees that client is removing an inexistent block or
adding a block to an existent position, resend the MapBlock.
+TODO: Generate map from the area the client is looking at
+
Objects:
TODO: Better handling of objects and mobs
@@ -1409,10 +1411,11 @@ int main(int argc, char *argv[]) video::E_DRIVER_TYPE driverType;
#ifdef _WIN32
- //driverType = video::EDT_DIRECT3D9; // Doesn't seem to work
+ //driverType = video::EDT_DIRECT3D9;
driverType = video::EDT_OPENGL;
#else
driverType = video::EDT_OPENGL;
+ //driverType = video::EDT_BURNINGSVIDEO;
#endif
// create device and exit if creation failed
diff --git a/src/map.cpp b/src/map.cpp index c290f69e9..d15ac0a7b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1317,17 +1317,26 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): */ { + dstream<<"Generating map point attribute lists"<<std::endl; + PointAttributeList *list_baseheight = m_padb.getList("hm_baseheight"); PointAttributeList *list_randmax = m_padb.getList("hm_randmax"); PointAttributeList *list_randfactor = m_padb.getList("hm_randfactor"); PointAttributeList *list_plants_amount = m_padb.getList("plants_amount"); PointAttributeList *list_caves_amount = m_padb.getList("caves_amount"); + + /* + NOTE: BEWARE: Too big amount of these will make map generation + slow. Especially those that are read by every block emerge. + */ - for(u32 i=0; i<3000; i++) + for(u32 i=0; i<15000; i++) { - u32 lim = MAP_GENERATION_LIMIT; - if(i < 200) - lim = 1000; + /*u32 lim = MAP_GENERATION_LIMIT; + if(i < 400) + lim = 2000;*/ + + u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 15000; v3s16 p( -lim + myrand()%(lim*2), @@ -1356,6 +1365,24 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): plants_amount = 0.0; } + + list_plants_amount->addPoint(p, Attribute(plants_amount)); + } + + for(u32 i=0; i<1000; i++) + { + /*u32 lim = MAP_GENERATION_LIMIT; + if(i < 400) + lim = 2000;*/ + + u32 lim = 500 + MAP_GENERATION_LIMIT * i / 1000; + + v3s16 p( + -lim + myrand()%(lim*2), + 0, + -lim + myrand()%(lim*2) + ); + float caves_amount = 0; if(myrand()%5 == 0) { @@ -1370,20 +1397,21 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): caves_amount = 0.05; } - list_plants_amount->addPoint(p, Attribute(plants_amount)); list_caves_amount->addPoint(p, Attribute(caves_amount)); } -#if 1 - for(u32 i=0; i<3000; i++) + + for(u32 i=0; i<5000; i++) { - u32 lim = MAP_GENERATION_LIMIT; - if(i < 100) - lim = 1000; + /*u32 lim = MAP_GENERATION_LIMIT; + if(i < 400) + lim = 2000;*/ + + u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 5000; v3s16 p( - -lim + myrand()%(lim*2), + -lim + (myrand()%(lim*2)), 0, - -lim + myrand()%(lim*2) + -lim + (myrand()%(lim*2)) ); /*s32 bh_i = (myrand()%200) - 50; @@ -1404,13 +1432,13 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): if(myrand()%4 == 0) { baseheight = 100; - randmax = 100; + randmax = 50; randfactor = 0.63; } - else if(myrand()%5 == 0) + else if(myrand()%6 == 0) { baseheight = 200; - randmax = 200; + randmax = 100; randfactor = 0.66; } else if(myrand()%4 == 0) @@ -1423,7 +1451,7 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): { baseheight = 0; randmax = 30; - randfactor = 0.60; + randfactor = 0.63; } else { @@ -1436,68 +1464,16 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): list_randmax->addPoint(p, Attribute(randmax)); list_randfactor->addPoint(p, Attribute(randfactor)); } -#endif /*list_baseheight->addPoint(v3s16(0,0,0), Attribute(5)); list_randmax->addPoint(v3s16(0,0,0), Attribute(20)); list_randfactor->addPoint(v3s16(0,0,0), Attribute(0.6));*/ - } - -#if 0 - { - PointAttributeList *palist = m_padb.getList("hm_baseheight"); - - { - v3s16 p(0,0,0); - Attribute attr; - attr.set("5"); - palist->addPoint(p, attr); - } - /*{ - v3s16 p(-50,-50,0); - Attribute attr; - attr.set("-10"); - palist->addPoint(p, attr); - } - - { - v3s16 p(50,0,50); - Attribute attr; - attr.set("200"); - palist->addPoint(p, attr); - }*/ + // Easy spawn point + /*list_baseheight->addPoint(v3s16(0,0,0), Attribute(0)); + list_randmax->addPoint(v3s16(0,0,0), Attribute(10)); + list_randfactor->addPoint(v3s16(0,0,0), Attribute(0.65));*/ } -#endif -#if 0 - { - PointAttributeList *palist = m_padb.getList("plants_amount"); - - // Back - { - v3s16 p(0,0,-100); - Attribute attr; - attr.set("0"); - palist->addPoint(p, attr); - } - - // Front right - { - v3s16 p(100,0,100); - Attribute attr; - attr.set("2.0"); - palist->addPoint(p, attr); - } - - // Front left - { - v3s16 p(-100,0,100); - Attribute attr; - attr.set("0.2"); - palist->addPoint(p, attr); - } - } -#endif /* Try to load map; if not found, create a new one. @@ -1704,6 +1680,8 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) Get local attributes */ + //dstream<<"emergeSector(): Reading point attribute lists"<<std::endl; + // Get plant amount from attributes PointAttributeList *palist = m_padb.getList("plants_amount"); assert(palist); @@ -1712,6 +1690,8 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) float local_plants_amount = palist->getInterpolatedFloat(nodepos2d); + //dstream<<"emergeSector(): done."<<std::endl; + /* Generate sector heightmap */ @@ -1810,7 +1790,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) /* Add ravine (randomly) */ - if(m_params.ravines_amount != 0) + if(m_params.ravines_amount > 0.001) { if(myrand()%(s32)(200.0 / m_params.ravines_amount) == 0) { @@ -2061,13 +2041,32 @@ MapBlock * ServerMap::emergeBlock( bool some_part_underground = block_y * MAP_BLOCKSIZE <= highest_ground_y; + bool mostly_underwater_surface = false; + if(highest_ground_y < WATER_LEVEL + && some_part_underground && !completely_underground) + mostly_underwater_surface = true; + /* Get local attributes */ + + //dstream<<"emergeBlock(): Getting local attributes"<<std::endl; + + float caves_amount = 0; - v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; - PointAttributeList *list_caves_amount = m_padb.getList("caves_amount"); - float caves_amount = list_caves_amount->getInterpolatedFloat(nodepos2d); + { + /* + NOTE: BEWARE: Too big amount of attribute points slows verything + down by a lot. + 1 interpolation from 5000 points takes 2-3ms. + */ + //TimeTaker timer("emergeBlock() local attribute retrieval"); + v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; + PointAttributeList *list_caves_amount = m_padb.getList("caves_amount"); + caves_amount = list_caves_amount->getInterpolatedFloat(nodepos2d); + } + + //dstream<<"emergeBlock(): Done"<<std::endl; /* Generate dungeons @@ -2082,6 +2081,7 @@ MapBlock * ServerMap::emergeBlock( } // Fill table +#if 1 { /* Initialize orp and ors. Try to find if some neighboring @@ -2207,21 +2207,34 @@ MapBlock * ServerMap::emergeBlock( continue_generating: /* - Don't always generate dungeon + Choose whether to actually generate dungeon */ bool do_generate_dungeons = true; // Don't generate if no part is underground if(!some_part_underground) + { do_generate_dungeons = false; - // If block is partly underground, caves are generated. + } + // Don't generate if mostly underwater surface + else if(mostly_underwater_surface) + { + do_generate_dungeons = false; + } + // Partly underground = cave else if(!completely_underground) - do_generate_dungeons = (rand() % 100 <= (u32)(caves_amount*100)); - // Always continue if found existing dungeons underground + { + do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100)); + } + // Found existing dungeon underground else if(found_existing && completely_underground) - do_generate_dungeons = true; - // If underground and no dungeons found + { + do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100)); + } + // Underground and no dungeons found else - do_generate_dungeons = (rand() % 2 == 0); + { + do_generate_dungeons = (rand() % 300 <= (s32)(caves_amount*100)); + } if(do_generate_dungeons) { @@ -2271,10 +2284,11 @@ continue_generating: } } } +#endif // Set to true if has caves. // Set when some non-air is changed to air when making caves. - bool has_caves = false; + bool has_dungeons = false; /* Apply temporary cave data to block @@ -2296,7 +2310,7 @@ continue_generating: if(is_ground_content(n.d)) { // Has now caves - has_caves = true; + has_dungeons = true; // Set air to node n.d = CONTENT_AIR; } @@ -2316,7 +2330,7 @@ continue_generating: Force lighting update if some part of block is partly underground and has caves. */ - /*if(some_part_underground && !completely_underground && has_caves) + /*if(some_part_underground && !completely_underground && has_dungeons) { //dstream<<"Half-ground caves"<<std::endl; lighting_invalidated_blocks[block->getPos()] = block; @@ -2336,9 +2350,9 @@ continue_generating: /* Add meseblocks */ - for(s16 i=0; i< underground_level/4 + 1; i++) + for(s16 i=0; i<underground_level/4 + 1; i++) { - if(myrand()%10 == 0) + if(myrand()%50 == 0) { v3s16 cp( (myrand()%(MAP_BLOCKSIZE-2))+1, @@ -2697,7 +2711,27 @@ continue_generating: changed_blocks.insert(block->getPos(), block); } - + + /* + Debug information + */ + if(0) + { + dstream + <<"lighting_invalidated_blocks.size()" + <<", has_dungeons" + <<", completely_ug" + <<", some_part_ug" + <<" "<<lighting_invalidated_blocks.size() + <<", "<<has_dungeons + <<", "<<completely_underground + <<", "<<some_part_underground + <<std::endl; + } + + /* + Debug mode operation + */ if(HAXMODE) { // Don't calculate lighting at all @@ -3412,6 +3446,17 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) if not seen on display */ + float range = 100000 * BS; + if(m_control.range_all == false) + range = m_control.wanted_range * BS; + + if(isBlockInSight(block->getPos(), camera_position, + camera_direction, range) == false) + { + continue; + } + +#if 0 v3s16 blockpos_nodes = block->getPosRelative(); // Block center position @@ -3434,8 +3479,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) { // If block is far away, don't draw it if(d > m_control.wanted_range * BS) - // This is nicer when fog is used - //if((dforward+d)/2 > m_control.wanted_range * BS) continue; } @@ -3460,7 +3503,23 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) if(cosangle < cos(FOV_ANGLE/2. * 4./3.)) continue; } +#endif + + v3s16 blockpos_nodes = block->getPosRelative(); + // Block center position + v3f blockpos( + ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS, + ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS, + ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS + ); + + // Block position relative to camera + v3f blockpos_relative = blockpos - camera_position; + + // Total distance + f32 d = blockpos_relative.getLength(); + /* Draw the faces of the block */ @@ -206,7 +206,7 @@ public: their differing fetch methods. */ virtual MapSector * emergeSector(v2s16 p) = 0; - + // Returns InvalidPositionException if not found MapBlock * getBlockNoCreate(v3s16 p); // Returns NULL if not found diff --git a/src/materials.cpp b/src/materials.cpp index 1c177e9a3..bc39619fc 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -13,9 +13,9 @@ void setStoneLikeDiggingProperties(u8 material, float toughness) DiggingProperties(true, 15.0*toughness, 0)); g_material_properties[material].setDiggingProperties("WPick", - DiggingProperties(true, 1.5*toughness, 65535./20.*toughness)); + DiggingProperties(true, 1.5*toughness, 65535./30.*toughness)); g_material_properties[material].setDiggingProperties("STPick", - DiggingProperties(true, 0.7*toughness, 65535./60.*toughness)); + DiggingProperties(true, 0.7*toughness, 65535./100.*toughness)); /*g_material_properties[material].setDiggingProperties("MesePick", DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/ diff --git a/src/player.cpp b/src/player.cpp index 3c06283a0..72e44f0e0 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -46,6 +46,20 @@ Player::~Player() // Y direction is ignored void Player::accelerate(v3f target_speed, f32 max_increase) { + v3f d_wanted = target_speed - m_speed; + d_wanted.Y = 0; + f32 dl_wanted = d_wanted.getLength(); + f32 dl = dl_wanted; + if(dl > max_increase) + dl = max_increase; + + v3f d = d_wanted.normalize() * dl; + + m_speed.X += d.X; + m_speed.Z += d.Z; + //m_speed += d; + +#if 0 // old code if(m_speed.X < target_speed.X - max_increase) m_speed.X += max_increase; else if(m_speed.X > target_speed.X + max_increase) @@ -63,6 +77,7 @@ void Player::accelerate(v3f target_speed, f32 max_increase) m_speed.Z = target_speed.Z; else if(m_speed.Z > target_speed.Z) m_speed.Z = target_speed.Z; +#endif } /* @@ -209,7 +224,7 @@ void LocalPlayer::move(f32 dtime, Map &map) position += m_speed * dtime; // Skip collision detection if player is non-local - if(isLocal() == false) + if(isLocal() == false || HAXMODE) { setPosition(position); return; @@ -286,10 +301,6 @@ void LocalPlayer::move(f32 dtime, Map &map) { // Doing nothing here will block the player from // walking over map borders - - // Go over borders in debug mode - if(HAXMODE) - continue; } core::aabbox3d<f32> nodebox = Map::getNodeBox( diff --git a/src/server.cpp b/src/server.cpp index da643339b..3b3dfb657 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -328,6 +328,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, v3s16 center_nodepos = floatToInt(playerpos); v3s16 center = getNodeBlockPos(center_nodepos); + + // Camera position and direction + v3f camera_pos = + playerpos + v3f(0, BS+BS/2, 0); + v3f camera_dir = v3f(0,0,1); + camera_dir.rotateYZBy(player->getPitch()); + camera_dir.rotateXZBy(player->getYaw()); /* Get the starting value of the block finder radius. @@ -496,6 +503,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3) generate = false; } + + /* + Don't draw if not in sight + */ + + if(isBlockInSight(p, camera_pos, camera_dir, 10000*BS) == false) + { + continue; + } /* Don't send already sent blocks @@ -511,6 +527,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, { /* Ignore block if it is not at ground surface + but don't ignore water surface blocks */ v2s16 p2d(p.X*MAP_BLOCKSIZE + MAP_BLOCKSIZE/2, p.Z*MAP_BLOCKSIZE + MAP_BLOCKSIZE/2); @@ -519,7 +536,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, if(y > GROUNDHEIGHT_VALID_MINVALUE) { f32 by = p.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE/2; - if(fabs(by - y) > MAP_BLOCKSIZE + MAP_BLOCKSIZE/3) + if(fabs(by - y) > MAP_BLOCKSIZE + MAP_BLOCKSIZE/3 + && fabs(by - WATER_LEVEL) >= MAP_BLOCKSIZE) continue; } } @@ -839,8 +857,11 @@ void RemoteClient::GotBlock(v3s16 p) if(m_blocks_sending.find(p) != NULL) m_blocks_sending.remove(p); else - dstream<<"RemoteClient::GotBlock(): Didn't find in" - " m_blocks_sending"<<std::endl; + { + /*dstream<<"RemoteClient::GotBlock(): Didn't find in" + " m_blocks_sending"<<std::endl;*/ + m_excess_gotblocks++; + } m_blocks_sent.insert(p, true); } @@ -1118,6 +1139,7 @@ void Server::AsyncRunStep() /* Flow water */ + if(g_settings.getBool("water_moves") == true) { float interval; @@ -3040,12 +3062,12 @@ Player *Server::emergePlayer(const char *name, const char *password) v2s16 nodepos; f32 groundheight = 0; // Try to find a good place a few times - for(s32 i=0; i<100; i++) + for(s32 i=0; i<500; i++) { - s32 range = 1 + i*4; + s32 range = 1 + i; // We're going to try to throw the player to this position - nodepos = v2s16(-range/2 + (myrand()%range), - -range/2 + (myrand()%range)); + nodepos = v2s16(-range + (myrand()%(range*2)), + -range + (myrand()%(range*2))); v2s16 sectorpos = getNodeSectorPos(nodepos); // Get sector m_env.getMap().emergeSector(sectorpos); @@ -3055,23 +3077,38 @@ Player *Server::emergePlayer(const char *name, const char *password) assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE); // Don't go underwater if(groundheight < WATER_LEVEL) + { + //dstream<<"-> Underwater"<<std::endl; continue; + } +#if 0 // Doesn't work, generating blocks is a bit too complicated for doing here + // Get block at point + v3s16 nodepos3d; + nodepos3d = v3s16(nodepos.X, groundheight+1, nodepos.Y); + v3s16 blockpos = getNodeBlockPos(nodepos3d); + ((ServerMap*)(&m_env.getMap()))->emergeBlock(blockpos); // Don't go inside ground try{ - v3s16 footpos(nodepos.X, groundheight+1, nodepos.Y); - v3s16 headpos(nodepos.X, groundheight+2, nodepos.Y); + /*v3s16 footpos(nodepos.X, groundheight+1, nodepos.Y); + v3s16 headpos(nodepos.X, groundheight+2, nodepos.Y);*/ + v3s16 footpos = nodepos3d + v3s16(0,0,0); + v3s16 headpos = nodepos3d + v3s16(0,1,0); if(m_env.getMap().getNode(footpos).d != CONTENT_AIR || m_env.getMap().getNode(headpos).d != CONTENT_AIR) { + dstream<<"-> Inside ground"<<std::endl; // In ground continue; } }catch(InvalidPositionException &e) { + dstream<<"-> Invalid position"<<std::endl; // Ignore invalid position continue; } +#endif // Found a good place + dstream<<"Searched through "<<i<<" places."<<std::endl; break; } #endif diff --git a/src/server.h b/src/server.h index 099be9e14..3d7d133fc 100644 --- a/src/server.h +++ b/src/server.h @@ -231,7 +231,8 @@ public: u8 pending_serialization_version; RemoteClient(): - m_time_from_building(9999) + m_time_from_building(9999), + m_excess_gotblocks(0) { peer_id = 0; serialization_version = SER_FMT_VER_INVALID; @@ -295,7 +296,9 @@ public: <<", m_blocks_sent.size()="<<m_blocks_sent.size() <<", m_blocks_sending.size()="<<m_blocks_sending.size() <<", m_nearest_unsent_d="<<m_nearest_unsent_d + <<", m_excess_gotblocks="<<m_excess_gotblocks <<std::endl; + m_excess_gotblocks = 0; } // Time from last placing or removing blocks @@ -347,6 +350,15 @@ private: */ core::map<v3s16, float> m_blocks_sending; JMutex m_blocks_sending_mutex; + + /* + Count of excess GotBlocks(). + There is an excess amount because the client sometimes + gets a block so late that the server sends it again, + and the client then sends two GOTBLOCKs. + This is resetted by PrintInfo() + */ + u32 m_excess_gotblocks; }; /*struct ServerSettings diff --git a/src/test.cpp b/src/test.cpp index d78c62120..1a172e4f5 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -748,7 +748,7 @@ struct TestHeightmap padb.getList("hm_baseheight")->addPoint(v2s16(BS1*2,BS1), Attribute(0)); padb.getList("hm_randmax")->addPoint(v2s16(BS1*2,BS1), Attribute(30)); - padb.getList("hm_randfactor")->addPoint(v2s16(BS1*2,BS1), Attribute(0.9)); + padb.getList("hm_randfactor")->addPoint(v2s16(BS1*2,BS1), Attribute(0.63)); UnlimitedHeightmap hm1(BS1, &padb); diff --git a/src/utility.cpp b/src/utility.cpp index d6ca48153..6f16b7658 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" #include "irrlichtwrapper.h" #include "gettime.h" +#include "mapblock.h" TimeTaker::TimeTaker(const char *name, u32 *result) { @@ -328,4 +329,58 @@ lopuks sit otetaan a/b } #endif +/* + blockpos: position of block in block coordinates + camera_pos: position of camera in nodes + camera_dir: an unit vector pointing to camera direction + range: viewing range +*/ +bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range) +{ + v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE; + + // Block center position + v3f blockpos( + ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS, + ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS, + ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS + ); + + // Block position relative to camera + v3f blockpos_relative = blockpos - camera_pos; + + // Distance in camera direction (+=front, -=back) + f32 dforward = blockpos_relative.dotProduct(camera_dir); + + // Total distance + f32 d = blockpos_relative.getLength(); + + // If block is far away, it's not in sight + if(d > range * BS) + return false; + + // Maximum radius of a block + f32 block_max_radius = 0.5*1.44*1.44*MAP_BLOCKSIZE*BS; + + // If block is (nearly) touching the camera, don't + // bother validating further (that is, render it anyway) + if(d > block_max_radius * 1.5) + { + // Cosine of the angle between the camera direction + // and the block direction (camera_dir is an unit vector) + f32 cosangle = dforward / d; + + // Compensate for the size of the block + // (as the block has to be shown even if it's a bit off FOV) + // This is an estimate. + cosangle += block_max_radius / dforward; + + // If block is not in the field of view, skip it + //if(cosangle < cos(FOV_ANGLE/2)) + if(cosangle < cos(FOV_ANGLE/2. * 4./3.)) + return false; + } + + return true; +} diff --git a/src/utility.h b/src/utility.h index 28cc95ddd..c4f45ba0f 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1574,5 +1574,12 @@ private: core::map<std::string, PointAttributeList*> m_lists; }; +/* + Miscellaneous functions +*/ + +bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range); + + #endif |