Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » spherical texture coordinates

This thread is locked; no one can reply to it. rss feed Print
spherical texture coordinates
Mike Farrell
Member #248
April 2000
avatar

I'm trying to wrap a texture around a sphere (similarly to the way GLU quadric spheres are textured) using its geometry as input.

I've written a function to convert the sphere's xyz rectangular coordinates to spherical ones and then in turn am using the u & v (phi & theta) spherical parameters as my texture coordinates. The only problem here is that u (the latitudal coordinate) repeats after it reaches 360 degrees. This is causing the texture coordinate to wrap around incorrectly at the pole (see attached screenshot).

For some reason, I just can't figure out how to fix this problem.

Here's my code

1 
2//real's are just floats
3//texc behaves like a 2d array where
4//index 0 is the r (horizontal) texture coordinate
5//and index 1 is the t (vertical) texture coordinate
6//v is the incoming 3D rectangular coordinate of a point
7//on the sphere and r is a supplied radius to save computation
8 
9static inline void spherical_texc(real r, const Vertex3D &v, Vertex &texc)
10{
11 real phi, theta,
12 s = sqrt(v[0]*v[0] + v[2]*v[2]);
13
14 phi = acos(v[1]/r);
15 if(s != 0)
16 theta = M_PI/2+((0 <= v[0]) ? asin(v[2]/s) : (M_PI-asin(v[2]/s)));
17 else theta = 0;
18
19 texc[0] = theta/(2*M_PI);
20 texc[1] = phi/M_PI;
21}

Plucky
Member #1,346
May 2001
avatar

Quote:

The only problem here is that u (the latitudal coordinate) repeats after it reaches 360 degrees.

?? phi can only be from 0 to 180 deg due to "acos". Are you talking about theta? Perhaps you need to describe the problem better; the picture wasn't that helpful.

Perhaps things can be simplified by:

const float precision = 0.000001;
if (v[0] > precision || v[0] < -precision) 
   theta = atan2(v[2] / v[0]);
else
   theta = 0.;

or similar.

Mike Farrell
Member #248
April 2000
avatar

The problem lies in the conversion from rectangular coordinates to spherical ones.

Since theta wraps around the sphere like latitude lines wrap around the earth, once you pass 360 degrees, you reset to 0. This makes the vertex that converts to a theta of 0 in spherical coordinates, also able to have the value 360. That may not matter for degrees, but when texture mapping, 0 and 1 and definitely two different values.

My desired result is what happens in blender when you turn the mapping mode to spherical instead of flat. I even downloaded the blender source code and used their spherical coordinate function thinking that would fix it. But I still had the EXACT same problem. Which means blender must fix the issue elsewhere but I can't find it in their code.

In other words, acos is necessary because of the nature of the problem.

Here's blenders code, it pretty much does the same thing my above algorithm does (and doesn't fix my problem still)

1/*from blender source code *********/
2static float saacos(float fac)
3{
4 if(fac<= -1.0f) return (float)M_PI;
5 else if(fac>=1.0f) return 0.0;
6 else return (float)acos(fac);
7}
8 
9static void spheremap(float x, float y, float z, float &u, float &v)
10{
11 float len;
12
13 len = sqrt(x*x+y*y+z*z);
14 if(len>0.0)
15 {
16 if(x==0.0 && y==0.0) u = 0.0; /* othwise domain error */
17 else u = (1.0 - atan2(x,y)/M_PI )/2.0;
18
19 z/=len;
20 v = 1.0- saacos(z)/M_PI;
21 }
22}
23/******************************/

Plucky
Member #1,346
May 2001
avatar

Have you checked to see if 'u' is ever > 1.0?

Perhaps the problem is in your vertices? Overlapping points? And that the blender code has no need to fix "the problem" to begin with.

Mike Farrell
Member #248
April 2000
avatar

I've checked the sphere vertex code many times over, the vertices are fine. If I do a flat method of texture mapping, it comes out ok.

Plucky
Member #1,346
May 2001
avatar

I understand the problem now. You want the u coordinates for the problem area to be say 0.95 --> 1.0, instead you're getting 0.95 --> 0.0 . Well, one way is to add another meridian of vertices that overlap the "starting points" where u=0, and set those texture coordinates to be u=1, instead.

Mike Farrell
Member #248
April 2000
avatar

I'm gonna try something else I think. Since the vertices are stored at the polygon level and not the vertex level, I'm going to essentially store the two sets of polygons that own the pole vertices: the ones with an angle increasing (start of the pole), and the ones with the angle decreasing (at the end of the pole) and that will be may way to determine whether I should use 0.0 or 1.0.

I'll post back if I have more trouble

Go to: