Example #1
0
 public void Render3D(Location pos, float rot, Location size)
 {
     BEPUutilities.Matrix rot1 = BEPUutilities.Matrix.CreateFromAxisAngle(BEPUutilities.Vector3.UnitZ, rot)
                                 * BEPUutilities.Matrix.CreateFromAxisAngle(BEPUutilities.Vector3.UnitX, (float)(Math.PI * 0.25));
     if (RenderedBlock != null)
     {
         TheClient.isVox = false;
         TheClient.SetVox();
         TheClient.Rendering.SetMinimumLight(0.9f, TheClient.MainWorldView);
         RenderedBlock.WorldTransform = BEPUutilities.Matrix.CreateScale(size.ToBVector() * 0.70f)
                                        * rot1
                                        * BEPUutilities.Matrix.CreateTranslation(pos.ToBVector());
         RenderedBlock.Render();
         TheClient.Rendering.SetMinimumLight(0f, TheClient.MainWorldView);
     }
     else if (RenderedModel != null)
     {
         TheClient.isVox = true;
         TheClient.SetEnts();
         TheClient.Rendering.SetMinimumLight(0.9f, TheClient.MainWorldView);
         BEPUutilities.RigidTransform rt = BEPUutilities.RigidTransform.Identity;
         RenderedModel.Shape.GetBoundingBox(ref rt, out BEPUutilities.BoundingBox bb);
         BEPUutilities.Vector3 scale = BEPUutilities.Vector3.Max(bb.Max, -bb.Min);
         float len = (float)scale.Length();
         RenderedModel.WorldTransform = BEPUutilities.Matrix.CreateScale(size.ToBVector() * len)
                                        * rot1
                                        * BEPUutilities.Matrix.CreateTranslation(pos.ToBVector());
         RenderedModel.RenderSimpler();
         TheClient.Rendering.SetMinimumLight(0f, TheClient.MainWorldView);
     }
 }
Example #2
0
        ///<summary>
        /// Casts a fat (sphere expanded) ray against the shape.  If the raycast appears to be stuck in the shape, the cast will be attempted
        /// with a smaller ray (scaled by the MotionSettings.CoreShapeScaling each time).
        ///</summary>
        ///<param name="ray">Ray to test against the shape.</param>
        ///<param name="radius">Radius of the ray.</param>
        ///<param name="target">Shape to test against.</param>
        ///<param name="shapeTransform">Transform to apply to the shape for the test.</param>
        ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        ///<param name="hit">Hit data of the sphere cast, if any.</param>
        ///<returns>Whether or not the sphere cast hit the shape.</returns>
        public static bool CCDSphereCast(Ray ray, float radius, ConvexShape target, ref RigidTransform shapeTransform, float maximumLength,
                                         out RayHit hit)
        {
            int iterations = 0;

            while (true)
            {
                if (GJKToolbox.SphereCast(ray, radius, target, ref shapeTransform, maximumLength, out hit) &&
                    hit.T > 0)
                {
                    //The ray cast isn't embedded in the shape, and it's less than maximum length away!
                    return(true);
                }
                if (hit.T > maximumLength || hit.T < 0)
                {
                    return(false); //Failure showed it was too far, or behind.
                }
                radius *= MotionSettings.CoreShapeScaling;
                iterations++;
                if (iterations > 3) //Limit could be configurable.
                {
                    //It's iterated too much, let's just do a last ditch attempt using a raycast and hope that can help.
                    return(GJKToolbox.RayCast(ray, target, ref shapeTransform, maximumLength, out hit) && hit.T > 0);
                }
            }
        }
Example #3
0
 public override void Render()
 {
     if (!Visible)
     {
         return;
     }
     TheClient.SetEnts();
     BEPUutilities.RigidTransform rt = new BEPUutilities.RigidTransform(GetPosition().ToBVector(), GetOrientation());
     BEPUutilities.Vector3 bmin;
     BEPUutilities.Vector3 bmax;
     BEPUutilities.RigidTransform.Transform(ref ModelMin, ref rt, out bmin);
     BEPUutilities.RigidTransform.Transform(ref ModelMax, ref rt, out bmax);
     if (TheClient.MainWorldView.CFrust != null && !TheClient.MainWorldView.CFrust.ContainsBox(bmin, bmax))
     {
         return;
     }
     Matrix4d orient = GetOrientationMatrix();
     Matrix4d mat = (Matrix4d.Scale(ClientUtilities.ConvertD(scale)) * orient * Matrix4d.CreateTranslation(ClientUtilities.ConvertD(GetPosition())));
     TheClient.MainWorldView.SetMatrix(2, mat);
     TheClient.Rendering.SetMinimumLight(0.0f);
     if (model.Meshes[0].vbo.Tex == null)
     {
         TheClient.Textures.White.Bind();
     }
     model.Draw(); // TODO: Animation?
 }
Example #4
0
        public override void Render()
        {
            if (!Visible)
            {
                return;
            }
            TheClient.SetEnts();
            BEPUutilities.RigidTransform rt = new BEPUutilities.RigidTransform(GetPosition().ToBVector(), GetOrientation());
            BEPUutilities.Vector3        bmin;
            BEPUutilities.Vector3        bmax;
            BEPUutilities.RigidTransform.Transform(ref ModelMin, ref rt, out bmin);
            BEPUutilities.RigidTransform.Transform(ref ModelMax, ref rt, out bmax);
            if (TheClient.MainWorldView.CFrust != null && !TheClient.MainWorldView.CFrust.ContainsBox(bmin, bmax))
            {
                return;
            }
            Matrix4d orient = GetOrientationMatrix();
            Matrix4d mat    = (Matrix4d.Scale(ClientUtilities.ConvertD(scale)) * orient * Matrix4d.CreateTranslation(ClientUtilities.ConvertD(GetPosition())));

            TheClient.MainWorldView.SetMatrix(2, mat);
            TheClient.Rendering.SetMinimumLight(0.0f);
            if (model.Meshes[0].vbo.Tex == null)
            {
                TheClient.Textures.White.Bind();
            }
            model.Draw(); // TODO: Animation?
        }
Example #5
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
        /// in the entry, this filter will be passed into inner ray casts.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayHit hit)
        {
            RayCastResult result;
            bool          toReturn = Shape.ConvexCast(castShape, ref startingTransform, ref sweep, filter, out result);

            hit = result.HitData;
            return(toReturn);
        }
