Exemple #1
0
        /// <summary>
        /// Indicates if a segment intersects a triangle
        /// </summary>
        /// <param name="seg"></param>
        /// <param name="triangle"></param>
        /// <returns>bool</returns>
        public static bool SegmentTriangleOverlap(Segment seg, Triangle triangle)
        {
            // the parameters - if hit then they get copied into the args
            float u, v, t;

            Vector3 e1 = triangle.Edge0;
            Vector3 e2 = triangle.Edge1;

            Vector3 p = Vector3.Cross(seg.Delta, e2);
            float a = Vector3.Dot(e1, p);

            if (a > -JiggleMath.Epsilon && a < JiggleMath.Epsilon)
                return false;

            float f = 1.0f / a;
            Vector3 s = seg.Origin - triangle.Origin;
            u = f * Vector3.Dot(s, p);

            if (u < 0.0f || u > 1.0f)
                return false;

            Vector3 q = Vector3.Cross(s, e1);
            v = f * Vector3.Dot(seg.Delta, q);

            if (v < 0.0f || (u + v) > 1.0f)
                return false;

            t = f * Vector3.Dot(e2, q);

            if (t < 0.0f || t > 1.0f)
                return false;

            return true;
        }
        public static float PointSegmentDistance(out float t, Vector3 pt, Segment seg)
        {
            Vector3 kDiff;
            float fT;

            Vector3.Subtract(ref pt, ref seg.Origin, out kDiff);
            Vector3.Dot(ref kDiff, ref seg.Delta, out fT);

            if (fT <= 0.0f)
            {
                fT = 0.0f;
            }
            else
            {
                float sqrLen = seg.Delta.LengthSquared();
                if (fT >= sqrLen)
                {
                    fT = 1.0f;
                    kDiff = kDiff - seg.Delta;
                }
                else
                {
                    fT = fT / sqrLen;
                    kDiff = kDiff - (fT * seg.Delta);
                }
            }

            t = fT;

            return kDiff.Length();
        }
 public bool Intersects(
     ref Vector3 position,
     ref Vector3 vector,
     out Vector3 resultPosition,
     out Vector3 resultNormal,
     out float resultFraction)
 {
     var segment = new Segment(position, vector);
     return SegmentIntersect(out resultFraction, out resultPosition, out resultNormal, segment);
 }
