Пример #1
0
void setup_particles()
{
  int i;
  for (i = 0; i < NUM_NOZZLES; i++) {
    spawn_particle(i);
  }    

}
Пример #2
0
void psys_update(struct psys_emitter *em, float tm)
{
	float dt, spawn_dt, spawn_tm;
	int i, spawn_count;
	struct psys_particle *p, pdummy;
	anm_time_t atm = ANM_SEC2TM(tm);

	if(!em->update) {
		fprintf(stderr, "psys_update called without an update callback\n");
		abort();
	}

	dt = tm - em->last_update;
	if(dt <= 0.0) {
		return;
	}

	psys_eval_attr(&em->attr, atm);

	/* how many particles to spawn for this interval ? */
	em->spawn_acc += psys_get_cur_value(&em->attr.rate) * dt;
	if(em->spawn_acc >= 1.0) {
		spawn_count = em->spawn_acc;
		em->spawn_acc = fmod(em->spawn_acc, 1.0);
	} else {
		spawn_count = 0;
	}

	if(spawn_count) {
		spawn_dt = dt / (float)spawn_count;
	}
	spawn_tm = em->last_update;
	for(i=0; i<spawn_count; i++) {
		if(em->attr.max_particles >= 0 && em->pcount >= em->attr.max_particles) {
			break;
		}

		/* update emitter position for this spawning */
		em->cur_pos = anm_get_position(&em->prs, ANM_SEC2TM(spawn_tm));

		if(!(p = palloc())) {
			return;
		}
		if(spawn_particle(em, p) == -1) {
			pfree(p);
		}
		spawn_tm += spawn_dt;
	}

	/* update all particles */
	p = em->plist;
	while(p) {
		em->update(em, p, tm, dt, em->upd_cls);
		p = p->next;
	}

	/* cleanup dead particles */
	pdummy.next = em->plist;
	p = &pdummy;
	while(p->next) {
		if(p->next->life <= 0) {
			struct psys_particle *tmp = p->next;
			p->next = p->next->next;
			pfree(tmp);
			em->pcount--;
		} else {
			p = p->next;
		}
	}
	em->plist = pdummy.next;

	em->last_update = tm;
}
Пример #3
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;
			}
		}
	}
}