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:
(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.