Dynamic sky, fog and cloud colors; sun and moon
authorPerttu Ahola <celeron55@gmail.com>
Fri, 16 Mar 2012 14:34:30 +0000 (16:34 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 18 Mar 2012 11:42:18 +0000 (13:42 +0200)
30 files changed:
share/client/textures/sunrisebg.png [new file with mode: 0644]
share/server/games/mesetint/mods/default/textures/skybox1.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox1_dawn.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox1_night.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox2.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox2_dawn.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox2_night.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox3.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox3_dawn.png [deleted file]
share/server/games/mesetint/mods/default/textures/skybox3_night.png [deleted file]
src/CMakeLists.txt
src/camera.cpp
src/client.cpp
src/client.h
src/clientmap.cpp
src/clientmap.h
src/clientserver.h
src/clouds.cpp
src/clouds.h
src/daynightratio.h [new file with mode: 0644]
src/defaultsettings.cpp
src/environment.cpp
src/environment.h
src/game.cpp
src/scriptapi.cpp
src/server.cpp
src/server.h
src/sky.cpp [new file with mode: 0644]
src/sky.h [new file with mode: 0644]
src/utility.h

diff --git a/share/client/textures/sunrisebg.png b/share/client/textures/sunrisebg.png
new file mode 100644 (file)
index 0000000..d8b010e
Binary files /dev/null and b/share/client/textures/sunrisebg.png differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox1.png b/share/server/games/mesetint/mods/default/textures/skybox1.png
deleted file mode 100644 (file)
index 9801d5f..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox1.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox1_dawn.png b/share/server/games/mesetint/mods/default/textures/skybox1_dawn.png
deleted file mode 100644 (file)
index 9711c47..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox1_dawn.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox1_night.png b/share/server/games/mesetint/mods/default/textures/skybox1_night.png
deleted file mode 100644 (file)
index 32e43a6..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox1_night.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox2.png b/share/server/games/mesetint/mods/default/textures/skybox2.png
deleted file mode 100644 (file)
index a8c94b4..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox2.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox2_dawn.png b/share/server/games/mesetint/mods/default/textures/skybox2_dawn.png
deleted file mode 100644 (file)
index a761dff..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox2_dawn.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox2_night.png b/share/server/games/mesetint/mods/default/textures/skybox2_night.png
deleted file mode 100644 (file)
index beb07a9..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox2_night.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox3.png b/share/server/games/mesetint/mods/default/textures/skybox3.png
deleted file mode 100644 (file)
index 2776ec7..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox3.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox3_dawn.png b/share/server/games/mesetint/mods/default/textures/skybox3_dawn.png
deleted file mode 100644 (file)
index 22c8cbe..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox3_dawn.png and /dev/null differ
diff --git a/share/server/games/mesetint/mods/default/textures/skybox3_night.png b/share/server/games/mesetint/mods/default/textures/skybox3_night.png
deleted file mode 100644 (file)
index bb50978..0000000
Binary files a/share/server/games/mesetint/mods/default/textures/skybox3_night.png and /dev/null differ
index e43ff411e9530a137c85ea015949ae30f0b30f74..d3d9d64dc561d10168e5ab90b5a74ee92c7f70be 100644 (file)
@@ -159,6 +159,7 @@ endif()
 # Client sources
 set(minetest_SRCS
        ${common_SRCS}
+       sky.cpp
        clientmap.cpp
        content_cso.cpp
        content_mapblock.cpp
index 531661679f27fee2c8e9d611799537c4a86d19ad..97571c77dbc5aca30e06e8db6ece1668769f13d5 100644 (file)
@@ -375,8 +375,12 @@ void Camera::updateViewingRange(f32 frametime_in)
                m_draw_control.wanted_range = viewing_range_max;
 
        // Just so big a value that everything rendered is visible
-       // Some more allowance than viewing_range_max * BS because of active objects etc.
-       m_cameranode->setFarValue(viewing_range_max * BS * 10);
+       // Some more allowance than viewing_range_max * BS because of clouds,
+       // active objects, etc.
+       if(viewing_range_max < 200*BS)
+               m_cameranode->setFarValue(200 * BS * 10);
+       else
+               m_cameranode->setFarValue(viewing_range_max * BS * 10);
 
        f32 wanted_fps = g_settings->getFloat("wanted_fps");
        wanted_fps = MYMAX(wanted_fps, 1.0);
index 6d992e7170bd280ba9c591a84b6e7630a1047f30..2148bfe59b438749d52dcac8ed668c3f6e5d080f 100644 (file)
@@ -247,14 +247,16 @@ Client::Client(
        m_animation_time(0),
        m_crack_level(-1),
        m_crack_pos(0,0,0),
-       m_time_of_day(0),
        m_map_seed(0),
        m_password(password),
        m_access_denied(false),
        m_texture_receive_progress(0),
        m_textures_received(false),
        m_itemdef_received(false),
-       m_nodedef_received(false)
+       m_nodedef_received(false),
+       m_time_of_day_set(false),
+       m_last_time_of_day_f(-1),
+       m_time_of_day_update_timer(0)
 {
        m_packetcounter_timer = 0.0;
        //m_delete_unused_sectors_timer = 0.0;
@@ -333,6 +335,8 @@ void Client::step(float dtime)
        if(m_animation_time > 60.0)
                m_animation_time -= 60.0;
 
+       m_time_of_day_update_timer += dtime;
+       
        //infostream<<"Client steps "<<dtime<<std::endl;
 
        {
@@ -1044,22 +1048,37 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                u16 time_of_day = readU16(&data[2]);
                time_of_day = time_of_day % 24000;
                //infostream<<"Client: time_of_day="<<time_of_day<<std::endl;
-               
-               /*
-                       time_of_day:
-                       0 = midnight
-                       12000 = midday
-               */
-               {
-                       m_env.setTimeOfDay(time_of_day);
-
-                       u32 dr = m_env.getDayNightRatio();
-
-                       infostream<<"Client: time_of_day="<<time_of_day
-                                       <<", dr="<<dr
-                                       <<std::endl;
+               float time_speed = 0;
+               if(datasize >= 2 + 2 + 4){
+                       time_speed = readF1000(&data[4]);
+               } else {
+                       // Old message; try to approximate speed of time by ourselves
+                       float time_of_day_f = (float)time_of_day / 24000.0;
+                       float tod_diff_f = 0;
+                       if(time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8)
+                               tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0;
+                       else
+                               tod_diff_f = time_of_day_f - m_last_time_of_day_f;
+                       m_last_time_of_day_f = time_of_day_f;
+                       float time_diff = m_time_of_day_update_timer;
+                       m_time_of_day_update_timer = 0;
+                       if(m_time_of_day_set){
+                               time_speed = 3600.0*24.0 * tod_diff_f / time_diff;
+                               infostream<<"Client: Measured time_of_day speed (old format): "
+                                               <<time_speed<<" tod_diff_f="<<tod_diff_f
+                                               <<" time_diff="<<time_diff<<std::endl;
+                       }
                }
+               
+               // Update environment
+               m_env.setTimeOfDay(time_of_day);
+               m_env.setTimeOfDaySpeed(time_speed);
+               m_time_of_day_set = true;
 
+               u32 dr = m_env.getDayNightRatio();
+               verbosestream<<"Client: time_of_day="<<time_of_day
+                               <<" time_speed="<<time_speed
+                               <<" dr="<<dr<<std::endl;
        }
        else if(command == TOCLIENT_CHAT_MESSAGE)
        {
@@ -2075,12 +2094,6 @@ void Client::setCrack(int level, v3s16 pos)
        }
 }
 
-u32 Client::getDayNightRatio()
-{
-       //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
-       return m_env.getDayNightRatio();
-}
-
 u16 Client::getHP()
 {
        Player *player = m_env.getLocalPlayer();
index 2f24f8813cc7dc2cf38deb551c7fde157831bec2..1903f3aa7b56c1bc6bf0dd9ec06ce20bf6383e6d 100644 (file)
@@ -256,8 +256,6 @@ public:
        int getCrackLevel();
        void setCrack(int level, v3s16 pos);
 
-       u32 getDayNightRatio();
-
        u16 getHP();
 
        float getAvgRtt()
@@ -350,8 +348,6 @@ private:
        float m_animation_time;
        int m_crack_level;
        v3s16 m_crack_pos;
-       // Received from the server. 0-23999
-       u32 m_time_of_day;
        // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
        //s32 m_daynight_i;
        //u32 m_daynight_ratio;
@@ -367,6 +363,11 @@ private:
        bool m_itemdef_received;
        bool m_nodedef_received;
        friend class FarMesh;
+
+       // time_of_day speed approximation for old protocol
+       bool m_time_of_day_set;
+       float m_last_time_of_day_f;
+       float m_time_of_day_update_timer;
 };
 
 #endif // !SERVER
index 15a790f9a314e6046ad8c1a7a05f6f613ed596b5..3aa8af84884c2ba65c64edc46770723b32369c34 100644 (file)
@@ -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();
index aead670c11590cf06e513b9296e35b4562687c62..3a906f8d6dc77958c89d5c0a7f20e7b1beca917b 100644 (file)
@@ -116,6 +116,9 @@ public:
 
        void renderMap(video::IVideoDriver* driver, s32 pass);
 
+       int getBackgroundBrightness(float max_d, u32 daylight_factor,
+                       int oldvalue, bool *sunlight_seen_result);
+
        void renderPostFx();
 
        // For debug printing
index 8badd177eb468d78797affa007facca9b0a14b37..b4e9ccfc8931fc3e4ced1132eaf7db859ef481d7 100644 (file)
@@ -135,6 +135,8 @@ enum ToClientCommand
        /*
                u16 command
                u16 time (0-23999)
+               Added in a later version:
+               f1000 time_speed
        */
 
        // (oops, there is some gap here)
@@ -453,11 +455,12 @@ enum ToServerCommand
 
 };
 
-inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
+inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed)
 {
-       SharedBuffer<u8> data(2+2);
+       SharedBuffer<u8> data(2+2+4);
        writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
        writeU16(&data[2], time);
+       writeF1000(&data[4], time_speed);
        return data;
 }
 
index 784d611f2a81469779346e05ff4dcd0013422e3d..b9afa54c8ee5f8534f0605f2d5d8faeccc2eb2ee 100644 (file)
@@ -29,24 +29,27 @@ Clouds::Clouds(
                scene::ISceneNode* parent,
                scene::ISceneManager* mgr,
                s32 id,
-               float cloud_y,
                u32 seed
 ):
        scene::ISceneNode(parent, mgr, id),
-       m_cloud_y(cloud_y),
        m_seed(seed),
        m_camera_pos(0,0),
        m_time(0)
 {
        m_material.setFlag(video::EMF_LIGHTING, false);
-       m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
+       //m_material.setFlag(video::EMF_BACK_FACE_CULLING, 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.setFlag(video::EMF_FOG_ENABLE, true);
+       m_material.setFlag(video::EMF_ANTI_ALIASING, true);
        //m_material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
+       m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 
-       m_box = core::aabbox3d<f32>(-BS*1000000,cloud_y-BS,-BS*1000000,
-                       BS*1000000,cloud_y+BS,BS*1000000);
+       m_cloud_y = BS*100;
+       //m_cloud_y = BS*50;
+
+       m_box = core::aabbox3d<f32>(-BS*1000000,m_cloud_y-BS,-BS*1000000,
+                       BS*1000000,m_cloud_y+BS,BS*1000000);
 
 }
 
@@ -58,8 +61,8 @@ void Clouds::OnRegisterSceneNode()
 {
        if(IsVisible)
        {
-               //SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
-               SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
+               SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
+               //SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
        }
 
        ISceneNode::OnRegisterSceneNode();
@@ -71,16 +74,16 @@ void Clouds::render()
 {
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
-       /*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
-               return;*/
-       if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
+       if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
+       //if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
                return;
 
        ScopeProfiler sp(g_profiler, "Rendering of clouds, avg", SPT_AVG);
-
-       int num_faces_to_draw = 1;
-       if(g_settings->getBool("enable_3d_clouds"))
-               num_faces_to_draw = 6;
+       
+       bool enable_3d = g_settings->getBool("enable_3d_clouds");
+       int num_faces_to_draw = enable_3d ? 6 : 1;
+       
+       m_material.setFlag(video::EMF_BACK_FACE_CULLING, enable_3d);
 
        driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
        driver->setMaterial(m_material);
@@ -90,8 +93,10 @@ void Clouds::render()
        */
 
        const s16 cloud_radius_i = 12;
-       const float cloud_size = BS*48;
-       const v2f cloud_speed(-BS*2, 0);
+       const float cloud_size = BS*64;
+       const v2f cloud_speed(0, -BS*2);
+       
+       const float cloud_full_radius = cloud_size * cloud_radius_i;
        
        // Position of cloud noise origin in world coordinates
        v2f world_cloud_origin_pos_f = m_time*cloud_speed;
@@ -110,33 +115,103 @@ void Clouds::render()
                center_of_drawing_in_noise_i.Y * cloud_size
        ) + world_cloud_origin_pos_f;
 
+       /*video::SColor c_top(128,b*240,b*240,b*255);
+       video::SColor c_side_1(128,b*230,b*230,b*255);
+       video::SColor c_side_2(128,b*220,b*220,b*245);
+       video::SColor c_bottom(128,b*205,b*205,b*230);*/
+       video::SColorf c_top_f(m_color);
+       video::SColorf c_side_1_f(m_color);
+       video::SColorf c_side_2_f(m_color);
+       video::SColorf c_bottom_f(m_color);
+       c_side_1_f.r *= 0.95;
+       c_side_1_f.g *= 0.95;
+       c_side_1_f.b *= 0.95;
+       c_side_2_f.r *= 0.90;
+       c_side_2_f.g *= 0.90;
+       c_side_2_f.b *= 0.90;
+       c_bottom_f.r *= 0.80;
+       c_bottom_f.g *= 0.80;
+       c_bottom_f.b *= 0.80;
+       c_top_f.a = 0.9;
+       c_side_1_f.a = 0.9;
+       c_side_2_f.a = 0.9;
+       c_bottom_f.a = 0.9;
+       video::SColor c_top = c_top_f.toSColor();
+       video::SColor c_side_1 = c_side_1_f.toSColor();
+       video::SColor c_side_2 = c_side_2_f.toSColor();
+       video::SColor c_bottom = c_bottom_f.toSColor();
+
+       // Get fog parameters for setting them back later
+       video::SColor fog_color(0,0,0,0);
+       video::E_FOG_TYPE fog_type = video::EFT_FOG_LINEAR;
+       f32 fog_start = 0;
+       f32 fog_end = 0;
+       f32 fog_density = 0;
+       bool fog_pixelfog = false;
+       bool fog_rangefog = false;
+       driver->getFog(fog_color, fog_type, fog_start, fog_end, fog_density,
+                       fog_pixelfog, fog_rangefog);
+       
+       // Set our own fog
+       driver->setFog(fog_color, fog_type, cloud_full_radius * 0.5,
+                       cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog);
+
+       // Read noise
+
+       bool *grid = new bool[cloud_radius_i*2*cloud_radius_i*2];
+
        for(s16 zi=-cloud_radius_i; zi<cloud_radius_i; zi++)
        for(s16 xi=-cloud_radius_i; xi<cloud_radius_i; xi++)
        {
+               u32 i = (zi+cloud_radius_i)*cloud_radius_i*2 + xi+cloud_radius_i;
+
                v2s16 p_in_noise_i(
                        xi+center_of_drawing_in_noise_i.X,
                        zi+center_of_drawing_in_noise_i.Y
                );
 
-               /*if((p_in_noise_i.X + p_in_noise_i.Y)%2==0)
-                       continue;*/
-               /*if((p_in_noise_i.X/2 + p_in_noise_i.Y/2)%2==0)
-                       continue;*/
-
-               v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f;
-               
+#if 0
                double noise = noise2d_perlin_abs(
                                (float)p_in_noise_i.X*cloud_size/BS/200,
                                (float)p_in_noise_i.Y*cloud_size/BS/200,
                                m_seed, 3, 0.4);
-               if(noise < 0.95)
+               grid[i] = (noise >= 0.80);
+#endif
+#if 1
+               double noise = noise2d_perlin(
+                               (float)p_in_noise_i.X*cloud_size/BS/200,
+                               (float)p_in_noise_i.Y*cloud_size/BS/200,
+                               m_seed, 3, 0.5);
+               grid[i] = (noise >= 0.4);
+#endif
+       }
+
+#define GETINDEX(x, z, radius) (((z)+(radius))*(radius)*2 + (x)+(radius))
+#define CONTAINS(x, z, radius) \
+       ((x) >= -(radius) && (x) < (radius) && (z) >= -(radius) && (z) < (radius))
+
+       for(s16 zi0=-cloud_radius_i; zi0<cloud_radius_i; zi0++)
+       for(s16 xi0=-cloud_radius_i; xi0<cloud_radius_i; xi0++)
+       {
+               s16 zi = zi0;
+               s16 xi = xi0;
+               // Draw from front to back (needed for transparency)
+               /*if(zi <= 0)
+                       zi = -cloud_radius_i - zi;
+               if(xi <= 0)
+                       xi = -cloud_radius_i - xi;*/
+               // Draw from back to front
+               if(zi >= 0)
+                       zi = cloud_radius_i - zi - 1;
+               if(xi >= 0)
+                       xi = cloud_radius_i - xi - 1;
+
+               u32 i = GETINDEX(xi, zi, cloud_radius_i);
+
+               if(grid[i] == false)
                        continue;
 
-               float b = m_brightness;
-               video::SColor c_top(128,b*240,b*240,b*255);
-               video::SColor c_side_1(128,b*230,b*230,b*255);
-               video::SColor c_side_2(128,b*220,b*220,b*245);
-               video::SColor c_bottom(128,b*205,b*205,b*230);
+               v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f;
 
                video::S3DVertex v[4] =
                {
@@ -146,55 +221,95 @@ void Clouds::render()
                        video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0)
                };
 
-               f32 rx = cloud_size;
+               /*if(zi <= 0 && xi <= 0){
+                       v[0].Color.setBlue(255);
+                       v[1].Color.setBlue(255);
+                       v[2].Color.setBlue(255);
+                       v[3].Color.setBlue(255);
+               }*/
+
+               f32 rx = cloud_size/2;
                f32 ry = 8*BS;
-               f32 rz = cloud_size;
+               f32 rz = cloud_size/2;
 
                for(int i=0; i<num_faces_to_draw; i++)
                {
                        switch(i)
                        {
                                case 0: // top
+                                       for(int j=0;j<4;j++){
+                                               v[j].Normal = v3f(0,1,0);
+                                       }
                                        v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
                                        v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
                                        v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
                                        v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
                                        break;
                                case 1: // back
-                                       for(int j=0;j<4;j++)
+                                       if(CONTAINS(xi, zi-1, cloud_radius_i)){
+                                               u32 j = GETINDEX(xi, zi-1, cloud_radius_i);
+                                               if(grid[j])
+                                                       continue;
+                                       }
+                                       for(int j=0;j<4;j++){
                                                v[j].Color=c_side_1;
+                                               v[j].Normal = v3f(0,0,-1);
+                                       }
                                        v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
                                        v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
                                        v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
                                        v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
                                        break;
                                case 2: //right
-                                       for(int j=0;j<4;j++)
+                                       if(CONTAINS(xi+1, zi, cloud_radius_i)){
+                                               u32 j = GETINDEX(xi+1, zi, cloud_radius_i);
+                                               if(grid[j])
+                                                       continue;
+                                       }
+                                       for(int j=0;j<4;j++){
                                                v[j].Color=c_side_2;
+                                               v[j].Normal = v3f(1,0,0);
+                                       }
                                        v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
                                        v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
                                        v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
                                        v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
                                        break;
                                case 3: // front
-                                       for(int j=0;j<4;j++)
+                                       if(CONTAINS(xi, zi+1, cloud_radius_i)){
+                                               u32 j = GETINDEX(xi, zi+1, cloud_radius_i);
+                                               if(grid[j])
+                                                       continue;
+                                       }
+                                       for(int j=0;j<4;j++){
                                                v[j].Color=c_side_1;
+                                               v[j].Normal = v3f(0,0,-1);
+                                       }
                                        v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
                                        v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
                                        v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
                                        v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
                                        break;
                                case 4: // left
-                                       for(int j=0;j<4;j++)
+                                       if(CONTAINS(xi-1, zi, cloud_radius_i)){
+                                               u32 j = GETINDEX(xi-1, zi, cloud_radius_i);
+                                               if(grid[j])
+                                                       continue;
+                                       }
+                                       for(int j=0;j<4;j++){
                                                v[j].Color=c_side_2;
+                                               v[j].Normal = v3f(-1,0,0);
+                                       }
                                        v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
                                        v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
                                        v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
                                        v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
                                        break;
                                case 5: // bottom
-                                       for(int j=0;j<4;j++)
+                                       for(int j=0;j<4;j++){
                                                v[j].Color=c_bottom;
+                                               v[j].Normal = v3f(0,-1,0);
+                                       }
                                        v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
                                        v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
                                        v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
@@ -210,8 +325,13 @@ void Clouds::render()
                        driver->drawVertexPrimitiveList(v, 4, indices, 2,
                                        video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
                }
-
        }
+
+       delete[] grid;
+       
+       // Restore fog settings
+       driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density,
+                       fog_pixelfog, fog_rangefog);
 }
 
 void Clouds::step(float dtime)
@@ -219,9 +339,11 @@ void Clouds::step(float dtime)
        m_time += dtime;
 }
 
-void Clouds::update(v2f camera_p, float brightness)
+void Clouds::update(v2f camera_p, video::SColorf color)
 {
        m_camera_pos = camera_p;
-       m_brightness = brightness;
+       m_color = color;
+       //m_brightness = brightness;
+       //dstream<<"m_brightness="<<m_brightness<<std::endl;
 }
 
index 59861371efd221c5e84a663cd1603e6619b8dff3..24c679f3d12fca5cc4ffb06eaa3ddda933b64a32 100644 (file)
@@ -30,7 +30,6 @@ public:
                        scene::ISceneNode* parent,
                        scene::ISceneManager* mgr,
                        s32 id,
-                       float cloud_y,
                        u32 seed
        );
 
