void TestUtilities::testAngleWrapAround() { UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001); UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001); UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001); UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001); for (float f = -720; f <= -360; f += 0.25) { UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001); } for (float f = -1440; f <= 1440; f += 0.25) { UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001); UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001); UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001); UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001); } }
inline static const char *yawToDirectionString(int yaw) { static const char *direction[4] = {"N +Z", "W -X", "S -Z", "E +X"}; yaw = wrapDegrees_0_360(yaw); yaw = (yaw + 45) % 360 / 90; return direction[yaw]; }
void gsMapper::drawMap(v3s16 position) { // width and height in nodes (these don't really need to be exact) s16 nwidth = floor(d_width / d_scale); s16 nheight = floor(d_height / d_scale); bool hasChanged = false; // check if position is outside the center if (d_valid) { if ( (position.X - d_border) < d_origin.X || (position.Z - d_border) < d_origin.Z || (position.X + d_border) > (d_origin.X + nwidth) || (position.Z + d_border) > (d_origin.Z + nheight) ) d_valid = false; } // recalculate the origin if (!d_valid || d_tracking) { d_origin.X = floor(position.X - (nwidth / 2)); d_origin.Y = d_surface; d_origin.Z = floor(position.Z - (nheight / 2)); d_valid = true; hasChanged = true; } // rescan next division of the map Map &map = d_client->getEnv().getMap(); v3s16 p; s16 x = 0; s16 y = 0; s16 z = 0; while (z < (nheight / 8) && (z + d_scanZ) < nheight) { p.Z = d_origin.Z + z + d_scanZ; x = 0; while (x < (nwidth / 8) && (x + d_scanX) < nwidth) { p.X = d_origin.X + x + d_scanX; bool b = true; // "above" mode: surface = mid-point for scanning if (d_above) { p.Y = d_surface + (d_scan / 2); for (y = 0; y < d_scan; y++) { if (b) { MapNode n = map.getNodeNoEx(p); p.Y--; if (n.param0 != CONTENT_IGNORE && n.param0 != CONTENT_AIR) { b = false; p.Y = d_surface; // check to see if this node is different from the map std::map<v3s16, u16>::iterator i2 = d_map.find(p); if ( i2 == d_map.end() || (i2 != d_map.end() && n.param0 != d_map[p]) ) { hasChanged = true; d_map[p] = n.param0; // change it } } } } // not "above" = use the radar for mapping } else { p.Y = position.Y + 1; MapNode n = map.getNodeNoEx(p); bool w = (n.param0 != CONTENT_IGNORE && n.param0 != CONTENT_AIR); int count = 0; u16 id = CONTENT_AIR; while (b) { if (w) // wall = scan up for air { p.Y++; n = map.getNodeNoEx(p); if (n.param0 == CONTENT_AIR) b = false; else id = n.param0; } else { // not wall = scan down for non-air p.Y--; n = map.getNodeNoEx(p); if (n.param0 != CONTENT_IGNORE && n.param0 != CONTENT_AIR) { id = n.param0; b = false; } } if (b && count++ >= (d_scan / 8)) { b = false; id = CONTENT_AIR; } } p.Y = d_surface; // the data is always flat std::map<v3s16, u16>::iterator i5 = d_radar.find(p); if ( i5 == d_radar.end() || (i5 != d_radar.end() && id != d_radar[p]) ) { hasChanged = true; d_radar[p] = id; // change it } } x++; } z++; } // move the scan block d_scanX += (nwidth / 8); if (d_scanX >= nwidth) { d_scanX = 0; d_scanZ += (nheight / 8); if (d_scanZ >= nheight) d_scanZ = 0; } video::IVideoDriver *driver = d_device->getVideoDriver(); if (hasChanged || !d_hastex) { // set up the image core::dimension2d<u32> dim(nwidth, nheight); video::IImage *image = driver->createImage(video::ECF_A8R8G8B8, dim); assert(image); bool psum = false; for (z = 0; z < nheight; z++) { for (x = 0; x < nwidth; x++) { p.X = d_origin.X + x; p.Y = d_surface; p.Z = d_origin.Z + z; u16 i = CONTENT_IGNORE; if (d_above) { std::map<v3s16, u16>::iterator i3 = d_map.find(p); if (i3 != d_map.end()) i = d_map[p]; } else { std::map<v3s16, u16>::iterator i6 = d_radar.find(p); if (i6 != d_radar.end()) i = d_radar[p]; } video::SColor c = getColorFromId(i); c.setAlpha(d_alpha); image->setPixel(x, nheight - z - 1, c); if (i != CONTENT_IGNORE) psum = true; } } // image -> texture if (psum && d_cooldown2 == 0) { if (d_hastex) { driver->removeTexture(d_texture); d_hastex = false; } std::string f = "gsmapper__" + itos(d_device->getTimer()->getRealTime()); d_texture = driver->addTexture(f.c_str(), image); assert(d_texture); d_hastex = true; d_cooldown2 = 5; // don't generate too many textures all at once } else { d_cooldown2--; if (d_cooldown2 < 0) d_cooldown2 = 0; } image->drop(); } // draw map texture if (d_hastex) { driver->draw2DImage( d_texture, core::rect<s32>(d_posx, d_posy, d_posx+d_width, d_posy+d_height), core::rect<s32>(0, 0, nwidth, nheight), 0, 0, true ); } // draw local player marker if (d_tsrc->isKnownSourceImage("player_marker0.png")) { v3s16 p = floatToInt(d_player->getPosition(), BS); if ( p.X >= d_origin.X && p.X <= (d_origin.X + nwidth) && p.Z >= d_origin.Z && p.Z <= (d_origin.Z + nheight) ) { f32 y = floor(360 - wrapDegrees_0_360(d_player->getYaw())); if (y < 0) y = 0; int r = floor(y / 90.0); int a = floor(fmod(y, 90.0) / 10.0); std::string f = "player_marker" + itos(a) + ".png"; video::ITexture *pmarker = d_tsrc->getTexture(f); assert(pmarker); v2u32 size = pmarker->getOriginalSize(); if (r > 0) { core::dimension2d<u32> dim(size.X, size.Y); video::IImage *image1 = driver->createImage(pmarker, core::position2d<s32>(0, 0), dim); assert(image1); // rotate image video::IImage *image2 = driver->createImage(video::ECF_A8R8G8B8, dim); assert(image2); for (u32 y = 0; y < size.Y; y++) for (u32 x = 0; x < size.X; x++) { video::SColor c; if (r == 1) { c = image1->getPixel(y, (size.X - x - 1)); } else if (r == 2) { c = image1->getPixel((size.X - x - 1), (size.Y - y - 1)); } else { c = image1->getPixel((size.Y - y - 1), x); } image2->setPixel(x, y, c); } image1->drop(); if (d_hasptex) { driver->removeTexture(d_pmarker); d_hasptex = false; } d_pmarker = driver->addTexture("playermarker__temp__", image2); assert(d_pmarker); pmarker = d_pmarker; d_hasptex = true; image2->drop(); } s32 sx = d_posx + floor((p.X - d_origin.X) * d_scale) - (size.X / 2); s32 sy = d_posy + floor((nheight - (p.Z - d_origin.Z)) * d_scale) - (size.Y / 2); driver->draw2DImage( pmarker, core::rect<s32>(sx, sy, sx+size.X, sy+size.Y), core::rect<s32>(0, 0, size.X, size.Y), 0, 0, true ); } } }
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.35); //video::SColorf bgcolor_bright_normal_f(170./255,200./255,230./255, 1.0); video::SColorf bgcolor_bright_normal_f(155./255,193./255,240./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 bgcolor_bright_dawn_f (155./255*1.2,193./255,240./255, 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); video::SColorf cloudcolor_bright_dawn_f(1.0, 0.875, 0.75); float cloud_color_change_fraction = 0.95; if(sunlight_seen){ if(fabs(time_brightness - m_brightness) < 0.2){ m_brightness = m_brightness * 0.95 + time_brightness * 0.05; } else { m_brightness = m_brightness * 0.80 + time_brightness * 0.20; cloud_color_change_fraction = 0.0; } } 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_skycolor_bright_f = m_skycolor_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_clouds_visible = false; } // Horizon coloring based on sun and moon direction during sunset and sunrise video::SColor pointcolor = video::SColor(255, 255, 255, m_bgcolor.getAlpha()); if (m_directional_colored_fog) { if (m_horizon_blend() != 0) { // calculate hemisphere value from yaw f32 pointcolor_blend = wrapDegrees_0_360(m_player->getYaw() + 90); if (pointcolor_blend > 180) pointcolor_blend = 360 - pointcolor_blend; pointcolor_blend /= 180; // bound view angle to determine where transition starts and ends pointcolor_blend = rangelim(1 - pointcolor_blend * 1.375, 0, 1 / 1.375) * 1.375; // combine the colors when looking up or down, otherwise turning looks weird pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::abs(m_player->getPitch())) / 90 * 1.5, 1)); // invert direction to match where the sun and moon are rising if (m_time_of_day > 0.5) pointcolor_blend = 1 - pointcolor_blend; // horizon colors of sun and moon f32 pointcolor_light = rangelim(m_time_brightness * 3, 0.2, 1); video::SColorf pointcolor_sun_f(1, 1, 1, 1); pointcolor_sun_f.r = pointcolor_light * 1; pointcolor_sun_f.b = pointcolor_light * (0.25 + (rangelim(m_time_brightness, 0.25, 0.75) - 0.25) * 2 * 0.75); pointcolor_sun_f.g = pointcolor_light * (pointcolor_sun_f.b * 0.375 + (rangelim(m_time_brightness, 0.05, 0.15) - 0.05) * 10 * 0.625); video::SColorf pointcolor_moon_f(0.5 * pointcolor_light, 0.6 * pointcolor_light, 0.8 * pointcolor_light, 1); video::SColor pointcolor_sun = pointcolor_sun_f.toSColor(); video::SColor pointcolor_moon = pointcolor_moon_f.toSColor(); // calculate the blend color pointcolor = m_mix_scolor(pointcolor_moon, pointcolor_sun, pointcolor_blend); } } 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); if (m_directional_colored_fog) { m_bgcolor = m_mix_scolor(m_bgcolor, pointcolor, m_horizon_blend() * 0.5); } 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); if (m_directional_colored_fog) { m_skycolor = m_mix_scolor(m_skycolor, pointcolor, m_horizon_blend() * 0.25); } float cloud_direct_brightness = 0; if(sunlight_seen) { if (!m_directional_colored_fog) { cloud_direct_brightness = time_brightness; if(time_brightness >= 0.2 && time_brightness < 0.7) cloud_direct_brightness *= 1.3; } else { cloud_direct_brightness = MYMIN(m_horizon_blend() * 0.15 + m_time_brightness, 1); } } else { cloud_direct_brightness = direct_brightness; } m_cloud_brightness = m_cloud_brightness * cloud_color_change_fraction + cloud_direct_brightness * (1.0 - cloud_color_change_fraction); m_cloudcolor_f = video::SColorf( m_cloudcolor_bright_f.r * m_cloud_brightness, m_cloudcolor_bright_f.g * m_cloud_brightness, m_cloudcolor_bright_f.b * m_cloud_brightness, 1.0); if (m_directional_colored_fog) { m_cloudcolor_f = m_mix_scolorf(m_cloudcolor_f, video::SColorf(pointcolor), m_horizon_blend() * 0.25); } }
void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_control, const CameraOrientation &cam, const PointedThing &pointed_old, float dtime) { v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); if (m_flags.show_debug) { static float drawtime_avg = 0; drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05; u16 fps = 1.0 / stats.dtime_jitter.avg; std::ostringstream os(std::ios_base::binary); os << std::fixed << PROJECT_NAME_C " " << g_version_hash << ", FPS: " << fps << std::setprecision(0) << ", drawtime: " << drawtime_avg << "ms" << std::setprecision(1) << ", dtime jitter: " << (stats.dtime_jitter.max_fraction * 100.0) << "%" << std::setprecision(1) << ", view range: " << (draw_control->range_all ? "All" : itos(draw_control->wanted_range)) << std::setprecision(3) << ", RTT: " << client->getRTT() << "s"; setStaticText(m_guitext, utf8_to_wide(os.str()).c_str()); m_guitext->setRelativePosition(core::rect<s32>(5, 5, screensize.X, 5 + g_fontengine->getTextHeight())); } // Finally set the guitext visible depending on the flag m_guitext->setVisible(m_flags.show_debug); if (m_flags.show_debug) { LocalPlayer *player = client->getEnv().getLocalPlayer(); v3f player_position = player->getPosition(); std::ostringstream os(std::ios_base::binary); os << std::setprecision(1) << std::fixed << "pos: (" << (player_position.X / BS) << ", " << (player_position.Y / BS) << ", " << (player_position.Z / BS) << "), yaw: " << (wrapDegrees_0_360(cam.camera_yaw)) << "° " << yawToDirectionString(cam.camera_yaw) << ", seed: " << ((u64)client->getMapSeed()); if (pointed_old.type == POINTEDTHING_NODE) { ClientMap &map = client->getEnv().getClientMap(); const NodeDefManager *nodedef = client->getNodeDefManager(); MapNode n = map.getNodeNoEx(pointed_old.node_undersurface); if (n.getContent() != CONTENT_IGNORE && nodedef->get(n).name != "unknown") { os << ", pointed: " << nodedef->get(n).name << ", param2: " << (u64) n.getParam2(); } } setStaticText(m_guitext2, utf8_to_wide(os.str()).c_str()); m_guitext2->setRelativePosition(core::rect<s32>(5, 5 + g_fontengine->getTextHeight(), screensize.X, 5 + g_fontengine->getTextHeight() * 2 )); } m_guitext2->setVisible(m_flags.show_debug); setStaticText(m_guitext_info, translate_string(m_infotext).c_str()); m_guitext_info->setVisible(m_flags.show_hud && g_menumgr.menuCount() == 0); static const float statustext_time_max = 1.5f; if (!m_statustext.empty()) { m_statustext_time += dtime; if (m_statustext_time >= statustext_time_max) { clearStatusText(); m_statustext_time = 0.0f; } } setStaticText(m_guitext_status, translate_string(m_statustext).c_str()); m_guitext_status->setVisible(!m_statustext.empty()); if (!m_statustext.empty()) { s32 status_width = m_guitext_status->getTextWidth(); s32 status_height = m_guitext_status->getTextHeight(); s32 status_y = screensize.Y - 150; s32 status_x = (screensize.X - status_width) / 2; m_guitext_status->setRelativePosition(core::rect<s32>(status_x , status_y - status_height, status_x + status_width, status_y)); // Fade out video::SColor final_color = m_statustext_initial_color; final_color.setAlpha(0); video::SColor fade_color = m_statustext_initial_color.getInterpolated_quadratic( m_statustext_initial_color, final_color, m_statustext_time / statustext_time_max); m_guitext_status->setOverrideColor(fade_color); m_guitext_status->enableOverrideColor(true); } }
void Sky::update(float time_of_day, float time_brightness, float direct_brightness, bool sunlight_seen, CameraMode cam_mode, float yaw, float pitch) { // 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, cam_mode, yaw, pitch); } return; } scene::ICameraSceneNode* camera = SceneManager->getActiveCamera(); v3POS player_position = floatToInt(camera->getPosition(), BS)+camera_offset; float shift1 = (float)player_position.Y / MAP_GENERATION_LIMIT; float height_color = 1; if (shift1 > 0) height_color -= shift1*0.8; 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.35); //video::SColorf bgcolor_bright_normal_f(170./255,200./255,230./255, 1.0); video::SColorf bgcolor_bright_normal_f(155./255,193./255,240./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 bgcolor_bright_dawn_f (155./255*1.2,193./255,240./255, 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); video::SColorf cloudcolor_bright_dawn_f(1.0, 0.875, 0.75); float cloud_color_change_fraction = 0.95; if(sunlight_seen){ if(fabs(time_brightness - m_brightness) < 0.2){ m_brightness = m_brightness * 0.95 + time_brightness * 0.05; } else { m_brightness = m_brightness * 0.80 + time_brightness * 0.20; cloud_color_change_fraction = 0.0; } } 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_skycolor_bright_f = m_skycolor_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_clouds_visible = false; } video::SColor bgcolor_bright = m_bgcolor_bright_f.toSColor(); m_bgcolor = video::SColor( 255, bgcolor_bright.getRed() * m_brightness* height_color, bgcolor_bright.getGreen() * m_brightness* height_color, bgcolor_bright.getBlue() * m_brightness* height_color); video::SColor skycolor_bright = m_skycolor_bright_f.toSColor(); m_skycolor = video::SColor( 255, skycolor_bright.getRed() * m_brightness * height_color, skycolor_bright.getGreen() * m_brightness * height_color, skycolor_bright.getBlue() * m_brightness * height_color); // Horizon coloring based on sun and moon direction during sunset and sunrise video::SColor pointcolor = video::SColor(255, 255, 255, m_bgcolor.getAlpha()); if (m_directional_colored_fog) { if (m_horizon_blend() != 0) { // calculate hemisphere value from yaw, (inverted in third person front view) s8 dir_factor = 1; if (cam_mode > CAMERA_MODE_THIRD) dir_factor = -1; f32 pointcolor_blend = wrapDegrees_0_360( yaw*dir_factor + 90); if (pointcolor_blend > 180) pointcolor_blend = 360 - pointcolor_blend; pointcolor_blend /= 180; // bound view angle to determine where transition starts and ends pointcolor_blend = rangelim(1 - pointcolor_blend * 1.375, 0, 1 / 1.375) * 1.375; // combine the colors when looking up or down, otherwise turning looks weird pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::abs(pitch)) / 90 * 1.5, 1)); // invert direction to match where the sun and moon are rising if (m_time_of_day > 0.5) pointcolor_blend = 1 - pointcolor_blend; // horizon colors of sun and moon f32 pointcolor_light = rangelim(m_time_brightness * 3, 0.2, 1); video::SColorf pointcolor_sun_f(1, 1, 1, 1); if (m_sun_tonemap) { pointcolor_sun_f.r = pointcolor_light * (float)m_materials[3].EmissiveColor.getRed() / 255; pointcolor_sun_f.b = pointcolor_light * (float)m_materials[3].EmissiveColor.getBlue() / 255; pointcolor_sun_f.g = pointcolor_light * (float)m_materials[3].EmissiveColor.getGreen() / 255; } else { pointcolor_sun_f.r = pointcolor_light * 1; pointcolor_sun_f.b = pointcolor_light * (0.25 + (rangelim(m_time_brightness, 0.25, 0.75) - 0.25) * 2 * 0.75); pointcolor_sun_f.g = pointcolor_light * (pointcolor_sun_f.b * 0.375 + (rangelim(m_time_brightness, 0.05, 0.15) - 0.05) * 10 * 0.625); } video::SColorf pointcolor_moon_f(0.5 * pointcolor_light, 0.6 * pointcolor_light, 0.8 * pointcolor_light, 1); if (m_moon_tonemap) { pointcolor_moon_f.r = pointcolor_light * (float)m_materials[4].EmissiveColor.getRed() / 255; pointcolor_moon_f.b = pointcolor_light * (float)m_materials[4].EmissiveColor.getBlue() / 255; pointcolor_moon_f.g = pointcolor_light * (float)m_materials[4].EmissiveColor.getGreen() / 255; } video::SColor pointcolor_sun = pointcolor_sun_f.toSColor(); video::SColor pointcolor_moon = pointcolor_moon_f.toSColor(); // calculate the blend color pointcolor = m_mix_scolor(pointcolor_moon, pointcolor_sun, pointcolor_blend); } m_bgcolor = m_mix_scolor(m_bgcolor, pointcolor, m_horizon_blend() * 0.5); m_skycolor = m_mix_scolor(m_skycolor, pointcolor, m_horizon_blend() * 0.25); } float cloud_direct_brightness = 0; if(sunlight_seen) { if (!m_directional_colored_fog) { cloud_direct_brightness = time_brightness; if(time_brightness >= 0.2 && time_brightness < 0.7) cloud_direct_brightness *= 1.3; } else { cloud_direct_brightness = MYMIN(m_horizon_blend() * 0.15 + m_time_brightness, 1); } } else { cloud_direct_brightness = direct_brightness; } m_cloud_brightness = m_cloud_brightness * cloud_color_change_fraction + cloud_direct_brightness * (1.0 - cloud_color_change_fraction); m_cloudcolor_f = video::SColorf( m_cloudcolor_bright_f.r * m_cloud_brightness, m_cloudcolor_bright_f.g * m_cloud_brightness, m_cloudcolor_bright_f.b * m_cloud_brightness, 1.0); if (m_directional_colored_fog) { m_cloudcolor_f = m_mix_scolorf(m_cloudcolor_f, video::SColorf(pointcolor), m_horizon_blend() * 0.25); } }
void Sky::update(float time_of_day, float time_brightness, float direct_brightness, bool sunlight_seen, CameraMode cam_mode, float yaw, float pitch) { // 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, cam_mode, yaw, pitch); } return; } m_time_of_day = time_of_day; m_time_brightness = time_brightness; m_sunlight_seen = sunlight_seen; m_bodies_visible = true; bool is_dawn = (time_brightness >= 0.20 && time_brightness < 0.35); /* Development colours video::SColorf bgcolor_bright_normal_f(170. / 255, 200. / 255, 230. / 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 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); */ video::SColorf bgcolor_bright_normal_f = video::SColor(255, 155, 193, 240); video::SColorf bgcolor_bright_indoor_f = video::SColor(255, 100, 100, 100); video::SColorf bgcolor_bright_dawn_f = video::SColor(255, 186, 193, 240); video::SColorf bgcolor_bright_night_f = video::SColor(255, 64, 144, 255); 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 skycolor_bright_night_f = video::SColor(255, 0, 107, 255); // pure white: becomes "diffuse light component" for clouds video::SColorf cloudcolor_bright_normal_f = video::SColor(255, 255, 255, 255); // dawn-factoring version of pure white (note: R is above 1.0) video::SColorf cloudcolor_bright_dawn_f(255.0f/240.0f, 223.0f/240.0f, 191.0f/255.0f); float cloud_color_change_fraction = 0.95; if (sunlight_seen) { if (std::fabs(time_brightness - m_brightness) < 0.2f) { m_brightness = m_brightness * 0.95 + time_brightness * 0.05; } else { m_brightness = m_brightness * 0.80 + time_brightness * 0.20; cloud_color_change_fraction = 0.0; } } 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) { // 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 { if (time_brightness < 0.07) { // Night m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated( bgcolor_bright_night_f, color_change_fraction); m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated( skycolor_bright_night_f, color_change_fraction); } else { // Day 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_skycolor_bright_f = m_skycolor_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_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 ); // Horizon coloring based on sun and moon direction during sunset and sunrise video::SColor pointcolor = video::SColor(m_bgcolor.getAlpha(), 255, 255, 255); if (m_directional_colored_fog) { if (m_horizon_blend() != 0) { // Calculate hemisphere value from yaw, (inverted in third person front view) s8 dir_factor = 1; if (cam_mode > CAMERA_MODE_THIRD) dir_factor = -1; f32 pointcolor_blend = wrapDegrees_0_360(yaw * dir_factor + 90); if (pointcolor_blend > 180) pointcolor_blend = 360 - pointcolor_blend; pointcolor_blend /= 180; // Bound view angle to determine where transition starts and ends pointcolor_blend = rangelim(1 - pointcolor_blend * 1.375, 0, 1 / 1.375) * 1.375; // Combine the colors when looking up or down, otherwise turning looks weird pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::fabs(pitch)) / 90 * 1.5, 1)); // Invert direction to match where the sun and moon are rising if (m_time_of_day > 0.5) pointcolor_blend = 1 - pointcolor_blend; // Horizon colors of sun and moon f32 pointcolor_light = rangelim(m_time_brightness * 3, 0.2, 1); video::SColorf pointcolor_sun_f(1, 1, 1, 1); if (m_sun_tonemap) { pointcolor_sun_f.r = pointcolor_light * (float)m_materials[3].EmissiveColor.getRed() / 255; pointcolor_sun_f.b = pointcolor_light * (float)m_materials[3].EmissiveColor.getBlue() / 255; pointcolor_sun_f.g = pointcolor_light * (float)m_materials[3].EmissiveColor.getGreen() / 255; } else { pointcolor_sun_f.r = pointcolor_light * 1; pointcolor_sun_f.b = pointcolor_light * (0.25 + (rangelim(m_time_brightness, 0.25, 0.75) - 0.25) * 2 * 0.75); pointcolor_sun_f.g = pointcolor_light * (pointcolor_sun_f.b * 0.375 + (rangelim(m_time_brightness, 0.05, 0.15) - 0.05) * 10 * 0.625); } video::SColorf pointcolor_moon_f(0.5 * pointcolor_light, 0.6 * pointcolor_light, 0.8 * pointcolor_light, 1); if (m_moon_tonemap) { pointcolor_moon_f.r = pointcolor_light * (float)m_materials[4].EmissiveColor.getRed() / 255; pointcolor_moon_f.b = pointcolor_light * (float)m_materials[4].EmissiveColor.getBlue() / 255; pointcolor_moon_f.g = pointcolor_light * (float)m_materials[4].EmissiveColor.getGreen() / 255; } video::SColor pointcolor_sun = pointcolor_sun_f.toSColor(); video::SColor pointcolor_moon = pointcolor_moon_f.toSColor(); // Calculate the blend color pointcolor = m_mix_scolor(pointcolor_moon, pointcolor_sun, pointcolor_blend); } m_bgcolor = m_mix_scolor(m_bgcolor, pointcolor, m_horizon_blend() * 0.5); m_skycolor = m_mix_scolor(m_skycolor, pointcolor, m_horizon_blend() * 0.25); } float cloud_direct_brightness = 0; if (sunlight_seen) { if (!m_directional_colored_fog) { cloud_direct_brightness = time_brightness; if (time_brightness >= 0.2 && time_brightness < 0.7) cloud_direct_brightness *= 1.3; } else { cloud_direct_brightness = MYMIN(m_horizon_blend() * 0.15 + m_time_brightness, 1); } } else { cloud_direct_brightness = direct_brightness; } m_cloud_brightness = m_cloud_brightness * cloud_color_change_fraction + cloud_direct_brightness * (1.0 - cloud_color_change_fraction); m_cloudcolor_f = video::SColorf( m_cloudcolor_bright_f.r * m_cloud_brightness, m_cloudcolor_bright_f.g * m_cloud_brightness, m_cloudcolor_bright_f.b * m_cloud_brightness, 1.0 ); if (m_directional_colored_fog) { m_cloudcolor_f = m_mix_scolorf(m_cloudcolor_f, video::SColorf(pointcolor), m_horizon_blend() * 0.25); } }
void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } // If attached, check that our parent is still there. If it isn't, detach. if(m_attachment_parent_id && !isAttached()) { m_attachment_parent_id = 0; m_attachment_bone = ""; m_attachment_position = v3f(0,0,0); m_attachment_rotation = v3f(0,0,0); sendPosition(false, true); } m_last_sent_position_timer += dtime; // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally // If the object gets detached this comes into effect automatically from the last known origin if(isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); m_base_position = pos; m_velocity = v3f(0,0,0); m_acceleration = v3f(0,0,0); } else { if(m_prop.physical){ aabb3f box = m_prop.collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.25; // Distance per iteration v3f p_pos = m_base_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(m_env, m_env->getGameDef(), pos_max_d, box, m_prop.stepheight, dtime, &p_pos, &p_velocity, p_acceleration, this, m_prop.collideWithObjects); // Apply results m_base_position = p_pos; m_velocity = p_velocity; m_acceleration = p_acceleration; } else { m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; m_velocity += dtime * m_acceleration; } if (m_prop.automatic_face_movement_dir && (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) { float target_yaw = atan2(m_velocity.Z, m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset; float max_rotation_delta = dtime * m_prop.automatic_face_movement_max_rotation_per_sec; m_yaw = wrapDegrees_0_360(m_yaw); wrappedApproachShortest(m_yaw, target_yaw, max_rotation_delta, 360.f); } } if(m_registered){ m_env->getScriptIface()->luaentity_Step(m_id, dtime); } if (!send_recommended) return; if(!isAttached()) { // TODO: force send when acceleration changes enough? float minchange = 0.2*BS; if(m_last_sent_position_timer > 1.0){ minchange = 0.01*BS; } else if(m_last_sent_position_timer > 0.2){ minchange = 0.05*BS; } float move_d = m_base_position.getDistanceFrom(m_last_sent_position); move_d += m_last_sent_move_precision; float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); if (move_d > minchange || vel_d > minchange || std::fabs(m_yaw - m_last_sent_yaw) > 1.0) { sendPosition(true, false); } } if (!m_armor_groups_sent) { m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_animation_sent) { m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_animation_speed_sent) { m_animation_speed_sent = true; std::string str = gob_cmd_update_animation_speed(m_animation_speed); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if (!m_bone_position_sent) { m_bone_position_sent = true; for (std::unordered_map<std::string, core::vector2d<v3f>>::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if (!m_attachment_sent) { m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }