Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

calculation mathematics of local scale, position and rotation relative to parent transform

Discussion in 'Scripting' started by xorza, Dec 15, 2014.

  1. xorza

    xorza

    Joined:
    Dec 15, 2014
    Posts:
    3
    I have an OpenGL C# project, that I would like to give functionality like Unity3D game engine.

    Introduction: I have Transform class that provides transformations matrix to shader. Each transform can have parent transform. Code that calculates final transformations matrix looks like this:

    public Vector3 LocalPosition { get; set; }
    public Quaternion LocalRotation { get; set; }
    public Vector3 LocalScale { get; set; }

    public Matrix GetModelMatrix() {
    Matrix result;
    if(HasParent)
    result = Parent.GetModelMatrix();
    else
    result = Matrix.CreateIdentity();

    ApplyLocalTransformations(result);
    return result;
    }
    private void ApplyLocalTransform(Matrix matrix)
    {
    matrix.Translate(LocalPosition);
    matrix.Rotate(LocalRotation);
    matrix.Scale(LocalScale);
    }

    As you see LocalPosition, LocalScale and LocalRotation are transformations RELATIVE to parent. This code works fine.

    Problem: I want to add 3 more properties (hello Unity3D):

    public Vector3 AbsolutePosition { get; set; }
    public Quaternion AbsoluteRotation { get; set; }
    public Vector3 AbsoluteScale { get; set; }

    I want to have ability to get and set absolute transformations to child transforms. While setting Absolute values Local should be updated consistently and vice versa.

    Example: We have parent at position (1, 1, 1) and child with LocalPosition = (0, 0, 0), having this information we can calculate child's AbsolutePosition = (1, 1, 1). Now we set child's AbsolutePosition = (0, 0, 0). It's LocalPosition will now be = (-1, -1, -1). It's a very simple example, in real scenario we have to consider parent's scale and rotation to calculate Position.

    How to calculate Absolute and Local Position i have an idea: I can take last column from transformations matrix and it will be my AbsolutePosition. To get LocalPosition i can subtract from AbsolutePosition last column of parent transformations matrix. But mathematics behind Rotation and Scale still unclear for me.

    Question: Can you help me with algorithm that will calculate Local and Absolute Position, Rotation and Scale?

    P.S.: considering performance would be great.

    http://stackoverflow.com/q/27551201/1204080

    you can get some reputation there :)
     
    Last edited: Dec 18, 2014
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,895
    Most of that is just various applications of linear algebra. If you google for "learn to write a 3d game engine" you will probably find some links to some foundation mathematics about how it all comes about, the specific matrix calculations, etc.
     
  3. BBeck

    BBeck

    Joined:
    Jan 12, 2014
    Posts:
    57
    So, this is definitely linear algebra. But it's pretty simple once you understand matrices in game programming. Hopefully, I'll do a video soon.

    There are several cool game programming tricks with matrices. One of them is the parent-child relationship.

    First understand that a world matrix, or transformation matrix, holds the position, orientation, and scale of a mesh, or model, all simultaneously. That one matrix can be multiplied by the position of a vertex and it will place that vertex perfectly in the 3D world. The same matrix can be used over and over again for all 1 million or however many vertices there are in the model.

    But that is all relative to the origin which in 3D is at 0,0,0.

    In a parent-child relationship, they both have a matrix. Except the child's actual position is the parent times the child. When you multiply matrices, you combine the information in them. So, by multiplying the parent times the child, you combine the position, orientation, and scale of both. The parent only has its own matrix, but the child has the combination of the two because you multiply the two together.

    This relationship can go infinitely deep. You can have great-great-great-great-great-grandchildren or deeper.

    Because the child maintains an independent matrix, it can be manipulated independently, but because it multiplies (or combines) its matrix with all the matrices of its ancestors, its position, orientation, and scale are all relative to its ancestors.

    The parent's position becomes the origin of the child. And the parent is relative to its parent which is relative to its parents and so forth.

    This is all brought to you by the miracle of matrix multiplication. When you multiply two world, or transformation, matrices you combine them. You would think that that would be addition, but its not. Just like you would think subtraction would pull them apart but you actually need to multiply by the inverse of a matrix to pull them back apart.

    Hopefully, that's more clear than mud.
     
  4. BBeck

    BBeck

    Joined:
    Jan 12, 2014
    Posts:
    57
    Again, I really need to do a video on this. But as far as rotations and scales. A transformation matrix, or world matrix, stores all 3 simultaneously. This is partially because its a 4 by 4 matrix in a 3D world. Look at the identity matrix. It stores the value of 1 at 1,1 and 2,2 and 3,3 and 4,4 in the matrix. That's what we would consider an empty matrix. It's position is the origin at 0,0,0. It's orientation is no rotation. And it's scale is 1 on all 3 axis. As far as scale, all you have to do is change the value to something other than 1 at 1,1 and 2,2 and 3,3 and 4,4 to scale it.

    Depending on whether it's row or column major, the matrix will have a row or column that basically represents the three axes in 3D space.

    Maybe the best way to think about what a matrix contains is to think of three mutually perpendicular axes. An X axis, a Y axis, and a Z axis. Think of them as 3 vectors (you need to understand what a vector is but that's another discussion). Each vector is an arrow that points in the direction of those 3 mutually perpendicular axes. You will have an entire column or row that represents each vector.

    But those three mutually perpendicular vectors represent a 3 dimensional world space. You could also call that an orientation. If you increase the length of any of those vectors you will scale along that axis. The position is stored in that 4th dimension and is basically an offset since the 3 vectors should be at the origin; the position repositions them at a specific 3 dimensional spot.

    So the matrix basically contains 3 mutually perpendicular vectors that represent an orientation and the length of each vector represents the scale along that axis and there is a positional value that offsets the origin of the world space represented by the 3 vectors.

    Clear as mud?
     
  5. xorza

    xorza

    Joined:
    Dec 15, 2014
    Posts:
    3
    thanks for your replies, it's a bit clearer for me now.

    okay, lets imagine:
    i have parent and child transform matrices. parent is scaled, rotated and translated, child matrix has transformations also. thing that remains unclear is- what happens when i'm setting child absolutePosition to some value? it's localPosition is also changed, but i cannot calculate it like childLocalPosition =parentLocalposition - childAbsolutePosition, i need to consider parent scale and rotation, parent's parent position, location and scale and so on...

    i have ParentTransformMatrix and ChildTransformMatrix. how do i calculate ChildLocalPosition while setting ChildAbsolutePosition? and vice versa? same question about scale and rotation.

    thanks a lot for your time trying to help me :)
     
  6. xorza

    xorza

    Joined:
    Dec 15, 2014
    Posts:
    3
    i updated thread head, i think now my question is much more clear