/// <summary>
    /// Creates the mesh from .vol file, and applies it to the mesh collider for the gameObject
    /// <para>
    /// Uses the LoadSingleton to get the vertices, surface triangles and tetrahedral elements.
    /// Once loaded it applies these vertices and surface triangles to the mesh's vertices and triangles before calculating the normals.
    /// Finally it adds the mesh to the mesh collider.
    /// </para>
    /// <see cref="https://docs.unity3d.com/ScriptReference/Mesh.html">For information on procedurally generating meshes in Unity</see>
    /// </summary>
    private void createInitialMesh()
    {
        // Initialise lists
        vertices         = new List <Vector3> {
        };
        surfaceTriangles = new List <int> {
        };
        elements         = new List <Vector4> {
        };

        // Grab an instance of the volumetric loader
        LoadSingleton instance = LoadSingleton.getInstance();

        // Get the vertices, surface triangles indices and the tetrahedral element indices
        instance.loadFile(meshFile, ref vertices, ref surfaceTriangles, ref elements);

        Mesh mesh = GetComponent <MeshFilter>().mesh; // Grab the mesh of the current game component.

        mesh.Clear();                                 // Clear the mesh to start fresh just in case.

        mesh.vertices  = vertices.ToArray();          // Convert to an array and add to our mesh
        mesh.triangles = surfaceTriangles.ToArray();  // Convert to an array and add to our mesh

        mesh.RecalculateNormals();                    // So that materials, and light displayed properly we need normals, use recalculate normals to get this

        // Pass the mesh to the mesh collider! and tell it that convex is true so that the mesh collider can be used with rigid bodies, otherwise rigidbodies has to be set to kinematic
        GetComponent <MeshCollider>().sharedMesh = mesh;
        GetComponent <MeshCollider>().convex     = true;
    }
コード例 #2
0
        public void TestInstance()
        {
            LoadSingleton ls  = LoadSingleton.Instance;
            LoadSingleton ls1 = LoadSingleton.Instance;

            Assert.AreEqual(ls, ls1);
        }
 ///<summary>
 /// Singleton getInstance method
 /// <para>
 ///	Using lazy instantiation, checks to see if the instance has already been created before returning the instance, if it hasnt it creates a new one.
 /// </para>
 ///<see cref="https://msdn.microsoft.com/en-gb/library/ff650316.aspx"> Uses a Property approach to returning the instance, changed to a simpler get method
 ///</summary>
 /// <returns>The instance of the LoadSingleton to be used by other classes.</returns>
 public static LoadSingleton getInstance()
 {
     if (instance == null)
     {
         instance = new LoadSingleton();
     }
     return(instance);
 }
