We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOpenGL and 3D Libraries › Globe: Spherical Texturemap
Pages: 1 2 
Globe: Spherical Texturemap? (Read 5683 times)
Globe: Spherical Texturemap?
Jan 3rd, 2006, 11:33pm
 
I'd like to make a world globe to zoom around in.

A friend just did this in Blender .. and when I asked how he did it, he said he found a rectangular map of the world and used that as a texture map onto a sphere!  I'm a bit surprised that works, but it looked fine, even at the poles!

Is this possible in Processing?
Re: Globe: Spherical Texturemap?
Reply #1 - Jan 4th, 2006, 12:51am
 
Sure, it can look strange mapping a rectangle to a sphere when you're near the poles, however.

Just make a sphere using a 360 degree sweep of a semi-circle, and set the texture coordinates based on the two sweeps.  You will probably want to use a little trig for the vertical coordinate, but horizontal should simply be the fraction of the 360 degree sweep.

I'm not sure if the built-in sphere function provides any texture support, I don't believe so, but you could pull its code from CVS and modify that.  It's worth knowing how to build a sphere from polygons, though.
Re: Globe: Spherical Texturemap?
Reply #2 - Jan 4th, 2006, 10:23am
 

This is something from alpha processing that I borrowed from Toxi. It would need modifying for Beta, but shouldn't take long and does exactly what you want. Check the code for redundant methods etc., as there could be all sorts of my crap in it still.


Code:

float[] cx,cz,sphereX,sphereY,sphereZ;

int currRes=0;
boolean filled=true;

BImage texmap;
BImage mask;

void setup() {
size(400,400);

texmap = loadImage("night.jpg");
mask = loadImage("circularmask.gif");

textureMode(IMAGE_SPACE);
}

void loop() {
background(255);
// image(mask,0,0,width,height);
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);
}





// generic routine to draw textured sphere,
// based on current settings of sphereDetail()
void texturedSphere(float r, BImage t) {
int v1,v11,v2;
float[] sphereX=g.sphereX;
float[] sphereY=g.sphereY;
float[] sphereZ=g.sphereZ;
int sphere_detail=g.sphere_detail;

beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sphere_detail);
float iv=(float)(t.height-1)/(sphere_detail);
float u=0,v=iv;
for (int i = 0; i < sphere_detail; 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 < sphere_detail; i++) {
v1=v11=voff;
voff += sphere_detail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sphere_detail; 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 < sphere_detail; 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;}
}
Re: Globe: Spherical Texturemap?
Reply #3 - Apr 24th, 2006, 7:13am
 
could someone post an update version of this code? i was having problems updating it and i need it for a project soon

thanks
Re: Globe: Spherical Texturemap?
Reply #4 - Apr 24th, 2006, 9:48am
 
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! Wink

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;}
}

Re: Globe: Spherical Texturemap?
Reply #5 - May 4th, 2006, 7:19am
 
Thanks! helped alot!
Re: Globe: Spherical Texturemap?
Reply #6 - Mar 27th, 2007, 11:29pm
 
I've gotten this code to work in 121 and 123, but not in 124. Does anyone know why this might be?
Re: Globe: Spherical Texturemap?
Reply #7 - Mar 27th, 2007, 11:52pm
 
This modified version of the above code works in 0121 but not 0124. In this version, the sphere is drawn to a separate PGraphics before being drawn onto the screen, and I think this is where there's an issue. Does anyone know why this might be?

Code:

float[] cx,cz,sphereX,sphereY,sphereZ;

int currRes=0;
boolean filled=true;

PImage texmap;
PGraphics pg;

void setup() {
size(400,400);
pg = createGraphics(400,400, P3D);

texmap = loadImage("thrill179.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);
}

pg.textureMode(IMAGE);
}

void draw() {
pg.beginDraw();
pg.background(255);

pg.translate(100+mouseX/2,mouseY,-100);
pg.rotateX(mouseY*0.02);
pg.rotateY(mouseX*0.01);

pg.noStroke();
if(mesh) {pg.stroke(200,200,0);}


sphereDetail(sdetail);
texturedSphere(mouseY, texmap, pg);
pg.endDraw();
pg.modified = true;

image(pg, 0, 0);
}

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, PGraphics pg) {
int v1,v11,v2;

pg.beginShape(TRIANGLE_STRIP);
pg.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++) {
pg.vertex(0, -r, 0,u,0);
pg.vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r,u,v);
u+=iu;
}
pg.vertex(0, -r, 0,u,0);
pg.vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r,u,v);
pg.endShape();

// middle rings
int voff = 0;
for(int i = 2; i < sphereDetail; i++) {
v1=v11=voff;
voff += sphereDetail;
v2=voff;
u=0;
pg.beginShape(TRIANGLE_STRIP);
pg.texture(t);
for (int j = 0; j < sphereDetail; j++) {
pg.vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r,u,v);
pg.vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r,u,v+iv);
u+=iu;
}
// close each ring
v1=v11;
v2=voff;
pg.vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r,u,v);
pg.vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r,u,v+iv);
pg.endShape();
v+=iv;
}
u=0;
// add the northern cap
pg.beginShape(TRIANGLE_STRIP);
pg.texture(t);
for (int i = 0; i < sphereDetail; i++) {
v2 = voff + i;
pg.vertex(0, r, 0,u,v+iv);
pg.vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r,u,v);
u+=iu;
}
pg.vertex(0, r, 0,u,v+iv);
pg.vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r,u,v);
pg.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;}
}
Re: Globe: Spherical Texturemap?
Reply #8 - Mar 28th, 2007, 12:00am
 
