Page 1 of 1

Compound Body entity with boxes. Incorrect local transform.

Posted: Sat Apr 16, 2011 1:34 pm
by Spankenstein
I've created a compound bound from a series of boxes:

Code: Select all

            int numVoxels = voxelAnimator.VoxelSettings.Length;

            List<CompoundShapeEntry> boxes = new List<CompoundShapeEntry>(numVoxels); 

            for (int i = 0; i < numVoxels; ++i)
            {
                BoxShape box = new BoxShape(
                    voxelAnimator.VoxelSettings[i].Size,
                    voxelAnimator.VoxelSettings[i].Size,
                    voxelAnimator.VoxelSettings[i].Size
                    );

                boxes.Add(
                    new CompoundShapeEntry(
                        box,
                        voxelAnimator.VoxelSettings[i].Position
                    )
                );
            }

            entity = new CompoundBody(boxes);
The problem is that when I draw the original voxels and the white compound body they are not in the same place:

Image

How can I make sure the compound body is centered correctly?

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sat Apr 16, 2011 6:36 pm
by Norbo
The Position of the CompoundBody immediately after construction is the offset that needs to be applied to the graphic.

It's also possible to get the data from the CompoundShape constructor if you were making one to re-use with multiple entities (it has an out parameter in one of its constructors for the computed center position).

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sat Apr 16, 2011 7:29 pm
by Spankenstein
I'm using the compound body world transform to transform the voxel positions:

Code: Select all

            int numQuadrangles = voxelAnimator.Quadrangles.Length;

            for (int i = 0; i < numQuadrangles; ++i)
            {
                quadrangles[i].Transform(entity.WorldTransform);
            }
Are you saying that I need to apply an offset of:

Code: Select all

Matrix.CreateTranslation(-ComputedCenter())
giving:

Code: Select all

quadrangles[i].Transform(Matrix.CreateTranslation(-ComputedCenter()) * entity.WorldTransform);
each frame. Wouldn't that upset other calculations based on the entity position?

Also, BoxShape doesn't provide a constructor with an out parameter like TriangleShape does?

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sat Apr 16, 2011 7:58 pm
by Norbo
Yes, create a transform that essentially recenters the graphic to the origin of the compound before applying the entity's world transform. It shouldn't cause any problems; it's just changing the location at which the graphic is located. It never affects the physics in any way, and only reads from the physics system at initialization once.
Also, BoxShape doesn't provide a constructor with an out parameter like TriangleShape does?
Correct; BoxShapes (and some other ones like SphereShape, ConeShape, etc.) are built already centered. If it had an out parameter, it would always be Vector3.Zero. Only shapes that require recentering have an out parameter.

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sat Apr 16, 2011 9:09 pm
by Spankenstein
It shouldn't cause any problems; it's just changing the location at which the graphic is located. It never affects the physics in any way, and only reads from the physics system at initialization once.
The problem is that I just can't get my head around it. For example, if I create a Compound Body made from one cube with a position at the origin:

Code: Select all

            BoxShape box = new BoxShape(1f, 1f, 1f);
            boxes.Add(new CompoundShapeEntry(box, Vector3.Zero));
The compound body position is not centered around the origin, even though it's world transform translation is (0, 0 ,0). Why would this be the case?!
Correct; BoxShapes (and some other ones like SphereShape, ConeShape, etc.) are built already centered. If it had an out parameter, it would always be Vector3.Zero. Only shapes that require recentering have an out parameter.
So what can I use to recenter the compound body around the origin permanently?

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sat Apr 16, 2011 9:38 pm
by Norbo

Code: Select all

           var boxes = new List<CompoundShapeEntry>();
            BoxShape box = new BoxShape(1f, 1f, 1f);
            boxes.Add(new CompoundShapeEntry(box, Vector3.Zero));
            CompoundBody body = new CompoundBody(boxes);
Using that, body.Position is Vector3.Zero, as expected. Additionally, body.WorldTransform.Translation is also Vector3.Zero, as expected- the WorldTransform property is just a convenience property that uses the Position and Orientation(Matrix).

Code: Select all

            var boxes = new List<CompoundShapeEntry>();
            BoxShape box = new BoxShape(1f, 1f, 1f);
            boxes.Add(new CompoundShapeEntry(box, new Vector3(1, 1, 1)));
            CompoundBody body = new CompoundBody(boxes);
Note the different local translation on the CompoundShapeEntry. If you look at the body.Position on this version, it says (1,1,1), since that's the location of the center of the compound shape (which, in this example, is a single shape at (1,1,1)). Internally, the CompoundShape stores the BoxShape with a local transformation with translation of (0,0,0), since the subshape is perfectly aligned with the compound local origin (because it's the only shape).

Code: Select all

            var boxes = new List<CompoundShapeEntry>();
            boxes.Add(new CompoundShapeEntry(new BoxShape(1f, 1f, 1f), new Vector3(1, 1, 0)));
            boxes.Add(new CompoundShapeEntry(new BoxShape(1f, 1f, 1f), new Vector3(-1, 1, 0)));
            CompoundBody body = new CompoundBody(boxes);
The above shows a two-box body. The body.Position is now (0,1,0), since that's the weighted average of the locations of the shapes. The internal local transformations of the box shapes in the compound shape are (1,0,0) and (-1,0,0).

So let's imagine you had a graphic that was created such that its local origin was at (0,0,0) and the box shape models were positioned at (1,1,0) and (-1,1,0). If the compound didn't move and you just directly rendered the graphic without transforming it using the entity's position, the shapes would match.

However, because the entity's transform now includes an offset, you need to apply the reverse offset to the graphic to realign them. In other words, apply a local transform of -InitialCenterOffset (where InitialCenterOffset = body.Position right after initialization) before applying entity.WorldTransform.

Re: Compound Body entity with boxes. Incorrect local transf

Posted: Sun Apr 17, 2011 10:27 am
by Spankenstein
Thanks for taking the time to explain. I understand what is going on now.