Exemple #4
0
        public override void CollDetect(CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Capsule oldCapsule0 = (Capsule)info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0);
            Capsule newCapsule0 = (Capsule)info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0);
            Segment oldSeg0 = new Segment(oldCapsule0.Position, oldCapsule0.Length * oldCapsule0.Orientation.Backward);
            Segment newSeg0 = new Segment(newCapsule0.Position, newCapsule0.Length * newCapsule0.Orientation.Backward);

            Capsule oldCapsule1 = (Capsule)info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1);
            Capsule newCapsule1 = (Capsule)info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1);
            Segment oldSeg1 = new Segment(oldCapsule1.Position, oldCapsule1.Length * oldCapsule1.Orientation.Backward);
            Segment newSeg1 = new Segment(newCapsule1.Position, newCapsule1.Length * newCapsule1.Orientation.Backward);

            float radSum = newCapsule0.Radius + newCapsule1.Radius;

            float oldt0, oldt1;
            float newt0, newt1;
            float oldDistSq = Distance.SegmentSegmentDistanceSq(out oldt0, out oldt1, oldSeg0, oldSeg1);
            float newDistSq = Distance.SegmentSegmentDistanceSq(out newt0, out newt1, newSeg0, newSeg1);

            if (System.Math.Min(oldDistSq, newDistSq) < ((radSum + collTolerance) * (radSum + collTolerance)))
            {
                Vector3 pos0 = oldSeg0.GetPoint(oldt0);
                Vector3 pos1 = oldSeg1.GetPoint(oldt1);

                Vector3 delta = pos0 - pos1;

                float dist = (float)System.Math.Sqrt((float)oldDistSq);
                float depth = radSum - dist;

                if (dist > JiggleMath.Epsilon)
                {
                    delta /= dist;
                }
                else
                {
                    // todo - make this not random
                    delta = Vector3.Transform(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                Vector3 worldPos = pos1 +
                    (oldCapsule1.Radius - 0.5f * depth) * delta;

                unsafe
                {
                    SmallCollPointInfo collInfo = new SmallCollPointInfo(worldPos - body0Pos, worldPos - body1Pos, depth);
                    collisionFunctor.CollisionNotify(ref info, ref delta, &collInfo, 1);
                }

            }
        }
Exemple #5
0
        /// <summary>
        /// Indicates if a segment overlaps an AABox
        /// </summary>
        /// <param name="seg"></param>
        /// <param name="AABox"></param>
        /// <returns>bool</returns>
        public static bool SegmentAABoxOverlap(Segment seg, AABox AABox)
        {
            Vector3 p0 = seg.Origin;
            Vector3 p1 = seg.GetEnd();

            float[] faceOffsets = new float[2];

            // The AABox faces are aligned with the world directions. Loop
            // over the 3 directions and do the two tests.
            for (int iDir = 0; iDir < 3; iDir++)
            {
                int jDir = (iDir + 1) % 3;
                int kDir = (iDir + 2) % 3;

                // one plane goes through the origin, one is offset
                faceOffsets[0] = JiggleUnsafe.Get(AABox.MinPos, iDir);
                faceOffsets[1] = JiggleUnsafe.Get(AABox.MaxPos, iDir);

                for (int iFace = 0; iFace < 2; iFace++)
                {
                    // distance of each point from to the face plane
                    float dist0 = JiggleUnsafe.Get(ref p0, iDir) - faceOffsets[iFace];
                    float dist1 = JiggleUnsafe.Get(ref p1, iDir) - faceOffsets[iFace];
                    float frac = -1.0f;

                    if (dist0 * dist1 < -JiggleMath.Epsilon)
                        frac = -dist0 / (dist1 - dist0);
                    else if (System.Math.Abs(dist0) < JiggleMath.Epsilon)
                        frac = 0.0f;
                    else if (System.Math.Abs(dist1) < JiggleMath.Epsilon)
                        frac = 1.0f;

                    if (frac >= 0.0f)
                    {
                        //Assert(frac <= 1.0f);
                        Vector3 pt = seg.GetPoint(frac);

                        // check the point is within the face rectangle
                        if ((JiggleUnsafe.Get(ref pt, jDir) > JiggleUnsafe.Get(AABox.MinPos, jDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, jDir) < JiggleUnsafe.Get(AABox.MaxPos, jDir) + JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) > JiggleUnsafe.Get(AABox.MinPos, kDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) < JiggleUnsafe.Get(AABox.MaxPos, kDir) + JiggleMath.Epsilon))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
Exemple #6
0
        public static bool SegmentCapsuleIntersection(out float tS, Segment seg, Capsule capsule)
        {
            float bestFrac = float.MaxValue;

            tS = 0;

            // do the main sides
            float sideFrac = float.MaxValue;
            if (!SegmentInfiniteCylinderIntersection(out sideFrac, seg,
                    new Segment(capsule.Position, capsule.Orientation.Backward),
                    capsule.Radius))
                return false; // check this

            // only keep this if the side intersection point is within the capsule segment ends
            Vector3 sidePos = seg.GetPoint(sideFrac);
            if (Vector3.Dot(sidePos - capsule.Position, capsule.Orientation.Backward) < 0.0f)
                sideFrac = float.MaxValue;
            else if (Vector3.Dot(sidePos - capsule.GetEnd(), capsule.Orientation.Backward) > 0.0f)
                sideFrac = float.MaxValue;

            // do the two ends
            float originFrac = float.MaxValue;
            SegmentSphereIntersection(out originFrac, seg, new Sphere(capsule.Position, capsule.Radius));
            float endFrac = float.MaxValue; // Check this!
            SegmentSphereIntersection(out endFrac, seg, new Sphere(capsule.Position, capsule.Radius));

            bestFrac = MathHelper.Min(sideFrac, originFrac);
            bestFrac = MathHelper.Min(bestFrac, endFrac);

            if (bestFrac <= 1.0f)
            {
                tS = bestFrac;
                return true;
            }

            return false;
        }
        public void OnFire(Vector3 muzzlePosition, Vector3 muzzleDir)
        {
            if (coolDownTimeRemaining <= 0)
            {
                //fpsModel.SetAnimationLayer("Pistol_Idle", 0.0f);
                fpsModel.GetAnimationLayer().AddAnimation("Pistol_Fire", true);
                //fpsModel.SetAnimationLayer("Pistol_Fire", 1.0f);
                coolDownTimeRemaining = ResourceManager.Inst.GetAnimation("Pistol_Fire").EndTime;
                float dist;
                CollisionSkin skin;
                Vector3 pos, normal;

                Segment seg = new Segment(muzzlePosition, muzzleDir * 50);

                scene.GetPhysicsEngine().CollisionSystem.SegmentIntersect(out dist, out skin, out pos, out normal, seg, ignorePred);
                if (skin != null)
                {
                    Decal decal = new Decal();
                    decal.SetMaterial("BulletMetal1");
                    decal.Normal = normal;
                    decal.Scale = new Vector2(0.25f, 0.25f);
                    Vector3 posNew = seg.Origin + seg.Delta * dist;
                    decal.Transformation.SetPosition(posNew);
                    decal.IsPersistent = false;
                    scene.AddEntity("bullet", decal);
                    ParticleEffect bulletEffect = ResourceManager.Inst.GetParticleEffect("BulletEffect");
                    ParticleEmitter collideEmitter = new ParticleEmitter(bulletEffect, 16);
                    collideEmitter.EmitOnce = true;
                    NormalTransform newTransform = new NormalTransform();
                    newTransform.ConformToNormal(normal);
                    newTransform.SetPosition(pos);
                    collideEmitter.Transformation = newTransform;
                    scene.AddEntity("bulletEmitter", collideEmitter);
                }
            }
        }
        InteractNode GetInteractNode(Microsoft.Xna.Framework.Ray lookRay)
        {
            float collisionDist;
            CollisionSkin skin = null;
            Vector3 pos, normal;
            Segment seg = new Segment(lookRay.Position, lookRay.Direction * MAX_INTERACT_DIST);
            scene.GetPhysicsEngine().CollisionSystem.SegmentIntersect(out collisionDist, out skin, out pos, out normal, seg, pred);

            float bestDist = (skin != null) ? collisionDist : float.PositiveInfinity;
            InteractNode bestNode = null;
            for (int i = 0; i < interactables.Count; i++)
            {
                InteractObject interactObj = interactables[i].GetInteractObject();

                BoundingBox bounds =  interactObj.Transformation.TransformBounds(interactObj.GetMesh().GetBounds());
                float? intersection = lookRay.Intersects(bounds);
                if (intersection.HasValue)
                {
                    float dist = intersection.Value;
                    if (dist < bestDist && dist <= MAX_INTERACT_DIST)
                    {
                        InteractNode node = interactObj.GetInteractNode();
                        if (node.IsEnabled())
                        {
                            bestDist = dist;
                            bestNode = interactObj.GetInteractNode();
                        }
                    }
                }
            }
            return bestNode;
        }
Exemple #9
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="fracOut"></param>
        /// <param name="posOut"></param>
        /// <param name="normalOut"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float fracOut, out Vector3 posOut, out Vector3 normalOut, Segment seg)
        {
            fracOut = float.MaxValue;
            posOut = normalOut = Vector3.Zero;

            // algo taken from p674 of realting rendering
            // needs debugging
            float min = float.MinValue;
            float max = float.MaxValue;

            // BEN-OPTIMISATION: Faster code.
            Vector3 centre = GetCentre();
            Vector3 p;
            Vector3.Subtract(ref centre, ref seg.Origin, out p);
            Vector3 h;
            h.X = sideLengths.X * 0.5f;
            h.Y = sideLengths.Y * 0.5f;
            h.Z = sideLengths.Z * 0.5f;

            int dirMax = 0;
            int dirMin = 0;
            int dir = 0;

            // BEN-OPTIMISATIOIN: Ugly inlining and variable reuse for marginal speed increase.
            #region "Original Code"
            /*
            Vector3[] matrixVec = new Vector3[3];
            matrixVec[0] = transform.Orientation.Right;
            matrixVec[1] = transform.Orientation.Up;
            matrixVec[2] = transform.Orientation.Backward;

            float[] vectorFloat = new float[3];
            vectorFloat[0] = h.X;
            vectorFloat[1] = h.Y;
            vectorFloat[2] = h.Z;

            for (dir = 0; dir < 3; dir++)
            {
                float e = Vector3.Dot(matrixVec[dir], p);
                float f = Vector3.Dot(matrixVec[dir], seg.Delta);

                if (System.Math.Abs(f) > JiggleMath.Epsilon)
                {
                    float t1 = (e + vectorFloat[dir]) / f;
                    float t2 = (e - vectorFloat[dir]) / f;

                    if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }

                    if (t1 > min)
                    {
                        min = t1;
                        dirMin = dir;
                    }
                    if (t2 < max)
                    {
                        max = t2;
                        dirMax = dir;
                    }

                    if (min > max)
                        return false;

                    if (max < 0.0f)
                        return false;
                }
                else if ((-e - vectorFloat[dir] > 0.0f) ||
                    (-e + vectorFloat[dir] < 0.0f))
                {
                    return false;
                }
            }
            */
            #endregion

            #region "Faster code albeit scarier code!"

            float e = Vector3.Dot(transform.Orientation.Right(), p);
            float f = Vector3.Dot(transform.Orientation.Right(), seg.Delta);

            if (System.Math.Abs(f) > JiggleMath.Epsilon)
            {
                float t1 = (e + h.X) / f;
                float t2 = (e - h.X) / f;

                if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }

                if (t1 > min)
                {
                    min = t1;
                    dirMin = 0;
                }
                if (t2 < max)
                {
                    max = t2;
                    dirMax = 0;
                }

                if (min > max)
                    return false;

                if (max < 0.0f)
                    return false;
            }
            else if ((-e - h.X > 0.0f) || (-e + h.X < 0.0f))
            {
                return false;
            }

            e = Vector3.Dot(transform.Orientation.Up(), p);
            f = Vector3.Dot(transform.Orientation.Up(), seg.Delta);

            if (System.Math.Abs(f) > JiggleMath.Epsilon)
            {
                float t1 = (e + h.Y) / f;
                float t2 = (e - h.Y) / f;

                if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }

                if (t1 > min)
                {
                    min = t1;
                    dirMin = 1;
                }
                if (t2 < max)
                {
                    max = t2;
                    dirMax = 1;
                }

                if (min > max)
                    return false;

                if (max < 0.0f)
                    return false;
            }
            else if ((-e - h.Y > 0.0f) || (-e + h.Y < 0.0f))
            {
                return false;
            }

            e = Vector3.Dot(transform.Orientation.Backward(), p);
            f = Vector3.Dot(transform.Orientation.Backward(), seg.Delta);

            if (System.Math.Abs(f) > JiggleMath.Epsilon)
            {
                float t1 = (e + h.Z) / f;
                float t2 = (e - h.Z) / f;

                if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }

                if (t1 > min)
                {
                    min = t1;
                    dirMin = 2;
                }
                if (t2 < max)
                {
                    max = t2;
                    dirMax = 2;
                }

                if (min > max)
                    return false;

                if (max < 0.0f)
                    return false;
            }
            else if ((-e - h.Z > 0.0f) || (-e + h.Z < 0.0f))
            {
                return false;
            }
            #endregion

            if (min > 0.0f)
            {
                dir = dirMin;
                fracOut = min;
            }
            else
            {
                dir = dirMax;
                fracOut = max;
            }

            if (dir == 0)
            {
                fracOut = OpenTKHelper.Clamp(fracOut, 0.0f, 1.0f);
                posOut = seg.GetPoint(fracOut);
                if (Vector3.Dot(transform.Orientation.Right(), seg.Delta) > 0.0f)
                    normalOut = -transform.Orientation.Right();
                else
                    normalOut = transform.Orientation.Right();
            }
            else if (dir == 1)
            {
                fracOut = OpenTKHelper.Clamp(fracOut, 0.0f, 1.0f);
                posOut = seg.GetPoint(fracOut);
                if (Vector3.Dot(transform.Orientation.Up(), seg.Delta) > 0.0f)
                    normalOut = -transform.Orientation.Up();
                else
                    normalOut = transform.Orientation.Up();
            }
            else
            {
                fracOut = OpenTKHelper.Clamp(fracOut, 0.0f, 1.0f);
                posOut = seg.GetPoint(fracOut);
                if (Vector3.Dot(transform.Orientation.Backward(), seg.Delta) > 0.0f)
                    normalOut = -transform.Orientation.Backward();
                else
                    normalOut = transform.Orientation.Backward();
            }

            return true;
        }
        /// <summary>
        /// GetBoxTriangleIntersectionPoints
        /// Pushes intersection points onto the back of pts. Returns the
        /// number of points found.
        /// Points that are close together (compared to 
        /// combinationDistance) get combined
        /// </summary>
        /// <param name="pts"></param>
        /// <param name="box"></param>
        /// <param name="triangle"></param>
        /// <param name="combinationDistance"></param>
        /// <returns>int</returns>
        private static int GetBoxTriangleIntersectionPoints(List<Vector3> pts, Box box, Triangle triangle, float combinationDistance)
        {
            // first intersect each edge of the box with the triangle
            Box.Edge[] edges;
            box.GetEdges(out edges);
            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);

            float tS;
            float tv1, tv2;

            // BEN-OPTIMISATION: Allocating just one Vector3 to be reused.
            Vector3 point = new Vector3();

            int iEdge;
            for (iEdge = 0; iEdge < 12; ++iEdge)
            {
                Box.Edge edge = edges[iEdge];
                Segment seg = new Segment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]);
                if (Intersection.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle))
                {
                    // BEN-OPTIMISATION: Reusing the existing point variable instead allocating new ones.
                    //                   This also allows point to be based by reference.
                    seg.GetPoint(ref point, tS);
                    AddPoint(pts, ref point, combinationDistance * combinationDistance);
                }
            }

            Vector3 pos, n;
            // now each edge of the triangle with the box
            for (iEdge = 0; iEdge < 3; ++iEdge)
            {
                #region "BEN-OPTIMISATION: Remove excess allocations and pass variables by reference."
                // ORIGINAL CODE:
                /*Vector3 pt0 = triangle.GetPoint(iEdge);
                Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3);
                Segment s1 = new Segment(pt0, pt1 - pt0);
                Segment s2 = new Segment(pt1, pt0 - pt1);*/

                // OPTIMISED CODE:
                Vector3 pt0 = triangle.GetPoint(iEdge);
                Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3);

                Vector3 difference1;
                Vector3 difference2;

                Vector3.Subtract(ref pt1, ref pt0, out difference1);
                Vector3.Subtract(ref pt0, ref pt1, out difference2);

                Segment s1 = new Segment(ref pt0, ref difference1);
                Segment s2 = new Segment(ref pt1, ref difference2);
                #endregion

                if (box.SegmentIntersect(out tS, out pos, out n, s1))
                    AddPoint(pts, ref pos, combinationDistance * combinationDistance);
                if (box.SegmentIntersect(out tS, out pos, out n, s2))
                    AddPoint(pts, ref pos, combinationDistance * combinationDistance);
            }

            return pts.Count;
        }