@@ -65,13 +64,14 @@ public:
 
        void step(float dtime);
 
-       void update(v2f camera_p, float brightness);
+       void update(v2f camera_p, video::SColorf color);
 
 private:
        video::SMaterial m_material;
        core::aabbox3d<f32> m_box;
        float m_cloud_y;
        float m_brightness;
+       video::SColorf m_color;
        u32 m_seed;
        v2f m_camera_pos;
        float m_time;
diff --git a/src/daynightratio.h b/src/daynightratio.h
new file mode 100644 (file)
index 0000000..1b075c4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+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
+(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.
+
+You should have received a copy of the GNU 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.
+*/
+
+#ifndef DAYNIGHTRATIO_HEADER
+#define DAYNIGHTRATIO_HEADER
+
+inline u32 time_to_daynight_ratio(u32 time_of_day)
+{
+       s32 t = time_of_day%24000;
+       if(t < 4500 || t >= 19500)
+               return 150;
+       else if(t < 4750 || t >= 19250)
+               return 250;
+       else if(t < 5000 || t >= 19000)
+               return 350;
+       else if(t < 5250 || t >= 18750)
+               return 500;
+       else if(t < 5500 || t >= 18500)
+               return 675;
+       else if(t < 5750 || t >= 18250)
+               return 875;
+       else
+               return 1000;
+}
+
+#endif
+
index 97b00d4219a8ec3c30c026536ea1718292c9c8cc..a777ed736578dc062f2fb8f3921c44c423f982f1 100644 (file)
@@ -71,7 +71,7 @@ void set_default_settings(Settings *settings)
        settings->setDefault("fps_max", "60");
        // A bit more than the server will send around the player, to make fog blend well
        settings->setDefault("viewing_range_nodes_min", "35");
-       settings->setDefault("viewing_range_nodes_max", "128");
+       settings->setDefault("viewing_range_nodes_max", "160");
        settings->setDefault("screenW", "800");
        settings->setDefault("screenH", "600");
        settings->setDefault("address", "");
@@ -121,11 +121,11 @@ void set_default_settings(Settings *settings)
        settings->setDefault("active_block_range", "2");
        //settings->setDefault("max_simultaneous_block_sends_per_client", "1");
        // This causes frametime jitter on client side, or does it?
-       settings->setDefault("max_simultaneous_block_sends_per_client", "2");
-       settings->setDefault("max_simultaneous_block_sends_server_total", "8");
-       settings->setDefault("max_block_send_distance", "7");
-       settings->setDefault("max_block_generate_distance", "5");
-       settings->setDefault("time_send_interval", "20");
+       settings->setDefault("max_simultaneous_block_sends_per_client", "4");
+       settings->setDefault("max_simultaneous_block_sends_server_total", "20");
+       settings->setDefault("max_block_send_distance", "10");
+       settings->setDefault("max_block_generate_distance", "6");
+       settings->setDefault("time_send_interval", "5");
        settings->setDefault("time_speed", "96");
        settings->setDefault("server_unload_unused_data_timeout", "29");
        settings->setDefault("server_map_save_interval", "5.3");
index 93649eed5b532f1eeec2577ec5ee4d6745f43ecd..e713ab610cbebe5dc72b578c1a6a0296c7df2f93 100644 (file)
@@ -41,11 +41,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef SERVER
 #include "clientmap.h"
 #endif
+#include "daynightratio.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
 Environment::Environment():
-       m_time_of_day(9000)
+       m_time_of_day(9000),
+       m_time_of_day_f(9000./24000),
+       m_time_of_day_speed(0),
+       m_time_counter(0)
 {
 }
 
@@ -195,17 +199,35 @@ void Environment::printPlayers(std::ostream &o)
        }
 }
 
