public void DissipateDeformation(bool addNoise) { foreach (VertexGroup group in vertexQueue) { // Debug.Log("Initial queue contains " + group.vertexIndices[0]); } while (vertexQueue.Count > 0) { VertexGroup current = vertexQueue.Dequeue(); current.SetEnqueued(teamId, false); // Debug.Log("Vertex group " + current.vertexIndices[0] + " dequeued"); oldEdgeSqrLengths.Clear(); for (int j = 0; j < current.connectingEdges.Count; j++) { oldEdgeSqrLengths.Add(current.connectingEdges[j].sqrLength); } float sqrStretchiness = stretchiness * stretchiness; for (int j = 0; j < current.connectingEdges.Count; j++) { VertexGroup adjacent = current.connectingEdges[j].OtherVertexGroup(current); // Check if adjacent vertex has been moved. if (adjacent.GetWasMoved(teamId)) { // Get vector of edge between vertices. Vector3 edge = current.pos - adjacent.pos; // ohno edge too long if (edge.sqrMagnitude > sqrStretchiness * oldEdgeSqrLengths[j]) { // make edge right length edge.Normalize(); float randomNoise = 1; if (addNoise) { randomNoise = Random.value * 0.2f + 0.9f; } float edgeStretchiness = stretchiness * randomNoise; edge *= edgeStretchiness * Mathf.Sqrt(oldEdgeSqrLengths[j]); // move vertices so edge is not too long. current.MoveTo(vertices, adjacent.pos + edge, false); current.connectingEdges[j].UpdateEdgeLength(); current.SetWasMoved(teamId, true); } } } if (current.GetWasMoved(teamId)) { // Add adjacent, unmoved vertices into the queue for traversal for (int j = 0; j < current.connectingEdges.Count; j++) { // Get adjacent vertex group VertexGroup adjacent = current.connectingEdges[j].OtherVertexGroup(current); // Add it to the queue if it hasn't already been moved if (!adjacent.GetEnqueued(teamId) && !adjacent.GetWasMoved(teamId)) { vertexQueue.Enqueue(adjacent); adjacent.SetEnqueued(teamId, true); // Debug.Log("Vertex group " + adjacent.vertexIndices[0] + " enqueued"); } } } //moved.Add(current); current.SetWasMoved(teamId, true); } string meshName; if (meshType == MeshstateTracker.MeshTypes.interceptor) { meshName = "interceptor"; } else if (meshType == MeshstateTracker.MeshTypes.ace) { meshName = "ace"; } else if (meshType == MeshstateTracker.MeshTypes.bomber) { meshName = "bomber"; } else { meshName = "bike"; } for (int i = 0; i < meshGraph.groups.Length; i++) { meshGraph.groups[i].SetWasMoved(teamId, false); if (meshGraph.groups[i].GetEnqueued(teamId)) { Debug.LogWarning("Vertex group " + meshGraph.groups[i].vertexIndices[0] + " marked as still in queue. mesh: " + meshName); meshGraph.groups[i].SetEnqueued(teamId, false); } } // Update the mesh deformableMeshes[0].GetMeshFilter().mesh.SetVertices(vertices); deformableMeshes[0].GetMeshFilter().mesh.RecalculateNormals(); if (interfaceCar != null) { frWheel.transform.localPosition = frWheelVertexGroup.pos; flWheel.transform.localPosition = flWheelVertexGroup.pos; rrWheel.transform.localPosition = rrWheelVertexGroup.pos; rlWheel.transform.localPosition = rlWheelVertexGroup.pos; } }
// Explode the mesh at a given position, with a given force public void ExplodeMeshAt(Vector3 pos, float force, bool addNoise = true) { pos = transform.InverseTransformPoint(pos); VertexGroup closest = GetClosestVertexGroup(pos); // Make a queue (it breadth first traversal time) vertexQueue.Enqueue(closest); closest.SetEnqueued(teamId, true); // Move each vertex, making sure that it doesn't stretch too far from its neighbours while (vertexQueue.Count > 0) { VertexGroup current = vertexQueue.Dequeue(); current.SetEnqueued(teamId, false); oldEdgeSqrLengths.Clear(); for (int j = 0; j < current.connectingEdges.Count; j++) { oldEdgeSqrLengths.Add(current.connectingEdges[j].sqrLength); } // Calculate deformation vector Vector3 deformation = current.pos - pos; float deformationForce = force / deformation.sqrMagnitude; if (addNoise) { deformationForce *= Random.value * 0.2f + 0.9f; } deformation.Normalize(); deformation *= Mathf.Clamp(deformationForce / vertexWeight, 0, 0.5f); current.MoveBy(vertices, deformation, false); for (int j = 0; j < current.connectingEdges.Count; j++) { VertexGroup adjacent = current.connectingEdges[j].OtherVertexGroup(current); // Check if adjacent vertex has been moved. if (adjacent.GetWasMoved(teamId)) { // Get vector of edge between vertices. Vector3 edge = current.pos - adjacent.pos; // ohno edge too long if (edge.sqrMagnitude > stretchiness * stretchiness * oldEdgeSqrLengths[j]) { // make edge right length edge.Normalize(); float randomNoise = 1; if (addNoise) { randomNoise = Random.value * 0.2f + 0.9f; } float edgeStretchiness = stretchiness * randomNoise; edge *= edgeStretchiness * Mathf.Sqrt(oldEdgeSqrLengths[j]); // move vertices so edge is not too long. current.MoveTo(vertices, adjacent.pos + edge, false); current.connectingEdges[j].UpdateEdgeLength(); } } } current.SetWasMoved(teamId, true); // Add adjacent, unmoved vertices into the queue for traversal for (int j = 0; j < current.connectingEdges.Count; j++) { // Get adjacent vertex group VertexGroup adjacent = current.connectingEdges[j].OtherVertexGroup(current); // Add it to the queue if it hasn't already been moved if (!adjacent.GetEnqueued(teamId) && !adjacent.GetWasMoved(teamId)) { vertexQueue.Enqueue(adjacent); adjacent.SetEnqueued(teamId, true); } } } for (int i = 0; i < meshGraph.groups.Length; i++) { meshGraph.groups[i].SetWasMoved(teamId, false); if (meshGraph.groups[i].GetEnqueued(teamId)) { Debug.LogWarning("Vertex marked as still in queue."); meshGraph.groups[i].SetEnqueued(teamId, false); } } // Update the mesh deformableMeshes[0].GetMeshFilter().mesh.SetVertices(vertices); deformableMeshes[0].GetMeshFilter().mesh.RecalculateNormals(); }