'GravitationalField' - How do I get the field to ignore?

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

'GravitationalField' - How do I get the field to ignore?

Post by Spankenstein »

I have an entity associated with a GravitationalField class. This means that I have a kinematic or dynamic model that denotes the origin of the field.

The entity is there so it can be interacted with via a GUI. The position of the GravitationalField is always at the centroid of the associated entity.

Code: Select all

        public GravitationalFieldPrimitive(Game1 game, GravitationalFieldPrimitiveSettings settings)
            : base(game, settings = settings == null ? new GravitationalFieldPrimitiveSettings() : settings)
        {
            // Higher multiplier = Higher gravity (stronger attractive force)
            // Maximum value for 'MaxAcceleration' should be 50 
            // Object shaking occurs after the max value unless the 'space.TimeStepSettings.TimeStepDuration' value is decreased
            gravField = new GravitationalField(
                new InfiniteForceFieldShape(), 
                settings.Position, 
                settings.GravitationalFieldStrength, 
                50
                );
            
            // Force entities in range to wake up
            gravField.ForceWakeUp = true;

            game.Space.Add(gravField);
        }
How can I get the GravitationalField class to ignore the dynamic entity associated with it in the GravitationalFieldPrimitive class?

This is not normally a problem if the associated entity is kinematic but it needs to be ignored when the associated entity is dynamic.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: 'GravitationalField' - How do I get the field to ignore?

Post by Norbo »

A custom shape could be used. Here's the code from the infinite shape:

Code: Select all

    /// <summary>
    /// Defines the area in which a force field works using an entity's shape.
    /// </summary>
    public class InfiniteForceFieldShape : ForceFieldShape
    {
        /// <summary>
        /// Determines the possibly involved entities.
        /// </summary>
        /// <returns>Possibly involved entities.</returns>
        public override IList<Entity> GetPossiblyAffectedEntities()
        {
            return (ForceField as ISpaceObject).Space.Entities;
        }

        /// <summary>
        /// Determines if the entity is affected by the force field.
        /// </summary>
        /// <param name="testEntity">Entity to test.</param>
        /// <returns>Whether the entity is affected.</returns>
        public override bool IsEntityAffected(Entity testEntity)
        {
            return true;
        }
    }
GetPossiblyAffectedEntities runs first to gather candidates. Since it's called from a single threaded context, keeping this fast can be important. The following IsEntityEffected allows fine grained checks to run on each candidate from a multithreaded context. So, you could override the IsEntityAffected method and check the testEntity against the followed entity.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: 'GravitationalField' - How do I get the field to ignore?

Post by Spankenstein »

Thanks Norbo.

So something like this wouldn't be too bad an implementation I hope:

Code: Select all

        public override bool IsEntityAffected(Entity testEntity)
        {
            var o = testEntity.CollisionInformation.Tag as GravitationalFieldPrimitive;

            return o == null ? true : false;
        }
Also, the new version (1.2.0) is great! :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: 'GravitationalField' - How do I get the field to ignore?

Post by Norbo »

That would work; the cost of that method will likely be completely overwhelmed by everything else going on. If testing shows you need every nanosecond, changing it to a single direct entity equality test would probably be marginally faster (by avoiding a cast), but it almost certainly won't matter.
Also, the new version (1.2.0) is great!
Glad to hear it :)
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: 'GravitationalField' - How do I get the field to ignore?

Post by Spankenstein »

changing it to a single direct entity equality test would probably be marginally faster
Good point:

Code: Select all

    public class InfiniteForceFieldShapeCustom : ForceFieldShape
    {
        public Entity owner;

        public InfiniteForceFieldShapeCustom(Entity owner)
        {
            this.owner = owner;
        }

        /// <summary>
        /// Determines the possibly involved entities.
        /// </summary>
        /// <returns>Possibly involved entities.</returns>
        public override IList<Entity> GetPossiblyAffectedEntities()
        {
            return (ForceField as ISpaceObject).Space.Entities;
        }

        /// <summary>
        /// Determines if the entity is affected by the force field.
        /// </summary>
        /// <param name="testEntity">Entity to test.</param>
        /// <returns>Whether the entity is affected.</returns>
        public override bool IsEntityAffected(Entity testEntity)
        {
            //var o = testEntity.CollisionInformation.Tag as GravitationalFieldPrimitive;
            //return o == null ? true : false;

            return testEntity != owner;
        }
    }
Post Reply