# Thread: Texture on a Sphere

1. ## Texture on a Sphere

I have used this code to put a texture on my sphere, but it doesn't work.

Code:
```float z = r * cosf (seg * fDeltaSegAngle);
float x = r * sinf (seg * fDeltaSegAngle);
float z1 = r1 * cosf (seg * fDeltaSegAngle);
float x1 = r1 * sinf (seg * fDeltaSegAngle);

(*p_Vertices).position = D3DXVECTOR3 (x,y,z);
(*p_Vertices).color = D3DCOLOR_ARGB (100,100,1,1);
(*p_Vertices).tu = -(FLOAT)seg/(FLOAT)30.0;
(*p_Vertices).tv = (FLOAT)ring /(FLOAT)15.0;
p_Vertices++;```
The - before the tu component has been borrowed the BumpEarth example that comes with the SDK, but I don't really understand why that should be there.

Such texturing works for cylinders, but not for spheres, why? I have seen
BumpEarth example that comes with the DirectX8 SDK, but that doesn't use
the D3DXCreateTextureFromFile() that I would wan't to use.

2. Here is how you calculate UV coordinates for a sphere:

Given two UNIT vectors a vector from center to equator and center to north pole.

So.

Code:
```Sn = normal at intersection
Sp = (xp, yp, zp) and // north pole
Se = (xe, ye, ze ) // equator

Phi = arccos( -Sn DOT Sp );
v = Phi / PI;

Theta = ( arccos((Se DOT Sn) / sin(Theta)) ) / ( 2 * PI );

if( ((Sp CROSS Se) DOT Sn ) > 0 )
u = Theta
else
u = 1 - Theta;```
You can look it up online and get a derivation mathematically. I don't feel like typing it out. Its much easier if I had a whiteboard or something. Hope this helps you.

3. ## I still have a problem !!!!!

My problems with the sphere continue.

Well, last time the code was rather incomplete. Here's the complete thing.
I have added Normals for the calculation of the texture cordinates, as
suggested. I am using a 256 x 256 .bmp file as my input file in
CreateTextureFromFile (.....), but all I get in the end is a skeleton of
a sphere, no texture, nothing.

Here's the InitGeometry() function
Code:
```void CMainframe::InitGeometry()
{
if (FAILED (D3DXCreateTextureFromFile (g_pd3dDevice,"BANANA.BMP",&g_pTex)))
throw "Could not load Texture, Fatal failure";

if (FAILED (g_pd3dDevice->CreateVertexBuffer (2*15*31*sizeof (CUSTOMVERTEX),
0,D3DFVF_CUSTOMVERTEX,
D3DPOOL_MANAGED,
&g_pVB)))
throw "Failed to CreateVertexBuffer()";

CUSTOMVERTEX* p_Vertices;

if (FAILED (g_pVB->Lock (0,0,(BYTE**)&p_Vertices,0)))
throw "Failed to Lock()";

float fDeltaRingAngle = D3DX_PI / 15.0f;
float fDeltaSegAngle = 2.0f * D3DX_PI / 30.0f;

for (DWORD ring=0; ring<=15;ring++)
{
float r = 3 * sinf (ring * fDeltaRingAngle );
float y = 3.05 * cosf (ring * fDeltaRingAngle);
float r1 = sinf ((ring + 1) * fDeltaRingAngle);
float y1 = cosf ((ring+1) * fDeltaRingAngle);

for (DWORD seg=0;seg <= 30 ; seg++)
{
float z = r * cosf (seg * fDeltaSegAngle);
float x = r * sinf (seg * fDeltaSegAngle);
float z1 = r1 * cosf (seg * fDeltaSegAngle);
float x1 = r1 * sinf (seg * fDeltaSegAngle);

(*p_Vertices).position = D3DXVECTOR3 (x,y,z);
(*p_Vertices).color = D3DCOLOR_ARGB (100,100,1,1);
(*p_Vertices).normal=D3DXVECTOR3 (x,y,z);

//Calculate the texture Co-ordinates

(*p_Vertices).tu = asinf(x)/D3DX_PI + 0.5f;
(*p_Vertices).tv = asinf(y)/D3DX_PI + 0.5f;
p_Vertices++;

}
}

g_pVB -> Unlock();
}```

