Basic question: Transforming a vertex is shaking my worldview

Wow, I always thought I had had matrix transformations pretty well figured out until now.

So say I have a vertex, conveniently located at the origin (0,0,0). If I want to apply a transform to this vertex -- namely, a translation, I could do something like this:

Matrix translationMatrix = Matrix.Translation(100.0f, 50.0f, 0.0f); // a simple 2D translation
Vector3 myVector = new Vector3(0, 0, 0);
myVector.TransformCoordinate(translationMatrix);

As expected, my vector gets transformed to its new value: (100, 50, 0). Now let's get crazy. Assume that I want to apply a transform that consists of a rotation and our previously used translation, i.e.:

Matrix translationMatrix = Matrix.Translation(100.0f, 50.0f, 0.0f);
Matrix rotationMatrix = Matrix.RotationZ((float)Math.PI / 2.0f); // 90 degrees around the Z axis
Matrix concatenatedMatrix = rotationMatrix * translationMatrix;
Vector3 myVector = new Vector3(0, 0, 0);

myVector.TransformCoordinate(concatenatedMatrix);

Now obviously, my vector would equal (50, -100, 0) after being first rotated 90 degrees and then translated relative to the new coordinate system, right Wrong. For some reason, my vector still ends up at (100, 50, 0). Why in the world does it make no difference if I'm using a translation matrix versus a concatenated rotation/translation matrix



Answer this question

