Browse Source

cpu_particles: Return uniform density spheres.

The current implementation normalizes points from a uniform distribution
on a cube. This creates a non-uniform distribution on the sphere.
Simon Puchert 6 years ago
parent
commit
18ba1bc824
2 changed files with 6 additions and 3 deletions
  1. 3 2
      scene/2d/cpu_particles_2d.cpp
  2. 3 1
      scene/3d/cpu_particles.cpp

+ 3 - 2
scene/2d/cpu_particles_2d.cpp

@@ -661,8 +661,9 @@ void CPUParticles2D::_particles_process(float p_delta) {
 					//do none
 				} break;
 				case EMISSION_SHAPE_SPHERE: {
-					Vector3 sphere_shape = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0).normalized() * emission_sphere_radius;
-					p.transform[2] = Vector2(sphere_shape.x, sphere_shape.y);
+					float s = Math::randf(), t = 2.0 * Math_PI * Math::randf();
+					float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
+					p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
 				} break;
 				case EMISSION_SHAPE_RECTANGLE: {
 					p.transform[2] = Vector2(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_rect_extents;

+ 3 - 1
scene/3d/cpu_particles.cpp

@@ -643,7 +643,9 @@ void CPUParticles::_particles_process(float p_delta) {
 					//do none
 				} break;
 				case EMISSION_SHAPE_SPHERE: {
-					p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0).normalized() * emission_sphere_radius;
+					float s = 2.0 * Math::randf() - 1.0, t = 2.0 * Math_PI * Math::randf();
+					float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
+					p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s);
 				} break;
 				case EMISSION_SHAPE_BOX: {
 					p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_box_extents;