From 7773e68c2a42659b4a34af56e1fc799ffc9362ed Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 18 Jun 2011 12:42:17 +0300 Subject: [PATCH] farmesh is now usable. --- src/client.h | 2 + src/defaultsettings.cpp | 4 +- src/farmesh.cpp | 230 +++++++++++++++++++++++++++++++++------- src/farmesh.h | 22 ++-- src/game.cpp | 24 +++-- src/map.cpp | 37 +++++-- src/map.h | 16 +-- 7 files changed, 259 insertions(+), 76 deletions(-) diff --git a/src/client.h b/src/client.h index 1bfbe62..a1b1c66 100644 --- a/src/client.h +++ b/src/client.h @@ -450,6 +450,8 @@ private: InventoryContext m_inventory_context; Queue m_client_event_queue; + + friend class FarMesh; }; #endif // !SERVER diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 8ae5694..209d20b 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -49,7 +49,7 @@ void set_default_settings() g_settings.setDefault("wanted_fps", "30"); g_settings.setDefault("fps_max", "60"); g_settings.setDefault("viewing_range_nodes_max", "300"); - g_settings.setDefault("viewing_range_nodes_min", "35"); + g_settings.setDefault("viewing_range_nodes_min", "28"); g_settings.setDefault("screenW", "800"); g_settings.setDefault("screenH", "600"); g_settings.setDefault("address", ""); @@ -67,7 +67,7 @@ void set_default_settings() g_settings.setDefault("continuous_forward", "false"); g_settings.setDefault("fast_move", "false"); g_settings.setDefault("invert_mouse", "false"); - g_settings.setDefault("enable_farmesh", "false"); + g_settings.setDefault("enable_farmesh", "true"); g_settings.setDefault("enable_clouds", "true"); // Server stuff diff --git a/src/farmesh.cpp b/src/farmesh.cpp index e484796..3faac16 100644 --- a/src/farmesh.cpp +++ b/src/farmesh.cpp @@ -27,26 +27,52 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include "noise.h" #include "map.h" +#include "client.h" + +/* + Temporarily exposed map generator stuff + Should only be used for testing +*/ +extern double base_rock_level_2d(u64 seed, v2s16 p); +extern double get_mud_add_amount(u64 seed, v2s16 p); +extern bool get_have_sand(u64 seed, v2s16 p2d); +extern double tree_amount_2d(u64 seed, v2s16 p); + FarMesh::FarMesh( scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, - u64 seed + u64 seed, + Client *client ): scene::ISceneNode(parent, mgr, id), m_seed(seed), m_camera_pos(0,0), - m_time(0) + m_time(0), + m_client(client) { dstream<<__FUNCTION_NAME<getVideoDriver(); - m_material.setFlag(video::EMF_LIGHTING, false); - m_material.setFlag(video::EMF_BACK_FACE_CULLING, true); - m_material.setFlag(video::EMF_BILINEAR_FILTER, false); - m_material.setFlag(video::EMF_FOG_ENABLE, false); - //m_material.setFlag(video::EMF_ANTI_ALIASING, true); - //m_material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; + m_materials[0].setFlag(video::EMF_LIGHTING, false); + m_materials[0].setFlag(video::EMF_BACK_FACE_CULLING, true); + //m_materials[0].setFlag(video::EMF_BACK_FACE_CULLING, false); + m_materials[0].setFlag(video::EMF_BILINEAR_FILTER, false); + m_materials[0].setFlag(video::EMF_FOG_ENABLE, false); + //m_materials[0].setFlag(video::EMF_ANTI_ALIASING, true); + //m_materials[0].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; + m_materials[0].setFlag(video::EMF_FOG_ENABLE, true); + + m_materials[1].setFlag(video::EMF_LIGHTING, false); + m_materials[1].setFlag(video::EMF_BACK_FACE_CULLING, false); + m_materials[1].setFlag(video::EMF_BILINEAR_FILTER, false); + m_materials[1].setFlag(video::EMF_FOG_ENABLE, false); + m_materials[1].setTexture + (0, driver->getTexture(getTexturePath("treeprop.png").c_str())); + m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + m_materials[1].setFlag(video::EMF_FOG_ENABLE, true); m_box = core::aabbox3d(-BS*1000000,-BS*31000,-BS*1000000, BS*1000000,BS*31000,BS*1000000); @@ -58,13 +84,24 @@ FarMesh::~FarMesh() dstream<<__FUNCTION_NAME<registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); - //SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); - SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX); + SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); + //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX); } ISceneNode::OnRegisterSceneNode(); @@ -73,18 +110,34 @@ void FarMesh::OnRegisterSceneNode() #define MYROUND(x) (x > 0.0 ? (int)x : (int)x - 1) // Temporary hack -core::map g_heights; - -float ground_height(u64 seed, v2s16 p2d) +struct HeightPoint { - core::map::Node *n = g_heights.find(p2d); + float gh; // ground height + float ma; // mud amount + float have_sand; + float tree_amount; +}; +core::map g_heights; + +HeightPoint ground_height(u64 seed, v2s16 p2d) +{ + core::map::Node *n = g_heights.find(p2d); if(n) return n->getValue(); - float avg_mud_amount = 4; - float gh = BS*base_rock_level_2d(seed, p2d) + avg_mud_amount*BS; - //gh *= 10; - g_heights[p2d] = gh; - return gh; + HeightPoint hp; + hp.gh = BS*base_rock_level_2d(seed, p2d); + hp.gh -= BS*2; // Lower a bit so that it is not that much in the way + hp.ma = BS*get_mud_add_amount(seed, p2d); + hp.have_sand = get_have_sand(seed, p2d); + if(hp.gh > BS*WATER_LEVEL) + hp.tree_amount = tree_amount_2d(seed, p2d); + else + hp.tree_amount = 0; + // No mud has been added if mud amount is less than 2 + if(hp.ma < 2.0*BS) + hp.ma = 0.0; + g_heights[p2d] = hp; + return hp; } void FarMesh::render() @@ -93,16 +146,17 @@ void FarMesh::render() /*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT) return;*/ - /*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID) - return;*/ - if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SKY_BOX) + if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID) return; + /*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SKY_BOX) + return;*/ driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - driver->setMaterial(m_material); - const s16 grid_radius_i = 12; - const float grid_size = BS*50; + //const s16 grid_radius_i = 12; + //const float grid_size = BS*50; + const s16 grid_radius_i = 20; + const float grid_size = BS*MAP_BLOCKSIZE; const v2f grid_speed(-BS*0, 0); // Position of grid noise origin in world coordinates @@ -125,10 +179,19 @@ void FarMesh::render() for(s16 zi=-grid_radius_i; zi -dd && zi < dd && xi > -dd && xi < dd) + continue;*/ + v2s16 p_in_noise_i( xi+center_of_drawing_in_noise_i.X, zi+center_of_drawing_in_noise_i.Y ); + + // If sector was drawn, don't draw it this way + if(m_client->m_env.getClientMap().sectorWasDrawn(p_in_noise_i)) + continue; /*if((p_in_noise_i.X + p_in_noise_i.Y)%2==0) continue;*/ @@ -159,32 +222,50 @@ void FarMesh::render() (float)(p_in_noise_i.Y+0)*grid_size/BS/100, m_seed, 3, 0.5);*/ - float noise[4]; - noise[0] = ground_height(m_seed, v2s16( + HeightPoint hps[5]; + hps[0] = ground_height(m_seed, v2s16( (p_in_noise_i.X+0)*grid_size/BS, (p_in_noise_i.Y+0)*grid_size/BS)); - noise[1] = ground_height(m_seed, v2s16( + hps[1] = ground_height(m_seed, v2s16( (p_in_noise_i.X+0)*grid_size/BS, (p_in_noise_i.Y+1)*grid_size/BS)); - noise[2] = ground_height(m_seed, v2s16( + hps[2] = ground_height(m_seed, v2s16( (p_in_noise_i.X+1)*grid_size/BS, (p_in_noise_i.Y+1)*grid_size/BS)); - noise[3] = ground_height(m_seed, v2s16( + hps[3] = ground_height(m_seed, v2s16( (p_in_noise_i.X+1)*grid_size/BS, (p_in_noise_i.Y+0)*grid_size/BS)); - + v2s16 centerpoint( + (p_in_noise_i.X+0)*grid_size/BS+MAP_BLOCKSIZE/2, + (p_in_noise_i.Y+0)*grid_size/BS+MAP_BLOCKSIZE/2); + hps[4] = ground_height(m_seed, centerpoint); + + float noise[5]; float h_min = BS*65535; float h_max = -BS*65536; - for(u32 i=0; i<4; i++) + float ma_avg = 0; + float h_avg = 0; + u32 have_sand_count = 0; + float tree_amount_avg = 0; + for(u32 i=0; i<5; i++) { + noise[i] = hps[i].gh + hps[i].ma; if(noise[i] < h_min) h_min = noise[i]; if(noise[i] > h_max) h_max = noise[i]; + ma_avg += hps[i].ma; + h_avg += noise[i]; + if(hps[i].have_sand) + have_sand_count++; + tree_amount_avg += hps[i].tree_amount; } + ma_avg /= 5.0; + h_avg /= 5.0; + tree_amount_avg /= 5.0; + float steepness = (h_max - h_min)/grid_size; - float h_avg = (noise[0]+noise[1]+noise[2]+noise[3])/4.0; float light_f = noise[0]+noise[1]-noise[2]-noise[3]; light_f /= 100; if(light_f < -1.0) light_f = -1.0; @@ -198,7 +279,9 @@ void FarMesh::render() // Detect water if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS) { - c = video::SColor(128,59,86,146); + //c = video::SColor(255,59,86,146); + c = video::SColor(255,82,120,204); + /*// Set to water level for(u32 i=0; i<4; i++) { @@ -207,10 +290,33 @@ void FarMesh::render() }*/ light_f = 0; } + // Steep cliffs else if(steepness > 2.0) - c = video::SColor(128,128,128,128); + { + c = video::SColor(255,128,128,128); + } + // Basic ground else - c = video::SColor(128,107,134,51); + { + if(ma_avg < 2.0*BS) + { + c = video::SColor(255,128,128,128); + } + else + { + if(h_avg <= 2.5*BS && have_sand_count >= 2) + c = video::SColor(255,210,194,156); + else + { + /*// Trees if there are over 0.01 trees per MapNode + if(tree_amount_avg > 0.01) + c = video::SColor(255,50,128,50); + else + c = video::SColor(255,107,134,51);*/ + c = video::SColor(255,107,134,51); + } + } + } // Set to water level for(u32 i=0; i<4; i++) @@ -223,7 +329,9 @@ void FarMesh::render() if(b < 0) b = 0; if(b > 2) b = 2; - c = video::SColor(128, b*c.getRed(), b*c.getGreen(), b*c.getBlue()); + c = video::SColor(255, b*c.getRed(), b*c.getGreen(), b*c.getBlue()); + + driver->setMaterial(m_materials[0]); video::S3DVertex vertices[4] = { @@ -235,9 +343,54 @@ void FarMesh::render() u16 indices[] = {0,1,2,2,3,0}; driver->drawVertexPrimitiveList(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); + + // Add some trees if appropriate + if(tree_amount_avg > 0.006 && steepness < 1.0 + && ma_avg >= 2.0*BS && have_sand_count <= 2) + { + driver->setMaterial(m_materials[1]); + + float b = m_brightness; + c = video::SColor(255, b*255, b*255, b*255); + + { + video::S3DVertex vertices[4] = + { + video::S3DVertex(p0.X,noise[0],p0.Y, + 0,0,0, c, 0,1), + video::S3DVertex(p0.X,noise[1]+BS*MAP_BLOCKSIZE,p0.Y, + 0,0,0, c, 0,0), + video::S3DVertex(p1.X,noise[2]+BS*MAP_BLOCKSIZE,p1.Y, + 0,0,0, c, 1,0), + video::S3DVertex(p1.X,noise[3],p1.Y, + 0,0,0, c, 1,1), + }; + u16 indices[] = {0,1,2,2,3,0}; + driver->drawVertexPrimitiveList(vertices, 4, indices, 2, + video::EVT_STANDARD, scene::EPT_TRIANGLES, + video::EIT_16BIT); + } + { + video::S3DVertex vertices[4] = + { + video::S3DVertex(p1.X,noise[0],p0.Y, + 0,0,0, c, 0,1), + video::S3DVertex(p1.X,noise[1]+BS*MAP_BLOCKSIZE,p0.Y, + 0,0,0, c, 0,0), + video::S3DVertex(p0.X,noise[2]+BS*MAP_BLOCKSIZE,p1.Y, + 0,0,0, c, 1,0), + video::S3DVertex(p0.X,noise[3],p1.Y, + 0,0,0, c, 1,1), + }; + u16 indices[] = {0,1,2,2,3,0}; + driver->drawVertexPrimitiveList(vertices, 4, indices, 2, + video::EVT_STANDARD, scene::EPT_TRIANGLES, + video::EIT_16BIT); + } + } } - driver->clearZBuffer(); + //driver->clearZBuffer(); } void FarMesh::step(float dtime) @@ -251,3 +404,4 @@ void FarMesh::update(v2f camera_p, float brightness) m_brightness = brightness; } + diff --git a/src/farmesh.h b/src/farmesh.h index 12f5879..aea8065 100644 --- a/src/farmesh.h +++ b/src/farmesh.h @@ -27,6 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" +#define FARMESH_MATERIAL_COUNT 2 + +class Client; + class FarMesh : public scene::ISceneNode { public: @@ -34,7 +38,8 @@ public: scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, - u64 seed + u64 seed, + Client *client ); ~FarMesh(); @@ -52,15 +57,9 @@ public: return m_box; } - virtual u32 getMaterialCount() const - { - return 1; - } + virtual u32 getMaterialCount() const; - virtual video::SMaterial& getMaterial(u32 i) - { - return m_material; - } + virtual video::SMaterial& getMaterial(u32 i); /* Other stuff @@ -71,13 +70,14 @@ public: void update(v2f camera_p, float brightness); private: - video::SMaterial m_material; + video::SMaterial m_materials[FARMESH_MATERIAL_COUNT]; core::aabbox3d m_box; float m_cloud_y; float m_brightness; - u32 m_seed; + u64 m_seed; v2f m_camera_pos; float m_time; + Client *m_client; }; #endif diff --git a/src/game.cpp b/src/game.cpp index 7ad7746..237867b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -599,9 +599,9 @@ void update_skybox(video::IVideoDriver* driver, skybox->remove(); } - // Disable skybox if FarMesh is enabled + /*// Disable skybox if FarMesh is enabled if(g_settings.getBool("enable_farmesh")) - return; + return;*/ if(brightness >= 0.5) { @@ -836,7 +836,7 @@ void the_game( FarMesh *farmesh = NULL; if(g_settings.getBool("enable_farmesh")) { - farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed()); + farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed(), &client); } /* @@ -1844,11 +1844,19 @@ void the_game( if(g_settings.getBool("enable_fog") == true) { - f32 range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5; - if(draw_control.range_all) - range = 100000*BS; - if(range < 50*BS) - range = range * 0.5 + 25*BS; + f32 range; + if(farmesh) + { + range = BS*MAP_BLOCKSIZE*20; + } + else + { + range = draw_control.wanted_range*BS + MAP_BLOCKSIZE*BS*1.5; + if(draw_control.range_all) + range = 100000*BS; + if(range < 50*BS) + range = range * 0.5 + 25*BS; + } driver->setFog( bgcolor, diff --git a/src/map.cpp b/src/map.cpp index 9a6cb00..5cea4eb 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2129,6 +2129,16 @@ double get_mud_add_amount(u64 seed, v2s16 p) seed+91013, 3, 0.55)); } +bool get_have_sand(u64 seed, v2s16 p2d) +{ + // Determine whether to have sand here + double sandnoise = noise2d_perlin( + 0.5+(float)p2d.X/500, 0.5+(float)p2d.Y/500, + seed+59420, 3, 0.50); + + return (sandnoise > -0.15); +} + /* Adds random objects to block, depending on the content of the block */ @@ -3118,12 +3128,7 @@ void makeChunk(ChunkMakeData *data) // Node position in 2d v2s16 p2d = data->sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z); - // Determine whether to have sand here - double sandnoise = noise2d_perlin( - 0.5+(float)p2d.X/500, 0.5+(float)p2d.Y/500, - data->seed+59420, 3, 0.50); - - bool have_sand = (sandnoise > -0.15); + bool have_sand = get_have_sand(data->seed, p2d); if(have_sand == false) continue; @@ -5658,6 +5663,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) DSTACK(__FUNCTION_NAME); bool is_transparent_pass = pass == scene::ESNRP_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. @@ -5706,9 +5719,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) u32 blocks_would_have_drawn = 0; u32 blocks_drawn = 0; - //NOTE: The sectors map should be locked but we're not doing it - // because it'd cause too much delays - int timecheck_counter = 0; core::map::Iterator si; si = m_sectors.getIterator(); @@ -5748,6 +5758,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) /* Draw blocks */ + + u32 sector_blocks_drawn = 0; core::list< MapBlock * >::Iterator i; for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) @@ -5840,7 +5852,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) && m_control.range_all == false && d > m_control.wanted_min_range * BS) continue; + blocks_drawn++; + sector_blocks_drawn++; u32 c = mesh->getMeshBufferCount(); @@ -5866,6 +5880,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } } } // foreach sectorblocks + + if(sector_blocks_drawn != 0) + { + m_last_drawn_sectors[sp] = true; + } } m_control.blocks_drawn = blocks_drawn; diff --git a/src/map.h b/src/map.h index e74f89b..691f3bd 100644 --- a/src/map.h +++ b/src/map.h @@ -41,13 +41,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapchunk.h" #include "nodemetadata.h" -/* - Temporarily exposed map generator stuff - Should only be used for testing -*/ - -double base_rock_level_2d(u64 seed, v2s16 p); - /* MapEditEvent */ @@ -751,6 +744,12 @@ public: // For debug printing virtual void PrintInfo(std::ostream &out); + // Check if sector was drawn on last render() + bool sectorWasDrawn(v2s16 p) + { + return (m_last_drawn_sectors.find(p) != NULL); + } + private: Client *m_client; @@ -765,7 +764,8 @@ private: v3f m_camera_position; v3f m_camera_direction; JMutex m_camera_mutex; - + + core::map m_last_drawn_sectors; }; #endif