-/*void Environment::setDayNightRatio(u32 r)
-{
-       getDayNightRatio() = r;
-}*/
-
 u32 Environment::getDayNightRatio()
 {
-       //return getDayNightRatio();
        return time_to_daynight_ratio(m_time_of_day);
 }
 
+void Environment::stepTimeOfDay(float dtime)
+{
+       m_time_counter += dtime;
+       f32 speed = m_time_of_day_speed * 24000./(24.*3600);
+       u32 units = (u32)(m_time_counter*speed);
+       m_time_counter -= (f32)units / speed;
+       bool sync_f = false;
+       if(units > 0){
+               // Sync at overflow
+               if(m_time_of_day + units >= 24000)
+                       sync_f = true;
+               m_time_of_day = (m_time_of_day + units) % 24000;
+               if(sync_f)
+                       m_time_of_day_f = (float)m_time_of_day / 24000.0;
+       }
+       if(!sync_f){
+               m_time_of_day_f += m_time_of_day_speed/24/3600*dtime;
+               if(m_time_of_day_f > 1.0)
+                       m_time_of_day_f -= 1.0;
+               if(m_time_of_day_f < 0.0)
+                       m_time_of_day_f += 1.0;
+       }
+}
+
 /*
        ABMWithState
 */
@@ -893,6 +915,9 @@ void ServerEnvironment::step(float dtime)
        
        //TimeTaker timer("ServerEnv step");
 
