Beispiel #1
0
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);
	}
}
Beispiel #2
0
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];
}
Beispiel #3
0
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 );
		}
	}
}
Beispiel #4
0
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);
	}

}
Beispiel #5
0
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);
	}
}
Beispiel #6
0
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);
	}

}
Beispiel #7
0
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);
	}
}