World Location to Entity-centered Local Position

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

World Location to Entity-centered Local Position

Post by mcmonkey »

Let's say I have a point in world space.
This point is roughly 3 units to the left of a box.
I want to get this point's "local" point relative to the box. (EG, (3,0,0))
I want to then render something at that local point.
That way, if the entity moves or rotates, the point stays at the correct location relative to it...
and thus the rendered item appears to be part of the entity, rather than moving about on its own.

My end goal is the above, a rendered-only item appearing to be attached to an entity (the item initially is added in world space and then is attached to the entity from there)
The solution I came from is the world->local and local->world position conversions... but this doesn't account rotating the item, rather just moving it about in space.
How should I go about accomplishing this?

The best method I can come up with involves using the worldtransform/inverse of worldtransform to transform the point around and converting the quaternion to euler angles and adding/subtracting relative amounts... neither of which are particularly quick calculations, and I'd ideally want to do this for a lot of items at a pleasant 60 FPS.

(Sorry for bugging you with so many questions here, particularly when this question is not incredibly BEPU-specific... just, you're quick and helpful, and stackoverflow is neither... particularly when physics engines get involved)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: World Location to Entity-centered Local Position

Post by Norbo »

I suspect a 4x4 matrix inversion on every object would still be plenty fast enough (unless this is running on a phone, and even then it would probably be fine), but there is a pretty straightforward way to optimize it because entity transforms are rigid transforms. There are shortcuts to computing a rigid transform's inverse- for example, the inverse of a rotation matrix is its transpose, or the inverse of a rotation quaternion is its conjugate. The RigidTransform uses this fact:

Code: Select all

        ///<summary>
        /// Transforms a position by a rigid transform's inverse.
        ///</summary>
        ///<param name="position">Position to transform.</param>
        ///<param name="transform">Transform to invert and apply.</param>
        ///<param name="result">Transformed position.</param>
        public static void TransformByInverse(ref Vector3 position, ref RigidTransform transform, out Vector3 result)
        {
            Quaternion orientation;
            Vector3 intermediate;
            Vector3.Subtract(ref position, ref transform.Position, out intermediate);
            Quaternion.Conjugate(ref transform.Orientation, out orientation);
            Quaternion.Transform(ref intermediate, ref orientation, out result);
        }
Once you have the position in the entity's local space, the 'attached' world space state can be computed each frame by applying the current world transform to the local value.
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: World Location to Entity-centered Local Position

Post by mcmonkey »

That perfectly transforms the point location, thank you.

It does not, however, transform the rotation.

I essentially want the equivalent of a WeldJoint, except one of the two entities is not a physics entity (it's a very small / physics sim irrelevantly sized entity that appears in potentially huge numbers)

Worst case scenario, I could make it a noncolliding physics entity with an /actual/ WeldJoint in use, but I'm hoping there's a simpler way to calculate that.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: World Location to Entity-centered Local Position

Post by Norbo »

The same concept applies for a local transform. Take the original transform, multiply by the inverse transform (either invert and then multiply or use something like RigidTransform.MultiplyByInverse) to bring it into local space. Bring it into world space later by multiplying the local transform by the current world transform.
Post Reply