Пример #1
0
        public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth)
        {
            if (_manifold == null)
            {
                throw new BulletException("Manifold Pointer is null.");
            }

            //order in manifold needs to match

            if (depth > PersistentManifold.ContactBreakingThreshold)
            {
                return;
            }

            bool isSwapped = _manifold.BodyA != _bodyA;

            Vector3 pointA = pointInWorld + normalOnBInWorld * depth;
            Vector3 localA;
            Vector3 localB;

            if (isSwapped)
            {
                localA = MathHelper.InvXForm(_rootTransB, pointA);
                localB = MathHelper.InvXForm(_rootTransA, pointInWorld);
            }
            else
            {
                localA = MathHelper.InvXForm(_rootTransA, pointA);
                localB = MathHelper.InvXForm(_rootTransB, pointInWorld);
            }

            ManifoldPoint newPt = new ManifoldPoint(localA, localB, normalOnBInWorld, depth);

            int insertIndex = _manifold.GetCacheEntry(newPt);

            newPt.CombinedFriction    = CalculateCombinedFriction(_bodyA, _bodyB);
            newPt.CombinedRestitution = CalculateCombinedRestitution(_bodyA, _bodyB);

            //User can override friction and/or restitution
            if (_contactAddedCallback != null &&
                //and if either of the two bodies requires custom material
                ((_bodyA.CollisionFlags & CollisionOptions.CustomMaterialCallback) != 0 ||
                 (_bodyB.CollisionFlags & CollisionOptions.CustomMaterialCallback) != 0))
            {
                //experimental feature info, for per-triangle material etc.
                CollisionObject obj0 = isSwapped ? _bodyB : _bodyA;
                CollisionObject obj1 = isSwapped ? _bodyA : _bodyB;
                _contactAddedCallback(newPt, obj0, _partIdA, _indexA, obj1, _partIdB, _indexB);
            }

            if (insertIndex >= 0)
            {
                _manifold.ReplaceContactPoint(newPt, insertIndex);
            }
            else
            {
                _manifold.AddManifoldPoint(newPt);
            }
        }
Пример #2
0
        // sort cached points so most isolated points come first
        private int SortCachedPoints(ManifoldPoint pt)
        {
            //calculate 4 possible cases areas, and take biggest area
            //also need to keep 'deepest'

            int   maxPenetrationIndex = -1;
            float maxPenetration      = pt.Distance;

            for (int i = 0; i < 4; i++)
            {
                if (_pointCache[i].Distance < maxPenetration)
                {
                    maxPenetrationIndex = i;
                    maxPenetration      = _pointCache[i].Distance;
                }
            }

            float res0 = 0, res1 = 0, res2 = 0, res3 = 0;

            if (maxPenetrationIndex != 0)
            {
                Vector3 a0    = pt.LocalPointA - _pointCache[1].LocalPointA;
                Vector3 b0    = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA;
                Vector3 cross = Vector3.Cross(a0, b0);
                res0 = cross.LengthSquared();
            }
            if (maxPenetrationIndex != 1)
            {
                Vector3 a1    = pt.LocalPointA - _pointCache[0].LocalPointA;
                Vector3 b1    = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA;
                Vector3 cross = Vector3.Cross(a1, b1);
                res1 = cross.LengthSquared();
            }

            if (maxPenetrationIndex != 2)
            {
                Vector3 a2    = pt.LocalPointA - _pointCache[0].LocalPointA;
                Vector3 b2    = _pointCache[3].LocalPointA - _pointCache[1].LocalPointA;
                Vector3 cross = Vector3.Cross(a2, b2);
                res2 = cross.LengthSquared();
            }

            if (maxPenetrationIndex != 3)
            {
                Vector3 a3    = pt.LocalPointA - _pointCache[0].LocalPointA;
                Vector3 b3    = _pointCache[2].LocalPointA - _pointCache[1].LocalPointA;
                Vector3 cross = Vector3.Cross(a3, b3);
                res3 = cross.LengthSquared();
            }

            Vector4 maxvec      = new Vector4(res0, res1, res2, res3);
            int     biggestarea = MathHelper.ClosestAxis(maxvec);

            return(biggestarea);
        }
Пример #3
0
        private void ClearUserCache(ManifoldPoint pt)
        {
            if (pt != null)
            {
                object oldPtr = pt.UserPersistentData;

                if (oldPtr != null)
                {
                    if (pt.UserPersistentData != null && _contactDestroyedCallback != null)
                    {
                        _contactDestroyedCallback(pt.UserPersistentData);
                        pt.UserPersistentData = null;
                    }
                }
            }
        }
Пример #4
0
		public int GetCacheEntry(ManifoldPoint newPoint)
		{
			float shortestDist = ContactBreakingThreshold * ContactBreakingThreshold;
			int size = ContactsCount;
			int nearestPoint = -1;
			for (int i = 0; i < size; i++)
			{
				ManifoldPoint mp = _pointCache[i];

				Vector3 diffA = mp.LocalPointA - newPoint.LocalPointA;
				float distToManiPoint = Vector3.Dot(diffA, diffA);
				if (distToManiPoint < shortestDist)
				{
					shortestDist = distToManiPoint;
					nearestPoint = i;
				}
			}
			return nearestPoint;
		}