+       /* Step time of day */
+       stepTimeOfDay(dtime);
+
        /*
                Increment game time
        */
@@ -1861,6 +1886,9 @@ void ClientEnvironment::step(float dtime)
 {
        DSTACK(__FUNCTION_NAME);
 
+       /* Step time of day */
+       stepTimeOfDay(dtime);
+
        // Get some settings
        bool free_move = g_settings->getBool("free_move");
 
index a3a659c5b12dffade725e10530d58413a7d7df67..04df9be48b8a4d08f30fc1d96638094332d6f80f 100644 (file)
@@ -74,27 +74,39 @@ public:
        core::list<Player*> getPlayers(bool ignore_disconnected);
        void printPlayers(std::ostream &o);
        
-       //void setDayNightRatio(u32 r);
        u32 getDayNightRatio();
        
        // 0-23999
        virtual void setTimeOfDay(u32 time)
        {
                m_time_of_day = time;
+               m_time_of_day_f = (float)time / 24000.0;
        }
 
        u32 getTimeOfDay()
-       {
-               return m_time_of_day;
-       }
+       { return m_time_of_day; }
+
+       float getTimeOfDayF()
+       { return m_time_of_day_f; }
+
+       void stepTimeOfDay(float dtime);
+
+       void setTimeOfDaySpeed(float speed)
+       { m_time_of_day_speed = speed; }
+       
+       float getTimeOfDaySpeed()
+       { return m_time_of_day_speed; }
 
 protected:
        // peer_ids in here should be unique, except that there may be many 0s
        core::list<Player*> m_players;
-       // Brightness
-       //u32 m_daynight_ratio;
        // Time of day in milli-hours (0-23999); determines day and night
        u32 m_time_of_day;
+       // Time of day in 0...1
+       float m_time_of_day_f;
+       float m_time_of_day_speed;
+       // Used to buffer dtime for adding to m_time_of_day
+       float m_time_counter;
 };
 
 /*
index 778615cf90e7ad89cc812390cf99e1976583f800..04b9f105d505b4b107f9e471826277ab270c43fa 100644 (file)
@@ -54,6 +54,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "subgame.h"
 #include "quicktune_shortcutter.h"
 #include "clientmap.h"
+#include "sky.h"
 
 /*
        Setting this to 1 enables a special camera mode that forces
@@ -543,51 +544,6 @@ PointedThing getPointedThing(Client *client, v3f player_position,
        return result;
 }
 
-void update_skybox(video::IVideoDriver* driver, ITextureSource *tsrc,
-               scene::ISceneManager* smgr, scene::ISceneNode* &skybox,
-               float brightness)
-{
-       if(skybox)
-       {
-               skybox->remove();
-       }
-       
-       /*// Disable skybox if FarMesh is enabled
-       if(g_settings->getBool("enable_farmesh"))
-               return;*/
-       
-       if(brightness >= 0.7)
-       {
-               skybox = smgr->addSkyBoxSceneNode(
-                       tsrc->getTextureRaw("skybox2.png"),
-                       tsrc->getTextureRaw("skybox3.png"),
-                       tsrc->getTextureRaw("skybox1.png"),
-                       tsrc->getTextureRaw("skybox1.png"),
-                       tsrc->getTextureRaw("skybox1.png"),
-                       tsrc->getTextureRaw("skybox1.png"));
-       }
-       else if(brightness >= 0.2)
-       {
-               skybox = smgr->addSkyBoxSceneNode(
-                       tsrc->getTextureRaw("skybox2_dawn.png"),
-                       tsrc->getTextureRaw("skybox3_dawn.png"),
-                       tsrc->getTextureRaw("skybox1_dawn.png"),
-                       tsrc->getTextureRaw("skybox1_dawn.png"),
-                       tsrc->getTextureRaw("skybox1_dawn.png"),
-                       tsrc->getTextureRaw("skybox1_dawn.png"));
-       }
-       else
-       {
-               skybox = smgr->addSkyBoxSceneNode(
-                       tsrc->getTextureRaw("skybox2_night.png"),
-                       tsrc->getTextureRaw("skybox3_night.png"),
-                       tsrc->getTextureRaw("skybox1_night.png"),
-                       tsrc->getTextureRaw("skybox1_night.png"),
-                       tsrc->getTextureRaw("skybox1_night.png"),
-                       tsrc->getTextureRaw("skybox1_night.png"));
-       }
-}
-
 /*
        Draws a screen with a single text on it.
        Text will be removed when the screen is drawn the next time.
@@ -679,10 +635,6 @@ void the_game(
        //const s32 hotbar_imagesize = 64;
        s32 hotbar_imagesize = 48;
        
-       // The color of the sky
-       //video::SColor skycolor = video::SColor(255,140,186,250);
-       video::SColor bgcolor_bright = video::SColor(255,170,200,230);
-
        /*
                Draw "Loading" screen
        */
