Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

How to draw an icoSphere made of triangle_fans ?

edited February 2018

Hi !

I'm trying to make an icoSphere using the beginShape() function.

I've managed to draw a sphere made of particles but don't know how to connect those particles using the TRIANGLE_FAN parameter.

More specifically, there are 2 key parts that I can't figure out (from line 57):

• How many vertex() functions do I need to write within the double for loop ?
• What should be the coordinates of those vertices ?

Any help would be much appreciated.

from toxi.physics import VerletPhysics    ### using VerletPhysics engine
from particle import Particle   ### simple class containing a particle object

def setup():
global particules, physics, total
size(1080, 800, P3D)
smooth(8)

cam = PeasyCam(this, 110)
physics = VerletPhysics()

r = 180   ### radius of the sphere
total = 10  ### number of particles/points

particules = [[[] for e in range(total +1)] for f in range(total+1)]    ### 2D array list storing the particles locations

for e in range(0, total+1):
lon = map(e, 0, total, 0, PI)
for f in range(0, total+1):
lat = map(f, 0, total , 0, TWO_PI)

x = r * sin(lat) * cos(lon)
y = r * sin(lat) * sin (lon)
z = r * cos(lat)

particules[e][f] = Particle(x, y, z)

for e in range(total+1):
for f in range(total+1):
p = particules[e][f]
physics.addParticle(p)   ### adding the particles to the physics engine

def draw():
global particules, physics
background(0)

for e in range(total+1):    ### displaying the particles
for f in range(total+1):
p = particules[e][f]
p.display()

for e in range(total):
beginShape(TRIANGLE_FAN)  ### Trying to connect the particles with triangle fans
for f in range(total+1):
noFill()
strokeWeight(1)

p = particules[e][f-1]            ### PART TO CORRECT #### vertices and their coordinates ####
vertex(p.x(), p.y(), p.z())
p2 = particules[e+1][f]
vertex(p2.x(), p2.y(), p2.z())

endShape()
Tagged:

• The code above gives me this shape:

https://imgur.com/IaV2d7A

As you can see the triangle fans and not completed and most of the points are connected to one pole.

Any idea of what I should change in the following snippet ?

for e in range(total):
beginShape(TRIANGLE_FAN)
for f in range(total+1):
noFill()
strokeWeight(1)

p = particules[e][f-1]         ### PART TO CORRECT ####
vertex(p.x(), p.y(), p.z())
p2 = particules[e+1][f]
vertex(p2.x(), p2.y(), p2.z())

endShape()

• Please share your ideas, suggestions, code (even in Java)... anything !

• I tried and I failed... Shouldn't you be using TRIANGLE_STRIPS btw?

Check this post: https://www.openprocessing.org/sketch/92464

My attempt below but it has a bug.

Kf

//===========================================================================
// IMPORTS:
import peasy.PeasyCam;

//===========================================================================
// GLOBAL VARIABLES:

PeasyCam cam;

int r=180;
int sr=3;
int total=10;

PVector[][] vv=new PVector[total][total];

//===========================================================================
// PROCESSING DEFAULT FUNCTIONS:

void settings() {
size(1080, 800, P3D);
}

void setup() {

textAlign(CENTER, CENTER);
rectMode(CENTER);

noStroke();

smooth(8);
cam = new PeasyCam(this, 400);

for (int e=0; e<total; e++) {
float lon = map(e, 0, total, 0, TWO_PI);

for (int f=0; f<total; f++) {
float lat = map(f, 0, total, 0, PI);

PVector p = new PVector( r * sin(lat) * cos(lon),
r * sin(lat) * sin (lon),
r * cos(lat));
vv[e][f]=p;
}
}
}

void draw() {
background(0);
//noStroke();
stroke(0);

for (float e=0; e<total/1.0; e++) {
beginShape(TRIANGLE_STRIP);
for (float f=0; f<total; f++) {
fill(lerp(0, 255, e*1.0/total), lerp(0, 255, f*1.0/total), 25);

if (f-1>0) {
PVector p= vv[int(e)][int(f-1)%total];
vertex(p.x, p.y, p.z);
}

//if (e+1<total) {
PVector q= vv[int(e+1)%total][int(f-0)%total];
vertex(q.x, q.y, q.z);
//}
}
vertex(0, 0, -180);
endShape();
}
}

• You didn't need to start a new Question for this.

You don't use all triangle fans, just the top and bottom rows where you have a central point at the pole. The rest is triangle strips.

The sphere code in github does exactly this.

• @kfrajer: Hey that's super nice of you to share your attempt ! I did use TRIANGLE_STRIPS at first but koogs suggested me to use TRIANGLE_FANS instead. I've now managed to draw a sphere made of TRIANGLE_STRIPS and where the top and bottom only are made of TRIANGLE_FANS.

And thanks for the links, the icosahedron sketch is really interesting. I'm now wondering what are the difference between an icosphere and an icosahedron. Anyway I'll probably use a part of the code for my next attempt.

@koogs: As I just mentionned, I could draw a sphere made of triangle strips, where tops and bottoms only are triangle fans. HOWEVER (and this has more to do with my other question about springs) when I connect the vertices by springs the whole sphere falls apart. This is partly because I've now different meshes:

• 4 made of triangle fans for the poles (2 for each pole)
• 2 made of triangle strips for the "body" of the sphere (front and back)  I guess it'd be a better idea to draw a sphere based on a single mesh. Is that possible ? (with an icosahedron for instance ?)

Also what "sphere code" are you refering to ? Would you mind sharing a link ?

PS: This is what the same sphere looks like when I add springs to each vertices and tie the different meshes together: • processing sphere code. it's complicated but you can see from the comments it's three bits, the top, the middle and the bottom.

https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java#L8961

• Do you think it's possible to draw a sphere with a single mesh ? (one single part, no top, middle or bottom)

• Just brainstorming -- you might try basing your mesh algorithm on the points of a Fibonacci spiral. That walks a sphere from top to bottom as a spiral.

https://forum.processing.org/two/discussion/18779/move-a-single-point

• @jeremydouglass: That's a very interesting suggestion. I'll definitely look into it after I'm finished with my current polyhedron experiment. Thanks a lot !

• I just wanted to share a much less cumbersome approach based on @jeremydouglass last suggestion. It's a 2 step process:

• displaying points around a Fibonacci sphere
• triangulating those points with the Hemesh library

phi = (sqrt(5) + 1) / 2 - 1 #Golden Ratio
angle = phi * 2 * PI #Golden Angle
n_points, radius = 300, 200
liste = []

def setup():
global triangles, render
size(600, 600, P3D)
smooth(8)
render = WB_Render(this)

for p in range(n_points):
lon = angle * p
lon /= 2 * PI; lon -= floor(lon); lon *= 2 * PI
if lon > PI: lon -= 2 * PI
lat = asin(-1 + 2 * p / float(n_points))
new_points = WB_Point(radius * cos(lat) * cos(lon), radius * cos(lat) * sin(lon), radius * sin(lat))
liste.append(new_points)

triangulation = WB_Triangulate.alphaTriangulate3D(liste)

noFill()
beginShape(TRIANGLES)

def draw():
background(225,225,230)

translate(width/2, height/2)
for i in range(0, len(triangles), 3):
render.drawTriangle(liste[triangles[i]], liste[triangles[i+1]], liste[triangles[i+2]]) 