Example #6
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            hit = new RayHit();
            BoundingBox boundingBox;

            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref worldTransform, ref sweep, out boundingBox);
            var tri         = PhysicsThreadResources.GetTriangle();
            var hitElements = CommonResources.GetIntList();

            if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    AffineTransform.Transform(ref tri.vA, ref worldTransform, out tri.vA);
                    AffineTransform.Transform(ref tri.vB, ref worldTransform, out tri.vB);
                    AffineTransform.Transform(ref tri.vC, ref worldTransform, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.MaximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    tri.MaximumRadius   = (float)Math.Sqrt(tri.MaximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform {
                        Orientation = Quaternion.Identity, Position = center
                    };
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.MaximumRadius = 0;
                PhysicsThreadResources.GiveBack(tri);
                CommonResources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            PhysicsThreadResources.GiveBack(tri);
            CommonResources.GiveBack(hitElements);
            return(false);
        }
Example #7
0
        ///<summary>
        /// Gets the closest points between the shapes.
        ///</summary>
        ///<param name="shapeA">First shape of the pair.</param>
        ///<param name="shapeB">Second shape of the pair.</param>
        ///<param name="transformA">Transform to apply to the first shape.</param>
        ///<param name="transformB">Transform to apply to the second shape.</param>
        /// <param name="cachedSimplex">Simplex from a previous updated used to warmstart the current attempt.  Updated after each run.</param>
        ///<param name="closestPointA">Closest point on the first shape to the second shape.</param>
        ///<param name="closestPointB">Closest point on the second shape to the first shape.</param>
        ///<returns>Whether or not the objects were intersecting.  If they are intersecting, then the closest points cannot be identified.</returns>
        public static bool GetClosestPoints(ConvexShape shapeA, ConvexShape shapeB, ref RigidTransform transformA, ref RigidTransform transformB,
                                            ref CachedSimplex cachedSimplex, out Vector3 closestPointA, out Vector3 closestPointB)
        {
            RigidTransform localtransformB;

            MinkowskiToolbox.GetLocalTransform(ref transformA, ref transformB, out localtransformB);

            bool toReturn = GetClosestPoints(shapeA, shapeB, ref localtransformB, ref cachedSimplex, out closestPointA, out closestPointB);

            RigidTransform.Transform(ref closestPointA, ref transformA, out closestPointA);
            RigidTransform.Transform(ref closestPointB, ref transformA, out closestPointB);
            return(toReturn);
        }
Example #8
0
        public override void Fire()
        {
            const float ATTACK_RADIUS = 3.0f;
            const float ATTACK_LENGTH = 4.0f;
            // Play 'thwack' sound
            Actor owner = GameResources.ActorManager.GetActorById(OwnerActorId);
            BipedControllerComponent bipedControl = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            RigidTransform           alignCapsule = new RigidTransform(BepuVec3.Forward * ATTACK_LENGTH * 0.5f + BepuConverter.Convert(MuzzleOffset),
                                                                       BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2));

            Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value :
                           BepuConverter.Convert(bipedControl.Controller.ViewDirection));
            RigidTransform positionAndAim = new RigidTransform(bipedControl.Controller.Body.Position, BepuConverter.Convert(
                                                                   SpaceUtils.GetOrientation(aim, Vector3.Up)));

            RigidTransform attackTransform;

            RigidTransform.Transform(ref alignCapsule, ref positionAndAim, out attackTransform);

            ConvexShape          bashShape   = new CapsuleShape(ATTACK_LENGTH, ATTACK_RADIUS);
            BepuVec3             noSweep     = BepuVec3.Zero;
            List <RayCastResult> dudesBashed = new List <RayCastResult>();
            AttackFilter         filter      = new AttackFilter(GameResources.ActorManager.IsMob(OwnerActorId));

            GameResources.ActorManager.SimSpace.ConvexCast(bashShape, ref attackTransform, ref noSweep, filter.Test, dudesBashed);

            foreach (RayCastResult dude in dudesBashed)
            {
                EntityCollidable otherEntityCollidable = dude.HitObject as EntityCollidable;
                Terrain          otherTerrain          = dude.HitObject as Terrain;
                if (otherEntityCollidable != null &&
                    otherEntityCollidable.Entity != null &&
                    otherEntityCollidable.Entity.Tag != null)
                {
                    Actor      actorHit = GameResources.ActorManager.GetActorById((int)(otherEntityCollidable.Entity.Tag));
                    IDamagable damage   = actorHit.GetBehaviorThatImplementsType <IDamagable>();
                    if (damage != null)
                    {
                        damage.TakeDamage(Damage);
                        // TODO: P2: Query hit actor for appropiate damage effect e.g. blood and create it;
                    }
                    BashDust(dude.HitData.Location);
                }
                else if (otherTerrain != null)
                {
                    BashDust(dude.HitData.Location);
                }
            }
        }
Example #9
0
        ///<summary>
        /// Gets the closest points between the shapes.
        ///</summary>
        ///<param name="shapeA">First shape of the pair.</param>
        ///<param name="shapeB">Second shape of the pair.</param>
        ///<param name="transformA">Transform to apply to the first shape.</param>
        ///<param name="transformB">Transform to apply to the second shape.</param>
        ///<param name="closestPointA">Closest point on the first shape to the second shape.</param>
        ///<param name="closestPointB">Closest point on the second shape to the first shape.</param>
        ///<returns>Whether or not the objects were intersecting.  If they are intersecting, then the closest points cannot be identified.</returns>
        public static bool GetClosestPoints(ConvexShape shapeA, ConvexShape shapeB, ref RigidTransform transformA, ref RigidTransform transformB,
                                            out Vector3 closestPointA, out Vector3 closestPointB)
        {
            //The cached simplex stores locations that are local to the shapes.  A fairly decent initial state is between the centroids of the objects.
            //In local space, the centroids are at the origins.

            RigidTransform localtransformB;

            MinkowskiToolbox.GetLocalTransform(ref transformA, ref transformB, out localtransformB);

            var simplex = new CachedSimplex {
                State = SimplexState.Point
            };
            // new CachedSimplex(shapeA, shapeB, ref localtransformB);
            bool toReturn = GetClosestPoints(shapeA, shapeB, ref localtransformB, ref simplex, out closestPointA, out closestPointB);

            RigidTransform.Transform(ref closestPointA, ref transformA, out closestPointA);
            RigidTransform.Transform(ref closestPointB, ref transformA, out closestPointB);
            return(toReturn);
        }
