Sign in to follow this  

3D Sphere Texturing

This topic is 3371 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
        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);
            }
        }
Here is a picture of what it looks like when it renders: Free Image Hosting at www.ImageShack.us (Ignore the reness 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. [Edited by - Upinflames on September 20, 2008 12:20:26 PM]

Share this post


Link to post
Share on other sites

This topic is 3371 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this