IT could be related to this issue: http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1171574044
Re: Globe: Spherical Texturemap?
Reply #9 - Apr 25th, 2007, 8:00am
 
Uhh, could this texturedSphere(float radius, PImage texture) be included in the next version of Processing? I have a hard time modifying anything with it. Although I will keep trying.

Thanks.
Re: Globe: Spherical Texturemap?
Reply #10 - May 18th, 2007, 4:55am
 
I was able to display a spherical texturemap on 0124 based on the examples above...

Code:

/*

Textured sphere example

for basic construction method, see http://local.wasp.uwa.edu.au/~pbourke/texture_colour/spheremap/

*/

PImage material;

float mouseDeltaX;
float mouseDeltaY;

void setup() {

size(1200, 800, P3D);
noStroke();

material = loadImage("earth-hi.jpg");
texturedSphereDetail(12);
}

int r = 200;
float spin = 0f;
float tilt = -0.65f;

void draw() {
background(255);

translate(width / 2, height / 2);

rotateX(tilt);
rotateY(spin);

texturedSphere(100, material);

}

void mouseDragged(){
mouseDeltaY = (pmouseY-mouseY);
mouseDeltaX = (pmouseX-mouseX);
if (abs(mouseDeltaX) > abs(mouseDeltaY)) {
spin -= 0.01f * mouseDeltaX;
} else {
tilt += 0.01f * mouseDeltaY;
}
}

/*

Textured sphere implementation

*/

float PI = 3.14159f;
float texturedSphereX[][];
float texturedSphereY[][];
float texturedSphereZ[][];
float texturedSphereU[][];
float texturedSphereV[][];
int texturedSphereDetail;

/**
* Set the detail level for textured spheres
*/
void texturedSphereDetail(int detail) {
if (detail == texturedSphereDetail) return;

texturedSphereDetail = detail;

// construct the underlying vertex and uv map data

float step = PI / detail;
float ustep = 0.5f / detail;
float vstep = 1.0f / detail;

texturedSphereX = new float[detail + 1][2 * detail + 1];
texturedSphereY = new float[detail + 1][2 * detail + 1];
texturedSphereZ = new float[detail + 1][2 * detail + 1];
texturedSphereU = new float[detail + 1][2 * detail + 1];
texturedSphereV = new float[detail + 1][2 * detail + 1];

for (int i = 0; i <= detail; i++) {
float theta = step * i;
float y = cos(theta);
float sin_theta = sin(theta);
float v = 1.0f - vstep * i;

for (int j = 0; j <= 2 * detail; j++) {
float phi = step * j;
float x = sin_theta * cos(phi);
float z = sin_theta * sin(phi);

float u = 1.0f - ustep * j;
println(u + ", " + v);

texturedSphereX[i][j] = x;
texturedSphereY[i][j] = y;
texturedSphereZ[i][j] = z;
texturedSphereU[i][j] = u;
texturedSphereV[i][j] = v;

}

}
}

/**
* Create a textured sphere with the supplied radius and material
*/
void texturedSphere(float radius, PImage material) {
// build the sphere by stacking up cross sections
// KLUDGE: the poles could be built more efficiently
int nexti;
for (int i = 0; i < texturedSphereDetail; i = nexti) {
nexti = i + 1;
beginShape(QUAD_STRIP);
texture(material);
for (int j = 0; j <= 2 * texturedSphereDetail; j++) {
float u = material.width * texturedSphereU[i][j];

float x1 = r * texturedSphereX[i][j];
float y1 = r * texturedSphereY[i][j];
float z1 = r * texturedSphereZ[i][j];
float v1 = material.height * texturedSphereV[i][j];

float x2 = r * texturedSphereX[nexti][j];
float y2 = r * texturedSphereY[nexti][j];
float z2 = r * texturedSphereZ[nexti][j];
float v2 = material.height * texturedSphereV[nexti][j];

vertex(x1, y1, z1, u, v1);
vertex(x2, y2, z2, u, v2);
}
endShape();
}

}
Re: Globe: Spherical Texturemap?
Reply #11 - Jul 27th, 2007, 11:52pm
 
debucode - very cool, that works nicely.  Just watch for one small bug: in the texturedSphere() function you're using the global variable r instead of the passed variable radius as the radius of the sphere.  Once that's taken care of, this is very useful code.

[BTW, you also don't need to declare PI - Processing already declares it for you]
Re: Globe: Spherical Texturemap?
Reply #12 - Aug 3rd, 2007, 3:53am
 
Good catch on the radius. And I was completely ignorant of PI being declared for me.

I wound up using this code to make a realtime web traffic vizualization (projecting user searches onto an Earth globe) and made a couple of observations.

First, when I render using OpenGL (on the Mac) the performance increase is nice but the u,v coordinates have to be assigned not from the outermost edges of the texture map but from the "middle" of each pixel. Otherwise a seam forms on the sphere.

Second, you can take advantage of the fact that you have access to the texturedSphereX,Y,Z array to manipulate the globe on the fly. For instance I can "unfold" the sphere to a flat projection and back again. In my case I did this by simulating having spring forces that "pull" the array points towards the desired shape.
Re: Globe: Spherical Texturemap?
Reply #13 - Aug 3rd, 2007, 8:51am
 
Maybe the surfaceLib will help you. You can create a sphere and you can add texture that wrap around the sphere.
Re: Globe: Spherical Texturemap?
Reply #14 - Aug 24th, 2007, 9:26pm
 
Would you mind elaborating on what you mean by the "middle" of each pixel? I'm having the same seam issue... I'd really appreciate more specifics on your solution.
Pages: 1 2