From 52696e98b4dbba07ffb642bf675798acf312ae92 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 14 Jun 2019 13:22:19 -0700 Subject: [PATCH] fix CPU particles bug with local_coords and transform --- scene/2d/cpu_particles_2d.cpp | 45 ++++++++++++++++++++++++---- scene/2d/cpu_particles_2d.h | 2 ++ scene/3d/cpu_particles.cpp | 56 ++++++++++++++++++++++++++++++----- scene/3d/cpu_particles.h | 4 ++- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index ff27e0a29a7..08304e1e52e 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -85,7 +85,9 @@ void CPUParticles2D::set_randomness_ratio(float p_ratio) { void CPUParticles2D::set_use_local_coordinates(bool p_enable) { local_coords = p_enable; + set_notify_transform(!p_enable); } + void CPUParticles2D::set_speed_scale(float p_scale) { speed_scale = p_scale; @@ -865,11 +867,6 @@ void CPUParticles2D::_update_particle_data_buffer() { PoolVector::Read r = particles.read(); float *ptr = w.ptr(); - Transform2D un_transform; - if (!local_coords) { - un_transform = get_global_transform().affine_inverse(); - } - if (draw_order != DRAW_ORDER_INDEX) { ow = particle_order.write(); order = ow.ptr(); @@ -891,7 +888,7 @@ void CPUParticles2D::_update_particle_data_buffer() { Transform2D t = r[idx].transform; if (!local_coords) { - t = un_transform * t; + t = inv_emission_transform * t; } if (r[idx].active) { @@ -1060,6 +1057,42 @@ void CPUParticles2D::_notification(int p_what) { _update_particle_data_buffer(); } + + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + + inv_emission_transform = get_global_transform().affine_inverse(); + + if (!local_coords) { + + int pc = particles.size(); + + PoolVector::Write w = particle_data.write(); + PoolVector::Read r = particles.read(); + float *ptr = w.ptr(); + + for (int i = 0; i < pc; i++) { + + Transform2D t = inv_emission_transform * r[i].transform; + + if (r[i].active) { + + ptr[0] = t.elements[0][0]; + ptr[1] = t.elements[1][0]; + ptr[2] = 0; + ptr[3] = t.elements[2][0]; + ptr[4] = t.elements[0][1]; + ptr[5] = t.elements[1][1]; + ptr[6] = 0; + ptr[7] = t.elements[2][1]; + + } else { + zeromem(ptr, sizeof(float) * 8); + } + + ptr += 13; + } + } + } } void CPUParticles2D::convert_from_particles(Node *p_particles) { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 81343a46043..ccba576cb13 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -142,6 +142,8 @@ private: int fixed_fps; bool fractional_delta; + Transform2D inv_emission_transform; + DrawOrder draw_order; Ref texture; diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 138c446fea4..bc06e1a96e6 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -910,11 +910,6 @@ void CPUParticles::_update_particle_data_buffer() { PoolVector::Read r = particles.read(); float *ptr = w.ptr(); - Transform un_transform; - if (!local_coords) { - un_transform = get_global_transform().affine_inverse(); - } - if (draw_order != DRAW_ORDER_INDEX) { ow = particle_order.write(); order = ow.ptr(); @@ -932,7 +927,12 @@ void CPUParticles::_update_particle_data_buffer() { Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close if (local_coords) { - dir = un_transform.basis.xform(dir).normalized(); + + // will look different from Particles in editor as this is based on the camera in the scenetree + // and not the editor camera + dir = inv_emission_transform.xform(dir).normalized(); + } else { + dir = dir.normalized(); } SortArray sorter; @@ -950,7 +950,7 @@ void CPUParticles::_update_particle_data_buffer() { Transform t = r[idx].transform; if (!local_coords) { - t = un_transform * t; + t = inv_emission_transform * t; } if (r[idx].active) { @@ -1116,6 +1116,46 @@ void CPUParticles::_notification(int p_what) { _update_particle_data_buffer(); } } + + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + + inv_emission_transform = get_global_transform().affine_inverse(); + + if (!local_coords) { + + int pc = particles.size(); + + PoolVector::Write w = particle_data.write(); + PoolVector::Read r = particles.read(); + float *ptr = w.ptr(); + + for (int i = 0; i < pc; i++) { + + Transform t = inv_emission_transform * r[i].transform; + + if (r[i].active) { + ptr[0] = t.basis.elements[0][0]; + ptr[1] = t.basis.elements[0][1]; + ptr[2] = t.basis.elements[0][2]; + ptr[3] = t.origin.x; + ptr[4] = t.basis.elements[1][0]; + ptr[5] = t.basis.elements[1][1]; + ptr[6] = t.basis.elements[1][2]; + ptr[7] = t.origin.y; + ptr[8] = t.basis.elements[2][0]; + ptr[9] = t.basis.elements[2][1]; + ptr[10] = t.basis.elements[2][2]; + ptr[11] = t.origin.z; + } else { + zeromem(ptr, sizeof(float) * 12); + } + + ptr += 17; + } + + can_update = true; + } + } } void CPUParticles::convert_from_particles(Node *p_particles) { @@ -1393,6 +1433,8 @@ CPUParticles::CPUParticles() { cycle = 0; redraw = false; + set_notify_transform(true); + multimesh = VisualServer::get_singleton()->multimesh_create(); VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0); set_base(multimesh); diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index b863a3cb3fc..6784d49e92c 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -116,7 +116,7 @@ private: const Particle *particles; bool operator()(int p_a, int p_b) const { - return particles[p_a].time < particles[p_b].time; + return particles[p_a].time > particles[p_b].time; } }; @@ -142,6 +142,8 @@ private: int fixed_fps; bool fractional_delta; + Transform inv_emission_transform; + volatile bool can_update; DrawOrder draw_order;