Circular wind force field. How can I keep objects inside?

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

Circular wind force field. How can I keep objects inside?

Post by Spankenstein »

I've taken the tornado class and removed the upward forces to create a kind of circular wind effect:

Code: Select all

        protected override void CalculateImpulse(Entity e, float dt, out Vector3 impulse)
        {
            Vector3 position = Position;
            Vector3 entityPosition = e.Position;

            float entityHeight = Vector3.Dot(Axis, entityPosition - position + Axis * (Height * 0.5f));

            if (entityHeight < 0 || entityHeight > Height)
            {
                impulse = Vector3.Zero;
            }
            else
            {
                Vector3 closestPoint;
                Vector3 endpointA = position + Axis * Height * 0.5f;
                Vector3 endpointB = position - Axis * Height * 0.5f;
                Toolbox.GetClosestPointOnSegmentToPoint(ref endpointA, ref endpointB, ref entityPosition, out closestPoint);
                float entityDistanceFromTornado;
                Vector3.Distance(ref entityPosition, ref closestPoint, out entityDistanceFromTornado);
                //Compute the axis to the 
                Vector3 posClosest;
                float forceMultiplier;

                if (entityDistanceFromTornado > Radius)
                {
                    //outside tornado
                    forceMultiplier = Radius / entityDistanceFromTornado;
                    posClosest = (closestPoint - entityPosition) / entityDistanceFromTornado;
                }
                else if (entityDistanceFromTornado > Toolbox.Epsilon)
                {
                    //inside tornado
                    forceMultiplier = .5f + .5f * entityDistanceFromTornado / Radius;
                    posClosest = (closestPoint - entityPosition) / entityDistanceFromTornado;
                }
                else
                {
                    forceMultiplier = .5f;
                    posClosest = Toolbox.ZeroVector;
                }

                // Don't need to normalize the direction.  
                // Axis and posClosest are perpendicular and each normal, so the result is normal.
                Vector3 tangentialForceVector;
                Vector3 tangentDirection;

                if (SpinClockwise)
                {
                    Vector3.Cross(ref Axis, ref posClosest, out tangentDirection);
                }
                else
                {
                    Vector3.Cross(ref posClosest, ref Axis, out tangentDirection);
                }

                //Current velocity along the tangent direction.
                float dot = Vector3.Dot(e.LinearVelocity, tangentDirection);
                //Compute the velocity difference between the current and the maximum
                dot = HorizontalWindSpeed - dot;
                //Compute the force needed to reach the maximum, but clamp it to the amount of force that the tornado can apply
                dot = MathHelper.Clamp(dot * e.Mass, 0, HorizontalForce * dt);
                Vector3.Multiply(ref tangentDirection, dot, out tangentialForceVector);

                Vector3 inwardForceVector;
                dot = Vector3.Dot(e.LinearVelocity, posClosest);
                dot = InwardSuctionSpeed - dot;
                dot = MathHelper.Clamp(dot * e.Mass, 0, InwardForce * dt);
                Vector3.Multiply(ref posClosest, dot, out inwardForceVector);

                impulse = forceMultiplier * (tangentialForceVector + inwardForceVector);
            }
        }
I'm have a hard time keeping objects from flying out of the force field. Can anyone suggest how I could make the wind more likely to keep objects inside it without having to resort to some kind of gravitational field? In other words objects can be sucked in and move in a circular fashion around the field.

I've tried adjusting the inward suction speed and force but it makes little difference:

Code: Select all

            circularWind = new CircularWind(
                this,
                new BoundingBoxForceFieldShape(new BoundingBox(position - extents, position + extents)),
                position,
                Vector3.UnitY,
                5f,
                true,
                10f,            // Horizontal wind speed
                1000f,         // Inward suction speed
                10f,            // Horizontal force
                1000f,         // Inward force
                5f,
                space.BroadPhase.QueryAccelerator
                );
This video demonstrates an object being dropped into the wind field (denoted by the white ring) and flying out almost immediately: http://www.youtube.com/watch?v=arzrLe05wt0
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Circular wind force field. How can I keep objects insid

Post by Norbo »

In a 'tornado' of limited width, you just need to have sufficient inward force and speed. The smaller the tornado or higher the spin rate, the greater inward force/speed is required. The values required can be very, very high depending on the rest of the configuration. Also be aware that excessive inward force has problems of its own. It could just fling the object along the diameter of the tornado and out the other side.

At a sufficiently small size and sufficiently speeds, you may find that you can't set a high enough force/speed without instability. That can happen when there are insufficient time steps relative to the motion. The best thing to do there is to weaken the tornado, or decrease the time step duration.

In other words, the tornado is just a matter of tuning. There's not really anything special or fundamental you can do to make it a lot easier given the sample implementation.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: Circular wind force field. How can I keep objects insid

Post by Spankenstein »

I'll set up a fine tuning system and see what values work then.
Post Reply