How do I get facing/up vectors for a transform?

(Nolan) #1

Given a Transform which appears to include rotation, is it possible to get a vector representing the direction that transform is facing, along with its relative up vector?



(Kae) #2

I think you can use .isometry().inverse().rotation * direction to transform from object space to its parent’s space, which should get you what you want. For example, transform.isometry().inverse().rotation * Vector3::z() for the forward-facing direction. Replace z with y for up. If you use parents and want to get the world space direction, you need to use GlobalTransform which has some ordering issues. The GlobalTransform is being removed in a future release:

1 Like

(Gray Olson) #3

Given that the transformation is an isometry (i.e. a “true” linear rotation + a translation), which is enforced by the way that Transform is structured in Amethyst, the rotation matrix contained in the isometry is literally a transformation from the old X, Y, and Z basis vectors to the new new X, Y, and Z basis vectors. i.e. you can do transform.isometry().rotation.matrix().row(2) to get the new Z (forward) basis vector and transform.isometry().rotation.matrix().row(1) to get the new Y (up) basis vector. These vectors are relative to the vector space of the parent, as @kabergstrom said. To get the global, you’d use GlobalTransform which is just a single Matrix4 so it’s slightly more complex since you just want the first 3 values in the row, i.e. global_transform.0.row(2)[0..3] for the Z basis vector and global_transform.0.row(1)[0..3] for the Y.


(Nolan) #4

Thanks for the responses. Haven’t had a chance to test them out yet but am hoping to soon.


(Nolan) #5

Thanks, this seems to be working for me. I was just about to reuse this solution to calculate left/right/behind vectors and assume I can do something similar? I.e. the direction of local +X would be right, -X left, and -Z would be behind?

If so, since I’m using this more heavily, I’d like to use traits that aren’t going away. Should I stay away from GlobalTransform for this, and instead use the first solution? I don’t have any Parent components, so I shouldn’t need to convert local isometries to global ones I don’t think.

Thanks for all the support I’ve gotten here thus far.


(Nolan) #6

OK, sorry to keep bringing this back up–I just want to make sure I’m not doing something wrong or writing bad code. After lots of study of these examples, and after lots of logging of my positions relative to the directions I’m traveling, I have this:

            let mut direction = transform.isometry().rotation * Vector::z();
            direction *= -1.;
            info!("Direction: {:?}",;

Initially when I instantiate an object, I get:

[INFO][onslaught] Direction: [-0.0, -0.0, -1.0]

And this is correct. If I fly in the direction of travel, my Z coordinate does indeed decrease, and rotation seems to set these correctly. So, things I’m confused about:

  1. The first example in this thread would have me do the following:
            let mut direction = transform.isometry().rotation.inverse() * Vector::z();

But the presence or absence of .inverse() makes absolutely no difference here. It’s only by multiplying the rotation by -1 that I get a rotation in the correct direction. I’d have thought multiplying by -1 was an inverse. Am I misunderstanding why that’s there?

  1. transform.isometry().rotation.matrix().row(2) looks a bit cleaner, and avoids the vanishing GlobalTransform. Unfortunately, there’s no .matrix() method on the rotation. I got this to compile:
            let rotation = transform.isometry().rotation;
            let mut direction = rotation * Vector::z();
            direction *= -1.;
            info!("Direction: {:?}",;
            let direction2 = &rotation.coords.row(2);
            info!("Direction2: {}, {}, {}", direction2[0], direction2[1], direction2[2]);

And I wanted to see if the values equalled, but I get a matrix index out of bounds error.

So in short, my code seems to work, but I’m not sure why. Calling .inverse() on the rotation has no effect, and it seems like inverting a rotation should do something to the direction vector. :slight_smile: The second example looks a bit cleaner, and I’d like to compare their results, but I can’t make it work. Anyhow, I don’t like code that I don’t understand, and that a method named .inverse() has no effect on, so here I am again.