HorizontalMotionConstraint.Update questions

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
ecosky
Posts: 69
Joined: Fri Nov 04, 2011 7:13 am
Contact:

HorizontalMotionConstraint.Update questions

Post by ecosky »

In HorizontalMotionConstraint.Update in the character controller, I noticed something that probably wasn't intended:

Code: Select all

	Plane plane = new Plane(character.SupportFinder.HasTraction ? supportData.Normal : supportData.Normal, 0);
Regardless of HasTraction, it uses the supportData.Normal.

I noticed this when my code managed to generate a NaN in this method due to the supportData.Normal being (0,0,-1) which led to the velocityDirection.Normalize() doing a divide by zero (the character is walking off the edge of a cube).

I'm curious, there is a comment about "This method can return false when the line is parallel to the plane, but previous tests and the slope limit guarantee that it won't happen.". I was looking for these tests and slope limits, and I'm not yet seeing what this is referring to. Anyone have any tips there?

Thanks
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: HorizontalMotionConstraint.Update questions

Post by Norbo »

In HorizontalMotionConstraint.Update in the character controller, I noticed something that probably wasn't intended:
Code:
Plane plane = new Plane(character.SupportFinder.HasTraction ? supportData.Normal : supportData.Normal, 0);

Regardless of HasTraction, it uses the supportData.Normal.
That is indeed not intended :)
I noticed this when my code managed to generate a NaN in this method due to the supportData.Normal being (0,0,-1) which led to the velocityDirection.Normalize() doing a divide by zero (the character is walking off the edge of a cube).

I'm curious, there is a comment about "This method can return false when the line is parallel to the plane, but previous tests and the slope limit guarantee that it won't happen.". I was looking for these tests and slope limits, and I'm not yet seeing what this is referring to. Anyone have any tips there?
The support data is created by the support finder which has a MaximumSlope limit (used to determine if it's sliding or not), but more importantly for this particular line, it has a SideContactThreshold. Any contact which is too far up violates the SideContactThreshold and is considered with a side contact or head contact as opposed to a support contact. So, it should not be possible for there to be a 'support' contact which has a normal that is perfectly horizontal. As long as the contact isn't completely horizontal, the line-plane test will find an intersection.

The fact that there was a horizontal normal there implies something snuck its way through or something interfered.

Is the problem reliably reproducible? Is this using the CharacterController, SphereCharacterController, or both?

I'd guess that it's caused by a supplemental down ray bypassing the protection, though I wouldn't expect it to be very reproducible. I'll upload a new development version in a little bit to see if I can fix it.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: HorizontalMotionConstraint.Update questions

Post by Norbo »

The development version now includes the extra protections: http://bepuphysics.codeplex.com/SourceC ... evelopment
ecosky
Posts: 69
Joined: Fri Nov 04, 2011 7:13 am
Contact:

Re: HorizontalMotionConstraint.Update questions

Post by ecosky »

Hi, and thanks for the quick and helpful response :)

I am using the standard character controller. To integrate it into my game, I had to make some very minor changes - namely, modify the input logic to use a CharacterInputState struct which is prepared externally rather than reading keyboard input directly. I'll paste it here so you can see what I mean and perhaps consider a similar pattern in the future because it helps with the task of integration.

Code: Select all

	/// <summary>
	/// This is used to keep track of the requested character input state.
	/// </summary>
	public struct CharacterInputState
	{
		[Flags]
		public enum InputFlagTypes : byte
		{
			Forward = 1,
			Backward = 1<<1,
			Left = 1 << 2,
			Right = 1 << 3,
			Crouch = 1 << 4,
			Jump = 1 << 5
		}
		public InputFlagTypes InputFlags;
	}
And down below..

Code: Select all

			//Collect the movement impulses.

			Vector3 movementDir;
			var flags = inputState.InputFlags;
			Matrix mat;
			cameraController.Camera.GetInvWorldMatrix(out mat);

			if ((flags & CharacterInputState.InputFlagTypes.Forward) != 0)
			{
				movementDir = mat.Forward;
				totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
			}
			if ((flags & CharacterInputState.InputFlagTypes.Backward) != 0)
			{
				movementDir = mat.Forward;
				totalMovement -= Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
			}
			if ((flags & CharacterInputState.InputFlagTypes.Left) != 0)
			{
				movementDir = mat.Left;
				totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
			}
			if ((flags & CharacterInputState.InputFlagTypes.Right) != 0)
			{
				movementDir = mat.Right;
				totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
			}
			if (totalMovement == Vector2.Zero)
				CharacterController.HorizontalMotionConstraint.MovementDirection = Vector2.Zero;
			else
				CharacterController.HorizontalMotionConstraint.MovementDirection = Vector2.Normalize(totalMovement);

			CharacterController.StanceManager.DesiredStance = (flags & CharacterInputState.InputFlagTypes.Crouch) != 0 ? Stance.Crouching : Stance.Standing;

			//Jumping
			if ((flags & CharacterInputState.InputFlagTypes.Jump) != 0)
			{
				CharacterController.Jump();
			}

Anyway, back to the problem. I should mention I am using my own Collidable here. I am working on a voxel based game where a 3d array of voxels are managed by a single Collidable because I understand this is the best way to get the most performance in that situation. It's implemented, seems efficient, and works as far as I can tell. It has been providing correct ray casting results for some time now, but I am just now starting to test the rest of the physics. It seems to be mostly working with little things like this coming up. So far the problems have been my fault, and I wouldn't be surprised if my trouble is my own doing here.

That being said, it was 100% reproducible. I'll grab your update, see how it affects it and let you know what I find out. Thanks for your time!
ecosky
Posts: 69
Joined: Fri Nov 04, 2011 7:13 am
Contact:

Re: HorizontalMotionConstraint.Update questions

Post by ecosky »

That fixed it. I'm not sure what exactly triggered this edge case but I suppose its probably a byproduct of the entire environment being axis aligned cubes.
Thanks again!
Post Reply