Someone

Someone

  • NA
  • 1
  • 0

Putting a Texture on a sphere(MDX & C#)

Sep 21 2008 9:23 AM
Hello, I am doing a project that makes a 3D Earth that rotates. I have it all completed except the texture rendering differently. I am following ZMans tutorial on Coding4Fun. I am using C# and Managed DirectX. Here is my texturing procedure and my mesh creating procedure: [code] private void LoadMesh() { ExtendedMaterial[] materialarray; sphere = Mesh.FromFile(System.Windows.Forms.Application.StartupPath + @"\..\..\bin\Release\Sphere.x", MeshFlags.Managed, device, out materialarray); if ((materialarray != null) && (materialarray.Length > 0)) { m_materials = new Material[materialarray.Length]; for (int i = 0; i < materialarray.Length; i++) { m_materials[i] = materialarray[i].Material3D; m_materials[i].Ambient = m_materials[i].Diffuse; } } sphere = sphere.Clone(sphere.Options.Value, CustomVertex.PositionNormalTextured.Format, device); sphere = SetSphericalTexture(sphere.Clone(sphere.Options.Value, sphere.VertexFormat | VertexFormats.Texture0, sphere.Device)); //sphere.ComputeNormals(); VertexBuffer vertices = sphere.VertexBuffer; GraphicsStream stream = vertices.Lock(0, 0, LockFlags.None); Vector3 meshcenter; meshradius = Geometry.ComputeBoundingSphere(stream, sphere.NumberVertices, sphere.VertexFormat, out meshcenter); vertices.Unlock(); } private static Mesh SetSphericalTexture(Mesh mesh) { Vector3 vertexRay; Vector3 meshCenter; double phi; float u; Vector3 north = new Vector3(0f, 0f,1f); Vector3 equator = new Vector3(0f, 1f, 0f); Vector3 northEquatorCross = Vector3.Cross(north, equator); ComputeBoundingSphere(mesh, out meshCenter); using (VertexBuffer vb = mesh.VertexBuffer) { CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vb.Lock(0, typeof(CustomVertex.PositionNormalTextured), LockFlags.None, mesh.NumberVertices); try { for (int i = 0; i < verts.Length; i++) { //For each vertex take a ray from the centre of the mesh to the vertex //and normalize so the dot products work. vertexRay = Vector3.Normalize(verts[i].Position - meshCenter); ////Ref:http://www.cs.unc.edu/~rademach/xroads-RT/RTarticle.html and ////Glassner, A. (ed) An Introduction to Ray Tracing. Academic Press New York, N.Y. 1989. //phi = Math.Acos((double)Vector3.Dot(north, vertexRay)); //verts[i].Tv = (float)(phi / Math.PI); //if (phi == 0.0) //if north and vertex ray are coincident then we can pick an arbitray u since its the entire top/bottom line of the texture //{ // u = 0.5f; //} //else //{ // //Clamp the acos() param to 1.0/-1.0 (rounding errors are sometimes taking it slightly over. // u = (float)(Math.Acos(Math.Max(Math.Min((double)Vector3.Dot(equator, vertexRay) / Math.Sin(phi), 1.0), -1.0)) / (2.0 * Math.PI)); // if (Vector3.Dot(northEquatorCross, vertexRay) < 0.0) // { // verts[i].Tu = u; // } // else // { // verts[i].Tu = 1 - u; // } //} //Since we know we are using normalised axis we can simplify this somewhat! //Note these simplifcations only apply if the basis vectors are the unit axis //north=(0,0,1)=zaxis, equator=(0,1,0)=yaxis and north x equator=(1,0,0)=xaxis //since (0,0,1)dot(x,y,z)==z and (0,1,0)dot(x,y,z)==y //if north and vertex ray are coincident then we can pick an arbitray u since its the entire top/bottom line of the texture phi = Math.Acos((double)vertexRay.Z); verts[i].Tv = (float)(phi / Math.PI); if (vertexRay.Z == 1.0f || vertexRay.Z == -1.0f) { verts[i].Tu = 0.5f; } else { u = (float)(Math.Acos(Math.Max(Math.Min((double)vertexRay.Y / Math.Sin(phi), 1.0), -1.0)) / (2.0 * Math.PI)); //Since the cross product is just giving us (1,0,0) i.e. the xaxis //and the dot product was giving us a +ve or -ve angle, we can just compare the x value with 0 verts[i].Tu = (vertexRay.X > 0f) ? u : 1 - u; } } } finally { vb.Unlock(); } } return mesh; } public static float ComputeBoundingSphere(Mesh mesh, out Vector3 center) { // Lock the vertex buffer GraphicsStream data = null; try { data = mesh.LockVertexBuffer(LockFlags.ReadOnly); // Now compute the bounding sphere return Geometry.ComputeBoundingSphere(data, mesh.NumberVertices, mesh.VertexFormat, out center); } finally { // Make sure to unlock the vertex buffer if (data != null) mesh.UnlockVertexBuffer(); } } private void DrawMesh(Mesh mesh, Material[] meshmaterials) { for (int i = 0; i < meshmaterials.Length; i++) { device.Material = meshmaterials[i]; mesh.DrawSubset(i); } } [/code] Here is a picture of what it looks like when it renders: Free Image Hosting at www.ImageShack.us (Ignore the redness of it, I want it to be red.) If someone could help me that would be appreciated because I have been attempting to resolve it with no success. The texture file I am using is 720x360, can someone please help me fix it, I am in dire need of help.