Particle emittor from the surface of a sphere

Hi All,

I sat down to make a particle emitter and realized I didn’t know how to do a key part of it.

I’d like to draw a sphere and have particles emitted from the surface of it (think like the surface of a star).

The part I don’t know how to do is this: how do I find a point on the sphere?

I’d like to randomly pick points on the sphere. With that point, I’ll get the normal (I’m also fuzzy on how to do that, since I haven’t gotten to that part yet, I don’t know if it will be difficult or not). Then I’m have the particle fly out from the surface of the sphere, using the normal as a trajectory. Over time, the particle will fade to nothing.

Thanks in advance!
Steve

hello,

A sphere is a mesh.
you can get points on the sphere by getting vertices of the mesh

this will give you a vector of vertices which is the list of points the sphere is made of

ofSpherePrimitive sphere;
vector<ofVec3f> spherePoints = sphere.getMesh().getVertices();

Hi, this will give you a random point on a sphere, the randomness may not be evenly distributed, but it works fine for my purposes (which is often emitting particles from a sphere)

	// ------------------------------------------------------------
	static ofVec3f randomPointOnSphere()
	{
		float lambda = ofRandom(1.0f);
		float u = ofRandom(-1.0f, 1.0f);
		float phi = ofRandom( 2.0 * PI );
		
		ofVec3f p;
		p.x = pow(lambda, 1/3) * sqrt(1.0 - u * u) * cos(phi);
		p.y = pow(lambda, 1/3) * sqrt(1.0 - u * u) * sin(phi);
		p.z = pow(lambda, 1/3) * u;
		
		return p;
	}

this will create uniformly distributed points on an sphere, the original formula creates points on a hemisphere that’s why i then add the point twice, one multiplied with radius and the next with -radius.

#include "ofApp.h"
using namespace glm;

float radicalInverse_VdC(uint bits) {
    bits = (bits << 16u) | (bits >> 16u);
    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
    return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}

// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
vec2 hammersley(uint i, uint N) {
    return vec2(float(i)/float(N), radicalInverse_VdC(i));
}

vec3 hemisphereSample_uniform(uint i, uint N){
     vec2 E = hammersley(i,N);
     float u = E.x;
     float v = E.y;
     float phi = v * 2.0 * PI;
     float cosTheta = 1.0 - u;
     float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
     return vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
}

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0);
    mesh.setMode(OF_PRIMITIVE_POINTS);
    auto numSamples = 1024;
    auto radius = 100.f;
    for(int i=0;i<numSamples;i++){
        auto pointOnHemisphere = hemisphereSample_uniform(i,numSamples);
        mesh.addVertex(pointOnHemisphere * radius);
        mesh.addVertex(pointOnHemisphere * -radius);
    }
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){

    cam.begin();
    mesh.draw();
    cam.end();
}

i originally used this on a shader that’s why the vectors are vec*. it will work with glm vectors which would work in master but just change them to their equivalent ofVec* if you are using OF from the web page.

3 Likes

also the normal, since the sphere is centered in 0, is the vertex itself normalized whatever method you use

Thank you for all the replies! I’m going to try implementing this right now. Once I have a repo up, I’ll post that as well.