notgiven688/jitterphysics2

Converting XNA Matrix to JMatrix for TransformedShape

captainkidd5 opened this issue · 6 comments

It seems my rotated models are appearing different than the collision shapes in Jitter. Here is how I'm converting them:

public static JMatrix ToJMatrix(this Matrix matrix) { return new JMatrix( matrix.M11, matrix.M12, matrix.M13, matrix.M21, matrix.M22, matrix.M23, matrix.M31, matrix.M32, matrix.M33 ); }

Is this correct?

I'm then creating a transformedshape:

TransformedShape tfs1 = new(boxShape, center,rotationMatrix.ToJMatrix());

This looks okay. It depends on the definition of your transformations. Did you try to set the transpose, i.e. flipping Mxy to Myx. If this does not resolve the problem you can try to debug the transformation by utilizing RigidBody.DebugDraw to show where Jitter sees the shape in world space.

Okay I had no idea about the debug drawer, very handy thank you.

For any XNA/Monogame user which might stumble upon this in the future, here's a rough implementation of the IDebugDrawer I quickly whipped up. It's not terribly efficient and has a lot of room for improvement but it should give you a base.

public class JitterDebugDrawer : IDebugDrawer
 {
     private GraphicsDevice _graphics;
     private BasicEffect _basicEffect;
     private VertexPositionColor[] _verticies;
     private ushort _vertexCount;
     private ushort _triangleCount;
     public JitterDebugDrawer(GraphicsDevice graphics)
     {
         _graphics = graphics;
         _basicEffect = new BasicEffect(_graphics);
     }


     public void DrawPoint(in JVector p)
     {
         var vertices = new[] { new VertexPositionColor(p.ToXnaVector(), Color.Red) };
         _graphics.DrawUserPrimitives(PrimitiveType.PointList, vertices, 0, 1);
     }

     public void DrawSegment(in JVector pA, in JVector pB)
     {
         var vertices = new[] { new VertexPositionColor(pA.ToXnaVector(), Color.Blue), new VertexPositionColor(pB.ToXnaVector(), Color.Blue) };
         _graphics.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);
     }
     public void PrepareForRigidBody()
     {
         _vertexCount = 0;
         _triangleCount = 0;

         RasterizerState rasterState = new RasterizerState();
         rasterState.CullMode = CullMode.CullCounterClockwiseFace;
         _graphics.RasterizerState = rasterState;

         _basicEffect.View = Game1.Camera3D.ViewMatrix;
         _basicEffect.Projection = Game1.Camera3D.ProjectionMatrix;
         _basicEffect.CurrentTechnique.Passes[0].Apply();

         _basicEffect.VertexColorEnabled = true;
         _verticies = new VertexPositionColor[ushort.MaxValue];

     }

     public void DrawRigidBody()
     {
         _graphics.DrawUserPrimitives(PrimitiveType.TriangleList, _verticies, 0, _triangleCount);

     }
     public void DrawTriangle(in JVector pA, in JVector pB, in JVector pC)
     {
         _verticies[_vertexCount] = new VertexPositionColor(pA.ToXnaVector(), Color.Green);
         _vertexCount++;
         _verticies[_vertexCount] = new VertexPositionColor(pB.ToXnaVector(), Color.Green);
         _vertexCount++;

         _verticies[_vertexCount] = new VertexPositionColor(pC.ToXnaVector(), Color.Green);
         _vertexCount++;

         _triangleCount++;

     }
 }

When drawing a rigid body elsewhere in your code, call

PrepareForRigidBody();

then call Body.DebugDraw

then finally call DrawRigidBody()

At least this way you're doing a little bit of batching

Very nice. Have you been able to debug/fix the problem with the XNA<->Jitter conversion?

Unfortunately not. Here's my code for placing the rigid body on top of the visual model. Note that I am extracting bounding boxes from my mesh and using those as a list of shapes. From the gif you can see that the correct mesh is placed when no rotation occurs, but things go south quickly with any sort of rotation. It could very well be that my math is off however, as some of the boxes seems to be completely out of place in relation to one another
rigidbody_rotation_issue
:


     public void CreateFromMeshes(VoxelModel voxelModel, Vector3 position, Quaternion rotation)
     {

         ColliderType = ColliderType.Static;
         List<Shape> shapes = new();

         List<BoundingBox> boundingBoxes = VertexElementExtractor.CreateBoundingBox(voxelModel.StructureInfo.CollisionModel);
         foreach (BoundingBox boundingBox in boundingBoxes)
         {
             Vector3 center = (boundingBox.Max + boundingBox.Min) * 0.5f;

             Vector3 boxDimensions = boundingBox.Max - boundingBox.Min;

             rotation.Normalize();

             Matrix rotationMatrix = Matrix.CreateFromQuaternion(rotation);

             BoxShape boxShape = new BoxShape(boxDimensions.ToJitterVector());
             TransformedShape tfs1 = new(boxShape, center.ToJitterVector(),rotationMatrix.ToJMatrix());
             shapes.Add(tfs1);
      
         }

         CreateBody(World.CreateRigidBody());

         Body.Tag = this;
         Body.AddShape(shapes);
         Body.IsStatic = true;
         Body.Position = position.ToJitterVector();

     }

Also, I wasn't sure what you meant by

Did you try to set the transpose, i.e. flipping Mxy to Myx

Edit: I tried the following

       public static JMatrix ToJMatrix(this Matrix matrix)
       {
           return TransposeMatrix( new JMatrix(
               matrix.M11, matrix.M12, matrix.M13,
               matrix.M21, matrix.M22, matrix.M23,
               matrix.M31, matrix.M32, matrix.M33
           ));
       }

       public static JMatrix TransposeMatrix(JMatrix matrix)
       {
           return new JMatrix(
               matrix.M11, matrix.M21, matrix.M31,
               matrix.M12, matrix.M22, matrix.M32,
               matrix.M13, matrix.M23, matrix.M33
           );
       }

to no avail

This looks interesting. Is there a reason why you do not just build the (unrotated) house using box shapes and then apply the rotation and position of the house to the body, i.e.

...
Body.Position = position.ToJitterVector();
Body.Orientation = rotationMatrix;

?

Oh. I had no idea you could do that. Yes that completely solved it lol. Thank you a bunch, also I've made a pull request to add JitterPhysics2 to the official Monogame suggested libraries (there currently are no suggested 3D physics engines!) so hopefully that gets merged soon! Thanks for all your hard work