Exemple #11
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="fracOut"></param>
        /// <param name="skinOut"></param>
        /// <param name="posOut"></param>
        /// <param name="normalOut"></param>
        /// <param name="seg"></param>
        /// <param name="collisionPredicate"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Microsoft.Xna.Framework.Vector3 posOut, out Microsoft.Xna.Framework.Vector3 normalOut, JigLibX.Geometry.Segment seg, CollisionSkinPredicate1 collisionPredicate)
        {
            fracOut = float.MaxValue;
            skinOut = null;
            posOut  = normalOut = Vector3.Zero;

            float   frac;
            Vector3 pos;
            Vector3 normal;

            Vector3 segmentBeginning = seg.Origin;
            Vector3 segmentEnd       = seg.Origin + seg.Delta;

            Vector3 min = Vector3.Min(segmentBeginning, segmentEnd);
            Vector3 max = Vector3.Max(segmentBeginning, segmentEnd);

            active_.Clear();

            BoundingBox box = new BoundingBox(min, max);

            Extract(min, max, active_);

            float distanceSquared = float.MaxValue;
            int   nActive         = active_.Count;

            for (int i = 0; i != nActive; ++i)
            {
                CollisionSkin skin = active_[i];
                if (collisionPredicate == null || collisionPredicate.ConsiderSkin(skin))
                {
                    if (BoundingBoxHelper.OverlapTest(ref box, ref skin.WorldBoundingBox))
                    {
                        if (skin.SegmentIntersect(out frac, out pos, out normal, seg))
                        {
                            if (frac >= 0)
                            {
                                float newDistanceSquared = Vector3.DistanceSquared(segmentBeginning, pos);
                                if (newDistanceSquared < distanceSquared)
                                {
                                    distanceSquared = newDistanceSquared;

                                    fracOut   = frac;
                                    skinOut   = skin;
                                    posOut    = pos;
                                    normalOut = normal;
                                }
                            }
                        }
                    }
                }
            }

            return(fracOut <= 1);
        }
Exemple #12
0
        public override bool SegmentIntersect(out float fracOut, out Vector3 posOut, out Vector3 normalOut, Segment seg)
        {
            fracOut = float.MaxValue;
            posOut = normalOut = Vector3.Zero;

            // algo taken from p674 of realting rendering
            // needs debugging
            float min = float.MinValue;
            float max = float.MaxValue;

            Vector3 p = GetCentre() - seg.Origin;
            Vector3 h;
            h.X = sideLengths.X * 0.5f;
            h.Y = sideLengths.Y * 0.5f;
            h.Z = sideLengths.Z * 0.5f;

            int dirMax = 0;
            int dirMin = 0;
            int dir = 0;

            Vector3[] matrixVec = new Vector3[3];
            matrixVec[0] = transform.Orientation.Right;
            matrixVec[1] = transform.Orientation.Up;
            matrixVec[2] = transform.Orientation.Backward;

            float[] vectorFloat = new float[3];
            vectorFloat[0] = h.X;
            vectorFloat[1] = h.Y;
            vectorFloat[2] = h.Z;

            for (dir = 0; dir < 3; dir++)
            {
                float e = Vector3.Dot(matrixVec[dir], p);
                float f = Vector3.Dot(matrixVec[dir], seg.Delta);

                if (System.Math.Abs(f) > JiggleMath.Epsilon)
                {
                    float t1 = (e + vectorFloat[dir]) / f;
                    float t2 = (e - vectorFloat[dir]) / f;

                    if (t1 > t2){float tmp = t1;t1 = t2; t2 = tmp;}

                    if (t1 > min)
                    {
                        min = t1;
                        dirMin = dir;
                    }
                    if (t2 < max)
                    {
                        max = t2;
                        dirMax = dir;
                    }

                    if (min > max)
                        return false;

                    if (max < 0.0f)
                        return false;
                }
                else if((-e-vectorFloat[dir] > 0.0f) ||
                    (-e + vectorFloat[dir] < 0.0f))
                {
                    return false;
                }
            }

            if (min > 0.0f)
            {
                dir = dirMin;
                fracOut = min;
            }
            else
            {
                dir = dirMax;
                fracOut = max;
            }

            fracOut = MathHelper.Clamp(fracOut, 0.0f, 1.0f);
            posOut = seg.GetPoint(fracOut);
            if (Vector3.Dot(matrixVec[dir], seg.Delta) > 0.0f)
                normalOut = -matrixVec[dir];
            else
                normalOut = matrixVec[dir];

            return true;
        }
Exemple #13
0
        /// <summary>
        /// SegmentBoxDistanceSq
        /// </summary>
        /// <param name="pfLParam"></param>
        /// <param name="pfBParam0"></param>
        /// <param name="pfBParam1"></param>
        /// <param name="pfBParam2"></param>
        /// <param name="rkSeg"></param>
        /// <param name="rkBox"></param>
        /// <returns>float</returns>
        public static float SegmentBoxDistanceSq(out float pfLParam,
            out float pfBParam0, out float pfBParam1, out float pfBParam2,
            Segment rkSeg, Box rkBox)
        {
            pfLParam = pfBParam0 = pfBParam1 = pfBParam2 = 0.0f;

            Line line = new Line(rkSeg.Origin, rkSeg.Delta);

            float fLP, fBP0, fBP1, fBP2;
            float fSqrDistance = SqrDistance(line, rkBox, out fLP, out fBP0, out  fBP1, out fBP2);

            if (fLP >= 0.0f)
            {
                if (fLP <= 1.0f)
                {
                    pfLParam = fLP;
                    pfBParam0 = fBP0;// + 0.5f;
                    pfBParam1 = fBP1;// + 0.5f;
                    pfBParam2 = fBP2;// + 0.5f;

                    return MathHelper.Max(fSqrDistance, 0.0f);
                }
                else
                {
                    fSqrDistance = SqrDistance(rkSeg.Origin + rkSeg.Delta,
                                               rkBox, out pfBParam0, out pfBParam1, out  pfBParam2);

                    pfLParam = 1.0f;
                    return MathHelper.Max(fSqrDistance, 0.0f);
                }
            }
            else
            {
                fSqrDistance = SqrDistance(rkSeg.Origin, rkBox, out  pfBParam0, out  pfBParam1, out  pfBParam2);

                pfLParam = 0.0f;

                return MathHelper.Max(fSqrDistance, 0.0f);
            }
        }
Exemple #14
0
        /// <summary>
        /// SegmentTriangleDistanceSq
        /// </summary>
        /// <param name="segT"></param>
        /// <param name="triT0"></param>
        /// <param name="triT1"></param>
        /// <param name="seg"></param>
        /// <param name="triangle"></param>
        /// <returns>float</returns>
        public static float SegmentTriangleDistanceSq(out float segT, out float triT0, out float triT1, Segment seg, Triangle triangle)
        {
            // compare segment to all three edges of the triangle
            float distSq = float.MaxValue;

            if (Intersection.SegmentTriangleIntersection(out segT, out triT0, out triT1, seg, triangle))
            {
                segT = triT0 = triT1 = 0.0f;
                return 0.0f;
            }

            float s, t, u;
            float distEdgeSq;
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin, triangle.Edge0));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = t;
                triT1 = 0.0f;
            }
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin, triangle.Edge1));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = 0.0f;
                triT1 = t;
            }
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin + triangle.Edge0, triangle.Edge2));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = 1.0f - t;
                triT1 = t;
            }

            // compare segment end points to triangle interior
            float startTriSq = PointTriangleDistanceSq(out t, out u, seg.Origin, triangle);
            if (startTriSq < distSq)
            {
                distSq = startTriSq;
                segT = 0.0f;
                triT0 = t;
                triT1 = u;
            }
            float endTriSq = PointTriangleDistanceSq(out t, out u, seg.GetEnd(), triangle);
            if (endTriSq < distSq)
            {
                distSq = endTriSq;
                segT = 1.0f;
                triT0 = t;
                triT1 = u;
            }
            return distSq;
        }
