Discuss any questions about BEPUphysics or problems encountered.
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Sun Jun 29, 2008 9:28 pm
I'm using a MaximumSpeedConstraint in my scene. After a few seconds at high speed I can reliably get it to crash 100% of the time with the following call stack. The test is being run with a Box and StaticTriangleGroup with the Box as the moving Entity. Looks like some vectors are becoming invalid...possibly due to the constraint's interaction?
Code: Select all
mscorlib.dll!System.Math.Sign(float value = NaN) + 0x23 bytes
BEPUphysics.dll!BEPUphysics.Box.getExtremePoint(ref Microsoft.Xna.Framework.Vector3 d = {X:-1 Y:0 Z:0}, float margin = 0.04, ref Microsoft.Xna.Framework.Vector3 linearVelocity = {X:NaN Y:NaN Z:NaN}, ref Microsoft.Xna.Framework.Vector3 backwardLinearVelocity = {X:NaN Y:NaN Z:NaN}) + 0x17 bytes
BEPUphysics.dll!BEPUphysics.Entity.getExtremePoints(ref Microsoft.Xna.Framework.Vector3 d = {X:1 Y:0 Z:0}, out Microsoft.Xna.Framework.Vector3 min = {X:0 Y:0 Z:0}, out Microsoft.Xna.Framework.Vector3 max = {X:0 Y:0 Z:0}, float margin = 0.04, ref Microsoft.Xna.Framework.Vector3 linearVelocity = {X:NaN Y:NaN Z:NaN}, ref Microsoft.Xna.Framework.Vector3 backwardLinearVelocity = {X:NaN Y:NaN Z:NaN}) + 0x1b bytes
BEPUphysics.dll!BEPUphysics.Entity.findBoundingBox(ref Microsoft.Xna.Framework.Vector3 linearVelocity = {X:NaN Y:NaN Z:NaN}, ref Microsoft.Xna.Framework.Vector3 backwardLinearVelocity = {X:NaN Y:NaN Z:NaN}) + 0x17 bytes
BEPUphysics.dll!BEPUphysics.Space.update(float dt = 0.0166667, float timeSinceLastFrame = 0.0168094635) + 0x58a bytes
BEPUphysics.dll!BEPUphysics.Space.update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) + 0x42 bytes
Zukarakox
Not a Site Admin
Posts: 426 Joined: Mon Jul 10, 2006 4:28 am
Post
by Zukarakox » Sun Jun 29, 2008 9:49 pm
YOU BROKEEE ITTTT....
i has multiple toes
Norbo
Site Admin
Posts: 4929 Joined: Tue Jul 04, 2006 4:45 am
Post
by Norbo » Sun Jun 29, 2008 9:52 pm
Could you create a little reproduction setup for this error?
My current theory as to why this might happen relates to the inertia tensor of the box; have you modified it at all, perhaps setting rows to zero or anything? The maximum speed constraint won't play well with that sort of thing. Other than that, there isn't really anything else obviously/directly related to the constraint that could cause NaN-spam.
That exception specifically is the result of a propagation of NaN's, and is generally the catch-all for annoying velocity bugs.
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Sun Jun 29, 2008 10:48 pm
No, I'm not setting anything related to the inertia tensor of the box. Simply calling Box.applyImpulse each frame to accelerate the cube. I was procedurally rotating the linearMomentum vector but have disabled all of that in an attempt to pinpoint a possible culprit. However, none of that has helped so far. At this point, I've reduced it to Box.applyImpulse calls and Box.rotate calls for the update loop. I did have the maximumAngularSpeed set to 0.0f on the MaximumSpeedConstraint, so I tried setting it to some positive value. Didn't help.
At this point it's kind of tough to put together a simple repro case for this aside from sending over the whole project as it currently exists. It's a 360 only project at the moment. Is it possible to run an exe built for the 360 on the 360 without Visual Studio? Or do you pretty much have to have the solution and source code and build locally and then deploy in order to debug?
Norbo
Site Admin
Posts: 4929 Joined: Tue Jul 04, 2006 4:45 am
Post
by Norbo » Mon Jun 30, 2008 12:17 am
I am not 100% sure, but I think it would require the whole solution for deployment purposes.
Only thing I can think of is to check all of the velocities of the object after each apply impulse, and the orientation after each rotation. If all of them come out fine and yet it still explodes, I'll probably have to take a closer look. For those NaN's to pop up, there needs to be something nasty going on, and the only thing that I can see that could possibly cause them in the constraint is a matrix inversion, which apparently isn't the cause.
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Mon Jun 30, 2008 3:11 am
Okay, I've got assertions checking just about every component of every vector or matrix (that I have access to) that can change at the Entity level...and nothing is getting hit. Here's the state of the cube at the time of the crash:
I see that some of the "my" and "previous" member variables are also NaN...
Code: Select all
- m_Cube {BEPUphysics.Box} BEPUphysics.Box
- base {BEPUphysics.Box} BEPUphysics.Entity {BEPUphysics.Box}
allowedPenetration 0.025 float
angularDamping 0.75 float
+ angularMomentum {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
+ angularVelocity {X:81.73529 Y:-97.50146 Z:5.956311} Microsoft.Xna.Framework.Vector3
bounciness 0.0 float
+ boundingBox {Min:{X:-3.158347 Y:40.80492 Z:250.8726} Max:{X:5.326904 Y:49.29885 Z:255.7614}} Microsoft.Xna.Framework.BoundingBox
+ centerPosition {X:1.084278 Y:45.05188 Z:253.317} Microsoft.Xna.Framework.Vector3
collisionFilter 18446744073709551615 ulong
collisionMargin 0.04 float
compoundActivity true bool
+ compoundAngularMomentum {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
+ compoundAngularVelocity {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
compoundBody null BEPUphysics.CompoundBody
+ compoundCorrectiveAngularVelocity {X:0 Y:0 Z:0} Microsoft.Xna.Framework.Vector3
+ compoundCorrectiveLinearVelocity {X:0 Y:0 Z:0} Microsoft.Xna.Framework.Vector3
+ compoundInertiaTensorInverse { {M11:0.02026436 M12:-0.001954478 M13:-0.0008725619 M14:0} {M21:-0.001954478 M22:0.01064112 M23:-0.001182511 M24:0} {M31:-0.000872562 M32:-0.001182512 M33:0.01140407 M34:0} {M41:0 M42:0 M43:0 M44:0.9999999} } Microsoft.Xna.Framework.Matrix
+ compoundLinearMomentum {X:1634.706 Y:-1950.029 Z:119.1262} Microsoft.Xna.Framework.Vector3
+ compoundLinearVelocity {X:81.73529 Y:-97.50146 Z:5.956311} Microsoft.Xna.Framework.Vector3
compoundMass 20.0 float
+ compoundOrientationQuaternion {X:NaN Y:NaN Z:NaN W:NaN} Microsoft.Xna.Framework.Quaternion
+ compoundPosition {X:1.084278 Y:45.05188 Z:253.317} Microsoft.Xna.Framework.Vector3
+ compoundRotationMatrix { {M11:NaN M12:NaN M13:NaN M14:0} {M21:NaN M22:NaN M23:NaN M24:0} {M31:NaN M32:NaN M33:NaN M34:0} {M41:0 M42:0 M43:0 M44:1} } Microsoft.Xna.Framework.Matrix
+ constraints {System.Collections.Generic.List<BEPUphysics.Constraint>} System.Collections.Generic.List<BEPUphysics.Constraint>
+ controllers {System.Collections.Generic.List<BEPUphysics.Controller>} System.Collections.Generic.List<BEPUphysics.Controller>
+ correctiveAngularVelocity {X:0 Y:0 Z:0} Microsoft.Xna.Framework.Vector3
+ correctiveLinearVelocity {X:0 Y:0 Z:0} Microsoft.Xna.Framework.Vector3
density 0.8333333 float
+ force {X:54.90942 Y:18.10596 Z:-36.97366} Microsoft.Xna.Framework.Vector3
+ forces {System.Collections.Generic.List<BEPUphysics.Force>} System.Collections.Generic.List<BEPUphysics.Force>
framesBelowAngularVelocityThreshold 0 int
framesBelowLinearVelocityThreshold 0 int
friction 0.3 float
+ inertiaTensorInverse { {M11:0.02026436 M12:-0.001954478 M13:-0.0008725619 M14:0} {M21:-0.001954478 M22:0.01064112 M23:-0.001182511 M24:0} {M31:-0.000872562 M32:-0.001182512 M33:0.01140407 M34:0} {M41:0 M42:0 M43:0 M44:0.9999999} } Microsoft.Xna.Framework.Matrix
internalIterationFlag 0 byte
isActive true bool
isAffectedByGravity true bool
isAlwaysActive false bool
isDeactivationCandidate false bool
isMemberOfRayCastableContainer false bool
isPhysicallySimulated true bool
isSubBodyOfCompound false bool
isTangible true bool
linearDamping 0.0 float
+ linearMomentum {X:1634.706 Y:-1950.029 Z:119.1262} Microsoft.Xna.Framework.Vector3
+ linearVelocity {X:81.73529 Y:-97.50146 Z:5.956311} Microsoft.Xna.Framework.Vector3
+ localInertiaTensor { {M11:81.66667 M12:0 M13:0 M14:0} {M21:0 M22:106.6667 M23:0 M24:0} {M31:0 M32:0 M33:48.33334 M34:0} {M41:0 M42:0 M43:0 M44:1} } Microsoft.Xna.Framework.Matrix
+ localInertiaTensorInverse { {M11:0.0122449 M12:0 M13:0 M14:0} {M21:0 M22:0.009374999 M23:0 M24:0} {M31:0 M32:0 M33:0.02068965 M34:0} {M41:0 M42:0 M43:0 M44:0.9999999} } Microsoft.Xna.Framework.Matrix
+ localSpaceInertiaTensor { {M11:81.66667 M12:0 M13:0 M14:0} {M21:0 M22:106.6667 M23:0 M24:0} {M31:0 M32:0 M33:48.33334 M34:0} {M41:0 M42:0 M43:0 M44:1} } Microsoft.Xna.Framework.Matrix
margin 0.04 float
marginSquared 0.0016 float
mass 20.0 float
+ myAngularVelocity {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
+ myLinearVelocity {X:81.73529 Y:-97.50146 Z:5.956311} Microsoft.Xna.Framework.Vector3
+ mySpace {BEPUphysics.Space} BEPUphysics.Space
+ nonCollidableEntities {System.Collections.Generic.List<BEPUphysics.Entity>} System.Collections.Generic.List<BEPUphysics.Entity>
+ orientation {X:NaN Y:NaN Z:NaN W:NaN} Microsoft.Xna.Framework.Quaternion
+ orientationQuaternion {X:NaN Y:NaN Z:NaN W:NaN} Microsoft.Xna.Framework.Quaternion
+ position {X:1.084278 Y:45.05188 Z:253.317} Microsoft.Xna.Framework.Vector3
+ previousAngularMomentum {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
+ previousLinearMomentum {X:1634.706 Y:-1950.029 Z:119.1262} Microsoft.Xna.Framework.Vector3
+ rotation { {M11:NaN M12:NaN M13:NaN M14:0} {M21:NaN M22:NaN M23:NaN M24:0} {M31:NaN M32:NaN M33:NaN M34:0} {M41:0 M42:0 M43:0 M44:1} } Microsoft.Xna.Framework.Matrix
+ rotationMatrix { {M11:NaN M12:NaN M13:NaN M14:0} {M21:NaN M22:NaN M23:NaN M24:0} {M31:NaN M32:NaN M33:NaN M34:0} {M41:0 M42:0 M43:0 M44:1} } Microsoft.Xna.Framework.Matrix
+ simulationIsland {BEPUphysics.SimulationIsland} BEPUphysics.SimulationIsland
+ space {BEPUphysics.Space} BEPUphysics.Space
tag null object
+ torque {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
+ totalForce {X:54.90942 Y:18.10596 Z:-36.97366} Microsoft.Xna.Framework.Vector3
+ totalTorque {X:NaN Y:NaN Z:NaN} Microsoft.Xna.Framework.Vector3
useContinuousDetection true bool
useOneShotManifolds true bool
volume 24.0 float
halfHeight 0.5 float
halfLength 3.0 float
halfWidth 2.0 float
height 1.0 float
length 6.0 float
width 4.0 float
Norbo
Site Admin
Posts: 4929 Joined: Tue Jul 04, 2006 4:45 am
Post
by Norbo » Mon Jun 30, 2008 6:17 am
I managed to find the source; it was just an issue with the normalization of velocities eventually resulting in infinities due to the extremely small values involved (I probably should have noticed that sooner
). Unfortunately this can't be fixed externally, but it's pretty simple and can work as an example of using the constraint framework so I'll go ahead and release the source code:
Code: Select all
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using System.Diagnostics;
namespace BEPUphysics
{
/// <summary>
/// Prevents the target entity from moving faster than the specified speeds.
/// </summary>
public class MaximumSpeedConstraint:SingleBodyConstraint
{
/// <summary>
/// Maximum linear speed allowed.
/// </summary>
public float maximumLinearSpeed;
/// <summary>
/// Maximum angular speed allowed.
/// </summary>
public float maximumAngularSpeed;
Vector3 linearVelocityDirection;
Vector3 angularVelocityDirection;
Matrix inertiaTensor;
/// <summary>
/// Constructs a maximum speed constraint.
/// </summary>
/// <param name="e">Entity to target.</param>
/// <param name="maxLinearSpeed">Maximum linear speed allowed.</param>
/// <param name="maxAngularSpeed">Maximum angular speed allowed.</param>
public MaximumSpeedConstraint(Entity e, float maxLinearSpeed, float maxAngularSpeed)
{
entity = e;
maximumLinearSpeed = maxLinearSpeed;
maximumAngularSpeed = maxAngularSpeed;
}
/// <summary>
/// Calculates necessary information for velocity solving.
/// Called automatically by space.
/// </summary>
/// <param name="dt">Time in seconds since the last update.</param>
public override void preStep(float dt)
{
float linearVelocityMagnitudeSquared = entity.linearVelocity.LengthSquared();
if (linearVelocityMagnitudeSquared > 1E-40f)
linearVelocityDirection = entity.linearVelocity / (float)Math.Sqrt(linearVelocityMagnitudeSquared);
else
linearVelocityDirection = Vector3.Zero;
float angularVelocityMagnitudeSquared = entity.angularVelocity.LengthSquared();
if (angularVelocityMagnitudeSquared > 1E-40f)
angularVelocityDirection = entity.angularVelocity / (float)Math.Sqrt(angularVelocityMagnitudeSquared);
else
angularVelocityDirection = Vector3.Zero;
inertiaTensor = Matrix.Invert(entity.inertiaTensorInverse);
}
/// <summary>
/// Calculates and applies corrective impulses.
/// Called automatically by space.
/// </summary>
/// <param name="dt">Time in seconds since the last update.</param>
public override void applyImpulse(float dt)
{
float linearVelocity = Vector3.Dot(entity.myLinearVelocity, linearVelocityDirection);
if (linearVelocity > maximumLinearSpeed)
{
float diff = maximumLinearSpeed - linearVelocity;
Vector3 linearImpulse = (diff * entity.mass) * linearVelocityDirection;
entity.linearMomentum += linearImpulse;
entity.myLinearVelocity = entity.linearMomentum / entity.mass;
}
float angularVelocity = Vector3.Dot(entity.myAngularVelocity, angularVelocityDirection);
if (angularVelocity > maximumAngularSpeed)
{
float diff = maximumAngularSpeed - angularVelocity;
Vector3 angularImpulse = Vector3.Transform(diff * angularVelocityDirection, inertiaTensor);
entity.angularMomentum += angularImpulse;
entity.myAngularVelocity = Vector3.Transform(entity.angularMomentum, entity.inertiaTensorInverse);
}
}
}
}
The above source is made available under the same permissive zlib-style license as the demos, which can be found at
http://www.bepu-games.com/BEPUphysics/demoslicense.txt .
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Mon Jun 30, 2008 1:12 pm
Awesome. Thank you very much for taking the time to look through it and ultimately finding what the problem was/is.
Edit:
The following function doesn't have access to the "myLinearVelocity" and "myAngularVelocity" member variables, unless I'm just missing some silly C#-ism. I tried using just linearVelocity and angularVelocity instead, but the visual results are telling me that the two are not the same internally.
Code: Select all
public override void applyImpulse(float dt)
{
float linearVelocity = Vector3.Dot(entity.myLinearVelocity, linearVelocityDirection);
if (linearVelocity > maximumLinearSpeed)
{
float diff = maximumLinearSpeed - linearVelocity;
Vector3 linearImpulse = (diff * entity.mass) * linearVelocityDirection;
entity.linearMomentum += linearImpulse;
entity.myLinearVelocity = entity.linearMomentum / entity.mass;
}
float angularVelocity = Vector3.Dot(entity.myAngularVelocity, angularVelocityDirection);
if (angularVelocity > maximumAngularSpeed)
{
float diff = maximumAngularSpeed - angularVelocity;
Vector3 angularImpulse = Vector3.Transform(diff * angularVelocityDirection, inertiaTensor);
entity.angularMomentum += angularImpulse;
entity.myAngularVelocity = Vector3.Transform(entity.angularMomentum, entity.inertiaTensorInverse);
}
}
Norbo
Site Admin
Posts: 4929 Joined: Tue Jul 04, 2006 4:45 am
Post
by Norbo » Mon Jun 30, 2008 7:11 pm
Sorry about that, forgot about the ridiculous bug I had fixed that causes the angularVelocity property to get the
linear Velocity. Here's a workaround for the applyImpulse method, since setting the property still works in v0.5.2.
Code: Select all
/// <summary>
/// Calculates and applies corrective impulses.
/// Called automatically by space.
/// </summary>
/// <param name="dt">Time in seconds since the last update.</param>
public override void applyImpulse(float dt)
{
float linearVelocity = Vector3.Dot(entity.linearVelocity, linearVelocityDirection);
if (linearVelocity > maximumLinearSpeed)
{
float diff = maximumLinearSpeed - linearVelocity;
Vector3 linearImpulse = (diff * entity.mass) * linearVelocityDirection;
entity.linearMomentum += linearImpulse;
entity.linearVelocity = entity.linearMomentum / entity.mass;
}
float angularVelocity = Vector3.Dot(Vector3.Transform(entity.angularMomentum, entity.inertiaTensorInverse), angularVelocityDirection);
if (angularVelocity > maximumAngularSpeed)
{
float diff = maximumAngularSpeed - angularVelocity;
Vector3 angularImpulse = Vector3.Transform(diff * angularVelocityDirection, inertiaTensor);
entity.angularVelocity = Vector3.Transform(Vector3.Transform(entity.angularMomentum + angularImpulse, entity.inertiaTensorInverse), entity.inertiaTensorInverse);
}
}
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Mon Jun 30, 2008 7:36 pm
Ha! Yeah, that's the behavior I was seeing. The angularVelocity was somehow ending up with the linearVelocity. LOL It's all good. Thanks for the workaround. I'll either try it tonight or in the morning and report back.
Norbo wrote: Sorry about that, forgot about the ridiculous bug I had fixed that causes the angularVelocity property to get the linear Velocity. Here's a workaround for the applyImpulse method, since setting the property still works in v0.5.2.
BrianL
Posts: 54 Joined: Wed Jun 25, 2008 4:41 pm
Location: Panama City Beach, FL
Post
by BrianL » Tue Jul 01, 2008 1:12 pm
So far so good on the fix. Thanks.