Jump to content

  • Log In with Google      Sign In   
  • Create Account


andyS91

Member Since 19 Mar 2012
Offline Last Active May 29 2012 05:26 AM

Posts I've Made

In Topic: Distorted Texture on Sphere

20 March 2012 - 08:59 AM

Thank you very much - now I've got it! Posted Image
If someone is having the same problems, here's the code for adding texture coordinates to a standard sphere mesh:

public static void ComputeTexCoords(Device device, ref Mesh mesh)
		{
			mesh.ComputeNormals();
		  
			Mesh newMesh = mesh.Clone(device, mesh.CreationOptions, mesh.VertexFormat | VertexFormat.Texture1);
			mesh.Dispose();
			mesh = newMesh;
			VertexElement[] elems = mesh.GetDeclaration();
			int posElem = FindElementIndex(elems, DeclarationUsage.Position);
			int normalElem = FindElementIndex(elems, DeclarationUsage.Normal);
			int texCoordsElem = FindElementIndex(elems, DeclarationUsage.TextureCoordinate);
			DataStream ds = mesh.LockVertexBuffer(LockFlags.None);
			while (ds.Position < ds.Length)
			{
				long oldPos = ds.Position;
				Vector3 vec;
				ds.Position += elems[normalElem].Offset;
				vec = ds.Read<Vector3>();
				ds.Position = oldPos;
				var phi = Math.Acos((double)vec.Y);
				var v = (float)(phi / Math.PI);
				var u = 0f;

				if (vec.Y ==  1.0f || vec.Y  == -1.0f)
				{
					u = 0.5f;
				}
				else
				{
					u = (float)(Math.Acos(Math.Max(Math.Min(( double)-vec.Z /
					Math.Sin(phi),  1.0 ), -1.0)) / (2.0 * Math.PI)) ;
					u = (vec.X > 0f) ? u :  1 - u;
				}
				ds.Position += elems[texCoordsElem].Offset;
				ds.Write<float>(u);
				ds.Write<float>(v);
				ds.Position = oldPos + mesh.BytesPerVertex;
			}
			mesh.UnlockVertexBuffer();
		}

public static int FindElementIndex(VertexElement[] elems, DeclarationUsage usage)
		{
			for (int i = 0; i < elems.Length; ++i)
			{
				if (elems[i].Usage == usage)
					return i;
			}
			return -1;
		}

Just create a sphere with Mesh.CreateSphere and a Texture with Texture.FromFile, call the ComputeTexCoords method with this mesh and your D3D9 device as argument and set up drawing the texture with device.setTexture in your render method. I also recommend to set the renderstate to device.SetRenderState(RenderState.Wrap0, TextureWrapping.WrapCoordinate0) to avoid a ugly seam.

Most of the sourcecode isn't written by me (indeed I've written very less of it myself). The underlaying structure is from this post here: http://www.gamedev.n...ource-included/ with changes regarding the calculation of the UV-coordinates (which I've taken from here: http://channel9.msdn...Textures-Part-3). I hope the authors of those articles don't mind if I reuse their code.
Thanks again for your help and good luck for those who try to do the same ;)

PARTNERS