Abount quaternions and rotation

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
nikolaiko
Posts: 43
Joined: Mon Aug 04, 2014 8:26 am

Abount quaternions and rotation

Post by nikolaiko »

Hi, I working with BEPU engine for a while and have some questions about it.

1. I am using BEPUPhysics for server-side physics engine, and in the other hand - Unity to draw everything on client side. So, from client come request to move player in some direction (in other words it send request with desired speed vector). I am using CharacterController and set it's Body Linear Velocity property to this vector. But I want to rotate a body to this direction as well. All rotation and orientation operations are using quaternions, but I didn't understand it well (honestly didn't understand at all). So here is my code :

Code: Select all

Vector3 frd = CharacterController.Body.OrientationMatrix.Forward;

Vector3 refVector = (WalkDirection * MoveSpeed);
refVector = new Vector3(refVector.X, refVector.Y, refVector.Z * -1);

Quaternion rot;
Quaternion.GetQuaternionBetweenNormalizedVectors(ref frd, ref refVector, out rot);

Quaternion Target = Quaternion.Concatenate(CharacterController.Body.Orientation, rot);

//CharacterController.Body.Orientation = Quaternion.Slerp(CharacterController.Body.Orientation, Target, 5.0f);
CharacterController.Body.Orientation = Target;                                                         
So I getting actual forward direction. Multiplying speed vector from client with speed, then multiply Z part to -1 (I don't know why I need to do it, but for correct displaying in unity I need to do it). Then I took difference between actual and desired directions (orientations). And then add this difference to actual orientation. But on client it rotates character wrong. Maybe I doing something wrong? So :


2. I desided to do a simple app with BEPUPhysics (using XNAFramework). Add some entity's and try to rotate it in the same way. To see, maybe I am doing well, but problem in client side diasplaying. I created this app using some classes from demos, loaded static mesh, but didn't found any way to rotate it, so, how I can do it?


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

Re: Abount quaternions and rotation

Post by Norbo »

A couple of notes about character controller usage first:
I am using CharacterController and set it's Body Linear Velocity property to this vector.
Setting a CharacterController's LinearVelocity won't work very well in most cases. Its motion is controlled by the CharacterController.HorizontalMotionConstraint. It attempts to stop any motion which doesn't go along with the constraint's MovementDirection. So, if the MovementDirection is still at its default (0,0), the constraint will try to make the character stop relative to its support.
But I want to rotate a body to this direction as well.
I would recommend against rotating the CharacterController.Body. It's designed to have a fixed orientation- that's why the inertia tensor is infinite. No physical force can change its orientation or make it fall over.

Instead of rotating the character's body itself, I would recommend handling character facing direction in the gameplay logic and graphics side of things. For example, to draw the character with the right orientation, the graphical transform would take into the facing direction. It could additionally take into account the full view direction to transform the upper body or head to look up and down. (This approach captures more detail than the CharacterController.Body.Orientation version, since the body's orientation can't include any view pitch angle. It would make the whole cylinder tip over in a physically disruptive way.)

Check out the BEPUphysicsDemos CharacterControllerInput class for an example of how to control the character. Note the setting of both the CharacterController.HorizontalMotionConstraint.MovementDirection and CharacterController.ViewDirection in the Update method. The MovementDirection is interpreted based on the given ViewDirection.

Regarding the general transform manipulation issues:
So I getting actual forward direction. Multiplying speed vector from client with speed, then multiply Z part to -1 (I don't know why I need to do it, but for correct displaying in unity I need to do it). Then I took difference between actual and desired directions (orientations). And then add this difference to actual orientation. But on client it rotates character wrong. Maybe I doing something wrong?
One problem is that the Quaternion.GetQuaternionBetweenNormalizedVectors function assumes that the vectors it is given are unit length. Given that an orientation matrix is orthonormal, the 'frd' vector is unit length, but the refVector (WalkDirection * MoveSpeed) is not unit length.

Additionally, if the WalkDirection ever has any Y component (assuming the character's up direction is along the Y axis), the character's orientation could get into very strange states because it would include rotations which aren't strictly yawing. There's also the possibility that the character will rotate vertically rather than horizontally to reach a WalkDirection 180 degrees away from the current forward direction, since all rotations to the goal state are equally short.
2. I desided to do a simple app with BEPUPhysics (using XNAFramework). Add some entity's and try to rotate it in the same way. To see, maybe I am doing well, but problem in client side diasplaying. I created this app using some classes from demos, loaded static mesh, but didn't found any way to rotate it, so, how I can do it?
StaticMeshes are transformed by the AffineTransform passed into the constructor. Note the third parameter, from the StaticMeshDemo:

Code: Select all

var staticMesh = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(Matrix3x3.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), new Vector3(0, -10, 0)));
The affine transform is the combination of a linear transform (a 3x3 matrix) and a translation. To rotate it, pass in a different linear transform.

The transform can also be accessed after creating the mesh through the staticMesh.WorldTransform property.
nikolaiko
Posts: 43
Joined: Mon Aug 04, 2014 8:26 am

Re: Abount quaternions and rotation

Post by nikolaiko »

Thanks for the answer!

Looks like I worked in totaly wrong way all this time. :? Okey. I will try to fix this out. But I have some more questions.

1. I tried to use HorizontalMotionConstraint first. But I didn't found any way to set the speed of moving. I can set any vector, looks like HorizontalMotionConstraint.MovementDirection just setting direction. But how to set speed of moving direction?

2. So, you say it is better to forgot to Orientation property and work just with facing property. I know this question is beyond the engine, but how it should work? I mean, I need to create variable Facing and somehow connect it with Quaternion. Then user click some arrows I will receive Vector3 with desired direction. So, I will set direction of moving I will set HorizontalMotionConstraint.MovementDirection or LinearVelocity. Then I somehow modify Facing variable (without changing orientation or somethine else on server), and send it to client and client from this Facing variable will somehow create Quaternion to new rotation? The question is how to connect Facing variable with Vector3 and Quaternions. Maybe you know some links to sources there I can get some example of this mechanism?
nikolaiko
Posts: 43
Joined: Mon Aug 04, 2014 8:26 am

Re: Abount quaternions and rotation

Post by nikolaiko »

Ok, now I got it. I think.

I fixed issue with rotating, problem was in normalizing second vector. As Norbo mentioned in his post. And now my character is rotating very well, but I found one thing. Seems like engine in some reasons known only to it :) , some times or every update cycle just drop Body.Orientation to initial (0,0,0,1) values. And now I think I understand what, Norbo offered to do. I will declare separate variable of Quaternion class wich will store actual character facing. And I wil work with it.

But still I have some other questions, I will create another topic for it.

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

Re: Abount quaternions and rotation

Post by Norbo »

1. I tried to use HorizontalMotionConstraint first. But I didn't found any way to set the speed of moving. I can set any vector, looks like HorizontalMotionConstraint.MovementDirection just setting direction. But how to set speed of moving direction?
The character has different move speeds/forces depending on what state it is in. Check out the properties available in the CharacterController: StandingSpeed, CrouchingSpeed, AirSpeed, TractionForce, etc.

There's also a SpeedScale property if you want the character to move at a multiple of the specified speeds.
2. So, you say it is better to forgot to Orientation property and work just with facing property. I know this question is beyond the engine, but how it should work? I mean, I need to create variable Facing and somehow connect it with Quaternion. Then user click some arrows I will receive Vector3 with desired direction. So, I will set direction of moving I will set HorizontalMotionConstraint.MovementDirection or LinearVelocity. Then I somehow modify Facing variable (without changing orientation or somethine else on server), and send it to client and client from this Facing variable will somehow create Quaternion to new rotation? The question is how to connect Facing variable with Vector3 and Quaternions. Maybe you know some links to sources there I can get some example of this mechanism?
...
I will declare separate variable of Quaternion class wich will store actual character facing.
Unless you have some other system that is requires Quaternions, you don't need to deal with them at all. You can stick just to vectors and matrices if you are more comfortable with them.

For example, if all you want to do is make the character's graphical representation appear to be facing a certain direction represented by a Vector3, then the graphical world transform (usually represented as a Matrix) needs to take into account the view direction somehow. One option is to just use a helper function like Matrix.CreateWorld to create the transform from position, view direction, and up vector.
Seems like engine in some reasons known only to it :) , some times or every update cycle just drop Body.Orientation to initial (0,0,0,1) values.
The engine assumes the character controller can't rotate due to its infinite inertia tensor, so it never bothers doing any sort of orientation correction. I suspect something external is causing the orientation to reset.
Post Reply