• fullscreen
• MeshPoint.pde
• icosahedron.pde
• icosahedronSketch2.pde
• ```class MeshPoint {

public float x;
public float y;
public float z;
public float size;
public MeshPoint direction;

public MeshPoint() {
x = 0;
y = 0;
z = 0;
size = 0;
direction = new MeshPoint( true );
}

public MeshPoint( boolean nodirection ) {
x = 0;
y = 0;
z = 0;
size = 0;
}

public MeshPoint( float x, float y, float z ) {
this.x = x;
this.y = y;
this.z = z;
size = 0;
direction = new MeshPoint( true );
}

public void set( float x, float y, float z ) {
this.x = x;
this.y = y;
this.z = z;
}

public void set( MeshPoint mp ) {
x = mp.x;
y = mp.y;
z = mp.z;
}

public void plus( float x, float y, float z ) {
this.x += x;
this.y += y;
this.z += z;
}

public void plus( MeshPoint mp ) {
x += mp.x;
y += mp.y;
z += mp.z;
}

public void minus( float x, float y, float z ) {
this.x -= x;
this.y -= y;
this.z -= z;
}

public void minus( MeshPoint mp ) {
x -= mp.x;
y -= mp.y;
z -= mp.z;
}

public void multiply( float m ) {
x *= m;
y *= m;
z *= m;
}

public float dist( MeshPoint mp ) {
MeshPoint d = new MeshPoint( true );
d.plus( mp );
d.minus( this );
return d.len();
}

public float len() {
return sqrt( pow( x,2 ) + pow( y,2 ) + pow( z,2 ) );
}

public void normalise() {
float  l = len();
l = 1/l;
x *= l;
y *= l;
z *= l;
}

}
```
```// copied and adapted from http://code.google.com/p/webgltimer/source/browse/src/net/icapsid/counter/client/Icosahedron.java?r=170e4fcc41bf20700dcb6dc67272073af112c65c

import java.util.Iterator;
import java.util.List;

public class Icosahedron {

/*
public List< MeshPoint > pts = new ArrayList< MeshPoint >();
public List< Integer[] > faces = new ArrayList< Integer[] >();
public List< MeshPoint > faceNormals = new ArrayList< MeshPoint >();
*/

public MeshPoint[] pts;
public int[][] faces;
public MeshPoint[] faceNormals;

// public List<Float> vertexNormalsList = new ArrayList<Float>();
// public List<Float> vertexList = new ArrayList<Float>();

private final float X = 0.525731112119133606f;
private final float Z = 0.850650808352039932f;
private final float vdata[][] = {
{ -X, 0.0f, Z },
{ X, 0.0f, Z },
{ -X, 0.0f, -Z },
{ X, 0.0f, -Z },
{ 0.0f, Z, X },
{ 0.0f, Z, -X },
{ 0.0f, -Z, X },
{ 0.0f, -Z, -X },
{ Z, X, 0.0f },
{ -Z, X, 0.0f },
{ Z, -X, 0.0f },
{ -Z, -X, 0.0f }
};
private final int tindices[][] = {
{ 0, 4, 1 }, { 0, 9, 4 }, { 9, 5, 4 }, { 4, 5, 8 },
{ 4, 8, 1 }, { 8, 10, 1 }, { 8, 3, 10 }, { 5, 3, 8 },
{ 5, 2, 3 }, { 2, 7, 3 }, { 7, 10, 3 }, { 7, 6, 10 },
{ 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 }, { 6, 1, 10 },
{ 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 }, { 7, 2, 11 } };

int divisions;
int ptsNum;
int ptsCurrentIndex;
int facesNum;
int facesCurrentIndex;

public Icosahedron( int divisions ) {

this.divisions = divisions;
ptsCurrentIndex = 0;
ptsNum = renderPtsNum();
facesCurrentIndex = 0;
facesNum = renderFacesNum();

// println( "divisions: " + divisions + " => ptsNum: "+ptsNum +" / facesNum: "+ facesNum );

pts = new MeshPoint[ ptsNum ];
faces = new int[ facesNum ][ 3 ];
faceNormals = new MeshPoint[ facesNum ];

// Iterate over points
for (int i = 0; i < 20; ++i) {
subdivide(
vdata[tindices[i][0]],
vdata[tindices[i][1]],
vdata[tindices[i][2]], divisions );
}
renderNormals();

}

public int renderPtsNum() {
int output = 12;
int d = divisions;
while( d > 0 ) {
output = ( ( output - 2 ) * 4 ) + 2;
d--;
}
return output;
}

public int renderFacesNum() {
return (int) (20 * pow( 4, divisions ));
}

public void renderNormals() {

float third = 1.f / 3;

int i = 0;
while ( i < facesNum ) {

int[] li = faces[i];
MeshPoint mp = faceNormals[i];

mp.set( 0,0,0 );
mp.direction.set( 0,0,0 );

MeshPoint ref = pts[ li[0] ];
mp.plus( ref.x,ref.y,ref.z );
mp.direction.plus( ref.direction.x,ref.direction.y,ref.direction.z );

ref = pts[ li[1] ];
mp.plus( ref.x,ref.y,ref.z );
mp.direction.plus( ref.direction.x,ref.direction.y,ref.direction.z );

ref = pts[ li[2] ];
mp.plus( ref.x,ref.y,ref.z );
mp.direction.plus( ref.direction.x,ref.direction.y,ref.direction.z );

mp.multiply( third );
mp.direction.multiply( third );

i++;

}

}

private void norm(float v[]){

float len = 0;

for(int i = 0; i < 3; ++i){
len += v[i] *  v[i];
}

len = (float) Math.sqrt(len);

for(int i = 0; i < 3; ++i){
v[i] /= len;
}
}

int found = -1;
for ( int i = 0; i < ptsCurrentIndex; i++ ) {
MeshPoint mp = pts[i];
if ( mp.x == v[0] && mp.y == v[1] && mp.z == v[2] ) {
found = i;
break;
}
}
if ( found == -1 ) {
pts[ptsCurrentIndex] = new MeshPoint();
pts[ptsCurrentIndex].set( v[0], v[1], v[2] );
pts[ptsCurrentIndex].direction.set( v[0], v[1], v[2] );
found = ptsCurrentIndex;
ptsCurrentIndex++;
}
return found;
}

private void subdivide(float v1[], float v2[], float v3[], int depth) {

if (depth == 0) {
faces[facesCurrentIndex] = new int[] { f1,f2,f3 };
faceNormals[facesCurrentIndex] = new MeshPoint();
facesCurrentIndex++;
return;
}

float v12[] = new float[3];
float v23[] = new float[3];
float v31[] = new float[3];

for (int i = 0; i < 3; ++i) {
v12[i] = (v1[i] + v2[i]) / 2f;
v23[i] = (v2[i] + v3[i]) / 2f;
v31[i] = (v3[i] + v1[i]) / 2f;
}

norm(v12);
norm(v23);
norm(v31);

subdivide(v1, v12, v31, depth - 1);
subdivide(v2, v23, v12, depth - 1);
subdivide(v3, v31, v23, depth - 1);
subdivide(v12, v23, v31, depth - 1);
}
}
```
```float margins = 150;

float biggestdist = 0;
MeshPoint barycenter;
MeshPoint boundaryMin;
MeshPoint boundaryMax;
public ArrayList < MeshPoint > refpoints;

Icosahedron ico;
float icosize = 300;
static int ICOSUBDIVISION = 2;

boolean fillbag = true;

void setup() {
size( 800,600, P3D );
lights();

barycenter = new MeshPoint( true );

ico = new Icosahedron( ICOSUBDIVISION );

boundaryMin = new MeshPoint( true );
boundaryMin.set( -( (width-margins) * 0.5f ), -( (height-margins) * 0.5f ), -( (height-margins) * 0.5f ) );
boundaryMax = new MeshPoint( true );
boundaryMax.set( ( (width-margins) * 0.5f ), ( (height-margins) * 0.5f ), ( (height-margins) * 0.5f ) );

refpoints = new ArrayList < MeshPoint >();
for ( int i = 0; i < 20; i++ ) {
MeshPoint mp = new MeshPoint(
random( boundaryMin.x, boundaryMax.x ),
random( boundaryMin.y, boundaryMax.y ),
random( boundaryMin.z, boundaryMax.z ) );
/*
MeshPoint mp = new MeshPoint(
random( boundaryMin.x, boundaryMax.x ),
random( boundaryMin.y, boundaryMax.y ),
random( boundaryMin.z, boundaryMax.z ) );
*/
mp.size = 30 + i * 10;
mp.direction.set( random( -1,1 ), random( -1,1 ), random( -1,1 ) );
// mp.direction.set( random( -1,1 ), random( -1,1 ), 0 );
mp.direction.normalise();
mp.direction.multiply( 1.f );
}

noStroke();
fill( 255,0,0 );
}

void update() {
for ( int i = 0; i < refpoints.size(); i++ ) {
MeshPoint pt = refpoints.get(i);
pt.plus( pt.direction );
if ( pt.x + pt.direction.x < boundaryMin.x || pt.x + pt.direction.x > boundaryMax.x )
pt.direction.x *= -1;
if ( pt.y + pt.direction.y < boundaryMin.y || pt.y + pt.direction.y > boundaryMax.y )
pt.direction.y *= -1;
if ( pt.z + pt.direction.z < boundaryMin.z || pt.z + pt.direction.z > boundaryMax.z )
pt.direction.z *= -1;
}
float totalsize = 0;
for ( int i = 0; i < refpoints.size(); i++ ) { totalsize += refpoints.get(i).size; }
barycenter.set( 0,0,0 );
MeshPoint tmp = new MeshPoint( true );
for ( int i = 0; i < refpoints.size(); i++ ) {
tmp.set( refpoints.get(i) );
tmp.multiply( refpoints.get(i).size / totalsize );
barycenter.plus( tmp );
}
biggestdist = 0;
for ( int i = 0; i < refpoints.size(); i++ ) {
float tmd = barycenter.dist( refpoints.get(i) ) + ( refpoints.get(i).size * 0.5f ) + 10;
if ( tmd > biggestdist ) {
biggestdist = tmd;
}
}
icosize = biggestdist;
int previousclosest = 0;
MeshPoint tm = new MeshPoint();
MeshPoint m = new MeshPoint();
for ( int i = 0; i < ico.ptsNum; i++ ) {
tm.set( ico.pts[i] );
tm.multiply( biggestdist );
m.set( barycenter );
m.plus( tm );
// closest point
int closest = 0;
float d = 0;
for ( int p = 0; p < refpoints.size(); p++ ) {
MeshPoint pt = refpoints.get(p);
if ( p == 0 ) {
d = m.dist( pt ) - pt.size * 0.5f;
} else {
float tmd = m.dist( pt ) - pt.size * 0.5f;
if ( d > tmd ) {
closest = p;
d = tmd;
}
}
}
// setting the direction towards the closest point:
m.direction.set( refpoints.get( closest ) );
m.direction.minus( m );
float tml = m.direction.len();
m.direction.normalise();
m.direction.multiply( tml - refpoints.get( closest ).size * 0.5f );
// smooth gaps
/*
if ( i > 0 && previousclosest != closest ) {
// the current mesh point points to a different point then the prvious one!
// creating a point in the middle
MeshPoint prevmp = mesh.get( i-1 );
MeshPoint middle = new MeshPoint( true );
middle.set( prevmp.x + prevmp.direction.x, prevmp.y + prevmp.direction.y, prevmp.z + prevmp.direction.z );
middle.minus( m.x + m.direction.x, m.y + m.direction.y, m.z + m.direction.z );
middle.multiply( 1.f / 3 );
m.direction.plus( middle );
prevmp.direction.minus( middle );
}
*/
ico.pts[i].direction.set( m.direction );
previousclosest = closest;
}
}

void draw() {

float rx = frameCount / 700.f;
float ry = frameCount / 320.f;
// float rx = 0;
// float ry = 0;

update();

background( 255 );

ambientLight(30, 30, 30);
pushMatrix();
translate( width * 0.5, height * 0.5, 0 );
// rotateX( rx * 3 );
directionalLight(255, 255, 255, 0, -0.3, -1);
popMatrix();

PVector f1 = new PVector();
PVector f2 = new PVector();
PVector f3 = new PVector();
pushMatrix();
translate( width * 0.5, height * 0.5, -width * 0.25 );
rotateX( rx );
rotateY( ry );

pushMatrix();

translate( barycenter.x, barycenter.y, barycenter.z );

/*
noFill();
stroke( 255,0,0 );
for ( int i = 0; i < ico.facesNum; i++ ) {
beginShape();
for ( int k = 0; k < 3; k++ )
vertex( ico.pts[ ico.faces[i][k] ].x * icosize, ico.pts[ ico.faces[i][k] ].y * icosize, ico.pts[ ico.faces[i][k] ].z * icosize );
endShape( CLOSE );
}
*/
noStroke();
fill( 0,120,255 );
for ( int i = 0; i < ico.ptsNum; i++ ) {
MeshPoint mp = ico.pts[i];
pushMatrix();
translate( mp.x * icosize, mp.y * icosize, mp.z * icosize );
rotateY( -ry );
rotateX( -rx );
noStroke();
ellipse( 0,0, 5,5 );
popMatrix();
pushMatrix();
translate( mp.x * icosize, mp.y * icosize, mp.z * icosize );
stroke( 0,255,255 );
line( 0,0,0, mp.direction.x, mp.direction.y, mp.direction.z );
popMatrix();
}

if( fillbag ) {
noStroke();
fill( 255,0,0 );
} else {
noFill();
stroke( 255,0,0 );
strokeWeight( 2 );
}
for ( int i = 0; i < ico.facesNum; i++ ) {
beginShape();
for ( int k = 0; k < 3; k++ )
vertex(
(ico.pts[ ico.faces[i][k] ].x * icosize) + ico.pts[ ico.faces[i][k] ].direction.x,
(ico.pts[ ico.faces[i][k] ].y * icosize) + ico.pts[ ico.faces[i][k] ].direction.y,
(ico.pts[ ico.faces[i][k] ].z * icosize) + ico.pts[ ico.faces[i][k] ].direction.z );
endShape( CLOSE );
}

strokeWeight( 1 );

/*
for ( int i = 0; i < ico.vertexList.size(); i+=9 ) {
f1.x = ico.vertexList.get(i) * icosize;
f1.y = ico.vertexList.get(i+1) * icosize;
f1.z = ico.vertexList.get(i+2) * icosize;
f2.x = ico.vertexList.get(i+3) * icosize;
f2.y = ico.vertexList.get(i+4) * icosize;
f2.z = ico.vertexList.get(i+5) * icosize;
f3.x = ico.vertexList.get(i+6) * icosize;
f3.y = ico.vertexList.get(i+7) * icosize;
f3.z = ico.vertexList.get(i+8) * icosize;
beginShape();
vertex( f1.x, f1.y, f1.z );
vertex( f2.x, f2.y, f2.z );
vertex( f3.x, f3.y, f3.z );
endShape( CLOSE );
}

fill( 0,255,255 );
for ( int i = 0; i < ico.pts.size(); i++ ) {
MeshPoint mp = ico.pts.get(i);
pushMatrix();
translate( mp.x * icosize, mp.y * icosize, mp.z * icosize );
rotateY( -ry );
rotateX( -rx );
noStroke();
ellipse( 0,0, 10,10 );
popMatrix();
pushMatrix();
translate( mp.x * icosize, mp.y * icosize, mp.z * icosize );
stroke( 0,255,255 );
line( 0,0,0, mp.direction.x, mp.direction.y, mp.direction.z );
popMatrix();

pushMatrix();
// rotateX( rx );
// rotateY( ry );
// stroke( 0,255,255 );
translate(
mp.x * icosize + mp.direction.x,
mp.y * icosize + mp.direction.y,
mp.z * icosize + mp.direction.z );
rotateY( -ry );
rotateX( -rx );
ellipse( 0,0, 10,10 );
// line( 0,0,0, mp.direction.x, mp.direction.y, mp.direction.z );
popMatrix();

}
*/

popMatrix();

// drawing the balls
noFill();
strokeWeight( 2 );
for ( int i = 0; i < refpoints.size(); i++ ) {
MeshPoint pt = refpoints.get(i);
pushMatrix();
translate( pt.x, pt.y, pt.z );
rotateY( -ry );
rotateX( -rx );

stroke( 0,0,0 );
line( -5,0, 5,0 );
line( 0,-5, 0,5 );
// stroke( 0,0,0 );
ellipse( 0,0, pt.size,pt.size );
popMatrix();
}
strokeWeight( 1 );

popMatrix();

/*
fill( 0,0,0 );
text("icosahedron division: "+int( ICOSUBDIVISION ),20,40);
text("points: "+int( ico.ptsNum ),20,60);
text("faces: "+int( ico.facesNum ),20,80);
text("fps: "+int(frameRate),20,100);
*/

}

void keyPressed() {
if ( keyCode == 38 ) { // [up]
if ( ICOSUBDIVISION == 5 )
return;
ICOSUBDIVISION++;
ico = new Icosahedron( ICOSUBDIVISION );
} else if ( keyCode == 40 ) {  // [down]
if ( ICOSUBDIVISION == 0 )
return;
ICOSUBDIVISION--;
ico = new Icosahedron( ICOSUBDIVISION );
} else if ( keyCode == 70 ) { // 'f'
fillbag = !fillbag;
} else {
println( keyCode );
}
}

```

### tweaks (0)

This sketch is running as Java applet, exported from Processing.

Report Sketch

Report for inappropriate content

Your have successfully reported the sketch. Thank you very much for helping to keep OpenProcessing clean and tidy :)

8