Thursday, 2 April 2015

Unity 5: Create Mesh then Deform It

3 hours Code/Asset

Ok where to start, I have been busy following a tutorial and have come up with this, this code creates a cube then when you click on different vertices it makes the selected vertices go up or down in real time. I have been working on my commenting. It still needs more work.


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class DeformableMesh : MonoBehaviour
{
    public float pointDeformation = 0.01f;

    Mesh mesh;
    Material mat;
    List<Vector3> Points;
    List<Vector3> Verts;
    List<int> Tris;
    List<Vector2> UVs;

    float size = 0.5f;

   

    // Use to set up refernces between scripts Awake is called before Start.
    // Is called after all objects are initialzed but before scripts are run.
    void Awake ()
    {
       
    }
   
    // Use this for initialization
    void Start ()
    {
        Points = new List<Vector3>();

        //Setting the poistions of the verts
        Points.Add(new Vector3(-size, size,-size));
        Points.Add(new Vector3( size, size,-size));
        Points.Add(new Vector3( size,-size,-size));
        Points.Add(new Vector3(-size,-size,-size));

        Points.Add(new Vector3( size, size, size));
        Points.Add(new Vector3(-size, size, size));
        Points.Add(new Vector3(-size,-size, size));
        Points.Add(new Vector3( size,-size, size));

        Verts = new List<Vector3>();
        Tris = new List<int>();
        UVs = new List<Vector2>();
        CreateMesh();

    }
   
    // Render update is called once per frame
    void Update ()
    {

        // Controls to raise and lower points
        // If its not working check the mesh collider mesh slot
        if (Input.GetMouseButton(0))
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit ))
            {
                RaisePoint(FindNearestPoint(hit.point));
                Debug.Log(hit.point);
               
            }
        }
        if (Input.GetMouseButton(1))
        {
           
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                LowerPoint(FindNearestPoint(hit.point));
            }
        }
    }
   
    // Pysics update is called once per 1/60 seconds
    void FixedUpdate ()
    {
       
    }

    private Vector3 FindNearestPoint(Vector3 point)
    {
        Vector3 NearestPoint = new Vector3();
        float lastDistance = 99999999f;

        for (int i = 0; i < Points.Count; i++)
        {
            float distance = GetDistance(point, Points[i]);
            if (distance < lastDistance)
            {
                lastDistance = distance;
                NearestPoint = Points[i];
            }
        }
        return NearestPoint;
    }

    // Using math finding the distance between 2 points;
    private float GetDistance(Vector3 start, Vector3 end)
    {
        return Mathf.Sqrt(Mathf.Pow((start.x - end.x), 2) + Mathf.Pow((start.y - end.y), 2) + Mathf.Pow((start.z - end.z), 2));
    }
    private void RaisePoint(Vector3 point)
    {
        int index = -1;
        for (int i = 0; i < Points.Count; i++)
        {
            if (Points[i] == point)
            {
                index = i;
                break;
            }
        }
        if (index == -1)
        {
            Debug.LogError("Could not match points");
        }
        else
        {
            Vector3 newPoint = Points[index];
            newPoint.y += pointDeformation;
            Points[index] = newPoint;
            UpdateMesh();
        }
    }

        private void LowerPoint(Vector3 point)
    {
        int index = -1;
        for (int i = 0; i < Points.Count; i++)
        {
            if (Points[i] == point)
            {
                index = i;
                break;
            }
        }
        if (index == -1)
        {
            Debug.LogError("Could not match points");
        }
        else
        {
            Vector3 newPoint = Points[index];
            newPoint.y -= pointDeformation;
            Points[index] = newPoint;
            UpdateMesh();
        }
    }

    private void CreateMesh()
    {
        // Adding the requite components to show a mesh
        gameObject.AddComponent<MeshFilter>();
        gameObject.AddComponent<MeshRenderer>();
        gameObject.AddComponent<MeshCollider>();

        mat = Resources.Load("Materials/Defualt") as Material;
        if (mat == null)
        {
            Debug.LogError("Material not found");
            return;
        }

        MeshFilter meshFilter = GetComponent<MeshFilter>();
        if (meshFilter == null)
        {
            Debug.LogError("meshFilter not found");
            return;
        }

        mesh = meshFilter.sharedMesh;
        if (mesh == null)
        {
            meshFilter.mesh = new Mesh();
            mesh = meshFilter.sharedMesh;
        }

        MeshCollider meshCollier = GetComponent<MeshCollider>();
        if (meshCollier == null)
        {
            Debug.LogError("MeshCollider not found");
            return;
        }

        mesh.Clear();
        UpdateMesh();
    }

    private void UpdateMesh()
    {
        // Front Plane
        Verts.Add(Points[0]); Verts.Add(Points[1]); Verts.Add(Points[2]); Verts.Add(Points[3]);
        // Back Plane
        Verts.Add(Points[4]); Verts.Add(Points[5]); Verts.Add(Points[6]); Verts.Add(Points[7]);
        // Left Plane
        Verts.Add(Points[5]); Verts.Add(Points[0]); Verts.Add(Points[3]); Verts.Add(Points[6]);
        // Right Plane
        Verts.Add(Points[1]); Verts.Add(Points[4]); Verts.Add(Points[7]); Verts.Add(Points[2]);
        // Top Plane
        Verts.Add(Points[5]); Verts.Add(Points[4]); Verts.Add(Points[1]); Verts.Add(Points[0]);
        // Bottum Plane
        Verts.Add(Points[3]); Verts.Add(Points[2]); Verts.Add(Points[7]); Verts.Add(Points[6]);

        //Front Plane
        Tris.Add(0); Tris.Add(1); Tris.Add(2);
        Tris.Add(2); Tris.Add(3); Tris.Add(0);
        //Back Plane
        Tris.Add(4); Tris.Add(5); Tris.Add(6);
        Tris.Add(6); Tris.Add(7); Tris.Add(4);
        //Left Plane
        Tris.Add(8); Tris.Add(9); Tris.Add(10);
        Tris.Add(10); Tris.Add(11); Tris.Add(8);
        //Right Plane
        Tris.Add(12); Tris.Add(13); Tris.Add(14);
        Tris.Add(14); Tris.Add(15); Tris.Add(12);
        //Top Plane
        Tris.Add(16); Tris.Add(17); Tris.Add(18);
        Tris.Add(18); Tris.Add(19); Tris.Add(16);
        //Bottum Plane
        Tris.Add(20); Tris.Add(21); Tris.Add(22);
        Tris.Add(22); Tris.Add(23); Tris.Add(20);

        // Front Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));
        // Back Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));
        // Left Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));
        // Right Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));
        // Top Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));
        // Bottum Plane
        UVs.Add(new Vector2(0, 1));
        UVs.Add(new Vector2(1, 1));
        UVs.Add(new Vector2(1, 0));
        UVs.Add(new Vector2(0, 0));

        //Setting everything to arrays;
        mesh.vertices = Verts.ToArray();
        mesh.triangles = Tris.ToArray();
        mesh.uv = UVs.ToArray();

        //Clearing all the lists, so new ones can be created;
        Verts.Clear();
        Tris.Clear();
        UVs.Clear();

        //Telling unity to create the mesh with the above information
        MeshCollider meshCollider = GetComponent<MeshCollider>();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        RecalculateTangents(mesh);
        meshCollider.sharedMesh = null; // need to set shared mesh to null before setting the mesh.
        meshCollider.sharedMesh = mesh;
        gameObject.GetComponent<Renderer>().material = mat; // To access the renderer you need to get the component
        mesh.Optimize();
    }

    //Storing the data
    private static void RecalculateTangents(Mesh mesh)
    {
        int[] triangles = mesh.triangles;
        Vector3[] vertices = mesh.vertices;
        Vector2[] uv = mesh.uv;
        Vector3[] normals = mesh.normals;

        int triangleCount = triangles.Length;
        int vertexCount = vertices.Length;

        Vector3[] tan1 = new Vector3[vertexCount];
        Vector3[] tan2 = new Vector3[vertexCount];

        Vector4[] tangents = new Vector4[vertexCount];

        for (long a = 0; a < triangleCount; a += 3)
        {

            //Triangle Storage
            long tris1 = triangles[a + 0];
            long tris2 = triangles[a + 1];
            long tris3 = triangles[a + 2];

            //Vertices Storage
            Vector3 verts1 = vertices[tris1];
            Vector3 verts2 = vertices[tris2];
            Vector3 verts3 = vertices[tris3];

            //UV Storage
            Vector2 w1 = uv[tris1];
            Vector2 w2 = uv[tris2];
            Vector2 w3 = uv[tris3];

            //Verticies
            float x1 = verts2.x - verts1.x;
            float x2 = verts3.x - verts1.x;

            float y1 = verts2.y - verts1.y;
            float y2 = verts3.y - verts1.y;

            float z1 = verts2.z - verts1.z;
            float z2 = verts3.z - verts1.z;

            //UVS
            float s1 = w2.x - w1.x;
            float s2 = w3.x - w1.x;
            float t1 = w2.y - w1.y;
            float t2 = w3.y - w1.y;

            float div = s1 * t2 - s2 * t1;
            float r = div == 0.0f ? 0.0f : 1.0f / div;

            Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
            Vector3 tdir = new Vector3((s2 * x2 - s1 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

            tan1[tris1] += sdir;
            tan1[tris2] += sdir;
            tan1[tris3] += sdir;

            tan2[tris1] += tdir;
            tan2[tris2] += tdir;
            tan2[tris3] += tdir;
        }

        for (long a = 0; a < vertexCount; ++a)
        {
            Vector3 n = normals[a];
            Vector3 t = tan1[a];

            Vector3.OrthoNormalize(ref n, ref t);
            tangents[a].x = t.x;
            tangents[a].x = t.y;
            tangents[a].x = t.z;

            tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
        }

        mesh.tangents = tangents;
    }
}

No comments:

Post a Comment