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; } } } ); }
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; } } } }