Example #1
0
    public void CollisionStay(PhysXCollision collision)
    {
        if (collision.contactCount > 0 && collision.GetContact(0).separation < -minPenetration)
        {
            if ((collision.rigidBody == null || collision.rigidBody.mass >= minDeformationMass) &&
                !collision.collider.gameObject.CompareTag("DustGround"))
            {
                meshDeformationMarker.Begin();

                bool isInconvenient = collision.collider is PhysXMeshCollider && !((PhysXMeshCollider)collision.collider).convex;

                Vector3 collisionSurfaceNormal = Vector3.zero;
                Vector3 collisionSurfacePoint  = Vector3.zero;

                for (int i = 0; i < collision.contactCount; i++)
                {
                    PhysXContactPoint contactPoint     = collision.GetContact(i);
                    float             impulseMagnitude = contactPoint.impulse.magnitude;

                    collisionSurfaceNormal += contactPoint.normal;
                    collisionSurfacePoint  += contactPoint.point;
                }



                collisionSurfaceNormal /= collision.contactCount;
                collisionSurfacePoint  /= collision.contactCount;

                collisionSurfaceNormal = transform.InverseTransformDirection(collisionSurfaceNormal);
                collisionSurfacePoint  = transform.InverseTransformPoint(collisionSurfacePoint);

                gizmoSurfaceNormal = collisionSurfaceNormal;
                gizmoSurfacePoint  = collisionSurfacePoint;

                Vector3    oldPosition = collision.body.position;
                Quaternion oldRotation = collision.body.rotation;
                collision.body.position = transform.InverseTransformPoint(collision.body.position);
                collision.body.rotation = Quaternion.Inverse(transform.rotation) * collision.body.rotation;

                VertexGroup[] groups = meshGraph.groups;
                for (int i = 0; i < groups.Length; i++)
                {
                    VertexGroup current = groups[i];
                    Vector3     vertex  = current.pos;

                    if (IsBeyondCollisionSurface(collisionSurfaceNormal, collisionSurfacePoint, vertex))
                    {
                        if (isInconvenient || collision.collider.ClosestPoint(vertex) == vertex)
                        {
                            Vector3 deformation = DeformationFromCollisionSurface(collisionSurfaceNormal, collisionSurfacePoint, vertex);

                            // if (addNoise) deformation *= Random.value * multiplier + addition;

                            current.MoveBy(vertices, deformation, false);
                            current.SetWasMoved(teamId, true);

                            if (!current.GetEnqueued(teamId))
                            {
                                vertexQueue.Enqueue(current);
                                current.SetEnqueued(teamId, true);
                                // Debug.Log("Vertex group " + current.vertexIndices[0] + " enqueued due to collision");
                            }
                        }
                    }
                }

                collision.body.position = oldPosition;
                collision.body.rotation = oldRotation;

                dissipationNeeded = true;

                meshDeformationMarker.End();
            }
        }
    }
Example #2
0
    // 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();
    }