Example #10
0
        private static bool GetClosestPoints(ConvexShape shapeA, ConvexShape shapeB, ref RigidTransform localTransformB,
                                             ref CachedSimplex cachedSimplex, out Vector3 localClosestPointA, out Vector3 localClosestPointB)
        {
            var simplex = new PairSimplex(ref cachedSimplex, ref localTransformB);

            Vector3 closestPoint;
            int     count = 0;

            while (true)
            {
                if (simplex.GetPointClosestToOrigin(out closestPoint) || //Also reduces the simplex and computes barycentric coordinates if necessary.
                    closestPoint.LengthSquared() <= Toolbox.Epsilon * simplex.errorTolerance)
                {
                    //Intersecting.
                    localClosestPointA = Toolbox.ZeroVector;
                    localClosestPointB = Toolbox.ZeroVector;

                    simplex.UpdateCachedSimplex(ref cachedSimplex);
                    return(true);
                }

                if (++count > MaximumGJKIterations)
                {
                    break; //Must break BEFORE a new vertex is added if we're over the iteration limit.  This guarantees final simplex is not a tetrahedron.
                }
                if (simplex.GetNewSimplexPoint(shapeA, shapeB, count, ref closestPoint))
                {
                    //No progress towards origin, not intersecting.
                    break;
                }
            }
            //Compute closest points from the contributing simplexes and barycentric coordinates
            simplex.GetClosestPoints(out localClosestPointA, out localClosestPointB);
            //simplex.VerifyContributions();
            //if (Vector3.Distance(localClosestPointA - localClosestPointB, closestPoint) > .00001f)
            //    Debug.WriteLine("break.");
            simplex.UpdateCachedSimplex(ref cachedSimplex);
            return(false);
        }
Example #11
0
 ///<summary>
 /// Sweeps a shape against another shape using a given sweep vector.
 ///</summary>
 ///<param name="sweptShape">Shape to sweep.</param>
 ///<param name="target">Shape being swept against.</param>
 ///<param name="sweep">Sweep vector for the sweptShape.</param>
 ///<param name="startingSweptTransform">Starting transform of the sweptShape.</param>
 ///<param name="targetTransform">Transform to apply to the target shape.</param>
 ///<param name="hit">Hit data of the sweep test, if any.</param>
 ///<returns>Whether or not the swept shape hit the other shape.</returns>
 public static bool ConvexCast(ConvexShape sweptShape, ConvexShape target, ref Vector3 sweep, ref RigidTransform startingSweptTransform, ref RigidTransform targetTransform,
                               out RayHit hit)
 {
     return(ConvexCast(sweptShape, target, ref sweep, ref Toolbox.ZeroVector, ref startingSweptTransform, ref targetTransform, out hit));
 }
Example #12
0
        // Steer away from obstacles in the way. This method returns a zero vector if no correction is required.
        // It should be high priority and the steering from other behaviors should blend into the remaining space.
        // So if this returns a length 1.0f vector, avoiding the obstacle is most urgent and there is no room for other
        // steering.
        private Vector2 AvoidObstacles(Actor owner)
        {
            BipedControllerComponent bcc = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            // Conditions where we do not want to use this steering force.
            if (GetAngleFromVertical(bcc.Controller.Body.LinearVelocity) < MathHelper.PiOver4 ||    // We're probably falling...
                !bcc.Controller.SupportFinder.HasSupport ||
                !bcc.Controller.SupportFinder.HasTraction)
            {
                return(Vector2.Zero);
            }

            // Sphere cast ahead along facing.
            List <RayCastResult> obstacles          = new List <RayCastResult>();
            SphereShape          probe              = new SphereShape(bcc.Controller.BodyRadius * 1.1f);
            RigidTransform       probeStartPosition = new RigidTransform(bcc.Controller.Body.Position);
            // Add a small constant to the probe length because we want a minimum amount of forward probing, even if we are not moving.
            float          probeLength = Math.Max(BepuVec3.Dot(bcc.Controller.Body.LinearVelocity, bcc.Controller.ViewDirection), 0.0f) + 1.0f;
            BepuVec3       probeSweep  = bcc.Controller.ViewDirection * probeLength;
            ObstacleFilter filter      = new ObstacleFilter(bcc.Controller.Body.CollisionInformation);

            GameResources.ActorManager.SimSpace.ConvexCast(probe, ref probeStartPosition, ref probeSweep, filter.Test, obstacles);

            RayCastDistanceComparer rcdc = new RayCastDistanceComparer();

            obstacles.Sort(rcdc);

            BEPUutilities.Vector3 cross = BEPUutilities.Vector3.Zero;
            int obstacleIndex           = 0;

            do
            {
                if (obstacles.Count == obstacleIndex)
                {
                    return(Vector2.Zero);
                }

                cross = BEPUutilities.Vector3.Cross(bcc.Controller.ViewDirection, -obstacles[obstacleIndex++].HitData.Normal);
            }while (cross.X > 0.7f); // if cross.X > 0.7f, the obstacle is some kind of gentle ramp; ignore it.

            // dot will typically be negative and magnitude indicates how directly ahead the obstacle is.
            float dot = BEPUutilities.Vector3.Dot(bcc.Controller.ViewDirection, -obstacles[0].HitData.Normal);

            if (dot >= 0.0f) // The obstacle won't hinder us if we touch it.
            {
                return(Vector2.Zero);
            }

            // When cross.Y is positive, the object is generally to the right, so veer left (and vice versa).
            float directionSign = cross.Y >= 0.0f ? -1.0f : 1.0f;

            BEPUutilities.Vector2 result = BEPUutilities.Vector2.UnitX * directionSign * -dot;

            // Also scale response by how close the obstacle is.
            float distance = (obstacles[0].HitData.Location - bcc.Controller.Body.Position).Length();

            result *= MathHelper.Clamp((1.0f - distance / probeLength), 0.0f, 1.0f); // / Math.Abs(dot);


            // So far the result is in terms of 'velocity space'. Rotate it to align with the controller facing.
            float velocityTheta = (float)(Math.Atan2(-probeSweep.X, -probeSweep.Z));

            BEPUutilities.Matrix2x2 velocityWorld = SpaceUtils.Create2x2RotationMatrix(velocityTheta);
            float facingTheta = (float)(Math.Atan2(-bcc.Controller.HorizontalViewDirection.X, -bcc.Controller.HorizontalViewDirection.Z));

            BEPUutilities.Matrix2x2 facingWorldInv = SpaceUtils.Create2x2RotationMatrix(facingTheta);
            facingWorldInv.Transpose(); // We want the transpose/inverse of the facing transform because we want to transform the movement into 'facing space'.

            return(BepuConverter.Convert(SpaceUtils.TransformVec2(SpaceUtils.TransformVec2(result, velocityWorld), facingWorldInv)));
        }