Basic question: Transforming a vertex is shaking my worldview

  • visualcpp.h

    This still leaves my overall question though, which I'm having a hard time addressing.

    If I have a point in coordinate system Q, and then I transform the heck out of it multiple times, how can I get the resulting position of this point relative to my original coordinate system, Q

    And my next question is, how can I get the rotation angle relative to this coordinate system as well


  • isabella music

    I'll check out those Gamedev.net forums. It just seems so odd that this is a "hard" problem, because I thought this is exactly how objects are transformed into world coordinates with a scene graph.

    Remember the UW Gamedev class and the whole GeoNode class In order to calculate the world coordinates of a child GeoNode of a parent GeoNode, you multiply the parent's local transform (e.g. R*T) with the child's local transform, and magically the child object is placed into world space. It would seem then to be a trivial matter to determine where this lies in world space, because after all the video card draws this object in these new coordinates (well, after being projected into screen space), so clearly it knows the final position of each vertex.

    So how does the video card know where to draw each vertex All you do is set world/view/projection matrices, and these world matrices might be the product of many successive transforms. So it would seem that I could do whatever trick the video card does, and be able to, given a world transform, determine the point (in world space) where a given node in a scenegraph lies.


  • machevoletedame

    I don't think you can, there are many (an infinite number ) different ways that (1,1,1) can be transformed to (2,2,2) and you can't know for sure which of them actually did the transformation. You need to remember what you did.

    Try searching/asking in the math/algorithms forum on gamedev http://www.gamedev.net/community/forums/forum.asp forum_id=20

     



  • MusicGod

    Actually Andy, it turns out that my failure was a misunderstanding of what exactly a transformation implies.  Essentially, as you mentioned, I rotated the coordinate system, and then shifted the point (0,0,0) by the same distance relative to the new coordinate system.  What I want is the coordinates of this point in terms of the original coordinate system, and I mistakenly thought that my transformation would accomplish this.

    Instead, I need to make this minor change:

    Matrix translationMatrix = Matrix.Translation(100.0f, 50.0f, 0.0f);
    Matrix rotationMatrix = Matrix.RotationZ((float)Math.PI / 2.0f); // 90 degrees around the Z axis
    Matrix concatenatedMatrix = rotationMatrix * translationMatrix * Matrix.Inverse(rotationMatrix);
    Vector3 myVector = new Vector3(0, 0, 0);

    myVector.TransformCoordinate(concatenatedMatrix);

    This, using the properties of magic and/or the inverse rotational matrix, will (if I'm not getting this horribly wrong) rotate the coordinate system, transform the point, and then rotate back to the original coordinate system, leaving the point with components relative to this original system.  The new value of the vector is (50, -100, 0) as expected.

    This is one of those things I'll forget as soon as I look away from the screen.


  • Mohit Saini

    As you walk your scenegraph you calculate the transformation for each element and multiply in the parents transformation

    root = translate(x,y,x) * rotate(rx,ry,rz);

    child = root.tranform * translate(x,y,x) * rotate (rx, ry, rz)

    grandchile = child.transform * translate(x,y,x) * rotate (rx, ry, rz)

    x,y,z and rx, ry,rz are members of the node in the scene graph.

    (excuse me if I get the multiplications in the wrong oder, no matter how many times I do this I usually get something wrong)

    See http://msdn.microsoft.com/coding4fun/holiday/directxmas2/default.aspx - though this is in 3d and you can get away with 2d screen coordinates.



  • Betatester12345

    Whenever my translations don't work I always assume I have concatenated them the wrong way and I'm usally right.

    You are rotating then translationg, since rotations are around 0,0,0 (well when you use the matrix.rotation functions) then 0,0,0 always ends up right back at 0,0,0. Then you translate it to the same place.

    Flip the multiplication.... though that may or not be what you intended.

    Matrix concatenatedMatrix = translationMatrix * rotationMatrix;



  • Jeke

    Well, I've solved most of this problem (most importantly, the problem of my shattered worldview). One of my problems was a fundamental misunderstanding of how transformations work (and this is still puzzling me a little). I was under the impression that a rotation transformation, for example, in effect transformed the coordinate system in which a point lies. So, in the case of a point at (0, 0), rotating the coordinate system clockwise 90 degrees along the z axis would make the subsequent translation of 50 units in the y direction actually translate into 50 units in the x direction, because of the transformed coordinate system which rotated the y axis into the x axis, and the x axis into the negative y axis.

    If this still doesn't make sense, it may be because of my other major problem, which was forgetting that the positive Z-axis goes into the screen. This has major implications when using the Matrix.RotateZ method. Namely, it rotates vertices clockwise relative to some guy inside your monitor who's staring back at you. Since this guy is only imaginary, it makes it trickier to do the math.

    So essentially I was getting unexpected results because 1) I fundamentally misunderstood the behavior of transformations, and 2) I mixed up the positive and negative z-axis. In short, I was hopeless.


  • sharadha

    Maybe it would help if I explained the problem I'm trying to solve.

    I want to be able to create UI "panels" (or "skins", if you will) which may contain child panels. I want to be able to specify the local coordinates of a child panel, and during a render (or whenever needed), its screen coordinates will be computed. For example, if the parent panel is located at (50, 40) on the screen, and the child panel has local coordinates of (10, 0), I would expect the world coordinates of the child panel to be computed as (50 + 10, 40 + 0) = (60, 40). If the parent's position changes, the child's position will change accordingly (and all its children, and its children, etc.).

    So, for translations this is a trivial problem, since you can just do simple additions to find out net changes. But as soon as rotations are factored in, this becomes more complicated. If I rotate a parent skin, all of its children have to be transformed proportionally (which is the typical function of a scene graph hierarchy).

    The API I'm using (wrapping, actually) requires me to set the screen position of each element (I can't simply tell the API, "Hey, this child element is 10 pixels to the right of its parent", I have to do the calculations myself).

    Anyway, I hope this clears it up a bit.


  • Wangen

    Then I am confused.

    (I'm assuming the view and projection are fixed outside of the scenegraph here.)

    When you draw a scenegraph your objects are in object coordinates and you set a world matrix based on the position attributes of that object in the scene. So each object may have a x, y,z position and an rx, ry, rz rotation. At some point you use these 6 attributes to construct a world matrix for that particular object (you probably also include the world matrix of some parent object if there is hierarchy)

    The card does a simple multiplication of the vertex by the world transform. So yes given a world transform you can indeed turn object coordiantes into world coordinates in exactly the same way.

    I thought you were asking that given a world matrix could you determine x, y, z, rx, ry, rz and thats what I'm not sure about.



  • Basic question: Transforming a vertex is shaking my worldview