(Model) Rotation with an Offset

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
reeda1283
Posts: 20
Joined: Fri Dec 16, 2011 10:12 am

(Model) Rotation with an Offset

Post by reeda1283 »

Hi again Norbo:)

I am in need of some help, but I fear it may involve a greater understanding of linear algebra than I currently have. This is what I am trying to do:

1. Take an object (from a transformable shape, specifically) with an offset AND rotation (rotation is handled by the BEPU entity).
2. Display that model with the proper offsets :)

I am running into two issues:

I cannot simply use the WorldTransform of my entity, because it does not have scale applied (any possibility it will, someday?), so I have to build my world matrix from scratch (I think). The problem with that, is that I do not know how to get a world matrix that includes the entity's rotation/orientation, mainly because all I have been doing is Matrix.CreateTranslation, Matrix.CreateScale etc. :(

I feel there is something simple, be it a concept or technique, that I am missing here.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: (Model) Rotation with an Offset

Post by Norbo »

I cannot simply use the WorldTransform of my entity, because it does not have scale applied (any possibility it will, someday?)
Nope; the WorldTransform is the combined Position and Orientation of the entity. The scaling is a property of the shape, not the Entity itself, so the WorldTransform is oblivious to it. The world transform just pushes the collidable from its local space into world space. If the world transform included scaling, it would essentially be applying the scaling twice.
so I have to build my world matrix from scratch (I think). The problem with that, is that I do not know how to get a world matrix that includes the entity's rotation/orientation, mainly because all I have been doing is Matrix.CreateTranslation, Matrix.CreateScale etc.
Let's say you start with a mesh, and you create some entity that matches the mesh when it's unscaled. A transform is created which offsets the graphical mesh to match the physical mesh so that the graphic and collision shape match properly (more information can be found here: viewtopic.php?f=4&t=1511). For a ConvexHullShape whose center is not trivial to compute, the computed center is output for you to use. That center is the offset applied to the vertices to recenter the shape on the origin. Other shapes like BoxShape or SphereShape are created already centered on the origin- if your model is being approximated by one of those, you'll need to find some decent approximate offset to get the model to match.

At this point, if you told your entity go to some position and orientation, the already locally offset graphic should be transformed by the entity's WorldTransform. So the combined graphic world transform would look something like:

Code: Select all

effect.World = localOffsetTransform * entity.WorldTransform;
Recall that we had the graphic matching the collision shape in local space. Now that the same entity.WorldTransform has been applied to both the collision shape and the graphic (they are now in 'world space' instead of local space), they are still aligned.

So let's take a step back and try to implement scaling. As I mentioned earlier, scaling is a property of a collision shape as opposed to a Entity, so we need to change the shape. Whatever convex collision shape we were using before can be tossed into a TransformableShape.

It's important to note that the TransformableShape will not output an offset to apply to your graphic. Any ConvexShape that is given to the TransformableShape has already been centered on the local origin, so the TransformableShape doesn't have to bother. So, the graphic's local offset must be computed using the first shape.

The linear transform of the TransformableShape can then be set to the desired scale. Keep that transform handy; you'll apply it after the local offset. It is applied after the offset because the offset pulls the graphic onto the collision shape's local origin. If the scaling were applied first, the vertices would be scaled but in the wrong location.

After the offset and scale are applied, the graphic once again matches the collision shape's local space representation. From there, all you have to do is pull it into world space by multiplying by the world transform:

Code: Select all

effect.World = localOffsetTransform * scaleTransform * entity.WorldTransform;
reeda1283
Posts: 20
Joined: Fri Dec 16, 2011 10:12 am

Re: (Model) Rotation with an Offset

Post by reeda1283 »

Hey Norbo,
As always, thanks for the insight. Your answer not only solved my problem, but gave me a much better idea how Matrices work in general.

Thanks again for your awesome support of your awesome engine.
grimm
Posts: 1
Joined: Mon Feb 06, 2012 9:07 am

Re: (Model) Rotation with an Offset

Post by grimm »

Hi guys i was trying to start with bepu and i found this post very helpfull in understanding it, unfortunately i have a question about the way you are performing transforms. While you are doing location * scale * globals according to the wikipedia a transformation of a single vertex is in the form of A = T * V and not the other way around since the product is a dot product of rows v columns, therefore you cannot switch the two around more over the following should be the case unless im misunderstanding
V= vertex info
l = local position
L = global position
s = local scale
S = global scale
r = local rotation
R = global rotation
giving us a recursive sort of transformation chain.

L(R(S(l(r(sV))) Which in turn is the opposite of the described, and in fact what makes PushMultiply work so well in opengl when building scene graphs.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: (Model) Rotation with an Offset

Post by Norbo »

XNA uses row-major matrices. OpenGL uses column-major matrices. More information can be found here: http://forums.create.msdn.com/forums/p/ ... 44974.aspx

In other words, the nested transformations you describe is the same order as in my earlier post, just in a different format.

For example, transformed == transformed2:
Vector3 toTransform = new Vector3(1,2,3);

Matrix transformA = Matrix.CreateTranslation(new Vector3(10, 0,0));
Matrix transformB = Matrix.CreateRotationX(MathHelper.PiOver2);

Vector3 transformed = Vector3.Transform(toTransform, transformA * transformB);
Vector3 transformed2 = Vector3.Transform(Vector3.Transform(toTransform, transformA), transformB);
Post Reply