This is a bad hack that duplicates and overrides Toxi's sphere method from PGraphics3 as well as some other necessary stuff, due to access restrictions and my not being Java Savvy enough to get round them.
It's not ideal the rectangle onto sphere as it looks crappy round the poles (probably why it's not implemented!).
It's not very elegant and probably unstable with regards future releases, but in a pinch it'll work:
Sorry any offense this may cause!
Code:
float[] cx,cz,sphereX,sphereY,sphereZ;
int currRes=0;
boolean filled=true;
PImage texmap;
void setup() {
size(400,400, P3D);
texmap = loadImage("Fontcuberta2005-UFO.jpg");
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}
textureMode(IMAGE);
}
void draw() {
background(255);
translate(100+mouseX/2,mouseY,-100);
rotateX(mouseY*0.02);
rotateY(mouseX*0.01);
noStroke();
if(mesh) {stroke(200,200,0);}
sphereDetail(sdetail);
texturedSphere(mouseY, texmap);
}
int sphereDetail;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5f;
int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION);
public void sphereDetail(int res) {
if (res < 3) res = 3; // force a minimum res
if (res == sphereDetail) return;
float delta = (float)SINCOS_LENGTH/res;
float[] cx = new float[res];
float[] cz = new float[res];
// calc unit circle in XZ plane
for (int i = 0; i < res; i++) {
cx[i] = cosLUT[(int) (i*delta) % SINCOS_LENGTH];
cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
}
// computing vertexlist
// vertexlist starts at south pole
int vertCount = res * (res-1) + 2;
int currVert = 0;
// re-init arrays to store vertices
sphereX = new float[vertCount];
sphereY = new float[vertCount];
sphereZ = new float[vertCount];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;
// step along Y axis
for (int i = 1; i < res; i++) {
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
for (int j = 0; j < res; j++) {
sphereX[currVert] = cx[j] * curradius;
sphereY[currVert] = currY;
sphereZ[currVert++] = cz[j] * curradius;
}
angle += angle_step;
}
sphereDetail = res;
}
// generic routine to draw textured sphere,
// based on current settings of sphereDetail()
void texturedSphere(float r, PImage t) {
int v1,v11,v2;
beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sphereDetail);
float iv=(float)(t.height-1)/(sphereDetail);
float u=0,v=iv;
for (int i = 0; i < sphereDetail; i++) {
vertex(0, -r, 0,u,0);
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r,u,v);
u+=iu;
}
vertex(0, -r, 0,u,0);
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r,u,v);
endShape();
// middle rings
int voff = 0;
for(int i = 2; i < sphereDetail; i++) {
v1=v11=voff;
voff += sphereDetail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sphereDetail; j++) {
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r,u,v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r,u,v+iv);
u+=iu;
}
// close each ring
v1=v11;
v2=voff;
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r,u,v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r,u,v+iv);
endShape();
v+=iv;
}
u=0;
// add the northern cap
beginShape(TRIANGLE_STRIP);
texture(t);
for (int i = 0; i < sphereDetail; i++) {
v2 = voff + i;
vertex(0, r, 0,u,v+iv);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r,u,v);
u+=iu;
}
vertex(0, r, 0,u,v+iv);
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r,u,v);
endShape();
}
boolean mtoggle = false;
boolean mesh = false;
int sdetail = 30;
void keyPressed() {
if(key == 'm' && !mtoggle) {mesh=!mesh; mtoggle=true;}
if(key == LEFT && sdetail>3) {sdetail--;}
if(key == RIGHT && sdetail<50) {sdetail++;}
}
void keyReleased() {
if(key == 'm') {mtoggle=false;}
}