Пример #5
0
        public int GetCacheEntry(ManifoldPoint newPoint)
        {
            float shortestDist = ContactBreakingThreshold * ContactBreakingThreshold;
            int   size         = ContactsCount;
            int   nearestPoint = -1;

            for (int i = 0; i < size; i++)
            {
                ManifoldPoint mp = _pointCache[i];

                Vector3 diffA           = mp.LocalPointA - newPoint.LocalPointA;
                float   distToManiPoint = Vector3.Dot(diffA, diffA);
                if (distToManiPoint < shortestDist)
                {
                    shortestDist = distToManiPoint;
                    nearestPoint = i;
                }
            }
            return(nearestPoint);
        }
Пример #6
0
        public void AddManifoldPoint(ManifoldPoint newPoint)
        {
            if (!ValidContactDistance(newPoint))
            {
                throw new BulletException();
            }

            int insertIndex = ContactsCount;

            if (insertIndex == 4)
            {
                //sort cache so best points come first, based on area
                insertIndex = SortCachedPoints(newPoint);
            }
            else
            {
                _cachedPoints++;
            }
            ReplaceContactPoint(newPoint, insertIndex);
        }
Пример #7
0
        public void ReplaceContactPoint(ManifoldPoint newPoint, int insertIndex)
        {
            BulletDebug.Assert(ValidContactDistance(newPoint));

            if (_pointCache[insertIndex] != null)
            {
                int lifeTime = _pointCache[insertIndex].LifeTime;
                BulletDebug.Assert(lifeTime >= 0);
                object cache = _pointCache[insertIndex].UserPersistentData;

                _pointCache[insertIndex] = newPoint;

                _pointCache[insertIndex].UserPersistentData = cache;
                _pointCache[insertIndex].LifeTime           = lifeTime;
            }
            else
            {
                _pointCache[insertIndex] = newPoint;
            }

            //ClearUserCache(_pointCache[insertIndex]);
            //_pointCache[insertIndex] = newPoint;
        }
Пример #8
0
        // calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
        public void RefreshContactPoints(Matrix trA, Matrix trB)
        {
            // first refresh worldspace positions and distance
            for (int i = ContactsCount - 1; i >= 0; i--)
            {
                ManifoldPoint manifoldPoint = _pointCache[i];
                manifoldPoint.PositionWorldOnA = MathHelper.MatrixToVector(trA, manifoldPoint.LocalPointA);
                manifoldPoint.PositionWorldOnB = MathHelper.MatrixToVector(trB, manifoldPoint.LocalPointB);
                manifoldPoint.Distance         = Vector3.Dot(manifoldPoint.PositionWorldOnA - manifoldPoint.PositionWorldOnB, manifoldPoint.NormalWorldOnB);
                manifoldPoint.LifeTime++;
            }

            // then
            float   distance2d;
            Vector3 projectedDifference, projectedPoint;

            for (int i = ContactsCount - 1; i >= 0; i--)
            {
                ManifoldPoint manifoldPoint = _pointCache[i];
                //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
                if (!ValidContactDistance(manifoldPoint))
                {
                    RemoveContactPoint(i);
                }
                else
                {
                    //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
                    projectedPoint      = manifoldPoint.PositionWorldOnA - manifoldPoint.NormalWorldOnB * manifoldPoint.Distance;
                    projectedDifference = manifoldPoint.PositionWorldOnB - projectedPoint;
                    distance2d          = Vector3.Dot(projectedDifference, projectedDifference);
                    if (distance2d > ContactBreakingThreshold * ContactBreakingThreshold)
                    {
                        RemoveContactPoint(i);
                    }
                }
            }
        }
Пример #9
0
        public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth)
        {
            if (_manifold == null)
                throw new BulletException("Manifold Pointer is null.");

            //order in manifold needs to match

            if (depth > PersistentManifold.ContactBreakingThreshold)
                return;

            bool isSwapped = _manifold.BodyA != _bodyA;

            Vector3 pointA = pointInWorld + normalOnBInWorld * depth;
            Vector3 localA;
            Vector3 localB;

            if (isSwapped)
            {
                localA = MathHelper.InvXForm(_rootTransB, pointA);
                localB = MathHelper.InvXForm(_rootTransA, pointInWorld);
            }
            else
            {
                localA = MathHelper.InvXForm(_rootTransA, pointA);
                localB = MathHelper.InvXForm(_rootTransB, pointInWorld);
            }

            ManifoldPoint newPt = new ManifoldPoint(localA, localB, normalOnBInWorld, depth);

            int insertIndex = _manifold.GetCacheEntry(newPt);

            newPt.CombinedFriction = CalculateCombinedFriction(_bodyA, _bodyB);
            newPt.CombinedRestitution = CalculateCombinedRestitution(_bodyA, _bodyB);

            //User can override friction and/or restitution
            if (_contactAddedCallback != null &&
                //and if either of the two bodies requires custom material
                 ((_bodyA.CollisionFlags & CollisionOptions.CustomMaterialCallback) != 0 ||
                   (_bodyB.CollisionFlags & CollisionOptions.CustomMaterialCallback) != 0))
            {
                //experimental feature info, for per-triangle material etc.
                CollisionObject obj0 = isSwapped ? _bodyB : _bodyA;
                CollisionObject obj1 = isSwapped ? _bodyA : _bodyB;
                _contactAddedCallback(newPt, obj0, _partIdA, _indexA, obj1, _partIdB, _indexB);
            }

            if (insertIndex >= 0)
            {
                _manifold.ReplaceContactPoint(newPt, insertIndex);
            }
            else
            {
                _manifold.AddManifoldPoint(newPt);
            }
        }