Exemple #15
0
        public void OnUpdate()
        {
            fpsModel.OnUpdate();

            if (coolDownTimeRemaining > 0)
            {
                coolDownTimeRemaining -= Time.GameTime.ElapsedTime;
            }
            if (timeTilFire > 0)
                timeTilFire -= Time.GameTime.ElapsedTime;
            if (timeTilFire <= 0 && !hasFired)
            {
                hasFired = true;
                if(!datablock.IsMelee)
                    new Sound3D(datablock.GetSoundEffect((ammo > 0)?WeaponAnimations.Fire:WeaponAnimations.Empty), muzzlePos);
                if (ammo > 0 || datablock.IsMelee)
                {
                    ammo--;
                    float dist;
                    CollisionSkin skin;
                    Vector3 pos, normal;

                    Segment seg = new Segment(muzzlePos, muzzleDir * datablock.FireDistance);
                    Microsoft.Xna.Framework.Ray shootRay = new Microsoft.Xna.Framework.Ray(muzzlePos, muzzleDir);
                    bool anyActorHit = false;
                    scene.GetPhysicsEngine().CollisionSystem.SegmentIntersect(out dist, out skin, out pos, out normal, seg, ignorePred);
                    float segDist = (skin != null) ? Vector3.Distance(seg.Delta * dist, Vector3.Zero): float.PositiveInfinity;
                    for (int i = 0; i < scene.Actors.Count; i++)
                    {
                        Actor currActor = scene.Actors[i];
                        if (currActor != scene.MainPlayer)
                        {
                            float shootDist;
                            HitType hit = currActor.GetHit(shootRay, datablock.FireDistance, out shootDist);
                            if (hit != HitType.None)
                            {
                                if (skin == null || (shootDist <= segDist))
                                {
                                    currActor.ApplyDamage(datablock.Damage);
                                    ParticleEffect bloodEffect = ResourceManager.Inst.GetParticleEffect("BloodEffect");
                                    ParticleEmitter collideEmitter = new ParticleEmitter(bloodEffect, 16);
                                    collideEmitter.EmitOnce = true;
                                    NormalTransform newTransform = new NormalTransform();
                                    newTransform.ConformToNormal(-muzzleDir);
                                    newTransform.SetPosition(muzzlePos + muzzleDir*shootDist);
                                    collideEmitter.Transformation = newTransform;
                                    scene.AddEntity("bloodEmitter", collideEmitter);
                                    anyActorHit = true;
                                }
                            }
                        }
                    }
                    if (skin != null)
                    {
                        ParticleEffect bulletEffect = ResourceManager.Inst.GetParticleEffect("BulletEffect");
                        ParticleEmitter collideEmitter = new ParticleEmitter(bulletEffect, 16);
                        collideEmitter.EmitOnce = true;
                        NormalTransform newTransform = new NormalTransform();
                        newTransform.ConformToNormal(normal);
                        newTransform.SetPosition(pos);
                        collideEmitter.Transformation = newTransform;
                        scene.AddEntity("bulletEmitter", collideEmitter);
                    }
                    if(datablock.IsMelee)
                        new Sound3D(datablock.GetSoundEffect((anyActorHit) ? WeaponAnimations.SuccessHit : WeaponAnimations.Fire), muzzlePos);
                }
            }
        }
        public override bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Vector3 posOut, out Vector3 normalOut, Segment seg, CollisionSkinPredicate1 collisionPredicate)
        {
            int numSkins = skins.Count;
            BoundingBox segBox = BoundingBoxHelper.InitialBox;
            BoundingBoxHelper.AddSegment(seg, ref segBox);

            //initialise the outputs
            fracOut = float.MaxValue;
            skinOut = null;
            posOut = normalOut = Vector3.Zero;

            // working vars
            float frac;
            Vector3 pos;
            Vector3 normal;

            for (int iskin = 0; iskin < numSkins; ++iskin)
            {
                CollisionSkin skin = skins[iskin];
                if ((collisionPredicate == null) ||
                    collisionPredicate.ConsiderSkin(skin))
                {
                    // basic bbox test
                    if (BoundingBoxHelper.OverlapTest(ref skin.WorldBoundingBox, ref segBox))
                    {
                        if (skin.SegmentIntersect(out frac, out pos, out normal, seg))
                        {
                            if (frac < fracOut)
                            {
                                posOut = pos;
                                normalOut = normal;
                                skinOut = skin;
                                fracOut = frac;
                            }
                        }

                    }
                }
            }

            if (fracOut > 1.0f) return false;
            fracOut = MathHelper.Clamp(fracOut, 0.0f, 1.0f);
            return true;
        }
        /// <summary>
        /// CollDetectCapsuleStaticMeshOverlap
        /// </summary>
        /// <param name="oldCapsule"></param>
        /// <param name="newCapsule"></param>
        /// <param name="mesh"></param>
        /// <param name="info"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        private void CollDetectCapsuleStaticMeshOverlap(Capsule oldCapsule, Capsule newCapsule,
            TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor)
        {
            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            float capsuleTolR = collTolerance + newCapsule.Radius;
            float capsuleTolR2 = capsuleTolR * capsuleTolR;

            Vector3 collNormal = Vector3.Zero;

            BoundingBox bb = BoundingBoxHelper.InitialBox;
            BoundingBoxHelper.AddCapsule(newCapsule, ref bb);

            unsafe
            {
            #if USE_STACKALLOC
                SmallCollPointInfo* collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI];
                int* potentialTriangles = stackalloc int[MaxLocalStackTris];
                {
                    {
            #else
                SmallCollPointInfo[] collPtArray = SCPIStackAlloc();
                fixed (SmallCollPointInfo* collPts = collPtArray)
                {
                    int[] potTriArray = IntStackAlloc();
                    fixed (int* potentialTriangles = potTriArray)
                    {
            #endif
                        int numCollPts = 0;

                        int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb);

                        Vector3 capsuleStart = newCapsule.Position;
                        Vector3 capsuleEnd = newCapsule.GetEnd();
                        Matrix4 meshInvTransform = mesh.InverseTransformMatrix;

                        Vector3 meshSpaceCapsuleStart = Vector3.Transform(capsuleStart, meshInvTransform);
                        Vector3 meshSpaceCapsuleEnd = Vector3.Transform(capsuleEnd, meshInvTransform);

                        for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                        {
                            IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]);

                            // we do the plane test using the capsule in mesh space
                            float distToStart = meshTriangle.Plane.DotCoordinate(meshSpaceCapsuleStart);
                            float distToEnd = meshTriangle.Plane.DotCoordinate(meshSpaceCapsuleEnd);

                            // BEN-BUG-FIX: Fixed by replacing 0.0F with -capsuleTolR.
                            if ((distToStart > capsuleTolR && distToEnd > capsuleTolR)
                                || (distToStart < -capsuleTolR && distToEnd < -capsuleTolR))
                                continue;

                            // we now transform the triangle into world space (we could keep leave the mesh alone
                            // but at this point 3 vector transforms is probably not a major slow down)
                            int i0, i1, i2;
                            meshTriangle.GetVertexIndices(out i0, out i1, out i2);

                            Vector3 triVec0;
                            Vector3 triVec1;
                            Vector3 triVec2;
                            mesh.GetVertex(i0, out triVec0);
                            mesh.GetVertex(i1, out triVec1);
                            mesh.GetVertex(i2, out triVec2);

                            // Deano move tri into world space
                            Matrix4 transformMatrix = mesh.TransformMatrix;
                            Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0);
                            Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1);
                            Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2);
                            Triangle triangle = new Triangle(ref triVec0, ref triVec1, ref triVec2);

                            Segment seg = new Segment(capsuleStart, capsuleEnd - capsuleStart);

                            float tS, tT0, tT1;
                            float d2 = Distance.SegmentTriangleDistanceSq(out tS, out tT0, out tT1, seg, triangle);

                            if (d2 < capsuleTolR2)
                            {
                                Vector3 oldCapsuleStart = oldCapsule.Position;
                                Vector3 oldCapsuleEnd = oldCapsule.GetEnd();
                                Segment oldSeg = new Segment(oldCapsuleStart, oldCapsuleEnd - oldCapsuleStart);
                                d2 = Distance.SegmentTriangleDistanceSq(out tS, out tT0, out tT1, oldSeg, triangle);
                                // report result from old position
                                float dist = (float)System.Math.Sqrt(d2);
                                float depth = oldCapsule.Radius - dist;
                                Vector3 pt = triangle.GetPoint(tT0, tT1);
                                Vector3 collisionN = (d2 > JiggleMath.Epsilon) ? JiggleMath.NormalizeSafe(oldSeg.GetPoint(tS) - pt) :
                                    meshTriangle.Plane.Normal;
                                if (numCollPts < MaxLocalStackSCPI)
                                {
                                    // BEN-OPTIMISATION: Reused existing collPts.
                                    collPts[numCollPts].R0 = pt - body0Pos;
                                    collPts[numCollPts].R1 = pt - body1Pos;
                                    collPts[numCollPts++].InitialPenetration = depth;
                                }
                                collNormal += collisionN;
                            }
                        }
                        if (numCollPts > 0)
                        {
                            JiggleMath.NormalizeSafe(ref collNormal);
                            collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts);
                        }
            #if USE_STACKALLOC
                    }
               }
            #else
                    }
                    FreeStackAlloc(potTriArray);
                }
                FreeStackAlloc(collPtArray);
            #endif
            }
        }
