Function does not accept floating point Not-a-Number values.

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
vendetta
Posts: 18
Joined: Sat Dec 31, 2011 7:49 pm

Function does not accept floating point Not-a-Number values.

Post by vendetta »

Hi Norbo,
I'm working on a replay system using the character controller sample from the latest bepu physics.

I'm storing 1000 states (the state structure is posted below). I store 1 position each time I call space.Update() and it works almost perfectly.
However, its occasionally throwing the error "Function does not accept floating point Not-a-Number values."

I've attempted to follow other posts involving scaling my world up/down, however nothing I've read has worked.

Here is my stack trace:

Code: Select all

"   at System.Math.Sign(Single value)
   at BEPUphysics.CollisionShapes.ConvexShapes.CylinderShape.GetLocalExtremePointWithoutMargin(Vector3& direction, Vector3& extremePoint) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\CollisionShapes\\ConvexShapes\\CylinderShape.cs:line 93
   at BEPUphysics.CollisionShapes.ConvexShapes.CylinderShape.GetBoundingBox(RigidTransform& shapeTransform, BoundingBox& boundingBox) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\CollisionShapes\\ConvexShapes\\CylinderShape.cs:line 53
   at BEPUphysics.Collidables.MobileCollidables.ConvexCollidable`1.UpdateBoundingBoxInternal(Single dt) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\BroadPhaseEntries\\MobileCollidables\\ConvexCollidable.cs:line 86
   at BEPUphysics.Collidables.MobileCollidables.EntityCollidable.UpdateBoundingBox(Single dt) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\BroadPhaseEntries\\MobileCollidables\\EntityCollidable.cs:line 144
   at BEPUphysics.OtherSpaceStages.BoundingBoxUpdater.LoopBody(Int32 i) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\OtherSpaceStages\\BoundingBoxUpdater.cs:line 51
   at BEPUphysics.OtherSpaceStages.BoundingBoxUpdater.UpdateSingleThreaded() in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\OtherSpaceStages\\BoundingBoxUpdater.cs:line 83
   at BEPUphysics.MultithreadedProcessingStage.Update() in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\MultithreadedProcessingStage.cs:line 59
   at BEPUphysics.Space.DoTimeStep() in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\Space.cs:line 495
   at BEPUphysics.Space.Update(Single dt) in C:\\Users\\Mike\\Desktop\\bepuReplay\\bepuPhysics\\Space.cs:line 531
   at PredictiveBehavior.CLIENT.Update(GameTime gameTime) in C:\\Users\\Mike\\Desktop\\bepuReplay\\PredictiveBehavior\\Client.cs:line 358
   at Microsoft.Xna.Framework.Game.Tick()
   at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
   at Microsoft.Xna.Framework.GameHost.OnIdle()
   at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
   at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Microsoft.Xna.Framework.WindowsGameHost.Run()
   at Microsoft.Xna.Framework.Game.Run()
   at PredictiveBehavior.Program.Main(String[] args) in C:\\Users\\Mike\\Desktop\\bepuReplay\\PredictiveBehavior\\Program.cs:line 14"
Here is my State structure:

Code: Select all

  [Serializable]
    public struct State
    {

        public Quaternion Orientation;        
        public Vector3 Position;
	public Vector3 AngularVelocity; 
	public Vector3 LinearVelocity; 
	public Vector3 LinearMomentum;
        public float Yaw, Pitch;

        public static State GetFromCharacterController(CharacterControllerInput controller)
        {
            
            var body = controller.CharacterController.Body;            
            return new State
            {               
                AngularVelocity = body.AngularVelocity,
                LinearMomentum = body.LinearMomentum,
                LinearVelocity = body.LinearVelocity,
                Orientation = body.Orientation,
                Position = body.Position,  
                Yaw = controller.Camera.Yaw,
                Pitch = controller.Camera.Pitch,
            };
        }

        public void CopyToCharacterController(ref CharacterControllerInput controller)
        {
            var body = controller.CharacterController.Body;
            body.AngularVelocity = this.AngularVelocity;
            body.LinearMomentum = this.LinearMomentum;
            body.LinearVelocity = this.LinearVelocity;
            body.Orientation = this.Orientation;
            body.Position = this.Position;
            controller.Camera.Yaw = this.Yaw;
            controller.Camera.Pitch = this.Pitch;            
        }
    }
I'm using the CopyToCharacterController() method of the state before calling space.Update() when in replay mode. I've tried only setting the position and orientation of the body, but the exception is still thrown.

Thanks for any help on the subject,
vendetta
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Function does not accept floating point Not-a-Number val

Post by Norbo »

Try compiling BEPUphysics with the CHECKMATH compilation symbol. That will activate a bunch of validation code that might catch the NaN earlier in its propagation and narrow down the causes.
vendetta
Posts: 18
Joined: Sat Dec 31, 2011 7:49 pm

Re: Function does not accept floating point Not-a-Number val

Post by vendetta »

Hi Norbo,
I compiled with CHECKMATH and narrowed my problem down to Entity.Orientation.set

When the orientation from my replay buffer is 0,0,0,0 it throws the NaN error immediately after calling Quaternion.Normalize(ref value, out orientation); in EntityBase.cs on line 79.

I'm not sure why it would be doing this though, because the quaternion I'm storing in my replay buffer is copied from the entity's Orientation property; do you know of a reason why this could be happening?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Function does not accept floating point Not-a-Number val

Post by Norbo »

Is there any asynchronous access going on? Could the space (and thus possibly orientation) update while the orientation is being read? That could produce arbitrary corrupt values, though I would expect to see more varied bad values than just 0,0,0,0.

Could there be any interfering process between the recording and replay that modifies or corrupts the stored data?
vendetta
Posts: 18
Joined: Sat Dec 31, 2011 7:49 pm

Re: Function does not accept floating point Not-a-Number val

Post by vendetta »

Norbo wrote:Is there any asynchronous access going on? Could the space (and thus possibly orientation) update while the orientation is being read? That could produce arbitrary corrupt values, though I would expect to see more varied bad values than just 0,0,0,0.

Could there be any interfering process between the recording and replay that modifies or corrupts the stored data?
No, this is how I am updating / setting the position:

Code: Select all

 if (!inReplayMode)
            {                
                if (this.IsActive && GetActiveWindow() == this.Window.Handle)
                {
                    this.CharacterController.Update(timeStep, current);
                    camera.Update(timeStep, currentState, Mouse.GetState(), GamePad.GetState(PlayerIndex.One));
                    Mouse.SetPosition(200, 200);
                }
                State thisState = State.GetFromCharacterController(CharacterController); //method posted in original post
                buffer.Add(thisState);                
            }
            else
            {
                camera.Update(timeStep, currentState, 
                    new MouseState(200, 200, 0, ButtonState.Released, ButtonState.Released, 
                        ButtonState.Released, ButtonState.Released, ButtonState.Released), 
                        GamePad.GetState(PlayerIndex.One));
  
                if (buffer.Count > 0)
                {
                    this.CharacterController.Update(timeStep, new Input());
                    var first = buffer.Oldest(); //State struct posted above
                    first.CopyToCharacterController(ref CharacterController);   //Method code is posted in my original post
                    buffer.RemoveAt(0);
                }
                else
                {
                    inReplayMode = false;
                }
            }
I've also tried stripping out the above code and just using this:

Code: Select all

		 if (buffer.Count > 0)
                {                    
                    var first = buffer.Oldest();
                    first.CopyToCharacterController(ref CharacterController);                   
                    buffer.RemoveAt(0);
                }                
However it produces the same results. I've recorded several dozen replays (both writing to a file and just storing the buffer in memory temporarily) and the only time it fails is if the Orientation property is set to 0,0,0,0. It doesn't happen during every recording, either. It seems to be when I'm jumping and turning quickly that it becomes 0,0,0,0.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Function does not accept floating point Not-a-Number val

Post by Norbo »

The Orientation property grabs the direct state of the entity. If the Orientation was truly 0,0,0,0 then the simulation would crash quickly with a NaNsplosion or something similar. Further, since the CharacterController in particular has infinite inertia, it is incapable of changing orientation, so from the time it is initialized, it should always have an orientation of 0, 0, 0, 1 regardless of the simulation. This implies the bug is caused by some intermediate external shenanigans, but I do not immediately see them in any of the posted code.
vendetta
Posts: 18
Joined: Sat Dec 31, 2011 7:49 pm

Re: Function does not accept floating point Not-a-Number val

Post by vendetta »

Hi Norbo,
I rewrote my replay code and found out that it was due to using a custom RingBuffer<> class from here.

I changed it to a fixed State[] array and i can no longer reproduce the bug.

Thanks for your help (even though it wasn't a problem directly with bepu, you still were a huge help)!
Post Reply