Ok, that was long, and heres the Render()
Code:
```void CMainframe::Render()
{
// Clear the backbuffer and the zbuffer
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
D3DCOLOR_RGBA (0,0,255,0), 1.0f, 0 );

// Begin the scene
g_pd3dDevice->BeginScene();

// Setup the world, view, and projection matrices
SetUpMatrices();

// Setup the Textures
g_pd3dDevice->SetTexture( 0, g_pTex );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );

// Render the vertex buffer contents
g_pd3dDevice->SetStreamSource( 0, g_pVB, sizeof(CUSTOMVERTEX) );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 500	 );

// End the scene
g_pd3dDevice->EndScene();

// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

}```
So whats wrong really ? I am using the right (!!!) method to map them,
am I not ?

And yes, another interesting thing, although I am running this program on
a P4 2.4GHz machine, the sphere seems to rotate *painfully* slow. Parts
of it even seem to be disappearing at times. I find that rather funny
because I have played Unreal2 on this system, and that was running fine.
My Sphere couldn't possibly be demanding more resources or processing
than Unreal2. So why is this so slow ???

Thanks...
CJ

4. I think there might be an easier way to generate a 3D sphere, if we are talking about 3D here.

I've generated 3D spheres is VB and even in BASIC and all of them rotate very fast, even textured and gouraud shaded. Here is how I create a sphere.

Take the mathematical formula for a sphere and apply that to your 3D coords. I think this is the equation.

Here is the equation of a sphere in spherical coordinates, which is the easiest for me and eliminates the need to square values.

0<alpha<360
-90<beta<90

Now if we wanted a sphere with 10 facets in x and y directions we find the angle increment.

stepalpha=360/numfacets;
stepbeta=360/numfacets;

Alpha is the angle that should go from 0 to 360 and beta will go from -90 to 90. Radius is simply the amount you wish to displace each point on the sphere.

In order to connect these points to create a sphere I usually figure it this way. Since we know the number of facets around our sphere we know how to connect the dots.

Say we have 10 facets. That means that on each level we have 10 square faces to approximate our sphere. When we reach 10, we move down to the next set (from the top pole of the sphere) and render again. This means that all points will be separated by 11 points. So if we connect p1 to p2 (points 1 and 2) we have a horizontal line at the top of our quad. If we connect p3 to p4 we have a bottom horizontal line (points 12 and 13). So we connect points p1 and p3 (1 and 12) and points p2 and p4 (2 and 13) and we have one facet.

Code:
```p1---------p2
.               .
.               .
.               .
.               .
.               .
p3---------p4```
Create a polygon out of these points and you find that you simply have a quad or two triangles - very fast render indeed - w/o all those very slow trig functions. Notice with this method that you only use trig in the creation of your sphere - never during the render cycle.

All the sphere is, is a collection of points and lines out in 3D space. When you create polygons from those points in the above fashion you have broken the sphere down into many small triangles or polygons (depending on your approach). If you have Direct3D render this as a triangle list and then wrap your planet texture or whatever texture you have then you will see a big difference in the speed. I've programmed this in DJGPP and it's fast enough there to put into a game so I know D3D would scream.

To improve on speed even more - notice that you can simply change the number of facets in your sphere to reduce the number of polygons in the sphere. You could pre-compute coords for 3 sizes of spheres and then use those for your level of detail rendering. Take a look at Freelancer or Battlecruiser Millenium for an illustration of this. You will notice that the spheres (planets) gradually gain polygons as you approach them and slowly lose polygons as you move away from them.

Finally, since these spheres are simply a collection of polies, triangle lists, or linked list polygons (whatever you choose) you do not have to change your renderer to deal with spheres - so they are rendered just as fast as any other 3D object in your engine, complete with rotation and lighting at no additional cost.

Sorry so long. Hope this helps.

5. Just so you know we are on the same page, I too looked at the bump earth example and it seemed like a lot of trig for a simple effect. Imagine if you had multiple spheres on the screen. With their approach it would bring any giant to its knees quickly.

Their is another tutorial on NVidia's website concerning 3D spheres and this is exactly how they did it. I did not steal this info from them because I figure it out through trial and error first and then came upon NVidia's tutorial later. I was very shocked that NVidia took the same approach as I did because it seemed too simple. There is a thread on here concerning my experiments with 3D spheres from way back when - look it up on the search on this board. You will laugh at my first approach to the situation.

6. You will not get the bump-mapping with this approach, but you will get a textured sphere. I'll look for my code to see if its the effect you are wanting or if I'm way off base.