Exemple #18
0
        /// <summary> // TODO teting testing testing ...
        /// Adds the forces die to this wheel to the parent. Return value indicates if it's
        /// on the ground.
        /// </summary>
        /// <param name="dt"></param>
        public bool AddForcesToCar(float dt)
        {
            Vector3 force = Vector3.Zero;
            lastDisplacement = displacement;
            displacement = 0.0f;

            Body carBody = car.Chassis.Body;

            Vector3 worldPos = carBody.Position + Vector3.Transform(pos, carBody.Orientation);// *mPos;
            Vector3 worldAxis = Vector3.Transform(axisUp, carBody.Orientation);// *mAxisUp;

            //Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.Orientation.GetCol(0);
            // OpenGl has differnet row/column order for matrixes than XNA has ..
            Vector3 wheelFwd = Vector3.Transform(carBody.Orientation.Right, JiggleMath.RotationMatrix(steerAngle, worldAxis));
            //Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.GetOrientation().GetCol(0);
            Vector3 wheelUp = worldAxis;
            Vector3 wheelLeft = Vector3.Cross(wheelUp, wheelFwd);
            wheelLeft.Normalize();

            wheelUp = Vector3.Cross(wheelFwd, wheelLeft);

            // start of ray
            float rayLen = 2.0f * radius + travel;
            Vector3 wheelRayEnd = worldPos - radius * worldAxis;
            Segment wheelRay = new Segment(wheelRayEnd + rayLen * worldAxis, -rayLen * worldAxis);

            //Assert(PhysicsSystem.CurrentPhysicsSystem);
            CollisionSystem collSystem = PhysicsSystem.CurrentPhysicsSystem.CollisionSystem;

            ///Assert(collSystem);
            int numRaysUse = System.Math.Min(numRays, maxNumRays);

            // adjust the start position of the ray - divide the wheel into numRays+2
            // rays, but don't use the first/last.
            float deltaFwd = (2.0f * radius) / (numRaysUse + 1);
            float deltaFwdStart = deltaFwd;

            lastOnFloor = false;
            int bestIRay = 0;
            int iRay;

            for (iRay = 0; iRay < numRaysUse; ++iRay)
            {
                fracs[iRay] = float.MaxValue; //SCALAR_HUGE;
                // work out the offset relative to the middle ray
                float distFwd = (deltaFwdStart + iRay * deltaFwd) - radius;
                //float zOffset = mRadius * (1.0f - CosDeg(90.0f * (distFwd / mRadius)));
                float zOffset = radius * (1.0f - (float)System.Math.Cos( MathHelper.ToRadians( 90.0f * (distFwd / radius))));

                segments[iRay] = wheelRay;
                segments[iRay].Origin += distFwd * wheelFwd + zOffset * wheelUp;

                if (collSystem.SegmentIntersect(out fracs[iRay], out otherSkins[iRay],
                                                 out groundPositions[iRay], out groundNormals[iRay], segments[iRay], pred))
                {
                    lastOnFloor = true;

                    if (fracs[iRay] < fracs[bestIRay])
                        bestIRay = iRay;
                }
            }

            if (!lastOnFloor)
                return false;

            //Assert(bestIRay < numRays);

            // use the best one
            Vector3 groundPos = groundPositions[bestIRay];
            float frac = fracs[bestIRay];
            CollisionSkin otherSkin = otherSkins[bestIRay];

            //  const Vector3 groundNormal = (worldPos - segments[bestIRay].GetEnd()).NormaliseSafe();
            //  const Vector3 groundNormal = groundNormals[bestIRay];

            Vector3 groundNormal = worldAxis;

            if (numRaysUse > 1)
            {
                for (iRay = 0; iRay < numRaysUse; ++iRay)
                {
                    if (fracs[iRay] <= 1.0f)
                    {
                        groundNormal += (1.0f - fracs[iRay]) * (worldPos - segments[iRay].GetEnd());
                    }
                }

                JiggleMath.NormalizeSafe(ref groundNormal);
            }
            else
            {
                groundNormal = groundNormals[bestIRay];
            }

            //Assert(otherSkin);
            Body worldBody = otherSkin.Owner;

            displacement = rayLen * (1.0f - frac);
            displacement = MathHelper.Clamp(displacement, 0, travel);

            float displacementForceMag = displacement * spring;

            // reduce force when suspension is par to ground
            displacementForceMag *= Vector3.Dot(groundNormals[bestIRay], worldAxis);

            // apply damping
            float dampingForceMag = upSpeed * damping;

            float totalForceMag = displacementForceMag + dampingForceMag;

            if (totalForceMag < 0.0f) totalForceMag = 0.0f;

            Vector3 extraForce = totalForceMag * worldAxis;

            force += extraForce;

            // side-slip friction and drive force. Work out wheel- and floor-relative coordinate frame
            Vector3 groundUp = groundNormal;
            Vector3 groundLeft = Vector3.Cross(groundNormal, wheelFwd);
            JiggleMath.NormalizeSafe(ref groundLeft);

            Vector3 groundFwd = Vector3.Cross(groundLeft, groundUp);

            Vector3 wheelPointVel = carBody.Velocity +
             Vector3.Cross(carBody.AngularVelocity, Vector3.Transform( pos, carBody.Orientation));// * mPos);

            Vector3 rimVel = angVel * Vector3.Cross(wheelLeft, groundPos - worldPos);
            wheelPointVel += rimVel;

            // if sitting on another body then adjust for its velocity.
            if (worldBody != null)
            {
                Vector3 worldVel = worldBody.Velocity +
                 Vector3.Cross(worldBody.AngularVelocity, groundPos - worldBody.Position);

                wheelPointVel -= worldVel;
            }

            // sideways forces
            float noslipVel = 0.2f;
            float slipVel = 0.4f;
            float slipFactor = 0.7f;

            float smallVel = 3;
            float friction = sideFriction;

            float sideVel = Vector3.Dot(wheelPointVel, groundLeft);

            if ((sideVel > slipVel) || (sideVel < -slipVel))
                friction *= slipFactor;
            else
                if ((sideVel > noslipVel) || (sideVel < -noslipVel))
                    friction *= 1.0f - (1.0f - slipFactor) * (System.Math.Abs(sideVel) - noslipVel) / (slipVel - noslipVel);

            if (sideVel < 0.0f)
                friction *= -1.0f;

            if (System.Math.Abs(sideVel) < smallVel)
                friction *= System.Math.Abs(sideVel) / smallVel;

            float sideForce = -friction * totalForceMag;

            extraForce = sideForce * groundLeft;
            force += extraForce;

            // fwd/back forces
            friction = fwdFriction;
            float fwdVel = Vector3.Dot(wheelPointVel, groundFwd);

            if ((fwdVel > slipVel) || (fwdVel < -slipVel))
                friction *= slipFactor;
            else
                if ((fwdVel > noslipVel) || (fwdVel < -noslipVel))
                    friction *= 1.0f - (1.0f - slipFactor) * (System.Math.Abs(fwdVel) - noslipVel) / (slipVel - noslipVel);

            if (fwdVel < 0.0f)
                friction *= -1.0f;

            if (System.Math.Abs(fwdVel) < smallVel)
                friction *= System.Math.Abs(fwdVel) / smallVel;

            float fwdForce = -friction * totalForceMag;

            extraForce = fwdForce * groundFwd;
            force += extraForce;

            //if (!force.IsSensible())
            //{
            //  TRACE_FILE_IF(ONCE_1)
            //    TRACE("Bad force in car wheel\n");
            //  return true;
            //}

            // fwd force also spins the wheel
            Vector3 wheelCentreVel = carBody.Velocity +
             Vector3.Cross(carBody.AngularVelocity, Vector3.Transform(pos, carBody.Orientation));// * mPos);

            angVelForGrip = Vector3.Dot(wheelCentreVel, groundFwd) / radius;
            torque += -fwdForce * radius;

            // add force to car
            carBody.AddWorldForce(force, groundPos);

            //if (float.IsNaN(force.X))
            //    while(true){}
            //System.Diagnostics.Debug.WriteLine(force.ToString());

            // add force to the world
            if (worldBody != null && !worldBody.Immovable)
            {
                // todo get the position in the right place...
                // also limit the velocity that this force can produce by looking at the
                // mass/inertia of the other object
                float maxOtherBodyAcc = 500.0f;
                float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass;

                if (force.LengthSquared() > (maxOtherBodyForce * maxOtherBodyForce))
                    force *= maxOtherBodyForce / force.Length();

                worldBody.AddWorldForce(-force, groundPos);
            }
            return true;
        }
Exemple #19
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            // move segment into octree space
            seg.Origin = Vector3.Transform(seg.Origin, invTransform);
            seg.Delta = Vector3.TransformNormal(seg.Delta, invTransform);

            BoundingBox segBox = BoundingBoxHelper.InitialBox;
            BoundingBoxHelper.AddSegment(seg, ref segBox);

            unsafe
            {
            #if USE_STACKALLOC
                int* potentialTriangles = stackalloc int[MaxLocalStackTris];
                {
            #else
                int[] potTriArray = DetectFunctor.IntStackAlloc();
                fixed (int* potentialTriangles = potTriArray)
                {
            #endif
                    int numTriangles = GetTrianglesIntersectingtAABox(potentialTriangles, DetectFunctor.MaxLocalStackTris, ref segBox);

                    float tv1, tv2;

                    pos = Vector3.Zero;
                    normal = Vector3.Zero;

                    float bestFrac = float.MaxValue;
                    for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                    {
                        IndexedTriangle meshTriangle = GetTriangle(potentialTriangles[iTriangle]);
                        float thisFrac;
                        Triangle tri = new Triangle(GetVertex(meshTriangle.GetVertexIndex(0)),
                          GetVertex(meshTriangle.GetVertexIndex(1)),
                          GetVertex(meshTriangle.GetVertexIndex(2)));

                        if (Intersection.SegmentTriangleIntersection(out thisFrac, out tv1, out tv2, seg, tri))
                        {
                            if (thisFrac < bestFrac)
                            {
                                bestFrac = thisFrac;
                                // re-project
                                pos = Vector3.Transform(seg.GetPoint(thisFrac), transformMatrix);
                                normal = Vector3.TransformNormal(meshTriangle.Plane.Normal, transformMatrix);
                            }
                        }
                    }

                    frac = bestFrac;
                    if (bestFrac < float.MaxValue)
                    {
                        DetectFunctor.FreeStackAlloc(potTriArray);
                        return true;
                    }
                    else
                    {
                        DetectFunctor.FreeStackAlloc(potTriArray);
                        return false;
                    }
            #if USE_STACKALLOC
                }
            #else
                }
            #endif
            }
        }
Exemple #20
0
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            bool result = Intersection.SegmentCapsuleIntersection(out frac, seg, this);

            if (result)
            {
                pos = seg.GetPoint(frac);
                normal = pos - transform.Position;
                normal -= Vector3.Dot(normal, transform.Orientation.Backward) * transform.Orientation.Backward;
                JiggleMath.NormalizeSafe(ref normal);
            }
            else
            {
                pos = normal = Vector3.Zero;
            }

            return result;
        }
Exemple #21
0
 /// <summary>
 /// Intersect a segment with the world. If non-zero the predicate
 /// allows certain skins to be excluded
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="collisionPredicate"></param>
 /// <returns></returns>
 public abstract bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Vector3 posOut, out Vector3 normalOut,
     Segment seg, CollisionSkinPredicate1 collisionPredicate);
Exemple #22
0
        /// <summary>
        /// CollDetect
        /// </summary>
        /// <param name="infoOrig"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            // get the skins in the order that we're expectiing
            CollDetectInfo info = infoOrig;
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Capsule oldCapsule = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Capsule;
            Capsule newCapsule = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Capsule;
            Segment oldSeg = new Segment(oldCapsule.Position, oldCapsule.Length * oldCapsule.Orientation.Backward);
            Segment newSeg = new Segment(newCapsule.Position, newCapsule.Length * newCapsule.Orientation.Backward);

            float radius = oldCapsule.Radius;

            Box oldBox = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Box;
            Box newBox = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Box;

            float oldSegT;
            float oldBoxT0, oldBoxT1, oldBoxT2;
            float oldDistSq = Distance.SegmentBoxDistanceSq(out oldSegT, out oldBoxT0, out oldBoxT1, out oldBoxT2,oldSeg, oldBox);
            float newSegT;
            float newBoxT0, newBoxT1, newBoxT2;
            float newDistSq = Distance.SegmentBoxDistanceSq(out newSegT, out newBoxT0, out newBoxT1, out newBoxT2,newSeg, newBox);

            if (MathHelper.Min(oldDistSq, newDistSq) < ((radius + collTolerance) * (radius + collTolerance)))
            {
                Vector3 segPos = oldSeg.GetPoint(oldSegT);
                Vector3 boxPos = oldBox.GetCentre() + oldBoxT0 * oldBox.Orientation.Right +
                    oldBoxT1 * oldBox.Orientation.Up + oldBoxT2 * oldBox.Orientation.Backward;

                float dist = (float)System.Math.Sqrt((float)oldDistSq);
                float depth = radius - dist;

                Vector3 dir;

                if (dist > JiggleMath.Epsilon)
                {
                    dir = segPos - boxPos;
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else if ((segPos - oldBox.GetCentre()).LengthSquared() > JiggleMath.Epsilon)
                {
                    dir = segPos - oldBox.GetCentre();
                    JiggleMath.NormalizeSafe(ref dir);
                }
                else
                {
                    // todo - make this not random
                    dir = Vector3.Transform(Vector3.Backward, Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(random.Next(360))));
                }

                unsafe
                {
                    SmallCollPointInfo collInfo = new SmallCollPointInfo(boxPos - body0Pos, boxPos - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref dir, &collInfo, 1);
                }

            }
        }
Exemple #23
0
        /// <summary>
        /// PointSegmentDistanceSq
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="seg"></param>
        /// <param name="result"></param>
        public static void PointSegmentDistanceSq(ref Vector3 pt, ref Segment seg, out float result)
        {
            Vector3 kDiff;
            float fT;

            Vector3.Subtract(ref pt, ref seg.Origin, out kDiff);
            Vector3.Dot(ref kDiff, ref seg.Delta, out fT);

            if (fT <= 0.0f)
            {
                fT = 0.0f;
            }
            else
            {
                float sqrLen = seg.Delta.LengthSquared();
                if (fT >= sqrLen)
                {
                    fT = 1.0f;
                    kDiff = kDiff - seg.Delta;
                }
                else
                {
                    fT = fT / sqrLen;
                    kDiff = kDiff - (fT * seg.Delta);
                }
            }

            result = kDiff.LengthSquared();
        }
        /// <summary>
        /// Every skin must support a ray/segment intersection test -
        /// operates on the new value of the primitives
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            Vector3 segEnd = seg.GetEnd();
            frac = float.MaxValue;

            float thisSegLenRelToOrig = 1.0f;
            Segment segCopy = seg;

            pos = normal = Vector3.Zero;

            for (int prim = primitivesNewWorld.Count; prim-- != 0; )
            {
                float thisFrac;
                Vector3 newPosition = pos;

                if (primitivesNewWorld[prim].SegmentIntersect(out thisFrac, out newPosition, out normal, segCopy))
                {
                    pos = newPosition;
                    frac = thisFrac * thisSegLenRelToOrig;
                    segCopy.Delta *= thisFrac;
                    thisSegLenRelToOrig *= frac;
                }
            }

            //System.Diagnostics.Debug.WriteLineIf(frac <= 1.0f, pos);

            return (frac <= 1.0f);
        }
