示例#1
0
        private CollisionPoint GetDistance(
            IShape shapeA,
            IShape shapeB)
        {
            CollisionPointStructure collisionPoint = collisionDetectionEngine.Execute(shapeA, shapeB, double.MaxValue);

            if (collisionPoint == null)
            {
                return(null);
            }

            //TODO Gestire soft body, compound shape, concaveshape
            return(collisionPoint.CollisionPointBase[0].CollisionPoint);
        }
示例#2
0
        public List <JacobianConstraint> BuildContactConstraint(
            CollisionPointStructure collisionPointStr,
            IShape objectA,
            IShape objectB)
        {
            var contactConstraints = new List <JacobianConstraint>();

            if (objectA is ISoftShape &&
                !(objectB is SimSoftShape))
            {
                contactConstraints.AddRange(BuildSoftBodyVSRigidBodyCollisionConstraints(collisionPointStr, (ISoftShape)objectA, objectB));
            }
            else if (objectB is ISoftShape &&
                     !(objectA is SimSoftShape))
            {
                contactConstraints.AddRange(BuildSoftBodyVSRigidBodyCollisionConstraints(collisionPointStr, objectA, (ISoftShape)objectB));
            }
            else
            {
                contactConstraints.AddRange(BuildRigidBodyCollisionConstraints(collisionPointStr, objectA, objectB));
            }

            return(contactConstraints);
        }
示例#3
0
        private List <JacobianConstraint> BuildSoftBodyVSRigidBodyCollisionConstraints(
            CollisionPointStructure collisionPointStr,
            ISoftShape objectA,
            IShape objectB)
        {
            List <JacobianConstraint> contactConstraints = new List <JacobianConstraint>();

            IShape iSoftShape = (IShape)objectA;

            double restitutionCoeff = GetRestitutionCoeff(iSoftShape, objectB);

            double baumgarteStabValue = GetBaumgarteStabilizationValue(iSoftShape, objectB);

            for (int h = 0; h < collisionPointStr.CollisionPointBase.Length; h++)
            {
                int?[] linkedID = collisionPointStr.CollisionPointBase[h].CollisionPoint.CollisionPointA.LinkedID.Distinct().ToArray();

                double distanceSum = GetSoftBodyPointDistanceSum(
                    collisionPointStr.CollisionPointBase[h].CollisionPoint.CollisionPointA.Vertex,
                    objectA,
                    linkedID);

                for (int i = 0; i < linkedID.Length; i++)
                {
                    SoftShapePoint softShapePoint = objectA.ShapePoints.FirstOrDefault(x => x.ID == linkedID[i]);

                    if (softShapePoint == null)
                    {
                        continue;
                    }

                    double distanceWeigth = 1.0;

                    if (distanceSum > 0.0)
                    {
                        distanceWeigth = Vector3d.Length(softShapePoint.Position - collisionPointStr.CollisionPointBase[h].CollisionPoint.CollisionPointA.Vertex) / distanceSum;
                    }
                    if (distanceWeigth < 1E-10)
                    {
                        continue;
                    }

                    Vector3d ra = Vector3d.Zero();
                    Vector3d rb = collisionPointStr.CollisionPointBase[h].CollisionPoint.CollisionPointB.Vertex - objectB.Position;

                    ////Component
                    Vector3d linearComponentA = (-1.0 * collisionPointStr.CollisionPointBase[h].CollisionPoint.CollisionNormal).Normalize();
                    Vector3d linearComponentB = -1.0 * linearComponentA;

                    Vector3d angularComponentA = Vector3d.Zero();
                    Vector3d angularComponentB = -1.0 * rb.Cross(linearComponentA);

                    ////Velocity
                    Vector3d velocityA = softShapePoint.LinearVelocity;

                    Vector3d velocityB = objectB.LinearVelocity +
                                         objectB.AngularVelocity.Cross(rb);

                    Vector3d relativeVelocity = velocityB - velocityA;



                    if (relativeVelocity.Length() < 1E-12 &&
                        collisionPointStr.CollisionPointBase[h].CollisionPoint.Intersection &&
                        collisionPointStr.CollisionPointBase[h].CollisionPoint.Distance < 1E-10)
                    {
                        continue;
                    }

                    #region Normal direction contact

                    double linearComponent = linearComponentA.Dot(relativeVelocity);

                    double uCollision = restitutionCoeff * Math.Max(0.0, linearComponent);

                    if (uCollision <= 0.0 &&
                        !collisionPointStr.CollisionPointBase[h].CollisionPoint.Intersection)
                    {
                        continue;
                    }

                    double correctionParameter = 0.0;

                    if (collisionPointStr.CollisionPointBase[h].CollisionPoint.Intersection)
                    {
                        //Limit the Baum stabilization jitter effect
                        correctionParameter = Math.Max(Math.Max(collisionPointStr.CollisionPointBase[h].CollisionPoint.Distance - simulationParameters.CompenetrationTolerance, 0.0) *
                                                       baumgarteStabValue - uCollision, 0.0);
                    }

                    double correctedBounce = uCollision * distanceWeigth;
                    correctionParameter = correctionParameter * distanceWeigth;

                    JacobianConstraint normalContact = JacobianCommon.GetDOF(
                        linearComponentA,
                        linearComponentB,
                        angularComponentA,
                        angularComponentB,
                        softShapePoint,
                        objectB,
                        correctedBounce,
                        correctionParameter,
                        simulationParameters.NormalCFM,
                        0.0,
                        ConstraintType.Collision,
                        null);

                    #endregion

                    #region Friction Contact

                    JacobianConstraint[] frictionContact =
                        AddFrictionConstraints(
                            iSoftShape,
                            objectB,
                            simulationParameters,
                            linearComponentA,
                            relativeVelocity,
                            ra,
                            rb,
                            softShapePoint);

                    #endregion

                    contactConstraints.Add(normalContact);

                    int normalIndex = contactConstraints.Count - 1;
                    foreach (JacobianConstraint fjc in frictionContact)
                    {
                        fjc.SetContactReference(normalIndex);
                        contactConstraints.Add(fjc);
                    }
                }
            }

            return(contactConstraints);
        }
示例#4
0
        private List <JacobianConstraint> BuildRigidBodyCollisionConstraints(
            CollisionPointStructure collisionPointStr,
            IShape objectA,
            IShape objectB)
        {
            List <JacobianConstraint> contactConstraints = new List <JacobianConstraint>();

            double restitutionCoefficient =
                (objectA.RestitutionCoeff +
                 objectB.RestitutionCoeff) * 0.5;

            double baumgarteStabilizationValue =
                (objectA.RestoreCoeff +
                 objectB.RestoreCoeff) * 0.5;

            for (int h = 0; h < collisionPointStr.CollisionPointBase.Length; h++)
            {
                var collisionPointBase = collisionPointStr.CollisionPointBase[h];

                for (int k = 0; k < collisionPointBase.CollisionPoints.Length; k++)
                {
                    CollisionPoint collisionPoint = collisionPointBase.CollisionPoints[k];

                    Vector3d ra = collisionPoint.CollisionPointA.Vertex - objectA.Position;
                    Vector3d rb = collisionPoint.CollisionPointB.Vertex - objectB.Position;

                    Vector3d linearComponentA = (-1.0 * collisionPoint.CollisionNormal).Normalize();
                    Vector3d linearComponentB = -1.0 * linearComponentA;

                    Vector3d angularComponentA = ra.Cross(linearComponentA);
                    Vector3d angularComponentB = -1.0 * rb.Cross(linearComponentA);

                    Vector3d velocityA = objectA.LinearVelocity +
                                         objectA.AngularVelocity.Cross(ra);

                    Vector3d velocityB = objectB.LinearVelocity +
                                         objectB.AngularVelocity.Cross(rb);

                    Vector3d relativeVelocity = velocityB - velocityA;

                    if (relativeVelocity.Length() < 1E-12 &&
                        collisionPointBase.CollisionPoint.Intersection &&
                        collisionPointBase.CollisionPoint.Distance < 1E-10)
                    {
                        continue;
                    }

                    #region Normal direction contact

                    double linearComponent = linearComponentA.Dot(relativeVelocity);

                    double uCollision = restitutionCoefficient * Math.Max(0.0, linearComponent);

                    if (uCollision <= 0.0 &&
                        !collisionPointBase.CollisionPoint.Intersection)
                    {
                        continue;
                    }

                    double correctionParameter = 0.0;

                    if (collisionPointBase.CollisionPoint.Intersection)
                    {
                        //Limit the Baum stabilization jitter effect
                        correctionParameter = Math.Max(Math.Max(collisionPointBase.CollisionPoint.Distance - simulationParameters.CompenetrationTolerance, 0.0) *
                                                       baumgarteStabilizationValue, 0.0);
                    }

                    double correctedBounce = uCollision;

                    JacobianConstraint normalContact = JacobianCommon.GetDOF(
                        linearComponentA,
                        linearComponentB,
                        angularComponentA,
                        angularComponentB,
                        objectA,
                        objectB,
                        correctedBounce,
                        correctionParameter,
                        simulationParameters.NormalCFM,
                        0.0,
                        ConstraintType.Collision,
                        null);

                    #endregion

                    contactConstraints.Add(normalContact);

                    #region Friction Contact

                    JacobianConstraint[] frictionContact =
                        AddFrictionConstraints(
                            objectA,
                            objectB,
                            simulationParameters,
                            linearComponentA,
                            relativeVelocity,
                            ra,
                            rb);

                    #endregion

                    int normalIndex = contactConstraints.Count - 1;
                    foreach (JacobianConstraint fjc in frictionContact)
                    {
                        fjc.SetContactReference(normalIndex);
                        contactConstraints.Add(fjc);
                    }
                }
            }

            return(contactConstraints);
        }
示例#5
0
        public List <CollisionPointStructure> GetWarmStartedCollisionPoints(
            IShape[] shapes,
            List <CollisionPointStructure> previousCollisionPoints,
            List <CollisionPointStructure> actualCollisionPoints,
            Dictionary <int, StabilizationValues> previousShapesProperties)
        {
            UpdatePersistentCollisionCounter(
                previousCollisionPoints,
                actualCollisionPoints,
                previousShapesProperties,
                shapes);

            Dictionary <WarmStartHashSet, CollisionPointStructure> warmStartedCollisionPoints = new Dictionary <WarmStartHashSet, CollisionPointStructure>();

            int warmStartCounter = 15;

            foreach (var item in actualCollisionPoints)
            {
                WarmStartHashSet hashset = new WarmStartHashSet(
                    item.ObjectIndexA,
                    item.ObjectIndexB);

                if (collisionPointsCounterDictionary.TryGetValue(hashset, out Tuple <bool, int, CollisionPointStructure> value) &&
                    value.Item2 >= warmStartCounter)
                {
                    warmStartedCollisionPoints.Add(new WarmStartHashSet(item.ObjectIndexA, item.ObjectIndexB), value.Item3);
                    //}
                }
            }

            var outputCollisionPoints = new List <CollisionPointStructure>(actualCollisionPoints);

            for (int i = 0; i < outputCollisionPoints.Count; i++)
            {
                var hashSet = new WarmStartHashSet(outputCollisionPoints[i].ObjectIndexA, outputCollisionPoints[i].ObjectIndexB);

                if (warmStartedCollisionPoints.TryGetValue(hashSet, out CollisionPointStructure cPoint))
                {
                    CollisionPointStructure item = outputCollisionPoints[i];

                    int k = 0;

                    foreach (var value in item.CollisionPointBase[0].CollisionPoints)
                    {
                        //if (!value.Intersection)
                        //{
                        List <StartImpulseProperties> startImpulse = new List <StartImpulseProperties>
                        {
                            new StartImpulseProperties(0.0),
                            new StartImpulseProperties(0.0),
                            new StartImpulseProperties(0.0)
                        };

                        //CollisionPoint val = value;

                        //Get nearest
                        double minDistance = double.MaxValue;
                        foreach (var point in cPoint.CollisionPointBase[0].CollisionPoints)
                        {
                            double distAA = Vector3d.Length(point.CollisionPointA.Vertex - value.CollisionPointA.Vertex);
                            double distBA = Vector3d.Length(point.CollisionPointB.Vertex - value.CollisionPointA.Vertex);

                            if (distAA < minDistance ||
                                distBA < minDistance)
                            {
                                minDistance = (distAA < distBA) ? distAA : distBA;
                                //startImpulse = point.StartImpulseValue;
                            }

                            /*
                             * if (
                             *  (CheckCollisionPointDistance(point.CollisionPointA.Vertex, value.CollisionPointA.Vertex, 1E-2) &&
                             *   CheckCollisionPointDistance(point.CollisionPointB.Vertex, value.CollisionPointB.Vertex, 1E-2)) ||
                             *  (CheckCollisionPointDistance(point.CollisionPointA.Vertex, value.CollisionPointB.Vertex, 1E-2) &&
                             *   CheckCollisionPointDistance(point.CollisionPointB.Vertex, value.CollisionPointA.Vertex, 1E-2)))
                             * {
                             *  startImpulse = point.StartImpulseValue;
                             *  break;
                             * }
                             */
                        }

                        k++;
                        //}

                        //value.SetNormal(outputCollisionPoints[i].CollisionPointBase[0].CollisionPoint.CollisionNormal);
                    }

                    outputCollisionPoints[i] = item;
                    //}
                }
            }

            return(outputCollisionPoints);
        }
        public List <Partition> GetPartitions(
            CollisionPointStructure[] collisionPoints,
            List <IConstraint> joints,
            IShape[] shapes,
            ISoftShape[] softShapes)
        {
            List <SpatialPartition> spatialPartitions = CalculateSpatialPartitioning(collisionPoints, joints, shapes);

            List <Partition> partitions = new List <Partition>();

            if (spatialPartitions != null)
            {
                HashSet <int> totObjectIndex = new HashSet <int>();

                for (int i = 0; i < spatialPartitions.Count; i++)
                {
                    Partition     partitionItem = new Partition();
                    HashSet <int> objectIndex   = new HashSet <int>();

                    for (int j = 0; j < spatialPartitions[i].ObjectList.Count; j++)
                    {
                        if (spatialPartitions[i].ObjectList[j].Type == ContactGroupType.Collision)
                        {
                            CollisionPointStructure cpStruct = ConstraintHelper.Find(
                                collisionPoints,
                                spatialPartitions[i].ObjectList[j]);

                            if (cpStruct != null)
                            {
                                partitionItem.PartitionedCollisionPoints.Add(cpStruct);
                            }

                            objectIndex.Add(cpStruct.ObjectIndexA);
                            objectIndex.Add(cpStruct.ObjectIndexB);
                            totObjectIndex.Add(cpStruct.ObjectIndexA);
                            totObjectIndex.Add(cpStruct.ObjectIndexB);
                        }
                        else
                        {
                            IConstraint smJoint = joints.Find(item =>
                                                              item.GetObjectIndexA() == spatialPartitions[i].ObjectList[j].IndexA &&
                                                              item.GetObjectIndexB() == spatialPartitions[i].ObjectList[j].IndexB &&
                                                              item.GetKeyIndex() == spatialPartitions[i].ObjectList[j].KeyIndex);

                            partitionItem.PartitionedJoints.Add(smJoint);

                            objectIndex.Add(smJoint.GetObjectIndexA());
                            objectIndex.Add(smJoint.GetObjectIndexB());
                            totObjectIndex.Add(smJoint.GetObjectIndexA());
                            totObjectIndex.Add(smJoint.GetObjectIndexB());
                        }
                    }

                    ////Add Soft Body Constraints if is involved in collision
                    foreach (var item in objectIndex)
                    {
                        if (shapes[item] is ISoftShape softShape)
                        {
                            partitionItem.PartitionedJoints.AddRange(softShape.SoftConstraint);
                        }
                    }

                    partitions.Add(partitionItem);
                }

                ////Add Soft Body Constraints if is not involved in collision
                foreach (var item in softShapes)
                {
                    if (!totObjectIndex.Contains(((IShape)item).ID))
                    {
                        Partition partitionItem = new Partition();
                        partitionItem.PartitionedJoints.AddRange(item.SoftConstraint);
                        partitions.Add(partitionItem);
                    }
                }
            }
            else if (softShapes.Length > 0)
            {
                foreach (var softShape in softShapes)
                {
                    Partition partitionItem = new Partition();
                    partitionItem.PartitionedJoints.AddRange(softShape.SoftConstraint);
                    partitions.Add(partitionItem);
                }
            }

            return(partitions);
        }