Points on the surface of a Sphere using beginShape(POINTS or QUADS)

Hi everyone,

I’m looking for a way to draw a couple of thousands of points on the surface of a sphere. beginShape/endShape feels like an efficient way to draw them. For example as POINTS with strokeWeight(10). However, this makes them always face the camera instead of being perpendicular to the sphere. I was hoping setting the normal before the vertex would help but it seems not to.

I can think of two other ways to do it. But I was wondering if it can be done differently.

  1. using polar coordinates: rotate(…) followed by a translate(0,0,z)
  2. manually calculating the 4 corners of a quad perpendicular to the sphere (using crossproduct for this ?)

What do you think would be the best way to have the points perpendicular to the sphere’s surface?

Best wishes,
Rick

PVector points[] = new PVector[1000];

void setup() {
  size(600, 600, P3D);
    stroke(255);
  strokeWeight(10);
  noFill();
  for (int i=0; i<points.length; i++) {
    points[i] = PVector.random3D().mult(300);
  }
}

void draw() {
  ortho();
  background(0);
  translate(width/2, height/2);
  rotateY(mouseX*.01);
  rotateX(mouseY*.01);
  beginShape(POINTS);
  for (PVector v : points) {    
    vertex(v.x, v.y, v.z);    
  }
  endShape();
}
2 Likes

I don’t think that points are the right path

What about using circle() and rotate them correctly?

1 Like

Hello @companje,

Explore the PVector resources:

Consider this simple example:

PVector v;

void setup() 
  {
  size(600, 600, P3D);
  translate(width/2, height/2);
  v = new PVector(0, 0, 0);
  strokeWeight(5);
  for(int i = 0; i<1000; i++)
    {
    v.set(random(-1,1), random(-1, 1), random(-1, 1));
    v.normalize();
    v.mult(200);
    point(v.x, v.y, v.z);
    }  
  }

Back to workout…

Working mind and body at the same time!

:)

Dear GLV,

Thanks for your response. I think your code is quite identical to my approach. Please see me screenshot and source code. I am already using the PVector functions you suggest. My problem is (as well as in your code) that all the dots point in the same direction (towards the screen) instead of ‘facing outwards from the center’.

Best wishes,
Rick

1 Like

That it is! I cooked this up quickly and did not look at your code.

I will take another look later…

:)

1 Like

Hello,

Take a look here at the Cartesian Coordinates:

I used my original example for the random points, a translate, a rotate for phi and a rotate for theta and then drew a circle():

This approach was fresh in my head from a recent project.

:)

1 Like

As I said, I don’t think that points can be rotated properly so circle is better

And what about QUADS? I really would like to use beginShape/endShape so I can calculate my vertices up-front and render them in batch. That should be much faster than orienting and drawing thousands of circles.
I’m now trying to figure out how to calculate the 4 four corners of a quad using the cross-product. I’ll keep you posted.

1 Like

I’m happy now! :slight_smile: I use the cross product to calculate a local coordinate space perpendicular to the sphere. I add all vertices in setup() to a PShape and only call shape(dots) to draw them all at once in draw().

I hope it is useful for others.

Best wishes,
Rick

float dotRadius = 4;
float sphereRadius = 250;
PShape dots;

void setup() {
  size(700, 700, P3D);

  dots = createShape(GROUP);
  for (int i=0; i<1000; i++) {
    PVector n = PVector.random3D().mult(sphereRadius);

    //create an 'up' vector. it should not point in the same direction as the the normal
    PVector up = abs(n.x)<.99 ? new PVector(1, 0, 0) : new PVector(0, 1, 0); 

    //calculate local coordinate space using the crossproduct
    PVector t = n.cross(up).normalize(); //local x axis (red)
    PVector b = t.cross(n).normalize();  //local y axis (green)

    //draw circle perpendicular to sphere's surface
    PShape dot = createShape();
    dots.setStroke(false);
    dot.beginShape();
    for (int j=0, jj=16; j<=jj; j++) {
      float a = float(j)/jj * TWO_PI;
      float x = cos(a) * dotRadius;
      float y = sin(a) * dotRadius;
      vertex(dot, t.copy().mult(x).add(b.copy().mult(y)).add(n)); //(t*x)+(b*y)+n
    }
    dot.endShape();
    dots.addChild(dot);
  }
}

void draw() {
  background(0);
  translate(width/2, height/2);
  rotateX(mouseY*.01);
  rotateY(mouseX*.01);
  fill(0, 128, 200);
  noStroke();
  sphere(sphereRadius);
  shape(dots);
}

void vertex(PShape s, PVector p) {
  s.vertex(p.x, p.y, p.z);
}
3 Likes