Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to generate random Vector2/Vector3 points with uniform distribution in a circle/sphere #1731

Open
Xrayez opened this issue Oct 26, 2020 · 0 comments

Comments

@Xrayez
Copy link
Contributor

Xrayez commented Oct 26, 2020

Describe the project you are working on:

Goost - Godot Engine extension

See original feature request at godotengine/godot#34301.
See other related issues: godotengine/godot#7199, godotengine/godot#28264.

Describe the problem or limitation you are having in your project:

The issue is mainly with rand_range(), if you want to generate a bunch of points within a circle (not a square) with a proper uniform distribution rather than normal distribution, without even having to normalize the vectors.

Snippet from godotengine/godot#34301 (comment):

func new_direction() -> Vector2:
   var new_dir: = Vector2()
   new_dir.x = rand_range(-1, 1)
   new_dir.y = rand_range(-1, 1)
   return new_dir.normalized()

The same applies to Vector3.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:

This can be added to Geometry singleton (Geometry2D and Geometry3D in Godot 4.0 now) or RandomNumberGenerator.

For me, this is mainly quite useful for:

  • randomizing motion direction;
  • randomizing gravity direction;
  • restricting objects spawn area to circle/ring;
  • randomizing shots and explosions for various types of weapons (to simulate lack of accuracy);
  • shaking the camera by feeding random camera.offset.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

For 2D, see godotengine/godot#43103, or less complex alternative godotengine/godot#43343

Also, I've recently implemented a bunch of methods for this in goostengine/goost#28, which mostly rely on Math::random() functionality:

rand_point_in_circle(radius)
rand_point_on_circle(radius)
rand_point_in_ring(min_radius, max_radius)

I've actually added those to GoostGeometry2D singleton which is equivalent to Geometry singleton. In Random2D singleton now.

If this enhancement will not be used often, can it be worked around with a few lines of script?:

Sure. Here's a minimal implementation in GDScript for rand_point_in_circle():

static func rand_point_in_circle(p_radius = 1.0): # Unit length by default.
	var r = sqrt(rand_range(0.0, 1.0)) * p_radius
	var t = rand_range(0.0, 1.0) * TAU
	return Vector2(r * cos(t), r * sin(t))

But if you need to generate thousands of points, you'll hit performance bottleneck with GDScript.
Geometry.is_point_in_circle() could be used to help this on the script level by filtering out points which lie outside of a circle, but the distribution won't be uniform anymore.

godotengine/godot#31667 can also be easily worked around via script, but nonetheless it's in the engine.

Is there a reason why this should be core and not an add-on in the asset library?:

There's no reason to bloat Godot, but perhaps we could come up with some minimal core functionality which could solve most use cases. Other engines like Unity or Unreal Engine provide this out of the box, though:

@Xrayez Xrayez changed the title Add methods to generate random Vector2/Vector3 points with uniform distribution in a circle/sphere. Add methods to generate random Vector2/Vector3 points with uniform distribution in a circle/sphere Oct 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants