Circular wind force field. How can I keep objects inside?
Posted: Sun Jul 24, 2011 3:52 pm
I've taken the tornado class and removed the upward forces to create a kind of circular wind effect:
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:
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
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'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
);