Example #13
0
        private void ProcessAIStepHandler(object sender, UpdateStepEventArgs e)
        {
            // Check FOV, add any new foes to memory. And update existing ones. We may also have gained new memories by other means.

            // Get players and mobs in field of vision:
            List <RayCastResult> actorsInView = new List <RayCastResult>();

            ConeShape visionCone                 = new ConeShape(VisionDistance, VisionDistance);
            BipedControllerComponent bcc         = Owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            RigidTransform           tipOverCone = new RigidTransform(BepuVec3.Forward * VisionDistance * 0.75f,
                                                                      BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2));
            RigidTransform eyeLevelAndFacing = new RigidTransform(bcc.Controller.Body.Position - bcc.Controller.Down * bcc.Controller.Body.Height * 0.45f,
                                                                  BepuConverter.Convert(SpaceUtils.GetOrientation(BepuConverter.Convert(bcc.Controller.ViewDirection), Vector3.Up)));
            RigidTransform visionConeTransform;

            RigidTransform.Transform(ref tipOverCone, ref eyeLevelAndFacing, out visionConeTransform);
            BepuVec3           noSweep = BepuVec3.Zero;
            ViewInterestFilter filter  = new ViewInterestFilter(bcc.Controller.Body.CollisionInformation);

            GameResources.ActorManager.SimSpace.ConvexCast(visionCone, ref visionConeTransform, ref noSweep, filter.Test, actorsInView);

            for (int a = 0; a < actorsInView.Count; ++a)
            {
                // Does this actor warrant an addition to be made to our memory?
                // If so, check for LOS and recheck range. If those tests pass, modify the memory.
                EntityCollidable otherEntityCollidable = actorsInView[a].HitObject as EntityCollidable;
                // We can jump to the Id in the Tag property because we know the filter has validated this.
                int   actorId     = (int)(otherEntityCollidable.Entity.Tag);
                Actor viewedActor = GameResources.ActorManager.GetActorById(actorId);
                BipedControllerComponent viewedActorBcc = viewedActor.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
                BepuVec3 toSubject = viewedActorBcc.Controller.Body.Position - eyeLevelAndFacing.Position;

                // Check range:
                if (toSubject.LengthSquared() <= VisionDistance * VisionDistance)
                {
                    BepuRay losRay = new BepuRay(eyeLevelAndFacing.Position, toSubject);

                    RayCastResult losResult;
                    LOSFilter     losFilter = new LOSFilter(bcc.Controller.Body.CollisionInformation, otherEntityCollidable);
                    GameResources.ActorManager.SimSpace.RayCast(losRay, VisionDistance, losFilter.Test, out losResult);
                    EntityCollidable losEC = losResult.HitObject as EntityCollidable;

                    // Test for LOS:
                    if (losEC != null &&
                        losEC.Entity != null &&
                        losEC.Entity.Tag != null &&
                        (int)(losEC.Entity.Tag) == actorId)
                    {
                        // The viewed actor is either a player(foe) or a mob(ally).
                        if (GameResources.ActorManager.IsPlayer(actorId))
                        {
                            mMemory.SpotFoe(actorId);
                        }
                        else
                        {
                            IAgentStateManager agent = viewedActor.GetBehaviorThatImplementsType <IAgentStateManager>();
                            if (agent != null &&
                                agent.HasProperty(AgentPropertyName.ActiveOpponent))
                            {
                                int mobFoe = agent.GetProperty <int>(AgentPropertyName.ActiveOpponent);
                                mMemory.SenseFoe(mobFoe);
                            }
                        }
                    }
                }
            }

            // Evaluate current threats and select one to engage:
            int enemyId = mMemory.GetLargestThreat();

            if (enemyId != Actor.INVALID_ACTOR_ID)
            {
                if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent))
                {
                    if ((int)(mAgentProperties[AgentPropertyName.ActiveOpponent]) != enemyId)
                    {
                        mAgentProperties[AgentPropertyName.ActiveOpponent] = enemyId;
                    }
                }
                else
                {
                    mAgentProperties.Add(AgentPropertyName.ActiveOpponent, enemyId);
                }
            }
            else
            {
                if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent))
                {
                    mAgentProperties.Remove(AgentPropertyName.ActiveOpponent);
                }
            }

            TimeInState += e.GameTime.ElapsedGameTime;
            CurrentState.Update(mSteering, Owner, this);
            Vector2 locomotion = mSteering.ComputeForce(Owner);

            if (locomotion.LengthSquared() == 0.0f)
            {
                bcc.OrientationChange  = Quaternion.Identity;
                bcc.HorizontalMovement = Vector2.Zero;
            }
            else
            {
                bcc.OrientationChange  = Quaternion.CreateFromAxisAngle(Vector3.Up, (float)(Math.Atan2(-locomotion.X, locomotion.Y)));
                bcc.HorizontalMovement = locomotion.Length() * Vector2.UnitY;
            }

            mMemory.Fade(e.GameTime);
        }
