2

Im trying to make stars on the sky, but the stars distribution isnt even.

This is what i tried:

rx = rand(0.0f, PI*2.0f);
ry = rand(0.0f, PI);
x = sin(ry)*sin(rx)*range;
y = sin(ry)*cos(rx)*range;
z = cos(ry)*range;

Which results to:

img http://img716.imageshack.us/img716/3320/sphererandom.jpg

And:

rx = rand(-1.0f, 1.0f);
ry = rand(-1.0f, 1.0f);
rz = rand(-1.0f, 1.0f);
x = rx*range;
y = ry*range;
z = rz*range;

Which results to:

img2 http://img710.imageshack.us/img710/5152/squarerandom.jpg

(doesnt make a sphere, but opengl will not tell a difference, though).

As you can see, there is always some "corner" where are more points in average. How can i create random points on a sphere where the points will be distributed evenly?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Rookie
  • 4,064
  • 6
  • 54
  • 86

3 Answers3

4

you can do

z = rand(-1, 1)
rxy = sqrt(1 - z*z)
phi = rand(0, 2*PI)
x = rxy * cos(phi)
y = rxy * sin(phi)

Here rand(u,v) draws a uniform random from interal [u,v]

Kan Li
  • 8,557
  • 8
  • 53
  • 93
  • No. It can be derived mathematically. – Kan Li Jan 12 '12 at 17:14
  • @Alexandre C., it is not?! i tested the code, and i swear: i couldnt tell there was any concentration in anywhere! perfectly even to my eyes... – Rookie Jan 12 '12 at 17:25
  • 1
    @Drew, no. Suppose z = sin(t) and we choose z evenly distributed, so the probability a point is in [t, t+dt] is dP = 0.5dz = 0.5cos(t)dt. The surface area of the band [t, d+dt] is dS = 2PIcos(t)dt, so the density is dP/dS=(4PI)^-1, which is not a function of t. – Kan Li Jan 12 '12 at 17:30
  • for you nonbelievers: http://img848.imageshack.us/img848/640/perfectdistribution.jpg (500k points) using icando's algorithm. – Rookie Jan 12 '12 at 17:36
1

You don't need trigonometry if you can generate random gaussian variables, you can do (pseudocode)

x <- gauss()
y <- gauss()
z <- gauss()
norm <- sqrt(x^2 + y^2 + z^2)

result = (x / norm, y / norm, z / norm)

Or draw points inside the unit cube until one of them is inside the unit ball, then normalize:

double x, y, z;

do
{
    x = rand(-1, 1);
    y = rand(-1, 1);
    z = rand(-1, 1);
} while (x * x + y * y + z * z > 1);

double norm = sqrt(x * x + y * y + z * z);
x / norm; y /= norm; z /= norm;
Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • 1
    i thought about that latter, but i also thought that is quite slow: half of calculations are wasted because they get outside of sphere. im using icando's method now, and it really seems to work perfectly and is very fast too. – Rookie Jan 12 '12 at 17:34
  • I benchmarked just for you: 88.3ms with icando's method, 128.5ms with yours! i calculated 500k points. doesnt the CPU's have sin/cos somehow optimized these days...? oh, and i used mersenne rand. – Rookie Jan 13 '12 at 13:29
  • i thought mersenne was the best... PHP uses it for example and they call it best etc. – Rookie Jan 13 '12 at 16:38
  • ok, you asked for this. using xorshift with your algorithm: 91.5ms, using xorshift with icando's algorithm: 80.5ms. now you cant say anything, except "premature optimization" and stuff ;) – Rookie Jan 13 '12 at 22:22
0

It looks like you can see that it's the cartesian coordinates that are creating the concentrations.

Here is an explanation of one right (and wrong) way to get a proper distribution.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180