summaryrefslogtreecommitdiff
path: root/src/clientmap.cpp
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2012-03-16 16:34:30 +0200
committerPerttu Ahola <celeron55@gmail.com>2012-03-18 13:42:18 +0200
commit2e90ed07acd295387c0da6c0689d14665b6c125d (patch)
tree909687023e509db9010d443520835d3b87a2657b /src/clientmap.cpp
parent58bed83d03bbe53f8286640fbc33043800e1c318 (diff)
downloadminetest-2e90ed07acd295387c0da6c0689d14665b6c125d.tar.gz
minetest-2e90ed07acd295387c0da6c0689d14665b6c125d.tar.bz2
minetest-2e90ed07acd295387c0da6c0689d14665b6c125d.zip
Dynamic sky, fog and cloud colors; sun and moon
Diffstat (limited to 'src/clientmap.cpp')
-rw-r--r--src/clientmap.cpp181
1 files changed, 180 insertions, 1 deletions
diff --git a/src/clientmap.cpp b/src/clientmap.cpp
index 15a790f9a..3aa8af848 100644
--- a/src/clientmap.cpp
+++ b/src/clientmap.cpp
@@ -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
@@ -29,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "profiler.h"
#include "settings.h"
+#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
+
ClientMap::ClientMap(
Client *client,
IGameDef *gamedef,
@@ -189,7 +192,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;
@@ -509,6 +512,182 @@ 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;
+ }
+ }
+ 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(-80, 80),
+ 1.0,
+ 0.01 * myrand_range(-80, 80)
+ );
+ 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();