CompoundBody centre is not central?

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

CompoundBody centre is not central?

Post by Spankenstein »

I'm creating a CompoundBody from a list of indices and vertices which gives me a local offset for the final entity.

Code: Select all

            Vector3[] vertices = voxelMesh.Vertices;
            int[] indices = voxelMesh.Indices;

            int numIndices = indices.Length;
            int numTriangles = vertices.Length;

            var scaleTransform = Matrix.CreateScale(ScaleFactor);

            List<CompoundShapeEntry> triangles = new List<CompoundShapeEntry>(numIndices / 3);

            for (int i = 0; i < numIndices; i += 3)
            {
                // [Recentered Triangle]
                Vector3 centre;
                TriangleShape tri = new TriangleShape(
                    Vector3.Transform(vertices[indices[i]], scaleTransform),
                    Vector3.Transform(vertices[indices[i + 1]], scaleTransform),
                    Vector3.Transform(vertices[indices[i + 2]], scaleTransform),
                    out centre
                    );

                tri.Sidedness = TriangleSidedness.DoubleSided;

                triangles.Add(new CompoundShapeEntry(tri, centre, 1f));
            }

            entity = noMass ? new CompoundBody(triangles) : new CompoundBody(triangles, settings.Mass);

            // Set the centre/origin offset created by CompoundBody
            entityCentreOffset = Matrix.CreateTranslation(-entity.Position);                // Works correctly for scaling
The problem is that this is not always central.

For example using an offset of -entity.Position will result in the physics mesh (white wireframe) and model aligning but with a pivot point (yellow box) that is not central

Image

Whereas if I use an offset that is central to the model then I get a central pivot point but with a physics mesh that is not central (more pronounced when scaling)

Image

I am scaling the object using

Code: Select all

voxelMesh.WorldTransform = Matrix.CreateScale(ScaleFactor) * entityCentreOffset * entity.WorldTransform;
How can I correctly align the physics mesh (entity) to the central pivot point?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

While the compound body is computing the correct center of mass, it sounds like you want to offset the physics shape from the 'true' center of mass so that it rotates around an arbitrarily defined pivot point. If that's what you want, then the entity.CollisionInformation.LocalPosition will do the trick.

Setting the LocalPosition pushes the collision shape away from the entity.Position in the direction of Vector3.Transform(entity.CollisionInformation.LocalPosition, entity.Orientation). If you want to treat the origin of the graphics model as the pivot point, then instead of transforming the graphics model by the offset, move the collision shape by the offset with LocalPosition. The graphics and physics will still align, but rotation will be around the graphics origin.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

Not sure I follow what you are saying.

Both of the following have the same effect

Code: Select all

            entity.CollisionInformation.LocalPosition = entity.Position;
            //entity.CollisionInformation.LocalPosition = voxelMesh.PivotPoint;
with

Code: Select all

            voxelMesh.WorldTransform = Matrix.CreateScale(ScaleFactor) * entity.WorldTransform;
            voxelMesh.Draw(gameTime);
The mesh is positioned with a large offset from the model.

Image

The pivot point is not central to the model or the physics mesh.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

So long as you apply consistent transforms on both the graphics and the mesh, they will stay aligned. Focus on getting it aligned without performing any world space transforms yet; just get the local spaces consistent. Once they are consistent in local space, applying the world transform to both will work.

You started with alignment between the physics and graphics by offsetting the graphic by the initially computed center. If you want the graphics to move left by 1 unit in local space and you want the physics to match, the physics must be moved left by 1 unit in local space. To move the collision representation in local space, use the entity.CollisionInformation.LocalPosition. So, start with proper alignment and then add in the local offset to the graphics and the physics, and they will still be aligned.

Try this with an arbitrary fixed value to see how it works.

Once that is up and running, it's a matter of choosing the correct value for the offset to produce the desired effect.