コード例 #4
0
ファイル: SMSTest.cs プロジェクト: refracc/napier-bank
        public void TestConversion()
        {
            LoadSingleton _ls  = LoadSingleton.Instance;
            string        word = "ROTFL";

            sms.Text = word;
            string convert = sms.ConvertAbbreviations(word, _ls.GetAbbreviations());

            Assert.AreEqual(convert, word + " <" + _ls.GetAbbreviations()[word] + ">");
        }
    /// <summary>
    /// Creates the mesh from .vol file, and applies it to the mesh collider for the gameObject
    /// <para>
    /// Uses the LoadSingleton to get the vertices, surface triangles and tetrahedral elements.
    /// Once loaded it applies these vertices and surface triangles to the mesh's vertices and triangles before calculating the normals.
    /// Finally it adds the mesh to the mesh collider.
    /// </para>
    /// <see cref="https://docs.unity3d.com/ScriptReference/Mesh.html">For information on procedurally generating meshes in Unity</see>
    /// </summary>
    private void createInitialMesh()
    {
        // Initialise lists
        // FEMElements = new List<FEMElement> {};


        List <Vector3> vertices     = new List <Vector3> {
        };
        List <int> surfaceTriangles = new List <int> {
        };
        List <Vector4> elements     = new List <Vector4> {
        };

        // Grab an instance of the volumetric loader
        LoadSingleton instance = LoadSingleton.getInstance();

        // Get the vertices, surface triangles indices and the tetrahedral element indices
        instance.loadFile(meshFile, ref vertices, ref surfaceTriangles, ref elements);

        Mesh mesh = GetComponent <MeshFilter>().mesh; // Grab the mesh of the current game component.

        mesh.Clear();                                 // Clear the mesh to start fresh just in case.

        mesh.vertices  = vertices.ToArray();          // Convert to an array and add to our mesh
        mesh.triangles = surfaceTriangles.ToArray();  // Convert to an array and add to our mesh

        mesh.RecalculateNormals();                    // So that materials, and light displayed properly we need normals, use recalculate normals to get this

        // Pass the mesh to the mesh collider! and tell it that convex is true so that the mesh collider can be used with rigid bodies, otherwise rigidbodies has to be set to kinematic
        GetComponent <MeshCollider>().sharedMesh = mesh;
        GetComponent <MeshCollider>().convex     = true;


        //-------------------------------- Deformation --------------------------------

        data         = new elementData[elements.ToArray().Length];
        output       = new elementData[elements.ToArray().Length];
        COOStiffness = new CoordinateList[elements.ToArray().Length *10];



        for (int n = 0; n < data.Length; n++)
        {
            data[n].unDeformedPos      = new Matrix4x4();
            data[n].deformedPos        = new Matrix4x4();
            data[n].areaWeightNormals  = new Matrix4x4();
            data[n].elasticForceOnNode = new Matrix4x4();

            data[n].elementIndices = elements[n];



            for (int m = 0; m < 3; m++)
            {
                data[n].unDeformedPos[m, 0] = mesh.vertices[(int)elements[n].x - 1][m];
                data[n].unDeformedPos[m, 1] = mesh.vertices[(int)elements[n].y - 1][m];
                data[n].unDeformedPos[m, 2] = mesh.vertices[(int)elements[n].z - 1][m];
                data[n].unDeformedPos[m, 3] = mesh.vertices[(int)elements[n].w - 1][m];
            }
            data[n].deformedPos = data[n].unDeformedPos;
        }


        float nodeMass = GetComponent <Rigidbody>().mass / mesh.vertices.Length;
    }
    /// <summary>
    /// Creates the elements of the mass spring system using the volumetric information of the volumetric mesh file
    /// <para>
    /// Gets the mesh information using the loadSingleton, to get the vertices, surface triangles and the tetrahedral elements.
    /// Then loops through the elements creating a new gameobject for each and every tetrahedral element.
    /// Assigning the vertices, and surface triangles for each. As well as the sorting the colliders.
    /// </para>
    /// <see cref="https://docs.unity3d.com/ScriptReference/Mesh.html">For information on procedurally generating meshes in Unity</see>
    /// </summary>
    private void createElements()
    {
        List <Vector3> vertices = new List <Vector3> {
        };                                                      // The vertices of the volumetric mesh, loaded from LoadSingleton.


        List <int> surfaceTriangles = new List <int> {
        };                                              // Each group of 3 ints in the List correspond to the indices of the surface triangles.

        volumeIndices = new List <Vector4> {
        };

        LoadSingleton instance = LoadSingleton.getInstance();                               // Grab an instance of the volumetric loader

        instance.loadFile(meshFile, ref vertices, ref surfaceTriangles, ref volumeIndices); // Get the vertices, surface triangles indices and the tetrahedral element indices

        // Now Instantiate each element!
        foreach (Vector4 elementIndices in volumeIndices)
        {
            GameObject element = (GameObject)Instantiate <GameObject>(ElementPrefab);                              // Create a new gameobject from the prefab
            elements.Add(element);                                                                                 // Add to our list of  elements

            element.GetComponent <Rigidbody>().mass = GetComponent <Rigidbody>().mass / elements.ToArray().Length; // Give the element a fraction of the total mass

            Mesh mesh = element.GetComponent <MeshFilter>().mesh;                                                  // Grab the mesh object of the element, so we can assign the vertices and surface triangles
            mesh.Clear();

            Vector3[] tetraVert = new Vector3[4];             // Each tetrahedral element will have 4 vertices, so we will chuck them in this array

            for (int n = 0; n < 4; n++)
            {
                Vector3 verts = vertices.ToArray()[(int)elementIndices[n] - 1]; // So the indices of vertices belonging to each tetrahedral element are stored in the Vector4 element, so grab each one and subtract 1 as these indices start at 1 not 0.
                tetraVert[n] = verts;                                           // We can assign the vertex to one of the 4 in the tetrahedral element.
            }


            // We want to find the centre point of the tetrahedral element, so find the average point of the vertices
            Vector3 tetCentre = new Vector3();
            for (int n = 0; n < 4; n++)
            {
                tetCentre += tetraVert[n]; // Sum the values of the vertices
            }
            tetCentre /= 4;                // Divide by the number of vertices to get the average position ie the centre!

            // By subtracting the centre point from each vertexm they will now be centred around their own origin, rather than origin of the entire system
            for (int n = 0; n < 4; n++)
            {
                tetraVert[n] -= tetCentre;               // Make sure the verts are centred to this object, not the whole system
            }
            // The centre is now 0!

            // Now move the element, to its correct position and rotation,
            // This is the position of the whole system, plus the distance to the centre of the vertices for this element adjusted to take into account of any rotation
            element.transform.position = transform.position + transform.rotation * (tetCentre);
            element.transform.rotation = transform.rotation;             // Simply assigning the rotation of the element.
            if (clearDebris)
            {
                Destroy(element, 4);
            }


            int[] triangles = { 0, 1, 2, 1, 3, 2, 0, 2, 3, 0, 3, 1 };                    // The indices for surface triangles for each element

            // Assign the mesh variables
            mesh.vertices  = tetraVert;
            mesh.triangles = triangles;
            mesh.RecalculateNormals();             // Rather than assign the normals, let unity do it for us


            // Original EDEM used spherical elements, however object tends to turn into a puddle, so going to use mesh colliders
            // SphereCollider sphereCollider = element.GetComponent<SphereCollider>();
            MeshCollider meshCollider = element.GetComponent <MeshCollider>();

            // // if(sphereCollider.enabled){
            // //   // Now to find the distance to each surface using half plane tests!
            // //   float minDistance = Mathf.Abs(Vector3.Dot(mesh.normals[0],mesh.vertices[mesh.triangles[0]]));
            // //   for(int n = 1; n < 4; n++){
            // //       float newVal = Mathf.Abs(Vector3.Dot(mesh.normals[n],mesh.vertices[mesh.triangles[n*3]]));
            // //       if(newVal < minDistance){
            // //           minDistance = newVal;
            // //       }
            // //   }
            // //   sphereCollider.radius = minDistance;
            // //   sphereCollider.contactOffset = 0.001f;
            // //   meshCollider.enabled = false;
            // }else{
            if (!meshCollider.enabled)
            {
                meshCollider.enabled = true;
            }
            meshCollider.sharedMesh = mesh;
            // }
        }
        if (clearDebris)
        {
            Destroy(gameObject, 4);
        }
    }