@@ -891,13 +843,6 @@ void the_game(
        */
        client.afterContentReceived();
 
-       /*
-               Create skybox
-       */
-       float old_brightness = 1.0;
-       scene::ISceneNode* skybox = NULL;
-       update_skybox(driver, tsrc, smgr, skybox, 1.0);
-       
        /*
                Create the camera node
        */
@@ -912,13 +857,18 @@ void the_game(
                Clouds
        */
        
-       float cloud_height = BS*100;
        Clouds *clouds = NULL;
        if(g_settings->getBool("enable_clouds"))
        {
-               clouds = new Clouds(smgr->getRootSceneNode(), smgr, -1,
-                               cloud_height, time(0));
+               clouds = new Clouds(smgr->getRootSceneNode(), smgr, -1, time(0));
        }
+
+       /*
+               Skybox thingy
+       */
+
+       Sky *sky = NULL;
+       sky = new Sky(smgr->getRootSceneNode(), smgr, -1);
        
        /*
                FarMesh
@@ -1022,7 +972,7 @@ void the_game(
        // A test
        //throw con::PeerNotFoundException("lol");
 
-       float brightness = 1.0;
+       float recent_turn_speed = 0.0;
 
        core::list<float> frametime_log;
 
@@ -1054,6 +1004,9 @@ void the_game(
        u32 show_profiler = 0;
        u32 show_profiler_max = 3;  // Number of pages
 
+       float time_of_day = 0;
+       float time_of_day_smooth = 0;
+
        /*
                Main loop
        */
@@ -1639,6 +1592,7 @@ void the_game(
                        NOTE: Do this before client.setPlayerControl() to not cause a camera lag of one frame
                */
                
+               float turn_amount = 0;
                if((device->isWindowActive() && noMenuActive()) || random_input)
                {
                        if(!random_input)
@@ -1668,11 +1622,14 @@ void the_game(
                                        dx -= dtime * keyspeed;
                                if(input->isKeyDown(irr::KEY_RIGHT))
                                        dx += dtime * keyspeed;*/
-
-                               camera_yaw -= dx*0.2;
-                               camera_pitch += dy*0.2;
+                               
+                               float d = 0.2;
+                               camera_yaw -= dx*d;
+                               camera_pitch += dy*d;
                                if(camera_pitch < -89.5) camera_pitch = -89.5;
                                if(camera_pitch > 89.5) camera_pitch = 89.5;
+                               
+                               turn_amount = v2f(dx, dy).getLength() * d;
                        }
                        input->setMousePos(displaycenter.X, displaycenter.Y);
                }
@@ -1684,6 +1641,8 @@ void the_game(
                        //infostream<<"window inactive"<<std::endl;
                        first_loop_after_window_activation = true;
                }
+               recent_turn_speed = recent_turn_speed * 0.9 + turn_amount * 0.1;
+               //std::cerr<<"recent_turn_speed = "<<recent_turn_speed<<std::endl;
 
                /*
                        Player speed control
@@ -1786,8 +1745,6 @@ void the_game(
                                }
                                else if(event.type == CE_TEXTURES_UPDATED)
                                {
-                                       update_skybox(driver, tsrc, smgr, skybox, brightness);
-                                       
                                        update_wielded_item_trigger = true;
                                }
                        }
@@ -2155,41 +2112,77 @@ void the_game(
                /*
                        Calculate stuff for drawing
                */
-               
+
                /*
-                       Calculate general brightness
+                       Fog range
                */
-               u32 daynight_ratio = client.getDayNightRatio();
-               u8 light8 = decode_light((daynight_ratio * LIGHT_SUN) / 1000);
-               brightness = (float)light8/255.0;
-               video::SColor bgcolor;
-               if(brightness >= 0.2 && brightness < 0.7)
-                       bgcolor = video::SColor(
-                                       255,
-                                       bgcolor_bright.getRed() * brightness,
-                                       bgcolor_bright.getGreen() * brightness*0.7,
-                                       bgcolor_bright.getBlue() * brightness*0.5);
+       
+               f32 fog_range;
+               if(farmesh)
+               {
+                       fog_range = BS*farmesh_range;
+               }
                else
-                       bgcolor = video::SColor(
-                                       255,
-                                       bgcolor_bright.getRed() * brightness,
-                                       bgcolor_bright.getGreen() * brightness,
-                                       bgcolor_bright.getBlue() * brightness);
+               {
+                       fog_range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
+                       fog_range *= 0.9;
+                       if(draw_control.range_all)
+                               fog_range = 100000*BS;
+               }
 
                /*
-                       Update skybox
+                       Calculate general brightness
                */
-               if(fabs(brightness - old_brightness) > 0.01)
-                       update_skybox(driver, tsrc, smgr, skybox, brightness);
+               u32 daynight_ratio = client.getEnv().getDayNightRatio();
+               float time_brightness = (float)decode_light(
+                               (daynight_ratio * LIGHT_SUN) / 1000) / 255.0;
+               float direct_brightness = 0;
+               bool sunlight_seen = false;
+               if(g_settings->getBool("free_move")){
+                       direct_brightness = time_brightness;
+                       sunlight_seen = true;
+               } else {
+                       ScopeProfiler sp(g_profiler, "Detecting background light", SPT_AVG);
+                       float old_brightness = sky->getBrightness();
+                       direct_brightness = (float)client.getEnv().getClientMap()
+                                       .getBackgroundBrightness(MYMIN(fog_range*1.2, 60*BS),
+                                       daynight_ratio, (int)(old_brightness*255.5), &sunlight_seen)
+                                       / 255.0;
+               }
+               
+               time_of_day = client.getEnv().getTimeOfDayF();
+               float maxsm = 0.05;
+               if(fabs(time_of_day - time_of_day_smooth) > maxsm &&
+                               fabs(time_of_day - time_of_day_smooth + 1.0) > maxsm &&
+                               fabs(time_of_day - time_of_day_smooth - 1.0) > maxsm)
+                       time_of_day_smooth = time_of_day;
+               float todsm = 0.05;
+               if(time_of_day_smooth > 0.8 && time_of_day < 0.2)
+                       time_of_day_smooth = time_of_day_smooth * (1.0-todsm)
+                                       + (time_of_day+1.0) * todsm;
+               else
+                       time_of_day_smooth = time_of_day_smooth * (1.0-todsm)
+                                       + time_of_day * todsm;
+                       
+               sky->update(time_of_day_smooth, time_brightness, direct_brightness,
+                               sunlight_seen);
+               
+               float brightness = sky->getBrightness();
+               video::SColor bgcolor = sky->getBgColor();
+               video::SColor skycolor = sky->getSkyColor();
 
                /*
                        Update clouds
                */
-               if(clouds)
-               {
-                       clouds->step(dtime);
-                       clouds->update(v2f(player_position.X, player_position.Z),
-                                       brightness);
+               if(clouds){
+                       if(sky->getCloudsVisible()){
+                               clouds->setVisible(true);
+                               clouds->step(dtime);
+                               clouds->update(v2f(player_position.X, player_position.Z),
+                                               sky->getCloudColor());
+                       } else{
+                               clouds->setVisible(false);
+                       }
                }
                
                /*
@@ -2208,35 +2201,17 @@ void the_game(
                                        brightness, farmesh_range);
                }
                
-               // Store brightness value
-               old_brightness = brightness;
-
                /*
                        Fog
                */
                
                if(g_settings->getBool("enable_fog") == true && !force_fog_off)
                {
-                       f32 range;
-                       if(farmesh)
-                       {
-                               range = BS*farmesh_range;
-                       }
-                       else
-                       {
-                               range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
-                               range *= 0.9;
-                               if(draw_control.range_all)
-                                       range = 100000*BS;
-                               /*if(range < 50*BS)
-                                       range = range * 0.5 + 25*BS;*/
-                       }
-
                        driver->setFog(
                                bgcolor,
                                video::EFT_FOG_LINEAR,
-                               range*0.4,
-                               range*1.0,
+                               fog_range*0.4,
+                               fog_range*1.0,
                                0.01,
                                false, // pixel fog
                                false // range fog
@@ -2443,15 +2418,15 @@ void the_game(
                
                {
                        TimeTaker timer("beginScene");
-                       driver->beginScene(false, true, bgcolor);
                        //driver->beginScene(false, true, bgcolor);
+                       //driver->beginScene(true, true, bgcolor);
+                       driver->beginScene(true, true, skycolor);
                        beginscenetime = timer.stop(true);
                }
                
                //timer3.stop();
-               
+       
                //infostream<<"smgr->drawAll()"<<std::endl;
-               
                {
                        TimeTaker timer("smgr");
                        smgr->drawAll();
@@ -2570,6 +2545,11 @@ void the_game(
                                        NULL);
                }
 
+               // Clear Z buffer
+               driver->clearZBuffer();
+               // Draw some sky things
+               //draw_horizon(driver, camera.getCameraNode());
+               
                /*
                        End scene
                */
index e8ebecb5a93065f767670c52038aec90b1202cea..27ab2950be7c404446e605cc79f8f967d97f270d 100644 (file)
@@ -46,6 +46,7 @@ extern "C" {
 #include "content_nodemeta.h"
 #include "utility.h"
 #include "tool.h"
+#include "daynightratio.h"
 
 static void stackDump(lua_State *L, std::ostream &o)
 {
index 2139df957388a8b05740cdaf4440374541fdf9ec..f3bf1e23f5541d403a93552b0168ea1f68ae04bd 100644 (file)
@@ -854,7 +854,6 @@ Server::Server(
        m_craftdef(createCraftDefManager()),
        m_thread(this),
        m_emergethread(this),
-       m_time_counter(0),
        m_time_of_day_send_timer(0),
        m_uptime(0),
        m_shutdown_requested(false),
@@ -1197,19 +1196,12 @@ void Server::AsyncRunStep()
        }
 
        /*
-               Update m_time_of_day and overall game time
+               Update time of day and overall game time
        */
        {
                JMutexAutoLock envlock(m_env_mutex);
 
-               m_time_counter += dtime;
-               f32 speed = g_settings->getFloat("time_speed") * 24000./(24.*3600);
-               u32 units = (u32)(m_time_counter*speed);
-               m_time_counter -= (f32)units / speed;
-               
-               m_env->setTimeOfDay((m_env->getTimeOfDay() + units) % 24000);
-               
-               //infostream<<"Server: m_time_of_day = "<<m_time_of_day.get()<<std::endl;
+               m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
 
                /*
                        Send to clients at constant intervals
@@ -1231,7 +1223,7 @@ void Server::AsyncRunStep()
                                //Player *player = m_env->getPlayer(client->peer_id);
                                
                                SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
-                                               m_env->getTimeOfDay());
+                                               m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
                                // Send as reliable
                                m_con.Send(client->peer_id, 0, data, true);
                        }
@@ -2216,7 +2208,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                // Send time of day
                {
                        SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
-                                       m_env->getTimeOfDay());
+                                       m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
                        m_con.Send(peer_id, 0, data, true);
                }
                
index f149ac6871183248c9858274d9e3d51c323ef027..32ce8eb53f92488003c19bd6f19cfef01de60e5c 100644 (file)
@@ -426,11 +426,6 @@ public:
 
        core::list<PlayerInfo> getPlayerInfo();
 
-       /*u32 getDayNightRatio()
-       {
-               return time_to_daynight_ratio(m_time_of_day.get());
-       }*/
-       
        // Environment must be locked when called
        void setTimeOfDay(u32 time)
        {
@@ -714,10 +709,6 @@ private:
                Time related stuff
        */
 
-       // 0-23999
-       //MutexedVariable<u32> m_time_of_day;
-       // Used to buffer dtime for adding to m_time_of_day
-       float m_time_counter;
        // Timer for sending time of day over network
        float m_time_of_day_send_timer;
        // Uptime of server in seconds
diff --git a/src/sky.cpp b/src/sky.cpp
new file mode 100644 (file)
index 0000000..ba9b174
--- /dev/null
@@ -0,0 +1,446 @@
+#include "sky.h"
+#include "IVideoDriver.h"
+#include "ISceneManager.h"
+#include "ICameraSceneNode.h"
+#include "S3DVertex.h"
+#include "utility.h" // MYMIN
+#include "tile.h" // getTexturePath
+#include "noise.h" // easeCurve
+#include "main.h" // g_profiler
+#include "profiler.h"
+
+//! constructor
+Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id):
+               scene::ISceneNode(parent, mgr, id),
+               m_first_update(true),
+               m_brightness(0.5),
+               m_cloud_brightness(0.5),
+               m_bgcolor_bright_f(1,1,1,1),
+               m_skycolor_bright_f(1,1,1,1),
+               m_cloudcolor_bright_f(1,1,1,1)
+{
+       setAutomaticCulling(scene::EAC_OFF);
+       Box.MaxEdge.set(0,0,0);
+       Box.MinEdge.set(0,0,0);
+
+       // create material
+
+       video::SMaterial mat;
+       mat.Lighting = false;
+       mat.ZBuffer = video::ECFN_NEVER;
+       mat.ZWriteEnable = false;
+       mat.AntiAliasing=0;
+       mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
+       mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
+       mat.BackfaceCulling = false;
+
+       m_materials[0] = mat;
+
+       m_materials[1] = mat;
+       //m_materials[1].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
+       m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+
+       m_materials[2] = mat;
+       m_materials[2].setTexture(0, mgr->getVideoDriver()->getTexture(
+                       getTexturePath("sunrisebg.png").c_str()));
+       m_materials[2].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+       //m_materials[2].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
+
+       for(u32 i=0; i<SKY_STAR_COUNT; i++){
+               m_stars[i] = v3f(
+                       myrand_range(-10000,10000),
+                       myrand_range(-10000,10000),
+                       myrand_range(-10000,10000)
+               );
+               m_stars[i].normalize();
+       }
+}
+
+void Sky::OnRegisterSceneNode()
+{
+       if (IsVisible)
+               SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
+
+       scene::ISceneNode::OnRegisterSceneNode();
+}
+
+const core::aabbox3d<f32>& Sky::getBoundingBox() const
+{
+       return Box;
+}
+
+//! renders the node.
+void Sky::render()
+{
+       video::IVideoDriver* driver = SceneManager->getVideoDriver();
+       scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();
+
+       if (!camera || !driver)
+               return;
+       
+       ScopeProfiler sp(g_profiler, "Sky::render()", SPT_AVG);
+
+       // draw perspective skybox
+
+       core::matrix4 translate(AbsoluteTransformation);
+       translate.setTranslation(camera->getAbsolutePosition());
+
+       // Draw the sky box between the near and far clip plane
+       const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f;
+       core::matrix4 scale;
+       scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance));
+
+       driver->setTransform(video::ETS_WORLD, translate * scale);
+       
+       if(m_sunlight_seen)
+       {
+               float sunsize = 0.07;
+               video::SColorf suncolor_f(1, 1, 0, 1);
+               suncolor_f.r = 1;
+               suncolor_f.g = MYMAX(0.3, MYMIN(1.0, 0.7+m_time_brightness*(0.5)));
+               suncolor_f.b = MYMAX(0.0, m_brightness*0.95);
+               video::SColorf suncolor2_f(1, 1, 1, 1);
+               suncolor_f.r = 1;
+               suncolor_f.g = MYMAX(0.3, MYMIN(1.0, 0.85+m_time_brightness*(0.5)));
+               suncolor_f.b = MYMAX(0.0, m_brightness);
+
+               float moonsize = 0.04;
+               video::SColorf mooncolor_f(0.50, 0.57, 0.65, 1);
+               video::SColorf mooncolor2_f(0.85, 0.875, 0.9, 1);
+               
+               float nightlength = 0.41;
+               float wn = nightlength / 2;
+               float wicked_time_of_day = 0;
+               if(m_time_of_day > wn && m_time_of_day < 1.0 - wn)
+                       wicked_time_of_day = (m_time_of_day - wn)/(1.0-wn*2)*0.5 + 0.25;
+               else if(m_time_of_day < 0.5)
+                       wicked_time_of_day = m_time_of_day / wn * 0.25;
+               else
+                       wicked_time_of_day = 1.0 - ((1.0-m_time_of_day) / wn * 0.25);
+               /*std::cerr<<"time_of_day="<<m_time_of_day<<" -> "
+                               <<"wicked_time_of_day="<<wicked_time_of_day<<std::endl;*/
+
+               video::SColor suncolor = suncolor_f.toSColor();
+               video::SColor suncolor2 = suncolor2_f.toSColor();
+               video::SColor mooncolor = mooncolor_f.toSColor();
+               video::SColor mooncolor2 = mooncolor2_f.toSColor();
+
+               const f32 t = 1.0f;
+               const f32 o = 0.0f;
+               static const u16 indices[4] = {0,1,2,3};
+               video::S3DVertex vertices[4];
+
+               driver->setMaterial(m_materials[2]);
+               {
+                       float mid1 = 0.25;
+                       float mid = (wicked_time_of_day < 0.5 ? mid1 : (1.0 - mid1));
+                       float a_ = 1.0 - fabs(wicked_time_of_day - mid) * 35.0;
+                       float a = easeCurve(MYMAX(0, MYMIN(1, a_)));
+                       //std::cerr<<"a_="<<a_<<" a="<<a<<std::endl;
+                       video::SColor c(255,255,255,255);
+                       float y = -(1.0 - a) * 0.2;
+                       vertices[0] = video::S3DVertex(-1,-0.05+y,-1, 0,0,1, c, t, t);
+                       vertices[1] = video::S3DVertex( 1,-0.05+y,-1, 0,0,1, c, o, t);
+                       vertices[2] = video::S3DVertex( 1, 0.2+y,-1, 0,0,1, c, o, o);
+                       vertices[3] = video::S3DVertex(-1, 0.2+y,-1, 0,0,1, c, t, o);
+                       for(u32 i=0; i<4; i++){
+                               if(wicked_time_of_day < 0.5)
+                                       // Switch from -Z (south) to +X (east)
+                                       vertices[i].Pos.rotateXZBy(90);
+                               else
+                                       // Switch from -Z (south) to -X (west)
+                                       vertices[i].Pos.rotateXZBy(-90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+               }
+
+               driver->setMaterial(m_materials[1]);
+               
+               // Draw sun
+               if(wicked_time_of_day > 0.15 && wicked_time_of_day < 0.85)
+               {
+                       float d = sunsize * 1.7;
+                       video::SColor c = suncolor;
+                       c.setAlpha(0.05*255);
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to +X (east)
+                               vertices[i].Pos.rotateXZBy(90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+
+                       d = sunsize * 1.2;
+                       c = suncolor;
+                       c.setAlpha(0.15*255);
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to +X (east)
+                               vertices[i].Pos.rotateXZBy(90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+
+                       d = sunsize;
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, suncolor, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, suncolor, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, suncolor, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, suncolor, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to +X (east)
+                               vertices[i].Pos.rotateXZBy(90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+
+                       d = sunsize * 0.7;
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, suncolor2, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, suncolor2, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, suncolor2, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, suncolor2, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to +X (east)
+                               vertices[i].Pos.rotateXZBy(90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+               }
+               // Draw moon
+               if(wicked_time_of_day < 0.3 || wicked_time_of_day > 0.7)
+               {
+                       float d = moonsize * 1.9;
+                       video::SColor c = mooncolor;
+                       c.setAlpha(0.05*255);
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to -X (west)
+                               vertices[i].Pos.rotateXZBy(-90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+                       
+                       d = moonsize * 1.3;
+                       c = mooncolor;
+                       c.setAlpha(0.15*255);
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to -X (west)
+                               vertices[i].Pos.rotateXZBy(-90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+                       
+                       d = moonsize;
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, mooncolor, t, t);
+                       vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, mooncolor, o, t);
+                       vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, mooncolor, o, o);
+                       vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, mooncolor, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to -X (west)
+                               vertices[i].Pos.rotateXZBy(-90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+                       
+                       float d2 = moonsize * 0.6;
+                       vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, mooncolor2, t, t);
+                       vertices[1] = video::S3DVertex( d2,-d,-1, 0,0,1, mooncolor2, o, t);
+                       vertices[2] = video::S3DVertex( d2, d2,-1, 0,0,1, mooncolor2, o, o);
+                       vertices[3] = video::S3DVertex(-d, d2,-1, 0,0,1, mooncolor2, t, o);
+                       for(u32 i=0; i<4; i++){
+                               // Switch from -Z (south) to -X (west)
+                               vertices[i].Pos.rotateXZBy(-90);
+                               vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+               }
+               // Stars
+               do{
+                       float starbrightness = MYMAX(0, MYMIN(1,
+                                       (0.285 - fabs(wicked_time_of_day < 0.5 ?
+                                       wicked_time_of_day : (1.0 - wicked_time_of_day))) * 10));
+                       float f = starbrightness;
+                       video::SColor starcolor(255, f*120,f*120,f*120);
+                       if(starcolor.getBlue() < m_skycolor.getBlue())
+                               break;
+                       u16 indices[SKY_STAR_COUNT*4];
+                       video::S3DVertex vertices[SKY_STAR_COUNT*4];
+                       for(u32 i=0; i<SKY_STAR_COUNT; i++){
+                               indices[i*4+0] = i*4+0;
+                               indices[i*4+1] = i*4+1;
+                               indices[i*4+2] = i*4+2;
+                               indices[i*4+3] = i*4+3;
+                               v3f p = m_stars[i];
+                               core::CMatrix4<f32> a;
+                               float d = 0.005;
+                               a.buildRotateFromTo(v3f(0,1,0), v3f(d,1,0));
+                               v3f p1 = p;
+                               a.rotateVect(p1);
+                               a.buildRotateFromTo(v3f(0,1,0), v3f(d,1+d/2,d));
+                               v3f p2 = p;
+                               a.rotateVect(p2);
+                               a.buildRotateFromTo(v3f(0,1,0), v3f(0,1,d));
+                               v3f p3 = p;
+                               a.rotateVect(p3);
+                               p.rotateXYBy(wicked_time_of_day * 360 - 90);
+                               p1.rotateXYBy(wicked_time_of_day * 360 - 90);
+                               p2.rotateXYBy(wicked_time_of_day * 360 - 90);
+                               p3.rotateXYBy(wicked_time_of_day * 360 - 90);
+                               vertices[i*4+0].Pos = p;
+                               vertices[i*4+0].Color = starcolor;
+                               vertices[i*4+1].Pos = p1;
+                               vertices[i*4+1].Color = starcolor;
+                               vertices[i*4+2].Pos = p2;
+                               vertices[i*4+2].Color = starcolor;
+                               vertices[i*4+3].Pos = p3;
+                               vertices[i*4+3].Color = starcolor;
+                       }
+                       driver->drawVertexPrimitiveList(vertices, SKY_STAR_COUNT*4,
+                                       indices, SKY_STAR_COUNT, video::EVT_STANDARD,
+                                       scene::EPT_QUADS, video::EIT_16BIT);
+               }while(0);
+               
+               for(u32 j=0; j<2; j++)
+               {
+                       vertices[0] = video::S3DVertex(-1,-1.0,-1, 0,0,1, m_skycolor, t, t);
+                       vertices[1] = video::S3DVertex( 1,-1.0,-1, 0,0,1, m_skycolor, o, t);
+                       vertices[2] = video::S3DVertex( 1,-0.02,-1, 0,0,1, m_skycolor, o, o);
+                       vertices[3] = video::S3DVertex(-1,-0.02,-1, 0,0,1, m_skycolor, t, o);
+                       for(u32 i=0; i<4; i++){
+                               //if(wicked_time_of_day < 0.5)
+                               if(j==0)
+                                       // Switch from -Z (south) to +X (east)
+                                       vertices[i].Pos.rotateXZBy(90);
+                               else
+                                       // Switch from -Z (south) to -X (west)
+                                       vertices[i].Pos.rotateXZBy(-90);
+                       }
+                       driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
+               }
+       }
+}
+
+void Sky::update(float time_of_day, float time_brightness,
+               float direct_brightness, bool sunlight_seen)
+{
+       // Stabilize initial brightness and color values by flooding updates
+       if(m_first_update){
+               /*dstream<<"First update with time_of_day="<<time_of_day
+                               <<" time_brightness="<<time_brightness
+                               <<" direct_brightness="<<direct_brightness
+                               <<" sunlight_seen="<<sunlight_seen<<std::endl;*/
+               m_first_update = false;
+               for(u32 i=0; i<100; i++){
+                       update(time_of_day, time_brightness, direct_brightness,
+                                       sunlight_seen);
+               }
+               return;
+       }
+
+       m_time_of_day = time_of_day;
+       m_time_brightness = time_brightness;
+       m_sunlight_seen = sunlight_seen;
+       
+       bool is_dawn = (time_brightness >= 0.20 && time_brightness < 0.50);
+
+       video::SColorf bgcolor_bright_normal_f(170./255,200./255,230./255, 1.0);
+       video::SColorf bgcolor_bright_indoor_f(100./255,100./255,100./255, 1.0);
+       //video::SColorf bgcolor_bright_dawn_f(0.666,200./255*0.7,230./255*0.5,1.0);
+       //video::SColorf bgcolor_bright_dawn_f(0.666,0.549,0.220,1.0);
+       //video::SColorf bgcolor_bright_dawn_f(0.666*1.2,0.549*1.0,0.220*1.0, 1.0);
+       video::SColorf bgcolor_bright_dawn_f(0.666*1.2,0.549*1.0,0.220*1.2,1.0);
+
+       video::SColorf skycolor_bright_normal_f =
+                       video::SColor(255, 140, 186, 250);
+       video::SColorf skycolor_bright_dawn_f =
+                       video::SColor(255, 180, 186, 250);
+       
+       video::SColorf cloudcolor_bright_normal_f =
+                       video::SColor(255, 240,240,255);
+       //video::SColorf cloudcolor_bright_dawn_f(1.0, 0.591, 0.4);
+       //video::SColorf cloudcolor_bright_dawn_f(1.0, 0.65, 0.44);
+       video::SColorf cloudcolor_bright_dawn_f(1.0, 0.7, 0.5);
+
+       if(sunlight_seen){
+               //m_brightness = m_brightness * 0.95 + direct_brightness * 0.05;
+               m_brightness = m_brightness * 0.95 + time_brightness * 0.05;
+       }
+       else{
+               if(direct_brightness < m_brightness)
+                       m_brightness = m_brightness * 0.95 + direct_brightness * 0.05;
+               else
+                       m_brightness = m_brightness * 0.98 + direct_brightness * 0.02;
+       }
+       
+       m_clouds_visible = true;
+       float color_change_fraction = 0.98;
+       if(sunlight_seen){
+               if(is_dawn){
+                       m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
+                                       bgcolor_bright_dawn_f, color_change_fraction);
+                       m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
+                                       skycolor_bright_dawn_f, color_change_fraction);
+                       m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
+                                       cloudcolor_bright_dawn_f, color_change_fraction);
+               } else {
+                       m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
+                                       bgcolor_bright_normal_f, color_change_fraction);
+                       m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
+                                       skycolor_bright_normal_f, color_change_fraction);
+                       m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
+                                       cloudcolor_bright_normal_f, color_change_fraction);
+               }
+       } else {
+               m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
+                               bgcolor_bright_indoor_f, color_change_fraction);
+               m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
+                               cloudcolor_bright_normal_f, color_change_fraction);
+               m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
+                               bgcolor_bright_indoor_f, color_change_fraction);
+               m_clouds_visible = false;
+       }
+       video::SColor bgcolor_bright = m_bgcolor_bright_f.toSColor();
+       m_bgcolor = video::SColor(
+                       255,
+                       bgcolor_bright.getRed() * m_brightness,
+                       bgcolor_bright.getGreen() * m_brightness,
+                       bgcolor_bright.getBlue() * m_brightness);
+       
+       video::SColor skycolor_bright = m_skycolor_bright_f.toSColor();
+       m_skycolor = video::SColor(
+                       255,
+                       skycolor_bright.getRed() * m_brightness,
+                       skycolor_bright.getGreen() * m_brightness,
+                       skycolor_bright.getBlue() * m_brightness);
+       
+       float cloud_direct_brightness = 0;
+       if(sunlight_seen){
+               cloud_direct_brightness = time_brightness;
+               if(time_brightness >= 0.2 && time_brightness < 0.7)
+                               cloud_direct_brightness *= 1.3;
+       } else {
+               cloud_direct_brightness = direct_brightness;
+       }
+       m_cloud_brightness = m_cloud_brightness * 0.95 +
+                       cloud_direct_brightness * (1.0 - 0.95);
+       m_cloudcolor_f = video::SColorf(
+                       m_cloudcolor_bright_f.getRed() * m_cloud_brightness,
+                       m_cloudcolor_bright_f.getGreen() * m_cloud_brightness,
+                       m_cloudcolor_bright_f.getBlue() * m_cloud_brightness,
+                       1.0);
+
+}
+
+
diff --git a/src/sky.h b/src/sky.h
new file mode 100644 (file)
index 0000000..39e5923
--- /dev/null
+++ b/src/sky.h
@@ -0,0 +1,84 @@
+/*
+Minetest-c55
+Copyright (C) 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
+(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.
+
+You should have received a copy of the GNU 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.
+*/
+
+#include "common_irrlicht.h"
+#include <ISceneNode.h>
+
+#ifndef SKY_HEADER
+#define SKY_HEADER
+
+#define SKY_MATERIAL_COUNT 3
+#define SKY_STAR_COUNT 200
+
+// Skybox, rendered with zbuffer turned off, before all other nodes.
+class Sky : public scene::ISceneNode
+{
+public:
+       //! constructor
+       Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id);
+
+       virtual void OnRegisterSceneNode();
+
+       //! renders the node.
+       virtual void render();
+
+       virtual const core::aabbox3d<f32>& getBoundingBox() const;
+
+       // Used by Irrlicht for optimizing rendering
+       virtual video::SMaterial& getMaterial(u32 i)
+       { return m_materials[i]; }
+
+       // Used by Irrlicht for optimizing rendering
+       virtual u32 getMaterialCount() const
+       { return SKY_MATERIAL_COUNT; }
+
+       void update(float m_time_of_day, float time_brightness,
+                       float direct_brightness, bool sunlight_seen);
+       
+       float getBrightness(){ return m_brightness; }
+       video::SColor getBgColor(){ return m_bgcolor; }
+       video::SColor getSkyColor(){ return m_skycolor; }
+       
+       bool getCloudsVisible(){ return m_clouds_visible; }
+       video::SColorf getCloudColor(){ return m_cloudcolor_f; }
+
+private:
+       core::aabbox3d<f32> Box;
+       video::SMaterial m_materials[SKY_MATERIAL_COUNT];
+       
+       bool m_first_update;
+       float m_time_of_day;
+       float m_time_brightness;
+       bool m_sunlight_seen;
+       float m_brightness;
+       float m_cloud_brightness;
+       bool m_clouds_visible;
+       video::SColorf m_bgcolor_bright_f;
+       video::SColorf m_skycolor_bright_f;
+       video::SColorf m_cloudcolor_bright_f;
+       video::SColor m_bgcolor;
+       video::SColor m_skycolor;
+       video::SColorf m_cloudcolor_f;
+       v3f m_stars[SKY_STAR_COUNT];
+       u16 m_star_indices[SKY_STAR_COUNT*4];
+       video::S3DVertex m_star_vertices[SKY_STAR_COUNT*4];
+};
+
+#endif
+
index 15c01373561c8320202eb7a4d924cec876b9bb77..fbd76f23084e9f57e2a8a9ce49f35d48309680ac 100644 (file)
@@ -1751,21 +1751,6 @@ std::string deSerializeJsonString(std::istream &is);
 
 //
 
-inline u32 time_to_daynight_ratio(u32 time_of_day)
-{
-       s32 t = time_of_day%24000;
-       if(t < 4500 || t >= 19500)
-               return 150;
-       else if(t < 5000 || t >= 19000)
-               return 350;
-       else if(t < 5500 || t >= 18500)
-               return 500;
-       else if(t < 6000 || t >= 18000)
-               return 750;
-       else
-               return 1000;
-}
-
 // Random helper. Usually d=BS
 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
 {