Пример #10
0
 private int FindContactPoint(ManifoldPoint unUsed, int numUnused, ManifoldPoint pt)
 {
     return(0);
 }
Пример #11
0
		public bool ValidContactDistance(ManifoldPoint pt)
		{
			return pt.Distance <= ContactBreakingThreshold;
		}
Пример #12
0
		private void ClearUserCache(ManifoldPoint pt)
		{
			if (pt != null)
			{
				object oldPtr = pt.UserPersistentData;

				if (oldPtr != null)
				{
					if (pt.UserPersistentData != null && _contactDestroyedCallback != null)
					{
						_contactDestroyedCallback(pt.UserPersistentData);
						pt.UserPersistentData = null;
					}
				}
			}
		}
Пример #13
0
 public bool ValidContactDistance(ManifoldPoint pt)
 {
     return(pt.Distance <= ContactBreakingThreshold);
 }
Пример #14
0
		public void ReplaceContactPoint(ManifoldPoint newPoint, int insertIndex)
		{
			BulletDebug.Assert(ValidContactDistance(newPoint));

			if (_pointCache[insertIndex] != null)
			{
				int lifeTime = _pointCache[insertIndex].LifeTime;
				BulletDebug.Assert(lifeTime >= 0);
				object cache = _pointCache[insertIndex].UserPersistentData;

				_pointCache[insertIndex] = newPoint;

				_pointCache[insertIndex].UserPersistentData = cache;
				_pointCache[insertIndex].LifeTime = lifeTime;
			}
			else
			{
				_pointCache[insertIndex] = newPoint;
			}

			//ClearUserCache(_pointCache[insertIndex]);
			//_pointCache[insertIndex] = newPoint;
		}
Пример #15
0
		public void AddManifoldPoint(ManifoldPoint newPoint)
		{
			if (!ValidContactDistance(newPoint))
				throw new BulletException();

			int insertIndex = ContactsCount;
			if (insertIndex == 4)
			{
				//sort cache so best points come first, based on area
				insertIndex = SortCachedPoints(newPoint);
			}
			else
			{
				_cachedPoints++;
			}
			ReplaceContactPoint(newPoint, insertIndex);
		}
Пример #16
0
		// sort cached points so most isolated points come first
		private int SortCachedPoints(ManifoldPoint pt)
		{
			//calculate 4 possible cases areas, and take biggest area
			//also need to keep 'deepest'

			int maxPenetrationIndex = -1;
			float maxPenetration = pt.Distance;
			for (int i = 0; i < 4; i++)
			{
				if (_pointCache[i].Distance < maxPenetration)
				{
					maxPenetrationIndex = i;
					maxPenetration = _pointCache[i].Distance;
				}
			}

			float res0 = 0, res1 = 0, res2 = 0, res3 = 0;
			if (maxPenetrationIndex != 0)
			{
				Vector3 a0 = pt.LocalPointA - _pointCache[1].LocalPointA;
				Vector3 b0 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA;
				Vector3 cross = Vector3.Cross(a0, b0);
				res0 = cross.LengthSquared();
			}
			if (maxPenetrationIndex != 1)
			{
				Vector3 a1 = pt.LocalPointA - _pointCache[0].LocalPointA;
				Vector3 b1 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA;
				Vector3 cross = Vector3.Cross(a1, b1);
				res1 = cross.LengthSquared();
			}

			if (maxPenetrationIndex != 2)
			{
				Vector3 a2 = pt.LocalPointA - _pointCache[0].LocalPointA;
				Vector3 b2 = _pointCache[3].LocalPointA - _pointCache[1].LocalPointA;
				Vector3 cross = Vector3.Cross(a2, b2);
				res2 = cross.LengthSquared();
			}

			if (maxPenetrationIndex != 3)
			{
				Vector3 a3 = pt.LocalPointA - _pointCache[0].LocalPointA;
				Vector3 b3 = _pointCache[2].LocalPointA - _pointCache[1].LocalPointA;
				Vector3 cross = Vector3.Cross(a3, b3);
				res3 = cross.LengthSquared();
			}

			Vector4 maxvec = new Vector4(res0, res1, res2, res3);
			int biggestarea = MathHelper.ClosestAxis(maxvec);
			return biggestarea;
		}
Пример #17
0
		private int FindContactPoint(ManifoldPoint unUsed, int numUnused, ManifoldPoint pt) { return 0; }