Example #14
0
        public void ImpactHandler(object sender, UpdateStepEventArgs e)
        {
            GameResources.ActorManager.PostPhysicsUpdateStep -= ImpactHandler;
            // TODO: P2: Some boooom sound effects...

            TransformComponent myXForm = Owner.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);
            // Do a sphere cast to get actors in the blast radius
            List <RayCastResult> inRangeActors = new List <RayCastResult>();
            SphereShape          blastZone     = new SphereShape(mBlastRadius);
            RigidTransform       blastPosition = new RigidTransform(BepuConverter.Convert(myXForm.Translation));

            BEPUutilities.Vector3 bepuZero = BEPUutilities.Vector3.Zero;
            GameResources.ActorManager.SimSpace.ConvexCast(blastZone, ref blastPosition, ref bepuZero, inRangeActors);

            RayCastDistanceComparer rcdc = new RayCastDistanceComparer();

            for (int a = 0; a < inRangeActors.Count; ++a)
            {
                EntityCollidable inRangeEntityCollidable = inRangeActors[a].HitObject as EntityCollidable;
                if (inRangeEntityCollidable != null &&
                    inRangeEntityCollidable.Entity != null &&
                    inRangeEntityCollidable.Entity.Tag != null)
                {
                    Actor      blastedActor = GameResources.ActorManager.GetActorById((int)(inRangeEntityCollidable.Entity.Tag));
                    IDamagable actorDamage  = blastedActor.GetBehaviorThatImplementsType <IDamagable>();
                    DynamicCollisionComponent actorCollidable = blastedActor.GetComponent <DynamicCollisionComponent>(ActorComponent.ComponentType.Physics);
                    BepuVec3 blastToActorCenter = actorCollidable.Entity.Position - blastPosition.Position;
                    BepuRay  loeRay             = new BepuRay(blastPosition.Position, blastToActorCenter);
                    bool     hasCover           = false;
                    float    distance           = mBlastRadius;
                    if (actorDamage != null || (actorCollidable != null && actorCollidable.IsDynamic && !(actorCollidable.Entity.CollisionInformation.CollisionRules.Personal.HasFlag(BEPUphysics.CollisionRuleManagement.CollisionRule.NoSolver))))
                    {
                        List <RayCastResult> loeResults = new List <RayCastResult>();
                        GameResources.ActorManager.SimSpace.RayCast(loeRay, mBlastRadius, loeResults);
                        loeResults.Sort(rcdc);

                        for (int c = 0; c < loeResults.Count; ++c)
                        {
                            EntityCollidable possibleCover = loeResults[c].HitObject as EntityCollidable;
                            if (possibleCover != null &&
                                possibleCover.Entity == inRangeEntityCollidable.Entity)
                            {
                                // Hit
                                distance = loeResults[c].HitData.T;
                                break;
                            }
                            Terrain possibleCoverTerrain = loeResults[c].HitObject as Terrain;
                            if (possibleCoverTerrain != null)
                            {
                                hasCover = true;
                                break;
                            }
                            if (possibleCover != null &&
                                possibleCover.Entity != null &&
                                !possibleCover.Entity.IsDynamic)
                            {
                                hasCover = true;
                                break;
                            }
                        }
                    }

                    if (!hasCover && actorDamage != null)
                    {
                        actorDamage.TakeDamage((int)(MathHelper.Lerp(1.0f, 0.25f, distance / mBlastRadius) * mDamage));
                    }

                    if (!hasCover && actorCollidable != null && actorCollidable.IsDynamic && !(actorCollidable.Entity.CollisionInformation.CollisionRules.Personal.HasFlag(BEPUphysics.CollisionRuleManagement.CollisionRule.NoSolver)))
                    {
                        blastToActorCenter.Normalize();
                        blastToActorCenter = blastToActorCenter * 1200; // Math.Min(5000.0f / (distance + 1.0f));
                        actorCollidable.Entity.ApplyLinearImpulse(ref blastToActorCenter);
                        if (!actorCollidable.Entity.ActivityInformation.IsActive)
                        {
                            actorCollidable.Entity.ActivityInformation.Activate();
                        }
                    }
                }
            }

            DynamicCollisionComponent dcc = Owner.GetComponent <DynamicCollisionComponent>(ActorComponent.ComponentType.Physics);
            Vector3            myVelocity = BepuConverter.Convert(dcc.Entity.LinearVelocity);
            Actor              fireball   = GameResources.ActorManager.SpawnTemplate("ExplosionFire");
            TransformComponent fireXForm  = fireball.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);

            fireXForm.Translation = myXForm.Translation;
            ExplosionFire fireBehavior = fireball.GetBehavior <ExplosionFire>();

            fireBehavior.Emit(myVelocity);
            Actor smoke = GameResources.ActorManager.SpawnTemplate("ExplosionSmoke");
            TransformComponent smokeXForm = smoke.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);

            smokeXForm.Translation = myXForm.Translation;
            ExplosionSmoke smokeBehavior = smoke.GetBehavior <ExplosionSmoke>();

            smokeBehavior.Emit(myVelocity);

            Owner.Despawn();
        }
Example #15
0
 public override bool ConvexCast(ConvexShape castShape, ref BEPUutilities.RigidTransform startingTransform, ref BEPUutilities.Vector3 sweep, out BEPUutilities.RayHit hit)
 {
     throw new NotImplementedException();
 }
Example #16
0
        ///<summary>
        /// Tests if the pair is intersecting.
        ///</summary>
        ///<param name="shapeA">First shape of the pair.</param>
        ///<param name="shapeB">Second shape of the pair.</param>
        ///<param name="transformA">Transform to apply to the first shape.</param>
        ///<param name="transformB">Transform to apply to the second shape.</param>
        ///<param name="localSeparatingAxis">Warmstartable separating axis used by the method to quickly early-out if possible.  Updated to the latest separating axis after each run.</param>
        ///<returns>Whether or not the objects were intersecting.</returns>
        public static bool AreShapesIntersecting(ConvexShape shapeA, ConvexShape shapeB, ref RigidTransform transformA, ref RigidTransform transformB,
                                                 ref Vector3 localSeparatingAxis)
        {
            RigidTransform localtransformB;

            MinkowskiToolbox.GetLocalTransform(ref transformA, ref transformB, out localtransformB);

            //Warm start the simplex.
            var     simplex = new SimpleSimplex();
            Vector3 extremePoint;

            MinkowskiToolbox.GetLocalMinkowskiExtremePoint(shapeA, shapeB, ref localSeparatingAxis, ref localtransformB, out extremePoint);
            simplex.AddNewSimplexPoint(ref extremePoint);

            Vector3 closestPoint;
            int     count = 0;

            while (count++ < MaximumGJKIterations)
            {
                if (simplex.GetPointClosestToOrigin(out closestPoint) || //Also reduces the simplex.
                    closestPoint.LengthSquared() <= simplex.GetErrorTolerance() * Toolbox.BigEpsilon)
                {
                    //Intersecting, or so close to it that it will be difficult/expensive to figure out the separation.
                    return(true);
                }

                //Use the closest point as a direction.
                Vector3 direction;
                Vector3.Negate(ref closestPoint, out direction);
                MinkowskiToolbox.GetLocalMinkowskiExtremePoint(shapeA, shapeB, ref direction, ref localtransformB, out extremePoint);
                //Since this is a boolean test, we don't need to refine the simplex if it becomes apparent that we cannot reach the origin.
                //If the most extreme point at any given time does not go past the origin, then we can quit immediately.
                float dot;
                Vector3.Dot(ref extremePoint, ref closestPoint, out dot); //extreme point dotted against the direction pointing backwards towards the CSO.
                if (dot > 0)
                {
                    // If it's positive, that means that the direction pointing towards the origin produced an extreme point 'in front of' the origin, eliminating the possibility of any intersection.
                    localSeparatingAxis = direction;
                    return(false);
                }

                simplex.AddNewSimplexPoint(ref extremePoint);
            }
            return(false);
        }
Example #17
0
        ///<summary>
        /// Casts a fat (sphere expanded) ray against the shape.
        ///</summary>
        ///<param name="ray">Ray to test against the shape.</param>
        ///<param name="radius">Radius of the ray.</param>
        ///<param name="shape">Shape to test against.</param>
        ///<param name="shapeTransform">Transform to apply to the shape for the test.</param>
        ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        ///<param name="hit">Hit data of the sphere cast, if any.</param>
        ///<returns>Whether or not the sphere cast hit the shape.</returns>
        public static bool SphereCast(Ray ray, float radius, ConvexShape shape, ref RigidTransform shapeTransform, float maximumLength,
                                      out RayHit hit)
        {
            //Transform the ray into the object's local space.
            Vector3.Subtract(ref ray.Position, ref shapeTransform.Position, out ray.Position);
            Quaternion conjugate;

            Quaternion.Conjugate(ref shapeTransform.Orientation, out conjugate);
            Quaternion.Transform(ref ray.Position, ref conjugate, out ray.Position);
            Quaternion.Transform(ref ray.Direction, ref conjugate, out ray.Direction);

            Vector3 w, p;

            hit.T        = 0;
            hit.Location = ray.Position;
            hit.Normal   = Toolbox.ZeroVector;
            Vector3 v = hit.Location;

            RaySimplex simplex = new RaySimplex();

            float vw, vdir;
            int   count = 0;

            //This epsilon has a significant impact on performance and accuracy.  Changing it to use BigEpsilon instead increases speed by around 30-40% usually, but jigging is more evident.
            while (v.LengthSquared() >= Toolbox.Epsilon * simplex.GetErrorTolerance(ref ray.Position))
            {
                if (++count > MaximumGJKIterations)
                {
                    //It's taken too long to find a hit.  Numerical problems are probable; quit.
                    hit = new RayHit();
                    return(false);
                }

                shape.GetLocalExtremePointWithoutMargin(ref v, out p);
                Vector3 contribution;
                MinkowskiToolbox.ExpandMinkowskiSum(shape.collisionMargin, radius, ref v, out contribution);
                Vector3.Add(ref p, ref contribution, out p);

                Vector3.Subtract(ref hit.Location, ref p, out w);
                Vector3.Dot(ref v, ref w, out vw);
                if (vw > 0)
                {
                    Vector3.Dot(ref v, ref ray.Direction, out vdir);
                    hit.T = hit.T - vw / vdir;
                    if (vdir >= 0)
                    {
                        //We would have to back up!
                        return(false);
                    }
                    if (hit.T > maximumLength)
                    {
                        //If we've gone beyond where the ray can reach, there's obviously no hit.
                        return(false);
                    }
                    //Shift the ray up.
                    Vector3.Multiply(ref ray.Direction, hit.T, out hit.Location);
                    Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                    hit.Normal = v;
                }

                RaySimplex shiftedSimplex;
                simplex.AddNewSimplexPoint(ref p, ref hit.Location, out shiftedSimplex);

                shiftedSimplex.GetPointClosestToOrigin(ref simplex, out v);
            }
            //Transform the hit data into world space.
            Quaternion.Transform(ref hit.Normal, ref shapeTransform.Orientation, out hit.Normal);
            Quaternion.Transform(ref hit.Location, ref shapeTransform.Orientation, out hit.Location);
            Vector3.Add(ref hit.Location, ref shapeTransform.Position, out hit.Location);

            return(true);
        }
Example #18
0
        ///<summary>
        /// Sweeps two shapes against another.
        ///</summary>
        ///<param name="shapeA">First shape being swept.</param>
        ///<param name="shapeB">Second shape being swept.</param>
        ///<param name="sweepA">Sweep vector for the first shape.</param>
        ///<param name="sweepB">Sweep vector for the second shape.</param>
        ///<param name="transformA">Transform to apply to the first shape.</param>
        ///<param name="transformB">Transform to apply to the second shape.</param>
        ///<param name="hit">Hit data of the sweep test, if any.</param>
        ///<returns>Whether or not the swept shapes hit each other..</returns>
        public static bool ConvexCast(ConvexShape shapeA, ConvexShape shapeB, ref Vector3 sweepA, ref Vector3 sweepB, ref RigidTransform transformA, ref RigidTransform transformB,
                                      out RayHit hit)
        {
            //Put the velocity into shapeA's local space.
            Vector3 velocityWorld;

            Vector3.Subtract(ref sweepB, ref sweepA, out velocityWorld);
            Quaternion conjugateOrientationA;

            Quaternion.Conjugate(ref transformA.Orientation, out conjugateOrientationA);
            Vector3 rayDirection;

            Quaternion.Transform(ref velocityWorld, ref conjugateOrientationA, out rayDirection);
            //Transform b into a's local space.
            RigidTransform localTransformB;

            Quaternion.Concatenate(ref transformB.Orientation, ref conjugateOrientationA, out localTransformB.Orientation);
            Vector3.Subtract(ref transformB.Position, ref transformA.Position, out localTransformB.Position);
            Quaternion.Transform(ref localTransformB.Position, ref conjugateOrientationA, out localTransformB.Position);


            Vector3 w, p;

            hit.T        = 0;
            hit.Location = Vector3.Zero; //The ray starts at the origin.
            hit.Normal   = Toolbox.ZeroVector;
            Vector3 v = hit.Location;

            RaySimplex simplex = new RaySimplex();


            float vw, vdir;
            int   count = 0;

            do
            {
                if (++count > MaximumGJKIterations)
                {
                    //It's taken too long to find a hit.  Numerical problems are probable; quit.
                    hit = new RayHit();
                    return(false);
                }

                MinkowskiToolbox.GetLocalMinkowskiExtremePoint(shapeA, shapeB, ref v, ref localTransformB, out p);

                Vector3.Subtract(ref hit.Location, ref p, out w);
                Vector3.Dot(ref v, ref w, out vw);
                if (vw > 0)
                {
                    Vector3.Dot(ref v, ref rayDirection, out vdir);
                    if (vdir >= 0)
                    {
                        hit = new RayHit();
                        return(false);
                    }
                    hit.T = hit.T - vw / vdir;
                    if (hit.T > 1)
                    {
                        //If we've gone beyond where the ray can reach, there's obviously no hit.
                        hit = new RayHit();
                        return(false);
                    }
                    //Shift the ray up.
                    Vector3.Multiply(ref rayDirection, hit.T, out hit.Location);
                    //The ray origin is the origin!  Don't need to add any ray position.
                    hit.Normal = v;
                }

                RaySimplex shiftedSimplex;
                simplex.AddNewSimplexPoint(ref p, ref hit.Location, out shiftedSimplex);

                shiftedSimplex.GetPointClosestToOrigin(ref simplex, out v);

                //Could measure the progress of the ray.  If it's too little, could early out.
                //Not used by default since it's biased towards precision over performance.
            } while (v.LengthSquared() >= Toolbox.Epsilon * simplex.GetErrorTolerance(ref Toolbox.ZeroVector));
            //This epsilon has a significant impact on performance and accuracy.  Changing it to use BigEpsilon instead increases speed by around 30-40% usually, but jigging is more evident.
            //Transform the hit data into world space.
            Quaternion.Transform(ref hit.Normal, ref transformA.Orientation, out hit.Normal);
            Vector3.Multiply(ref velocityWorld, hit.T, out hit.Location);
            Vector3.Add(ref hit.Location, ref transformA.Position, out hit.Location);
            return(true);
        }