(The special case of this I was talking about in my previous post where you want to use the graphical model's origin just requires using the recentering output to offset the pieces consistently, assuming the graphical model was the input mesh or had an origin consistent with the graphical model.)
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

I think another problem lies with my wireframe representation.

Code: Select all

        private void DrawWireFrame(GameTime gameTime)
        {
            CompoundBody body = entity as CompoundBody;
            TriangleShape tri;
            Vector3 v0;
            Vector3 v1;
            Vector3 v2;

            int numShapes = body.Shapes.Count;

            for (int i = 0; i < numShapes; ++i)
            {
                tri = body.Shapes[i].Shape as TriangleShape;

                v0 = Vector3.Transform(tri.VertexA, body.Shapes[i].LocalTransform.Matrix);
                v1 = Vector3.Transform(tri.VertexB, body.Shapes[i].LocalTransform.Matrix);
                v2 = Vector3.Transform(tri.VertexC, body.Shapes[i].LocalTransform.Matrix);

                game.WireShapeDrawer.DrawTriangle(
                    Vector3.Transform(v0, entity.WorldTransform),
                    Vector3.Transform(v1, entity.WorldTransform),
                    Vector3.Transform(v2, entity.WorldTransform),
                    Color.White
                    );
            }
        }
The LocalTransform.Matrix does not appear to be affected when setting the LocalPosition

Code: Select all

entity.CollisionInformation.LocalPosition(vec3value);
Therefore the representation of the entity is not correct using the method above. Why does the LocalPosition not affect the LocalTransform?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

A compound child's LocalTransform is a property of the shape. The entity.CollisionInformation.LocalPosition is a property of the collidable. The collidable's LocalPosition cannot affect the shape's properties because the shape can be shared between multiple collidables. You can think of it as being a different local space; the colliable's LocalPosition can offset the shape's local space away from the entity's center of mass.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

So how do I incorporate the LocalPosition into the final transformed position (world space)

Should I translate the local shape transformation vertices by the offset?

Code: Select all

        private void DrawWireFrame(GameTime gameTime)
        {
            CompoundBody body = entity as CompoundBody;
            TriangleShape tri;
            Vector3 v0;
            Vector3 v1;
            Vector3 v2;

            int numShapes = body.Shapes.Count;

            for (int i = 0; i < numShapes; ++i)
            {
                tri = body.Shapes[i].Shape as TriangleShape;

                v0 = Vector3.Transform(tri.VertexA, body.Shapes[i].LocalTransform.Matrix);
                v1 = Vector3.Transform(tri.VertexB, body.Shapes[i].LocalTransform.Matrix);
                v2 = Vector3.Transform(tri.VertexC, body.Shapes[i].LocalTransform.Matrix);

                v0 += entity.CollisionInformation.LocalPosition;
                v1 += entity.CollisionInformation.LocalPosition;
                v2 += entity.CollisionInformation.LocalPosition;

                game.WireShapeDrawer.DrawTriangle(
                    Vector3.Transform(v0, entity.WorldTransform),
                    Vector3.Transform(v1, entity.WorldTransform),
                    Vector3.Transform(v2, entity.WorldTransform),
                    Color.White
                    );
            }
        }
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

Yup.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

In that case the model must have its own special transform to match the entity. I cannot simply have

Code: Select all

voxelMesh.WorldTransform = Matrix.CreateScale(ScaleFactor) * entity.WorldTransform;
The above only works when using the true centre of mass as the LocalPosition offset

Code: Select all

entity.CollisionInformation.LocalPosition = entity.Position;
That places the pivot point at the bottom left of the mesh

Image

How must I change the model mesh in this case?

EDIT:

To centralise around the model mesh pivot point I can use:

Code: Select all

entity.CollisionInformation.LocalPosition = entity.Position - voxelMesh.PivotPoint;
Now I just need to correctly align the mesh
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

To find the right local transform, recall that, if they start in alignment with each other, applying the same transform to the local space of the graphic and to the local space of the shape will result in the graphic and shape still being in alignment. Consistency is key :)
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

I thought that at first but it turns out I require

Collision Mesh

Code: Select all

entity.CollisionInformation.LocalPosition = entity.Position - (voxelMesh.PivotPoint * ScaleFactor);
Model

Code: Select all

voxelMesh.WorldTransform = Matrix.CreateTranslation(-voxelMesh.PivotPoint) * Matrix.CreateScale(ScaleFactor) * entity.WorldTransform;
I don't see the consistency between the two but maybe I have the wrong approach? It works perfectly for all models and pivot points.

Perhaps it is because the entity.Position offset is not required for the model because of a true centre of mass is not calculated for the model?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CompoundBody centre is not central?

Post by Norbo »

Perhaps it is because the entity.Position offset is not required for the model because of a true centre of mass is not calculated for the model?
Yup. The important thing to note is that an additional transform applied to both will only result in alignment if the two objects started in alignment. Once any misalignment is directly addressed with an offset on one or the the other, any additional transform applied to both will result in continued alignment.

Starting with misalignment and applying the same transform to both will just end up with a 'consistently' transformed set of misaligned objects.
Spankenstein
Posts: 249
Joined: Wed Nov 17, 2010 1:49 pm

Re: CompoundBody centre is not central?

Post by Spankenstein »

Excellent. Case solved! Thanks for the guidance :)
Post Reply