Пример #1
0
void interpolation_system::integrate_interpolated_transforms(const cosmos& cosm, const augs::delta variable_delta, const augs::delta fixed_delta_for_slowdowns) {
	if (!enabled) {
		return;
	}
	
	const auto seconds = variable_delta.in_seconds();
	const float slowdown_multipliers_decrease = seconds / fixed_delta_for_slowdowns.in_seconds();

	for (const auto e : cosm.get(processing_subjects::WITH_INTERPOLATION)) {
		const auto& actual = e.logic_transform();
		const auto& info = e.get<components::interpolation>();
		auto& integrated = get_interpolated(e);
		auto& cache = per_entity_cache[make_cache_id(e)];

		const float considered_positional_speed = interpolation_speed / (sqrt(cache.positional_slowdown_multiplier));
		const float considered_rotational_speed = interpolation_speed / (sqrt(cache.rotational_slowdown_multiplier));

		if (cache.positional_slowdown_multiplier > 1.f) {
			cache.positional_slowdown_multiplier -= slowdown_multipliers_decrease / 4;

			if (cache.positional_slowdown_multiplier < 1.f) {
				cache.positional_slowdown_multiplier = 1.f;
			}
		}

		if (cache.rotational_slowdown_multiplier > 1.f) {
			cache.rotational_slowdown_multiplier -= slowdown_multipliers_decrease / 4;

			if (cache.rotational_slowdown_multiplier < 1.f) {
				cache.rotational_slowdown_multiplier = 1.f;
			}
		}

		const float positional_averaging_constant = 1.0f - static_cast<float>(pow(info.base_exponent, considered_positional_speed * seconds));
		const float rotational_averaging_constant = 1.0f - static_cast<float>(pow(info.base_exponent, considered_rotational_speed * seconds));

		auto& recorded_pob = cache.recorded_place_of_birth;
		auto& recorded_ver = cache.recorded_version;
		const auto& pob = info.place_of_birth;
		const auto& ver = e.get_id().pool.version;

		if (recorded_pob == pob && recorded_ver == ver) {
			integrated = actual.interpolated_separate(integrated, positional_averaging_constant, rotational_averaging_constant);
		}
		else {
			integrated = actual;
			recorded_pob = pob;
			recorded_ver = ver;
		}
	}
}
void flying_number_indicator_system::advance(const augs::delta dt) {
	global_time_seconds += dt.in_seconds();

	erase_if(
		numbers,
		[this](const number& n) {
			const auto passed_time_seconds = global_time_seconds - n.time_of_occurence_seconds;
			return passed_time_seconds > n.in.maximum_duration_seconds;
		}
	);
}
void interpolation_system::integrate_interpolated_transforms(
	const interpolation_settings& settings,
	const cosmos& cosm,
	const augs::delta delta,
	const augs::delta fixed_delta_for_slowdowns
) {
	set_interpolation_enabled(settings.enabled);

	if (!enabled) {
		return;
	}
	
	const auto seconds = delta.in_seconds();

	if (seconds < 0.00001f) {
		return;
	}

	const float slowdown_multipliers_decrease = seconds / fixed_delta_for_slowdowns.in_seconds();

	cosm.for_each_having<components::interpolation>( 
		[&](const auto e) {
			const auto info = e.template get<components::interpolation>();
			const auto def = e.template get<invariants::interpolation>();

			auto& integrated = get_interpolated(e);
			auto& cache = per_entity_cache[e];

			const auto considered_positional_speed = settings.speed / (sqrt(cache.positional_slowdown_multiplier));
			const auto considered_rotational_speed = settings.speed / (sqrt(cache.rotational_slowdown_multiplier));

			if (cache.positional_slowdown_multiplier > 1.f) {
				cache.positional_slowdown_multiplier -= slowdown_multipliers_decrease / 4;

				if (cache.positional_slowdown_multiplier < 1.f) {
					cache.positional_slowdown_multiplier = 1.f;
				}
			}

			if (cache.rotational_slowdown_multiplier > 1.f) {
				cache.rotational_slowdown_multiplier -= slowdown_multipliers_decrease / 4;

				if (cache.rotational_slowdown_multiplier < 1.f) {
					cache.rotational_slowdown_multiplier = 1.f;
				}
			}

			const auto positional_averaging_constant = 1.0f - static_cast<float>(std::pow(def.base_exponent, considered_positional_speed * seconds));
			const auto rotational_averaging_constant = 1.0f - static_cast<float>(std::pow(def.base_exponent, considered_rotational_speed * seconds));

			auto& recorded_pob = cache.recorded_place_of_birth;
			auto& recorded_ver = cache.recorded_version;

			const auto pob = info.place_of_birth;
			const auto ver = e.get_id().raw.version;

			if (const auto actual = e.find_logic_transform()) {
				if (recorded_pob.compare(pob, 0.01f, 1.f) && recorded_ver == ver) {
					integrated = integrated.interp_separate(*actual, positional_averaging_constant, rotational_averaging_constant);
				}
				else {
					integrated = *actual;
					recorded_pob = pob;
					recorded_ver = ver;
				}
			}
		}
	);
}
Пример #4
0
void particles_simulation_system::advance_visible_streams_and_all_particles(camera_cone cone, const cosmos& cosmos, const augs::delta delta, interpolation_system& interp) {
	for (auto& particle_layer : particles) {
		for (auto& p : particle_layer) {
			p.integrate(delta.in_seconds());
		}

		erase_remove(particle_layer, [](const resources::particle& a) { return a.lifetime_ms >= a.max_lifetime_ms; });
	}

	cone.visible_world_area *= 2.5f;

	const auto targets = 
		cosmos[cosmos.systems_temporary.get<dynamic_tree_system>().determine_visible_entities_from_camera(cone, components::dynamic_tree_node::tree_type::PARTICLE_EXISTENCES)];

	for (const auto it : targets) {
		auto& cache = get_cache(it);
		const auto& existence = it.get<components::particles_existence>();

		const bool should_rebuild_cache = cache.recorded_existence != existence;

		if (should_rebuild_cache) {
			randomization rng = existence.rng_seed;
			cache.recorded_existence = existence;
			cache.emission_instances.clear();

			for (auto emission : (*existence.input.effect)) {
				emission.apply_modifier(existence.input.modifier);

				cache.emission_instances.push_back(emission_instance());
				auto& target_stream = *cache.emission_instances.rbegin();

				const auto var_v = rng.randval(emission.base_velocity_variation);
				//LOG("V: %x", var_v);
				target_stream.velocity.set(std::max(0.f, emission.base_velocity.first - var_v / 2), emission.base_velocity.second + var_v / 2);
				//LOG("Vl: %x Vu: %x", target_stream.velocity.first, target_stream.velocity.second);

				target_stream.stream_info = emission;
				target_stream.enable_streaming = true;
				target_stream.stream_lifetime_ms = 0.f;
				target_stream.angular_offset = rng.randval(emission.angular_offset);
				target_stream.target_spread = rng.randval(emission.spread_degrees);
				target_stream.target_particles_per_sec = rng.randval(emission.particles_per_sec);
				target_stream.swing_spread = rng.randval(emission.swing_spread);
				target_stream.swings_per_sec = rng.randval(emission.swings_per_sec);

				target_stream.min_swing_spread = rng.randval(emission.min_swing_spread);
				target_stream.min_swings_per_sec = rng.randval(emission.min_swings_per_sec);
				target_stream.max_swing_spread = rng.randval(emission.max_swing_spread);
				target_stream.max_swings_per_sec = rng.randval(emission.max_swings_per_sec);

				target_stream.stream_max_lifetime_ms = rng.randval(emission.stream_duration_ms);
				target_stream.stream_particles_to_spawn = rng.randval(emission.num_of_particles_to_spawn_initially);
				target_stream.swing_speed_change = rng.randval(emission.swing_speed_change_rate);
				target_stream.swing_spread_change = rng.randval(emission.swing_spread_change_rate);

				target_stream.fade_when_ms_remaining = rng.randval(emission.fade_when_ms_remaining);
			}
		}

		const auto& transform = it.viewing_transform(interp) + existence.current_displacement;
		randomization rng = cosmos.get_rng_seed_for(it) + cosmos.get_total_steps_passed();

		bool should_destroy = true;

		for (auto& instance : cache.emission_instances) {
			const float stream_delta = std::min(delta.in_milliseconds(), instance.stream_max_lifetime_ms - instance.stream_lifetime_ms);

			instance.stream_lifetime_ms += stream_delta;

			if (instance.stream_lifetime_ms > instance.stream_max_lifetime_ms) {
				continue;
			}

			auto new_particles_to_spawn_by_time = instance.target_particles_per_sec * (stream_delta / 1000.f);

			instance.stream_particles_to_spawn += new_particles_to_spawn_by_time;

			instance.swings_per_sec += rng.randval(-instance.swing_speed_change, instance.swing_speed_change);
			instance.swing_spread += rng.randval(-instance.swing_spread_change, instance.swing_spread_change);

			if (instance.max_swing_spread > 0) {
				augs::clamp(instance.swing_spread, instance.min_swing_spread, instance.max_swing_spread);
			}
			if (instance.max_swings_per_sec > 0) {
				augs::clamp(instance.swings_per_sec, instance.min_swings_per_sec, instance.max_swings_per_sec);
			}

			const int to_spawn = static_cast<int>(std::floor(instance.stream_particles_to_spawn));

			const auto segment_length = existence.distribute_within_segment_of_length;
			const vec2 segment_A = transform.pos + vec2().set_from_degrees(transform.rotation + 90).set_length(segment_length / 2);
			const vec2 segment_B = transform.pos - vec2().set_from_degrees(transform.rotation + 90).set_length(segment_length / 2);

			for (int i = 0; i < to_spawn; ++i) {
				const float t = (static_cast<float>(i) / to_spawn);
				const float time_elapsed = (1.f - t) * delta.in_seconds();

				const vec2 segment_position = augs::interp(segment_A, segment_B, rng.randval(0.f, 1.f));

				spawn_particle(rng, instance, segment_position, transform.rotation +
					instance.swing_spread * static_cast<float>(sin((instance.stream_lifetime_ms / 1000.f) * 2 * PI_f * instance.swings_per_sec))
					, instance.target_spread, instance.stream_info).integrate(time_elapsed);

				instance.stream_particles_to_spawn -= 1.f;
			}
		}
	}
}