Example #19
0
        //TODO: Consider changing the termination epsilons on these casts.  Epsilon * Modifier is okay, but there might be better options.

        ///<summary>
        /// Tests a ray against a convex shape.
        ///</summary>
        ///<param name="ray">Ray to test against the shape.</param>
        ///<param name="shape">Shape to test.</param>
        ///<param name="shapeTransform">Transform to apply to the shape for the test.</param>
        ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        ///<param name="hit">Hit data of the ray cast, if any.</param>
        ///<returns>Whether or not the ray hit the shape.</returns>
        public static bool RayCast(Ray ray, ConvexShape shape, ref RigidTransform shapeTransform, float maximumLength,
                                   out RayHit hit)
        {
            //Transform the ray into the object's local space.
            Vector3.Subtract(ref ray.Position, ref shapeTransform.Position, out ray.Position);
            Quaternion conjugate;

            Quaternion.Conjugate(ref shapeTransform.Orientation, out conjugate);
            Quaternion.Transform(ref ray.Position, ref conjugate, out ray.Position);
            Quaternion.Transform(ref ray.Direction, ref conjugate, out ray.Direction);

            Vector3 extremePointToRayOrigin, extremePoint;

            hit.T        = 0;
            hit.Location = ray.Position;
            hit.Normal   = Toolbox.ZeroVector;
            Vector3 closestOffset = hit.Location;

            RaySimplex simplex = new RaySimplex();

            float vw, closestPointDotDirection;
            int   count = 0;

            //This epsilon has a significant impact on performance and accuracy.  Changing it to use BigEpsilon instead increases speed by around 30-40% usually, but jigging is more evident.
            while (closestOffset.LengthSquared() >= Toolbox.Epsilon * simplex.GetErrorTolerance(ref ray.Position))
            {
                if (++count > MaximumGJKIterations)
                {
                    //It's taken too long to find a hit.  Numerical problems are probable; quit.
                    hit = new RayHit();
                    return(false);
                }

                shape.GetLocalExtremePoint(closestOffset, out extremePoint);

                Vector3.Subtract(ref hit.Location, ref extremePoint, out extremePointToRayOrigin);
                Vector3.Dot(ref closestOffset, ref extremePointToRayOrigin, out vw);
                //If the closest offset and the extreme point->ray origin direction point the same way,
                //then we might be able to conservatively advance the point towards the surface.
                if (vw > 0)
                {
                    Vector3.Dot(ref closestOffset, ref ray.Direction, out closestPointDotDirection);
                    if (closestPointDotDirection >= 0)
                    {
                        hit = new RayHit();
                        return(false);
                    }
                    hit.T = hit.T - vw / closestPointDotDirection;
                    if (hit.T > maximumLength)
                    {
                        //If we've gone beyond where the ray can reach, there's obviously no hit.
                        hit = new RayHit();
                        return(false);
                    }
                    //Shift the ray up.
                    Vector3.Multiply(ref ray.Direction, hit.T, out hit.Location);
                    Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                    hit.Normal = closestOffset;
                }

                RaySimplex shiftedSimplex;
                simplex.AddNewSimplexPoint(ref extremePoint, ref hit.Location, out shiftedSimplex);

                //Compute the offset from the simplex surface to the origin.
                shiftedSimplex.GetPointClosestToOrigin(ref simplex, out closestOffset);
            }
            //Transform the hit data into world space.
            Quaternion.Transform(ref hit.Normal, ref shapeTransform.Orientation, out hit.Normal);
            Quaternion.Transform(ref hit.Location, ref shapeTransform.Orientation, out hit.Location);
            Vector3.Add(ref hit.Location, ref shapeTransform.Position, out hit.Location);

            return(true);
        }
