How to do collision resolution correctly

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

How to do collision resolution correctly

Post by mos »

UPDATE:
Game1.cpp: https://gist.github.com/anonymous/b6574 ... 7b5dd63205
ConvertTo.cpp: https://gist.github.com/anonymous/39664 ... b15467964c

The three models are the default cubes from Blender with different colored materials on them.

------------------------------------------------------------------------------------

Original question:
I am new to 3D game development and stumbled upon BEPU physics engine. I am using MonoGame and installed BEPU Physics via NuGet.

I tried to follow the getting started page: http://bepuphysics.codeplex.com/wikipag ... umentation and was able to move a Box around.

However, the collision resolution is very weird. One cube is dynamic and the other is kinematic. When I move the dynamic one left and right, it doesn't slide smoothly (especially if I move to the edge of the other cube and move back). If I jump, it doesn't land perfectly either. It starts going a little crazy and becomes hard to control.

I have this to control:

Code: Select all

Space world;
Model cube;
Box cubeBox;

cube = this.Content.Load<Model>("Cube");
cubeBox = new Box(BEPUutilities.Vector3.Zero, 2f, 2f, 2f);
world.Add(cubeBox);

if(current != previous)
{
    if (Keyboard.GetState().IsKeyDown(Keys.Left))
        sphereBox.LinearVelocity += new BEPUutilities.Vector3(5f, 0f, 0f);

    if (Keyboard.GetState().IsKeyDown(Keys.Right))
        sphereBox.LinearVelocity -= new BEPUutilities.Vector3(5f, 0f, 0f);

    if (Keyboard.GetState().IsKeyDown(Keys.Space))
        sphereBox.LinearVelocity += new BEPUutilities.Vector3(0f, 5f, 0f);
}
Whole code: https://gist.github.com/anonymous/f4a8a ... 63ca9af325
Whole project (Visual Studio 2015): http://www.mediafire.com/download/i8uwf ... PUTest.zip
The cube is the default cube from Blender exported as a .dae.

Any help would be appreciated. Thank you!
Last edited by mos on Sun Sep 18, 2016 9:44 pm, edited 1 time in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: How to do collision resolution correctly

Post by Norbo »

At a glance, there may be two problems:
1) The world matrix used to draw the boxes only includes translation. For the nonrotating kinematic, that's not an issue, but for the dynamic object it will cause a mismatch between the graphics and physics. Note that the Entity has a convenience property called WorldTransform that you can use for this purpose.
2) Make sure that the graphic is drawn with the same local origin as the physics. For example, if the default blender cube has the origin at the bottom of the box, it would be offset from the physics because the local origin of rotation in a BEPUphysics box shape (and all other shapes) is at its center of mass. To fix it, the graphics should be locally offset to match the physics. For a more thorough explanation, check this documentation.
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

Re: How to do collision resolution correctly

Post by mos »

Thanks for the reply. Are you saying I should be doing effect.World = sphereBox.WorldTransform * Translation? If so, effect.World only takes the XNA Framework Matrix and not BEPUutilities. How would I convert sphereBox.WorldTransform to a XNA Matrix?

Luckily, the origin was at the center of the cube already so #2 shouldn't be an issue.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: How to do collision resolution correctly

Post by Norbo »

The WorldTransform already includes translation, so there is no need to re-include it. To convert the matrix type, just set the fields to the same values (M11, M12...). They are pretty much identical in structure.
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

Re: How to do collision resolution correctly

Post by mos »

Thank you so much! It works so much better now. Can I ask you one more question? What is the proper way to set the scale?

I created this conversion method:

Code: Select all

public static Matrix XNAMatrix(BEPUutilities.Matrix bepuMatrix)
{
	Matrix xnaMatrix = new Matrix();

	xnaMatrix.M11 = bepuMatrix.M11;
	xnaMatrix.M12 = bepuMatrix.M12;
	xnaMatrix.M13 = bepuMatrix.M13;
	xnaMatrix.M14 = bepuMatrix.M14;

	xnaMatrix.M21 = bepuMatrix.M21;
	xnaMatrix.M22 = bepuMatrix.M22;
	xnaMatrix.M23 = bepuMatrix.M23;
	xnaMatrix.M24 = bepuMatrix.M24;

	xnaMatrix.M31 = bepuMatrix.M31;
	xnaMatrix.M32 = bepuMatrix.M32;
	xnaMatrix.M33 = bepuMatrix.M33;
	xnaMatrix.M34 = bepuMatrix.M34;

	xnaMatrix.M41 = bepuMatrix.M41;
	xnaMatrix.M42 = bepuMatrix.M42;
	xnaMatrix.M43 = bepuMatrix.M43;
	xnaMatrix.M44 = bepuMatrix.M44;

	return xnaMatrix;
}
I set effect.World to this:

Code: Select all

ConvertTo.XNAMatrix(playerBox.WorldTransform)
This works perfectly. When I set the scale, I do

Code: Select all

ConvertTo.XNAMatrix(BEPUutilities.Matrix.CreateScale(0.5f, 0.5f, 0.5f) * playerBox.WorldTransform)

and the model become smaller; however, the Box remains the same width, length and height. You can see the scaled model just above whatever it is colliding with.

I tried making the box smaller in combination with the CreateScale method like this:

Code: Select all

playerBox.Width = 0.5f;
playerBox.Length = 0.5f;
playerBox.Height = 0.5f;
But this makes the model go slightly through whatever it is colliding with. How would I do this correctly?

Again thank you so much for the help!
Last edited by mos on Sun Sep 18, 2016 8:11 pm, edited 1 time in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: How to do collision resolution correctly

Post by Norbo »

If the graphic originally matched the physics when the physics was 2 units wide, and then you halved the graphical size down to 1 unit wide, then the physics should be 1 unit wide to match. In that code you directly set it to 0.5, rather than multiplying by 0.5. :)
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

Re: How to do collision resolution correctly

Post by mos »

Oooh, makes so much sense now. Thank you for all your help! :D
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

Re: How to do collision resolution correctly

Post by mos »

I have another problem if you don't mind helping again. When I press up, I add to the linear velocity in the Z direction. If there is a wall there, it will collide perfectly fine. However, if I hold Up while colliding with the wall, my model will stay there and not fall. It starts falling if I try to move left and right. Looks like this:

Image

It's the black cube here. I want it to be falling even if I'm holding Up and adding the velocity in the z direction. My code looks like this in the Update() method:

Code: Select all

if (Keyboard.GetState().IsKeyDown(Keys.Up))
	    playerBox.LinearVelocity += new BEPUutilities.Vector3(0f, 0f, 1f);
How can I make it so it slides down when there is nothing underneath the black cube instead of it just sticking to the wall while holding Up? I'm guessing this will happen in other directions too.

Whole code: https://gist.github.com/anonymous/8da83 ... b5fd62d233
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: How to do collision resolution correctly

Post by Norbo »

If I understand the situation right (I admit I'm kinda just glancing at things :)), it's probably just friction. If adding velocity along z pushes it into the wall, it will cause a force that counteracts tangential motion, including gravity. If it's stationary, the higher static coefficient will be used, making it even more likely to 'stick'. You can change the friction of an object by setting the Entity.Material.KineticFriction and StaticFriction properties. Note that the default MaterialManager.MaterialBlender uses multiplicative blending, so setting 0 friction on one of the two involved objects will make the pair have zero friction.
mos
Posts: 12
Joined: Sat Sep 17, 2016 3:21 am

Re: How to do collision resolution correctly

Post by mos »

Thank you very much! Didn't know there were friction settings. Setting kinetic friction to 0.3 made it work really good.
Post Reply