| 855 | static void SpawnParticle(dmArray<Particle>& particles, uint32_t* seed, dmParticleDDF::Emitter* ddf, const dmTransform::TransformS1& emitter_transform, Vector3 emitter_velocity, float emitter_properties[EMITTER_KEY_COUNT], float dt); |
| 856 | |
| 857 | static void UpdateEmitterState(Instance* instance, Emitter* emitter, EmitterPrototype* emitter_prototype, dmParticleDDF::Emitter* emitter_ddf, float dt) |
| 858 | { |
| 859 | DM_PROFILE(__FUNCTION__); |
| 860 | |
| 861 | if (emitter->m_State == EMITTER_STATE_PRESPAWN) |
| 862 | { |
| 863 | if (emitter->m_Timer >= emitter->m_StartDelay) |
| 864 | { |
| 865 | SetEmitterState(instance, emitter, EMITTER_STATE_SPAWNING); |
| 866 | emitter->m_Timer -= emitter->m_StartDelay; |
| 867 | } |
| 868 | } |
| 869 | // Step emitter life |
| 870 | emitter->m_Timer += dt; |
| 871 | if (emitter->m_State != EMITTER_STATE_PRESPAWN) { |
| 872 | // never go above duration |
| 873 | emitter->m_Timer = dmMath::Min(emitter->m_Timer, emitter->m_Duration); |
| 874 | } |
| 875 | if (emitter->m_State == EMITTER_STATE_SPAWNING) |
| 876 | { |
| 877 | // wrap looping emitters when they reach the end |
| 878 | if (IsEmitterLooping(emitter, emitter_ddf) && emitter->m_Timer >= emitter->m_Duration) |
| 879 | { |
| 880 | emitter->m_Timer -= emitter->m_Duration; |
| 881 | } |
| 882 | |
| 883 | // Evaluate spawn delay every frame while spawning (it might change) |
| 884 | float original_emitter_properties[EMITTER_KEY_COUNT]; |
| 885 | float emitter_properties[EMITTER_KEY_COUNT]; |
| 886 | EvaluateEmitterProperties(emitter, emitter_prototype->m_Properties, emitter->m_Duration, original_emitter_properties); |
| 887 | float spawn_rate = dmMath::Max(original_emitter_properties[EMITTER_KEY_SPAWN_RATE] + emitter->m_SpawnRateSpread, 0.0f); |
| 888 | emitter->m_ParticlesToSpawn += spawn_rate * dt; |
| 889 | |
| 890 | uint32_t spawn_count = (uint32_t)emitter->m_ParticlesToSpawn; |
| 891 | emitter->m_ParticlesToSpawn -= spawn_count; |
| 892 | uint32_t count = dmMath::Min(emitter->m_Particles.Remaining(), spawn_count); |
| 893 | dmTransform::TransformS1 emitter_transform(Vector3(emitter_ddf->m_Position), emitter_ddf->m_Rotation, 1.0f); |
| 894 | Vector3 emitter_velocity(0.0f); |
| 895 | if (emitter_ddf->m_Space == EMISSION_SPACE_WORLD) |
| 896 | { |
| 897 | emitter_transform = dmTransform::Mul(instance->m_WorldTransform, emitter_transform); |
| 898 | emitter_velocity = emitter->m_Velocity * emitter_ddf->m_InheritVelocity; |
| 899 | } |
| 900 | for (uint32_t i = 0; i < count; ++i) |
| 901 | { |
| 902 | for (uint32_t i = 0; i < EMITTER_KEY_COUNT; ++i) |
| 903 | { |
| 904 | // Apply spread per particle |
| 905 | float r = dmMath::Rand11(&emitter->m_Seed); |
| 906 | emitter_properties[i] = original_emitter_properties[i] + r * emitter_prototype->m_Properties[i].m_Spread; |
| 907 | } |
| 908 | SpawnParticle(emitter->m_Particles, &emitter->m_Seed, emitter_ddf, emitter_transform, emitter_velocity, emitter_properties, dt); |
| 909 | } |
| 910 | |
| 911 | if (!IsEmitterLooping(emitter, emitter_ddf) && emitter->m_Timer >= emitter->m_Duration) |
| 912 | StopEmitter(instance, emitter); |
| 913 | } |
| 914 | if (emitter->m_State == EMITTER_STATE_POSTSPAWN) |
no test coverage detected