Exemple #25
0
        /// <summary>
        /// Returns the distance of two segments.
        /// </summary>
        /// <param name="t0">Parametric representation of nearest point on seg0.</param>
        /// <param name="t1">Parametric representation of nearest point on seg0.</param>
        /// <param name="seg0">First segment to test.</param>
        /// <param name="seg1">Second segment to test.</param>
        /// <returns>float</returns>
        public static float SegmentSegmentDistanceSq(out float t0, out float t1, Segment seg0, Segment seg1)
        {
            Vector3 kDiff = seg0.Origin - seg1.Origin;
            float fA00 = seg0.Delta.LengthSquared();
            float fA01 = -Vector3.Dot(seg0.Delta, seg1.Delta);
            float fA11 = seg1.Delta.LengthSquared();
            float fB0 = Vector3.Dot(kDiff, seg0.Delta);
            float fC = kDiff.LengthSquared();
            float fDet = System.Math.Abs(fA00 * fA11 - fA01 * fA01);
            float fB1, fS, fT, fSqrDist, fTmp;

            if (fDet >= JiggleMath.Epsilon)
            {
                // line segments are not parallel
                fB1 = -Vector3.Dot(kDiff, seg1.Delta);
                fS = fA01 * fB1 - fA11 * fB0;
                fT = fA01 * fB0 - fA00 * fB1;

                if (fS >= 0.0f)
                {
                    if (fS <= fDet)
                    {
                        if (fT >= 0.0f)
                        {
                            if (fT <= fDet)  // region 0 (interior)
                            {
                                // minimum at two interior points of 3D lines
                                float fInvDet = 1.0f / fDet;
                                fS *= fInvDet;
                                fT *= fInvDet;
                                fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                                  fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                            }
                            else  // region 3 (side)
                            {
                                fT = 1.0f;
                                fTmp = fA01 + fB0;
                                if (fTmp >= 0.0f)
                                {
                                    fS = 0.0f;
                                    fSqrDist = fA11 + (2.0f) * fB1 + fC;
                                }
                                else if (-fTmp >= fA00)
                                {
                                    fS = 1.0f;
                                    fSqrDist = fA00 + fA11 + fC + (2.0f) * (fB1 + fTmp);
                                }
                                else
                                {
                                    fS = -fTmp / fA00;
                                    fSqrDist = fTmp * fS + fA11 + (2.0f) * fB1 + fC;
                                }
                            }
                        }
                        else  // region 7 (side)
                        {
                            fT = 0.0f;
                            if (fB0 >= 0.0f)
                            {
                                fS = 0.0f;
                                fSqrDist = fC;
                            }
                            else if (-fB0 >= fA00)
                            {
                                fS = 1.0f;
                                fSqrDist = fA00 + (2.0f) * fB0 + fC;
                            }
                            else
                            {
                                fS = -fB0 / fA00;
                                fSqrDist = fB0 * fS + fC;
                            }
                        }
                    }
                    else
                    {
                        if (fT >= 0.0f)
                        {
                            if (fT <= fDet)  // region 1 (side)
                            {
                                fS = 1.0f;
                                fTmp = fA01 + fB1;
                                if (fTmp >= 0.0f)
                                {
                                    fT = 0.0f;
                                    fSqrDist = fA00 + (2.0f) * fB0 + fC;
                                }
                                else if (-fTmp >= fA11)
                                {
                                    fT = 1.0f;
                                    fSqrDist = fA00 + fA11 + fC + (2.0f) * (fB0 + fTmp);
                                }
                                else
                                {
                                    fT = -fTmp / fA11;
                                    fSqrDist = fTmp * fT + fA00 + (2.0f) * fB0 + fC;
                                }
                            }
                            else  // region 2 (corner)
                            {
                                fTmp = fA01 + fB0;
                                if (-fTmp <= fA00)
                                {
                                    fT = 1.0f;
                                    if (fTmp >= 0.0f)
                                    {
                                        fS = 0.0f;
                                        fSqrDist = fA11 + (2.0f) * fB1 + fC;
                                    }
                                    else
                                    {
                                        fS = -fTmp / fA00;
                                        fSqrDist = fTmp * fS + fA11 + (2.0f) * fB1 + fC;
                                    }
                                }
                                else
                                {
                                    fS = 1.0f;
                                    fTmp = fA01 + fB1;
                                    if (fTmp >= 0.0f)
                                    {
                                        fT = 0.0f;
                                        fSqrDist = fA00 + (2.0f) * fB0 + fC;
                                    }
                                    else if (-fTmp >= fA11)
                                    {
                                        fT = 1.0f;
                                        fSqrDist = fA00 + fA11 + fC +
                                          (2.0f) * (fB0 + fTmp);
                                    }
                                    else
                                    {
                                        fT = -fTmp / fA11;
                                        fSqrDist = fTmp * fT + fA00 + (2.0f) * fB0 + fC;
                                    }
                                }
                            }
                        }
                        else  // region 8 (corner)
                        {
                            if (-fB0 < fA00)
                            {
                                fT = 0.0f;
                                if (fB0 >= 0.0f)
                                {
                                    fS = 0.0f;
                                    fSqrDist = fC;
                                }
                                else
                                {
                                    fS = -fB0 / fA00;
                                    fSqrDist = fB0 * fS + fC;
                                }
                            }
                            else
                            {
                                fS = 1.0f;
                                fTmp = fA01 + fB1;
                                if (fTmp >= 0.0f)
                                {
                                    fT = 0.0f;
                                    fSqrDist = fA00 + (2.0f) * fB0 + fC;
                                }
                                else if (-fTmp >= fA11)
                                {
                                    fT = 1.0f;
                                    fSqrDist = fA00 + fA11 + fC + (2.0f) * (fB0 + fTmp);
                                }
                                else
                                {
                                    fT = -fTmp / fA11;
                                    fSqrDist = fTmp * fT + fA00 + (2.0f) * fB0 + fC;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (fT >= 0.0f)
                    {
                        if (fT <= fDet)  // region 5 (side)
                        {
                            fS = 0.0f;
                            if (fB1 >= 0.0f)
                            {
                                fT = 0.0f;
                                fSqrDist = fC;
                            }
                            else if (-fB1 >= fA11)
                            {
                                fT = 1.0f;
                                fSqrDist = fA11 + (2.0f) * fB1 + fC;
                            }
                            else
                            {
                                fT = -fB1 / fA11;
                                fSqrDist = fB1 * fT + fC;
                            }
                        }
                        else  // region 4 (corner)
                        {
                            fTmp = fA01 + fB0;
                            if (fTmp < 0.0f)
                            {
                                fT = 1.0f;
                                if (-fTmp >= fA00)
                                {
                                    fS = 1.0f;
                                    fSqrDist = fA00 + fA11 + fC + (2.0f) * (fB1 + fTmp);
                                }
                                else
                                {
                                    fS = -fTmp / fA00;
                                    fSqrDist = fTmp * fS + fA11 + (2.0f) * fB1 + fC;
                                }
                            }
                            else
                            {
                                fS = 0.0f;
                                if (fB1 >= 0.0f)
                                {
                                    fT = 0.0f;
                                    fSqrDist = fC;
                                }
                                else if (-fB1 >= fA11)
                                {
                                    fT = 1.0f;
                                    fSqrDist = fA11 + (2.0f) * fB1 + fC;
                                }
                                else
                                {
                                    fT = -fB1 / fA11;
                                    fSqrDist = fB1 * fT + fC;
                                }
                            }
                        }
                    }
                    else   // region 6 (corner)
                    {
                        if (fB0 < 0.0f)
                        {
                            fT = 0.0f;
                            if (-fB0 >= fA00)
                            {
                                fS = 1.0f;
                                fSqrDist = fA00 + (2.0f) * fB0 + fC;
                            }
                            else
                            {
                                fS = -fB0 / fA00;
                                fSqrDist = fB0 * fS + fC;
                            }
                        }
                        else
                        {
                            fS = 0.0f;
                            if (fB1 >= 0.0f)
                            {
                                fT = 0.0f;
                                fSqrDist = fC;
                            }
                            else if (-fB1 >= fA11)
                            {
                                fT = 1.0f;
                                fSqrDist = fA11 + (2.0f) * fB1 + fC;
                            }
                            else
                            {
                                fT = -fB1 / fA11;
                                fSqrDist = fB1 * fT + fC;
                            }
                        }
                    }
                }
            }
            else
            {
                // line segments are parallel
                if (fA01 > 0.0f)
                {
                    // direction vectors form an obtuse angle
                    if (fB0 >= 0.0f)
                    {
                        fS = 0.0f;
                        fT = 0.0f;
                        fSqrDist = fC;
                    }
                    else if (-fB0 <= fA00)
                    {
                        fS = -fB0 / fA00;
                        fT = 0.0f;
                        fSqrDist = fB0 * fS + fC;
                    }
                    else
                    {
                        fB1 = -Vector3.Dot(kDiff, seg1.Delta);
                        fS = 1.0f;
                        fTmp = fA00 + fB0;
                        if (-fTmp >= fA01)
                        {
                            fT = 1.0f;
                            fSqrDist = fA00 + fA11 + fC + (2.0f) * (fA01 + fB0 + fB1);
                        }
                        else
                        {
                            fT = -fTmp / fA01;
                            fSqrDist = fA00 + (2.0f) * fB0 + fC + fT * (fA11 * fT +
                                                                      (2.0f) * (fA01 + fB1));
                        }
                    }
                }
                else
                {
                    // direction vectors form an acute angle
                    if (-fB0 >= fA00)
                    {
                        fS = 1.0f;
                        fT = 0.0f;
                        fSqrDist = fA00 + (2.0f) * fB0 + fC;
                    }
                    else if (fB0 <= 0.0f)
                    {
                        fS = -fB0 / fA00;
                        fT = 0.0f;
                        fSqrDist = fB0 * fS + fC;
                    }
                    else
                    {
                        fB1 = -Vector3.Dot(kDiff, seg1.Delta);
                        fS = 0.0f;
                        if (fB0 >= -fA01)
                        {
                            fT = 1.0f;
                            fSqrDist = fA11 + (2.0f) * fB1 + fC;
                        }
                        else
                        {
                            fT = -fB0 / fA01;
                            fSqrDist = fC + fT * ((2.0f) * fB1 + fA11 * fT);
                        }
                    }
                }
            }
            t0 = fS;
            t1 = fT;

            return System.Math.Abs(fSqrDist);
        }
Exemple #26
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            bool result;
            result = Intersection.SegmentSphereIntersection(out frac, seg, this);

            if (result)
            {
                pos = seg.GetPoint(frac);
                normal = pos - this.transform.Position;

                JiggleMath.NormalizeSafe(ref normal);
            }
            else
            {
                pos = Vector3.Zero;
                normal = Vector3.Zero;
            }

            return result;
        }
Exemple #27
0
 /// <summary>
 /// Must support intersection with a segment (ray cast)
 /// </summary>
 /// <param name="frac"></param>
 /// <param name="pos"></param>
 /// <param name="normal"></param>
 /// <param name="seg"></param>
 /// <returns>bool</returns>
 public abstract bool SegmentIntersect(out float frac,out Vector3 pos,
     out Vector3 normal,Segment seg);
        /// <summary>
        /// GetBoxTriangleIntersectionPoints
        /// Pushes intersection points onto the back of pts. Returns the
        /// number of points found.
        /// Points that are close together (compared to 
        /// combinationDistance) get combined
        /// </summary>
        /// <param name="pts"></param>
        /// <param name="box"></param>
        /// <param name="triangle"></param>
        /// <param name="combinationDistance"></param>
        /// <returns></returns>
        private static int GetBoxTriangleIntersectionPoints(List<Vector3> pts, Box box, Triangle triangle, float combinationDistance)
        {
            // first intersect each edge of the box with the triangle
            Box.Edge[] edges;
            box.GetEdges(out edges);
            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);

            float tS;
            float tv1, tv2;

            int iEdge;
            for (iEdge = 0; iEdge < 12; ++iEdge)
            {
                Box.Edge edge = edges[iEdge];
                Segment seg = new Segment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]);
                if (Intersection.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle))
                {
                     AddPoint(pts, seg.GetPoint(tS), combinationDistance * combinationDistance);
                }
            }

            Vector3 pos, n;
            // now each edge of the triangle with the box
            for (iEdge = 0; iEdge < 3; ++iEdge)
            {
                Vector3 pt0 = triangle.GetPoint(iEdge);
                Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3);
                Segment s1 = new Segment(pt0, pt1 - pt0);
                Segment s2 = new Segment(pt1, pt0 - pt1);
                if (box.SegmentIntersect(out tS, out pos, out n, s1))
                    AddPoint(pts, pos, combinationDistance * combinationDistance);
                if (box.SegmentIntersect(out tS, out pos, out n, s2))
                    AddPoint(pts, pos, combinationDistance * combinationDistance);
            }

            return pts.Count;
        }