Example #20
0
        // Steer away from obstacles in the way. This method returns a zero vector if no correction is required.
        // It should be high priority and the steering from other behaviors should blend into the remaining space.
        // So if this returns a length 1.0f vector, avoiding the obstacle is most urgent and there is no room for other
        // steering.
        private Vector2 AvoidObstacles(Actor owner)
        {
            BipedControllerComponent bcc = owner.GetComponent<BipedControllerComponent>(ActorComponent.ComponentType.Control);

            // Conditions where we do not want to use this steering force.
            if (GetAngleFromVertical(bcc.Controller.Body.LinearVelocity) < MathHelper.PiOver4 ||    // We're probably falling...
                !bcc.Controller.SupportFinder.HasSupport ||
                !bcc.Controller.SupportFinder.HasTraction)
                return Vector2.Zero;

            // Sphere cast ahead along facing.
            List<RayCastResult> obstacles = new List<RayCastResult>();
            SphereShape probe = new SphereShape(bcc.Controller.BodyRadius * 1.1f);
            RigidTransform probeStartPosition = new RigidTransform(bcc.Controller.Body.Position);
            // Add a small constant to the probe length because we want a minimum amount of forward probing, even if we are not moving.
            float probeLength = Math.Max(BepuVec3.Dot(bcc.Controller.Body.LinearVelocity, bcc.Controller.ViewDirection), 0.0f) + 1.0f;
            BepuVec3 probeSweep = bcc.Controller.ViewDirection * probeLength;
            ObstacleFilter filter = new ObstacleFilter(bcc.Controller.Body.CollisionInformation);
            GameResources.ActorManager.SimSpace.ConvexCast(probe, ref probeStartPosition, ref probeSweep, filter.Test, obstacles);

            RayCastDistanceComparer rcdc = new RayCastDistanceComparer();

            obstacles.Sort(rcdc);

            BEPUutilities.Vector3 cross = BEPUutilities.Vector3.Zero;
            int obstacleIndex = 0;
            do
            {
                if (obstacles.Count == obstacleIndex)
                    return Vector2.Zero;

                cross = BEPUutilities.Vector3.Cross(bcc.Controller.ViewDirection, -obstacles[obstacleIndex++].HitData.Normal);
            }
            while (cross.X > 0.7f); // if cross.X > 0.7f, the obstacle is some kind of gentle ramp; ignore it.

            // dot will typically be negative and magnitude indicates how directly ahead the obstacle is.
            float dot = BEPUutilities.Vector3.Dot(bcc.Controller.ViewDirection, -obstacles[0].HitData.Normal);
            if (dot >= 0.0f) // The obstacle won't hinder us if we touch it.
                return Vector2.Zero;

            // When cross.Y is positive, the object is generally to the right, so veer left (and vice versa).
            float directionSign = cross.Y >= 0.0f ? -1.0f : 1.0f;
            BEPUutilities.Vector2 result = BEPUutilities.Vector2.UnitX * directionSign * -dot;

            // Also scale response by how close the obstacle is.
            float distance = (obstacles[0].HitData.Location - bcc.Controller.Body.Position).Length();

            result *= MathHelper.Clamp((1.0f - distance / probeLength), 0.0f, 1.0f); // / Math.Abs(dot);

            // So far the result is in terms of 'velocity space'. Rotate it to align with the controller facing.
            float velocityTheta = (float)(Math.Atan2(-probeSweep.X, -probeSweep.Z));
            BEPUutilities.Matrix2x2 velocityWorld = SpaceUtils.Create2x2RotationMatrix(velocityTheta);
            float facingTheta = (float)(Math.Atan2(-bcc.Controller.HorizontalViewDirection.X, -bcc.Controller.HorizontalViewDirection.Z));
            BEPUutilities.Matrix2x2 facingWorldInv = SpaceUtils.Create2x2RotationMatrix(facingTheta);
            facingWorldInv.Transpose(); // We want the transpose/inverse of the facing transform because we want to transform the movement into 'facing space'.

            return BepuConverter.Convert(SpaceUtils.TransformVec2(SpaceUtils.TransformVec2(result, velocityWorld), facingWorldInv));
        }
Example #21
0
        ///<summary>
        /// Tests if the pair is intersecting.
        ///</summary>
        ///<param name="shapeA">First shape of the pair.</param>
        ///<param name="shapeB">Second shape of the pair.</param>
        ///<param name="transformA">Transform to apply to the first shape.</param>
        ///<param name="transformB">Transform to apply to the second shape.</param>
        ///<returns>Whether or not the shapes are intersecting.</returns>
        public static bool AreShapesIntersecting(ConvexShape shapeA, ConvexShape shapeB, ref RigidTransform transformA, ref RigidTransform transformB)
        {
            //Zero isn't a very good guess!  But it's a cheap guess.
            Vector3 separatingAxis = Toolbox.ZeroVector;

            return(AreShapesIntersecting(shapeA, shapeB, ref transformA, ref transformB, ref separatingAxis));
        }
Example #22
0
        public override void Fire()
        {
            const float ATTACK_RADIUS = 3.0f;
            const float ATTACK_LENGTH = 4.0f;
            // Play 'thwack' sound
            Actor owner = GameResources.ActorManager.GetActorById(OwnerActorId);
            BipedControllerComponent bipedControl = owner.GetComponent<BipedControllerComponent>(ActorComponent.ComponentType.Control);
            RigidTransform alignCapsule = new RigidTransform(BepuVec3.Forward * ATTACK_LENGTH * 0.5f + BepuConverter.Convert(MuzzleOffset),
                BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2));

            Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value :
                BepuConverter.Convert(bipedControl.Controller.ViewDirection));
            RigidTransform positionAndAim = new RigidTransform(bipedControl.Controller.Body.Position, BepuConverter.Convert(
                SpaceUtils.GetOrientation(aim, Vector3.Up)));

            RigidTransform attackTransform;
            RigidTransform.Transform(ref alignCapsule, ref positionAndAim, out attackTransform);

            ConvexShape bashShape = new CapsuleShape(ATTACK_LENGTH, ATTACK_RADIUS);
            BepuVec3 noSweep = BepuVec3.Zero;
            List<RayCastResult> dudesBashed = new List<RayCastResult>();
            AttackFilter filter = new AttackFilter(GameResources.ActorManager.IsMob(OwnerActorId));

            GameResources.ActorManager.SimSpace.ConvexCast(bashShape, ref attackTransform, ref noSweep, filter.Test, dudesBashed);

            foreach (RayCastResult dude in dudesBashed)
            {
                EntityCollidable otherEntityCollidable = dude.HitObject as EntityCollidable;
                Terrain otherTerrain = dude.HitObject as Terrain;
                if (otherEntityCollidable != null &&
                    otherEntityCollidable.Entity != null &&
                    otherEntityCollidable.Entity.Tag != null)
                {
                    Actor actorHit = GameResources.ActorManager.GetActorById((int)(otherEntityCollidable.Entity.Tag));
                    IDamagable damage = actorHit.GetBehaviorThatImplementsType<IDamagable>();
                    if (damage != null)
                    {
                        damage.TakeDamage(Damage);
                        // TODO: P2: Query hit actor for appropiate damage effect e.g. blood and create it;
                    }
                    BashDust(dude.HitData.Location);
                }
                else if (otherTerrain != null)
                {
                    BashDust(dude.HitData.Location);
                }
            }
        }