Thread: Finally a perfect sphere map

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Finally a perfect sphere map

    This source code was found on the net and is supposedly from the Blender source code.

    Code:
    float SAacos(float fac)
    {
      if(fac<= -1.0f) 
     {
       return (float)D3DX_PI;
     }
     else if(fac>=1.0f) 
     {
       return 0.0f;
     } else return (float)acos(fac);
    }
    
    void SphereMap(float x, float y, float z, float &u, float &v)  
    {
      float PI=D3DX_PI;
      float len;
      len = sqrt(x*x+y*y+z*z);
      if(len>0.0f) 
      {		
         if(x==0.0f && y==0.0f) 
        {
          u = 0.0f;	/* othwise domain error */
        }
        else 
        {
          u = (1.0f - atan2(x,y)/PI)/2;
        }
    
        z/=len;
        v = 1.0f- SAacos(z)/PI;
      }
    }

    This sphere map code works perfect with no distortions. Make sure your maps are a power of 2 and make sure the width is twice the height or a 2:1 ratio.
    Valid 2:1 ratios would be something like 512x256, 128x256, 1024x512, etc.

    Very handy for making planets. Extremely simple way to create spheres, planets, etc, is to use D3DXCreateSphere(), clone the mesh to add u,v coords, and use the above code to feed vertices in and get u,v coords out.

    Once you have done all this you must do this prior to rendering:

    m_pDevice->SetRenderState(D3DRS_WRAP0,D3DWRAP_U);

    This tells Direct3D to wrap the texture rendering. If you don't do this, the sphere will have this very ugly crease in it where the texture is attempting to wrap from <1.0f to 0.0f. Without telling Direct3D to treat this as a wrap instead of a complete texture address (.90f to 0.0f in normal mode would be a near complete texture address) it will not wrap the coords.

    Do not confuse this wrapping with the wrap mode of the texture stages. Also once you set this make sure you set it back to normal using this:

    m_pDevice->SetRenderState(D3DRS_WRAP0,0);

    The WRAP0 refers to sampler 0,1,2,3,4....etc, etc. So WRAP2 would be sampler 2.

    Why this code works is because acosf() has been wrapped to account for domain errors which occurs at the poles of the spheres. With this code the domain errors are caught and hard-coded values are returned which represent the correct values. Just using acosf() will NOT work.

    EDIT:
    There is still some distortion at the poles. Back to the drawing board.
    Last edited by VirtualAce; 12-13-2006 at 08:55 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Adding a Map to a program
    By Shogun32 in forum C++ Programming
    Replies: 1
    Last Post: 05-04-2009, 09:42 AM
  2. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  3. Creating a map engine.
    By suzakugaiden in forum Game Programming
    Replies: 11
    Last Post: 06-21-2005, 05:06 AM
  4. Sphere code not working
    By VirtualAce in forum Game Programming
    Replies: 2
    Last Post: 10-03-2004, 07:29 AM
  5. Searching STL Map Inside STL Map Object :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 11-14-2002, 09:11 AM