I did this just recently:
static void GenerateOnSphere (float *samples, int stride, int sampleCount, int seed)
{
std::mt19937 generator (seed);
std::uniform_real_distribution<float> rnd(0.f, 1.f);
int inputSize = sampleCount * 100; // generating much more samples than finally needed
std::vector< cy::Point3f > inputPoints(inputSize);
for (int i=0; i<inputSize; i++) // distrubuted randomly over the surface of a sphere
{
float theta = 2 * 3.14159265359f * rnd(generator);
float phi = acos(1 - 2 * rnd(generator));
inputPoints[i].x = sin(phi) * cos(theta);
inputPoints[i].y = sin(phi) * sin(theta);
inputPoints[i].z = cos(phi);
//Vis::RenderPoint((sVec3&)inputPoints[i], 0,0,1);
}
// but random samples are often not good enough, even if there distribution is guaranteed to be random.
// so i use said library to reduce the large set to nice poisson samples.
cy::WeightedSampleElimination< cy::Point3f, float, 3, int > wse;
int outputSize = sampleCount;
std::vector< cy::Point3f > outputPoints(outputSize);
//wse.Eliminate( inputPoints.data(), inputPoints.size(),
// outputPoints.data(), outputPoints.size(), true );
float d_max = 2 * wse.GetMaxPoissonDiskRadius( 2, outputPoints.size(), 4*3.14159265359f );
wse.Eliminate( inputPoints.data(), inputPoints.size(),
outputPoints.data(), outputPoints.size(),
true, d_max, 2 );
for (int i=0; i<outputSize; i++)
{
float *dst = (float*) (((char*)samples) + i*stride);
dst[0] = outputPoints[i][0];
dst[1] = outputPoints[i][1];
dst[2] = outputPoints[i][2];
}
/*for (int i=0; i<outputSize; i++)
{
float a = 4*3.14159265359f / float(outputSize);
float r = sqrt(4*3.14159265359f / (float(outputSize) * 3.14159265359f));
Vis::RenderPoint((sVec3&)outputPoints[i], float(i)/1000.f, 1-float(i)/1000.f, 0);
Vis::RenderCircle(r, (sVec3&)outputPoints[i], (sVec3&)outputPoints[i], float(i)/1000.f, 1-float(i)/1000.f, 0);
}*/
}
Using the library from here: http://www.cemyuksel.com/cyCodeBase/soln/poisson_disk_sampling.html
It's good. Actually i use it to generate 20 samples, and i generate procedural polyhedra (rocks) from that. The cool thing is if i want 5 faces, i take the first 5 samples. If i want 10 i take the first 10. The samples are ordered so adding one more always results in a poisson distribution. Very useful.
But maybe just that trig part of my code is what you want already.