Exemple #29
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal,Segment seg)
        {
            frac = 0;
            pos = Vector3.Zero;
            normal = Vector3.Up;

            //if (seg.Delta.Y > -JiggleMath.Epsilon )
            //    return false;

            Vector3 normalStart;
            float heightStart;

            GetHeightAndNormal(out heightStart, out normalStart,seg.Origin);

            if (heightStart < 0.0f)
                return false;

            Vector3 normalEnd;
            float heightEnd;
            Vector3 end = seg.GetEnd();
            GetHeightAndNormal(out heightEnd, out normalEnd,end);

            if (heightEnd > 0.0f)
                return false;

            // start is above, end is below...
            float depthEnd = -heightEnd;

            // normal is the weighted mean of these...
            float weightStart = 1.0f / (JiggleMath.Epsilon + heightStart);
            float weightEnd = 1.0f / (JiggleMath.Epsilon + depthEnd);

            normal = (normalStart * weightStart + normalEnd * weightEnd) /
              (weightStart + weightEnd);

            frac = heightStart / (heightStart + depthEnd + JiggleMath.Epsilon);

            pos = seg.GetPoint(frac);

            return true;
        }
        public override bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Microsoft.Xna.Framework.Vector3 posOut, out Microsoft.Xna.Framework.Vector3 normalOut, JigLibX.Geometry.Segment seg, CollisionSkinPredicate1 collisionPredicate)
        {
            fracOut = float.MaxValue;
            skinOut = null;
            posOut  = normalOut = Vector3.Zero;

            Vector3 min = seg.GetPoint(0);
            Vector3 tmp = seg.GetEnd();
            Vector3 max;

            Vector3.Max(ref min, ref tmp, out max);
            Vector3.Min(ref min, ref tmp, out min);

            BoundingBox box = new BoundingBox(min, max);
            float       frac;
            Vector3     pos;
            Vector3     normal;

            active_.Clear();
            Extract(min, max, active_);

            int nActive = active_.Count;

            for (int i = 0; i != nActive; ++i)
            {
                CollisionSkin skin = active_[i];
                if (collisionPredicate == null || collisionPredicate.ConsiderSkin(skin))
                {
                    if (BoundingBoxHelper.OverlapTest(ref box, ref skin.WorldBoundingBox))
                    {
                        if (skin.SegmentIntersect(out frac, out pos, out normal, seg))
                        {
                            if (frac >= 0 && frac < fracOut)
                            {
                                fracOut   = frac;
                                skinOut   = skin;
                                posOut    = pos;
                                normalOut = normal;
                            }
                        }
                    }
                }
            }
            return(fracOut <= 1);
        }
Exemple #31
0
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            bool result;
            if (result = Intersection.SegmentPlaneIntersection(out frac, seg, this))
            {
                pos = seg.GetPoint(frac);
                normal = this.Normal;
            }
            else
            {
                pos = Vector3.Zero;
                normal = Vector3.Zero;
            }

            return result;
        }
        /// <summary>
        /// CollDetect
        /// </summary>
        /// <param name="infoOrig"></param>
        /// <param name="collTolerance"></param>
        /// <param name="collisionFunctor"></param>
        public override void CollDetect(CollDetectInfo infoOrig, float collTolerance, CollisionFunctor collisionFunctor)
        {
            CollDetectInfo info = infoOrig;

            // get the skins in the order that we're expecting
            if (info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0).Type == this.Type1)
            {
                CollisionSkin skinSwap = info.Skin0;
                info.Skin0 = info.Skin1;
                info.Skin1 = skinSwap;
                int primSwap = info.IndexPrim0;
                info.IndexPrim0 = info.IndexPrim1;
                info.IndexPrim1 = primSwap;
            }

            Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            // todo - proper swept test
            Sphere oldSphere = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Sphere;
            Sphere newSphere = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Sphere;

            Capsule oldCapsule = info.Skin1.GetPrimitiveOldWorld(info.IndexPrim1) as Capsule;
            Capsule newCapsule = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as Capsule;

            Segment oldSeg = new Segment(oldCapsule.Position, oldCapsule.Length * oldCapsule.Orientation.Backward());
            Segment newSeg = new Segment(oldCapsule.Position, newCapsule.Length * newCapsule.Orientation.Backward());

            float radSum = newCapsule.Radius + newSphere.Radius;

            float oldt, newt;
            float oldDistSq = Distance.PointSegmentDistanceSq(out oldt, oldSphere.Position, oldSeg);
            float newDistSq = Distance.PointSegmentDistanceSq(out newt, newSphere.Position, newSeg);

            if (OpenTKHelper.Min(oldDistSq, newDistSq) < (radSum + collTolerance) * (radSum + collTolerance))
            {
                Vector3 segPos = oldSeg.GetPoint(oldt);
                Vector3 delta = oldSphere.Position - segPos;

                float dist = (float)System.Math.Sqrt((float)oldDistSq);
                float depth = radSum - dist;

                if (dist > JiggleMath.Epsilon)
                {
                    delta /= dist;
                }
                else
                {
                    // todo - make this not random
                    delta = Vector3Extensions.TransformNormal(Vector3Extensions.Backward, Matrix4.CreateFromAxisAngle(Vector3Extensions.Up, OpenTKHelper.ToRadians(random.Next(360))));
                }

                Vector3 worldPos = segPos +
                    ((oldCapsule.Radius - 0.5f * depth) * delta);
                unsafe
                {
                    SmallCollPointInfo collInfo = new SmallCollPointInfo(worldPos - body0Pos,
                        worldPos - body1Pos, depth);

                    collisionFunctor.CollisionNotify(ref info, ref delta, &collInfo, 1);
                }
            }
        }