/// <summary> /// This method destroys the mesh of an gameobject! /// This algorithm works by splitting the mesh into smaller objects by slicing the gameobject /// by different planes, which will be generated randomly, but all Planes will intersect at one /// point specified by the raycastHit. /// TODO: Refactoring! /// </summary> /// <param name="raycastHit">The center point of the destruction</param> /// <param name="explosionForce">The force of the explosion</param> /// <param name="explosionRadius">The distance from the explosion center</param> /// <returns>a list of all destruchtion-fragments</returns> public List<Destructor> DestroyGeometry(RaycastHit raycastHit, float explosionForce, float explosionRadius) { List<Destructor> destructionObjects = new List<Destructor>(); Vector3 hitpoint = raycastHit.point; Vector3 n; Plane randomPlane; Mesh startMesh = this.GetComponent<MeshFilter>().mesh; List<Mesh> destructionParts = new List<Mesh>(); List<Mesh> currentDestructionParts = new List<Mesh>(); destructionParts.Add(startMesh); uvMapper = uvMapperObject.GetComponent<UVMapper>(); if (uvMapper != null) { MeshSlicer slicer = new MeshSlicer(uvMapper); //Iterating over all jet existing mesh-fractures. //The algorithm uses old created fratures to create new. for (int i = 0; i < fractureCount; i++) { // A random vetor which is used to generate a new random slicing plane. n = GenerateRandomVector(); randomPlane = new Plane(n, hitpoint); // Iterating over all yet existing destruction parts and slicing them by the plane foreach (Mesh mesh in destructionParts) { currentDestructionParts.AddRange(slicer.SliceByPlane(mesh, randomPlane, this.transform)); } // the new created destruction parts are the base for the next iteration destructionParts = currentDestructionParts; currentDestructionParts = new List<Mesh>(); } GameObject destructedObject; MeshFilter destructedObjectMeshFilter; MeshRenderer destructedObjectMeshRenderer; Mesh destructedObjectMesh; Vector3 meshMidPoint; Mesh currentMesh; Vector3 newMeshMidpoint; // Creating new Gameobjects by using the meshes generated in the previous step. foreach (Mesh mesh in destructionParts) { if (mesh.vertices.Length > 0 && mesh.triangles.Length > 0) { // Initializing a new gameobject and bringing its pivot to the center of the objects mesh. meshMidPoint = transform.TransformPoint(MeshComponents.GetVerticesMidpoint(mesh.vertices)); destructedObject = (GameObject)GameObject.Instantiate(this.gameObject, meshMidPoint, Quaternion.identity); destructedObjectMeshFilter = destructedObject.GetComponent<MeshFilter>(); currentMesh = mesh.Translate(DevideVectors(destructedObjectMeshFilter.transform.InverseTransformDirection(transform.position - destructedObject.transform.position), destructedObject.transform.lossyScale)); newMeshMidpoint = transform.TransformPoint(MeshComponents.GetVerticesMidpoint(currentMesh.vertices)); // Adding the generated mesh-geometrie to the new created gameobject destructedObjectMesh = destructedObjectMeshFilter.mesh; destructedObjectMeshRenderer = destructedObject.GetComponent<MeshRenderer>(); destructedObjectMesh.Clear(); destructedObjectMeshFilter.mesh = currentMesh; //Updating the collider of the gameobject ChangeColliderToMeshCollider(destructedObject); destructedObject.GetComponent<MeshCollider>().sharedMesh = currentMesh; //Adding some explosiontforce to the gameobject foe vfx destructedObject.GetComponent<Rigidbody>().AddExplosionForce(explosionForce, raycastHit.point, explosionRadius); destructionObjects.Add(destructedObject.GetComponent<Destructor>()); } } //After all new fractureparts are generated -> destroy the source. DestroyImmediate(this.gameObject); } return destructionObjects; }
/// <summary> /// This method slices the mesh of the Gameobject by the specified plane. /// </summary> /// <param name="plane">The plane which shall seperate the objects mesh</param> public void SliceByPlane(Plane plane) { uvMapper = uvMapperObject.GetComponent<UVMapper>(); if (uvMapper != null) { MeshSlicer slicer = new MeshSlicer(uvMapper); MeshFilter meshFilter = this.GetComponent<MeshFilter>(); Mesh mesh = meshFilter.mesh; Mesh[] slicedMeshes = slicer.SliceByPlane(mesh, plane, this.transform); meshFilter.mesh.Clear(); if (slicedMeshes[0].vertices.Length > 0 && slicedMeshes[0].triangles.Length > 0) { //Setting the mesh of the gameobject which shall be splitted(Fracture1). meshFilter.mesh = slicedMeshes[0]; if (slicedMeshes[1].vertices.Length > 0 && slicedMeshes[1].triangles.Length > 0) { // copying the the gameobject which should be drestroyed(source) GameObject copy = (GameObject)GameObject.Instantiate(this.gameObject); // setting the mesh of the copy MeshFilter meshFilter2 = copy.GetComponent<MeshFilter>(); meshFilter2.mesh.Clear(); meshFilter2.mesh = slicedMeshes[1]; //Updating the collider of the copied gameobject copy.GetComponent<MeshCollider>().sharedMesh = meshFilter2.mesh; } } else if (slicedMeshes[1].vertices.Length > 0 && slicedMeshes[1].triangles.Length > 0) { meshFilter.mesh = slicedMeshes[1]; } //Updating the collider of this gameobject DestroyImmediate(this.GetComponent<MeshCollider>()); MeshCollider collider1 = this.gameObject.AddComponent<MeshCollider>(); collider1.convex = true; } }