fixed world space particles rubber banding
This commit is contained in:
parent
a2567f98db
commit
698799fb40
3 changed files with 35 additions and 24 deletions
|
@ -1060,7 +1060,35 @@ void ParticleSystem::processChunk(ChunkProcessorContext& ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::update(float dt, u32 emitter_idx, const Transform& delta_tr, PageAllocator& page_allocator) {
|
void ParticleSystem::applyTransform(const Transform& new_tr) {
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
if (m_total_time == 0) {
|
||||||
|
m_prev_frame_transform = new_tr;
|
||||||
|
}
|
||||||
|
const Transform delta_tr = new_tr.inverted() * m_prev_frame_transform;
|
||||||
|
for (i32 emitter_idx = 0; emitter_idx < m_emitters.size(); ++emitter_idx) {
|
||||||
|
Emitter& emitter = m_emitters[emitter_idx];
|
||||||
|
if ((u32)m_resource->getFlags() & (u32)ParticleSystemResource::Flags::WORLD_SPACE) {
|
||||||
|
jobs::forEach(emitter.particles_count, 4096, [&](u32 from, u32 to){
|
||||||
|
PROFILE_BLOCK("to world space");
|
||||||
|
// TODO make sure first 3 channels are position
|
||||||
|
float* LUMIX_RESTRICT x = emitter.channels[0].data;
|
||||||
|
float* LUMIX_RESTRICT y = emitter.channels[1].data;
|
||||||
|
float* LUMIX_RESTRICT z = emitter.channels[2].data;
|
||||||
|
for (u32 i = from; i < to; ++i) {
|
||||||
|
Vec3 p{x[i], y[i], z[i]};
|
||||||
|
p = Vec3(delta_tr.transform(p));
|
||||||
|
x[i] = p.x;
|
||||||
|
y[i] = p.y;
|
||||||
|
z[i] = p.z;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_prev_frame_transform = new_tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::update(float dt, u32 emitter_idx, PageAllocator& page_allocator) {
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
|
|
||||||
Emitter& emitter = m_emitters[emitter_idx];
|
Emitter& emitter = m_emitters[emitter_idx];
|
||||||
|
@ -1168,23 +1196,6 @@ void ParticleSystem::update(float dt, u32 emitter_idx, const Transform& delta_tr
|
||||||
profiler::pushInt("count", dst_emitter.resource_emitter.init_emit_count);
|
profiler::pushInt("count", dst_emitter.resource_emitter.init_emit_count);
|
||||||
emit(emitter_idx, Span(outputs, outputs_count), dst_emitter.resource_emitter.init_emit_count, 0);
|
emit(emitter_idx, Span(outputs, outputs_count), dst_emitter.resource_emitter.init_emit_count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((u32)m_resource->getFlags() & (u32)ParticleSystemResource::Flags::WORLD_SPACE) {
|
|
||||||
jobs::forEach(emitter.particles_count, 4096, [&](u32 from, u32 to){
|
|
||||||
PROFILE_BLOCK("to world space");
|
|
||||||
// TODO make sure first 3 channels are position
|
|
||||||
float* LUMIX_RESTRICT x = emitter.channels[0].data;
|
|
||||||
float* LUMIX_RESTRICT y = emitter.channels[1].data;
|
|
||||||
float* LUMIX_RESTRICT z = emitter.channels[2].data;
|
|
||||||
for (u32 i = from; i < to; ++i) {
|
|
||||||
Vec3 p{x[i], y[i], z[i]};
|
|
||||||
p = Vec3(delta_tr.transform(p));
|
|
||||||
x[i] = p.x;
|
|
||||||
y[i] = p.y;
|
|
||||||
z[i] = p.z;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParticleSystem::update(float dt, PageAllocator& page_allocator)
|
bool ParticleSystem::update(float dt, PageAllocator& page_allocator)
|
||||||
|
@ -1197,7 +1208,6 @@ bool ParticleSystem::update(float dt, PageAllocator& page_allocator)
|
||||||
m_constants[1] = m_total_time;
|
m_constants[1] = m_total_time;
|
||||||
|
|
||||||
if (m_total_time == 0) {
|
if (m_total_time == 0) {
|
||||||
m_prev_frame_transform = m_world.getTransform(*m_entity);
|
|
||||||
for (i32 emitter_idx = 0; emitter_idx < m_emitters.size(); ++emitter_idx) {
|
for (i32 emitter_idx = 0; emitter_idx < m_emitters.size(); ++emitter_idx) {
|
||||||
const ParticleSystemResource::Emitter& emitter = m_resource->getEmitters()[emitter_idx];
|
const ParticleSystemResource::Emitter& emitter = m_resource->getEmitters()[emitter_idx];
|
||||||
if (emitter.emit_inputs_count == 0) {
|
if (emitter.emit_inputs_count == 0) {
|
||||||
|
@ -1208,17 +1218,14 @@ bool ParticleSystem::update(float dt, PageAllocator& page_allocator)
|
||||||
|
|
||||||
m_total_time += dt;
|
m_total_time += dt;
|
||||||
|
|
||||||
const Transform world_tr = m_world.getTransform(*m_entity);
|
|
||||||
const Transform delta_tr = world_tr.inverted() * m_prev_frame_transform;
|
|
||||||
for (i32 emitter_idx = 0; emitter_idx < m_emitters.size(); ++emitter_idx) {
|
for (i32 emitter_idx = 0; emitter_idx < m_emitters.size(); ++emitter_idx) {
|
||||||
update(dt, emitter_idx, delta_tr, page_allocator);
|
update(dt, emitter_idx, page_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 c = 0;
|
u32 c = 0;
|
||||||
for (const Emitter& emitter : m_emitters) {
|
for (const Emitter& emitter : m_emitters) {
|
||||||
c += emitter.particles_count;
|
c += emitter.particles_count;
|
||||||
}
|
}
|
||||||
m_prev_frame_transform = world_tr;
|
|
||||||
return c == 0 && m_autodestroy;
|
return c == 0 && m_autodestroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,7 @@ struct LUMIX_RENDERER_API ParticleSystem {
|
||||||
|
|
||||||
void serialize(OutputMemoryStream& blob) const;
|
void serialize(OutputMemoryStream& blob) const;
|
||||||
void deserialize(InputMemoryStream& blob, bool has_autodestroy, bool emit_rate_removed, ResourceManagerHub& manager);
|
void deserialize(InputMemoryStream& blob, bool has_autodestroy, bool emit_rate_removed, ResourceManagerHub& manager);
|
||||||
|
void applyTransform(const Transform& new_tr);
|
||||||
bool update(float dt, PageAllocator& page_allocator);
|
bool update(float dt, PageAllocator& page_allocator);
|
||||||
ParticleSystemResource* getResource() const { return m_resource; }
|
ParticleSystemResource* getResource() const { return m_resource; }
|
||||||
void setResource(ParticleSystemResource* res);
|
void setResource(ParticleSystemResource* res);
|
||||||
|
@ -198,7 +199,7 @@ private:
|
||||||
|
|
||||||
void operator =(ParticleSystem&& rhs) = delete;
|
void operator =(ParticleSystem&& rhs) = delete;
|
||||||
void onResourceChanged(Resource::State old_state, Resource::State new_state, Resource&);
|
void onResourceChanged(Resource::State old_state, Resource::State new_state, Resource&);
|
||||||
void update(float dt, u32 emitter_idx, const Transform& delta_transform, PageAllocator& page_allocator);
|
void update(float dt, u32 emitter_idx, PageAllocator& page_allocator);
|
||||||
void emit(u32 emitter_idx, Span<const float> emit_data, u32 count, float time_step);
|
void emit(u32 emitter_idx, Span<const float> emit_data, u32 count, float time_step);
|
||||||
void ensureCapacity(Emitter& emitter, u32 num_new_particles);
|
void ensureCapacity(Emitter& emitter, u32 num_new_particles);
|
||||||
void run(RunningContext& ctx);
|
void run(RunningContext& ctx);
|
||||||
|
|
|
@ -1493,6 +1493,9 @@ struct RenderModuleImpl final : RenderModule {
|
||||||
m_culling_system->setPosition(entity, pos);
|
m_culling_system->setPosition(entity, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_world.hasComponent(entity, PARTICLE_EMITTER_TYPE)) {
|
||||||
|
m_particle_emitters[entity].applyTransform(m_world.getTransform(entity));
|
||||||
|
}
|
||||||
|
|
||||||
bool was_updating = m_is_updating_attachments;
|
bool was_updating = m_is_updating_attachments;
|
||||||
m_is_updating_attachments = true;
|
m_is_updating_attachments = true;
|
||||||
|
|
Loading…
Reference in a new issue