]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/clientmap.cpp
Add disable_jump and fall_damage_add_percent node groups
[dragonfireclient.git] / src / clientmap.cpp
index 15a790f9a314e6046ad8c1a7a05f6f613ed596b5..4d14cc1a24bfdb36acbcc7b82a87f00faf2e485b 100644 (file)
@@ -3,16 +3,16 @@ Minetest-c55
 Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU Lesser General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "client.h"
 #include "mapblock_mesh.h"
 #include <IMaterialRenderer.h>
+#include <matrix4.h>
 #include "log.h"
 #include "mapsector.h"
 #include "main.h" // dout_client, g_settings
@@ -28,6 +29,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock.h"
 #include "profiler.h"
 #include "settings.h"
+#include "util/mathconstants.h"
+
+#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
 ClientMap::ClientMap(
                Client *client,
@@ -43,7 +47,7 @@ ClientMap::ClientMap(
        m_control(control),
        m_camera_position(0,0,0),
        m_camera_direction(0,0,1),
-       m_camera_fov(PI)
+       m_camera_fov(M_PI)
 {
        m_camera_mutex.Init();
        assert(m_camera_mutex.IsInitialized());
@@ -189,7 +193,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
        */
        float animation_time = m_client->getAnimationTime();
        int crack = m_client->getCrackLevel();
-       u32 daynight_ratio = m_client->getDayNightRatio();
+       u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
 
        m_camera_mutex.Lock();
        v3f camera_position = m_camera_position;
@@ -321,6 +325,16 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                                Occlusion culling
                        */
 
+                       // No occlusion culling when free_move is on and camera is
+                       // inside ground
+                       bool occlusion_culling_enabled = true;
+                       if(g_settings->getBool("free_move")){
+                               MapNode n = getNodeNoEx(cam_pos_nodes);
+                               if(n.getContent() == CONTENT_IGNORE ||
+                                               nodemgr->get(n).solidness == 2)
+                                       occlusion_culling_enabled = false;
+                       }
+
                        v3s16 cpn = block->getPos() * MAP_BLOCKSIZE;
                        cpn += v3s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2);
                        float step = BS*1;
@@ -331,6 +345,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        s16 bs2 = MAP_BLOCKSIZE/2 + 1;
                        u32 needed_count = 1;
                        if(
+                               occlusion_culling_enabled &&
                                isOccluded(this, spn, cpn + v3s16(0,0,0),
                                        step, stepfac, startoff, endoff, needed_count, nodemgr) &&
                                isOccluded(this, spn, cpn + v3s16(bs2,bs2,bs2),
@@ -509,6 +524,183 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
 }
 
+static bool getVisibleBrightness(Map *map, v3f p0, v3f dir, float step,
+               float step_multiplier, float start_distance, float end_distance,
+               INodeDefManager *ndef, u32 daylight_factor, float sunlight_min_d,
+               int *result, bool *sunlight_seen)
+{
+       int brightness_sum = 0;
+       int brightness_count = 0;
+       float distance = start_distance;
+       dir.normalize();
+       v3f pf = p0;
+       pf += dir * distance;
+       int noncount = 0;
+       bool nonlight_seen = false;
+       bool allow_allowing_non_sunlight_propagates = false;
+       bool allow_non_sunlight_propagates = false;
+       // Check content nearly at camera position
+       {
+               v3s16 p = floatToInt(p0 /*+ dir * 3*BS*/, BS);
+               MapNode n = map->getNodeNoEx(p);
+               if(ndef->get(n).param_type == CPT_LIGHT &&
+                               !ndef->get(n).sunlight_propagates)
+                       allow_allowing_non_sunlight_propagates = true;
+       }
+       // If would start at CONTENT_IGNORE, start closer
+       {
+               v3s16 p = floatToInt(pf, BS);
+               MapNode n = map->getNodeNoEx(p);
+               if(n.getContent() == CONTENT_IGNORE){
+                       float newd = 2*BS;
+                       pf = p0 + dir * 2*newd;
+                       distance = newd;
+                       sunlight_min_d = 0;
+               }
+       }
+       for(int i=0; distance < end_distance; i++){
+               pf += dir * step;
+               distance += step;
+               step *= step_multiplier;
+               
+               v3s16 p = floatToInt(pf, BS);
+               MapNode n = map->getNodeNoEx(p);
+               if(allow_allowing_non_sunlight_propagates && i == 0 &&
+                               ndef->get(n).param_type == CPT_LIGHT &&
+                               !ndef->get(n).sunlight_propagates){
+                       allow_non_sunlight_propagates = true;
+               }
+               if(ndef->get(n).param_type != CPT_LIGHT ||
+                               (!ndef->get(n).sunlight_propagates &&
+                                       !allow_non_sunlight_propagates)){
+                       nonlight_seen = true;
+                       noncount++;
+                       if(noncount >= 4)
+                               break;
+                       continue;
+               }
+               if(distance >= sunlight_min_d && *sunlight_seen == false
+                               && nonlight_seen == false)
+                       if(n.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN)
+                               *sunlight_seen = true;
+               noncount = 0;
+               brightness_sum += decode_light(n.getLightBlend(daylight_factor, ndef));
+               brightness_count++;
+       }
+       *result = 0;
+       if(brightness_count == 0)
+               return false;
+       *result = brightness_sum / brightness_count;
+       /*std::cerr<<"Sampled "<<brightness_count<<" points; result="
+                       <<(*result)<<std::endl;*/
+       return true;
+}
+
+int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
+               int oldvalue, bool *sunlight_seen_result)
+{
+       const bool debugprint = false;
+       INodeDefManager *ndef = m_gamedef->ndef();
+       static v3f z_directions[50] = {
+               v3f(-100, 0, 0)
+       };
+       static f32 z_offsets[sizeof(z_directions)/sizeof(*z_directions)] = {
+               -1000,
+       };
+       if(z_directions[0].X < -99){
+               for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
+                       z_directions[i] = v3f(
+                               0.01 * myrand_range(-100, 100),
+                               1.0,
+                               0.01 * myrand_range(-100, 100)
+                       );
+                       z_offsets[i] = 0.01 * myrand_range(0,100);
+               }
+       }
+       if(debugprint)
+               std::cerr<<"In goes "<<PP(m_camera_direction)<<", out comes ";
+       int sunlight_seen_count = 0;
+       float sunlight_min_d = max_d*0.8;
+       if(sunlight_min_d > 35*BS)
+               sunlight_min_d = 35*BS;
+       core::array<int> values;
+       for(u32 i=0; i<sizeof(z_directions)/sizeof(*z_directions); i++){
+               v3f z_dir = z_directions[i];
+               z_dir.normalize();
+               core::CMatrix4<f32> a;
+               a.buildRotateFromTo(v3f(0,1,0), z_dir);
+               v3f dir = m_camera_direction;
+               a.rotateVect(dir);
+               int br = 0;
+               float step = BS*1.5;
+               if(max_d > 35*BS)
+                       step = max_d / 35 * 1.5;
+               float off = step * z_offsets[i];
+               bool sunlight_seen_now = false;
+               bool ok = getVisibleBrightness(this, m_camera_position, dir,
+                               step, 1.0, max_d*0.6+off, max_d, ndef, daylight_factor,
+                               sunlight_min_d,
+                               &br, &sunlight_seen_now);
+               if(sunlight_seen_now)
+                       sunlight_seen_count++;
+               if(!ok)
+                       continue;
+               values.push_back(br);
+               // Don't try too much if being in the sun is clear
+               if(sunlight_seen_count >= 20)
+                       break;
+       }
+       int brightness_sum = 0;
+       int brightness_count = 0;
+       values.sort();
+       u32 num_values_to_use = values.size();
+       if(num_values_to_use >= 10)
+               num_values_to_use -= num_values_to_use/2;
+       else if(num_values_to_use >= 7)
+               num_values_to_use -= num_values_to_use/3;
+       u32 first_value_i = (values.size() - num_values_to_use) / 2;
+       if(debugprint){
+               for(u32 i=0; i < first_value_i; i++)
+                       std::cerr<<values[i]<<" ";
+               std::cerr<<"[";
+       }
+       for(u32 i=first_value_i; i < first_value_i+num_values_to_use; i++){
+               if(debugprint)
+                       std::cerr<<values[i]<<" ";
+               brightness_sum += values[i];
+               brightness_count++;
+       }
+       if(debugprint){
+               std::cerr<<"]";
+               for(u32 i=first_value_i+num_values_to_use; i < values.size(); i++)
+                       std::cerr<<values[i]<<" ";
+       }
+       int ret = 0;
+       if(brightness_count == 0){
+               MapNode n = getNodeNoEx(floatToInt(m_camera_position, BS));
+               if(ndef->get(n).param_type == CPT_LIGHT){
+                       ret = decode_light(n.getLightBlend(daylight_factor, ndef));
+               } else {
+                       ret = oldvalue;
+                       //ret = blend_light(255, 0, daylight_factor);
+               }
+       } else {
+               /*float pre = (float)brightness_sum / (float)brightness_count;
+               float tmp = pre;
+               const float d = 0.2;
+               pre *= 1.0 + d*2;
+               pre -= tmp * d;
+               int preint = pre;
+               ret = MYMAX(0, MYMIN(255, preint));*/
+               ret = brightness_sum / brightness_count;
+       }
+       if(debugprint)
+               std::cerr<<"Result: "<<ret<<" sunlight_seen_count="
+                               <<sunlight_seen_count<<std::endl;
+       *sunlight_seen_result = (sunlight_seen_count > 0);
+       return ret;
+}
+
 void ClientMap::renderPostFx()
 {
        INodeDefManager *nodemgr = m_gamedef->ndef();