Texture on a Sphere

This is a discussion on Texture on a Sphere within the Game Programming forums, part of the General Programming Boards category; I have used this code to put a texture on my sphere, but it doesn't work. Code: float z = ...

  1. #1
    Registered User
    Join Date
    Nov 2002
    Posts
    42

    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.

    Please help.

  2. #2
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    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.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  3. #3
    Registered User
    Join Date
    Nov 2002
    Posts
    42

    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->SetVertexShader( D3DFVF_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. #4
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,586
    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

    newx=(cos(alpha)*sin(beta))*radius
    newy=(sin(alpha)*sin(beta))*radius
    newz=(sin(beta))*radius

    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. #5
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,586
    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. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,586
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. d3d9 c++ texture wrapper... again...
    By yaya in forum Game Programming
    Replies: 0
    Last Post: 04-01-2009, 01:08 PM
  2. D3d Texture Wrapper == ARRRGGGGHHH
    By yaya in forum Game Programming
    Replies: 1
    Last Post: 03-25-2009, 06:41 PM
  3. Replies: 4
    Last Post: 02-27-2008, 02:10 PM
  4. OpenGL - look trough surface -nehe lesson
    By GanglyLamb in forum Game Programming
    Replies: 8
    Last Post: 08-24-2006, 11:06 PM
  5. Pong is completed!!!
    By Shamino in forum Game Programming
    Replies: 11
    Last Post: 05-26-2005, 10:50 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21