Goals
IntroductionTo understand how components can be transformed and where and how they will appear on screen we first have to understand the concept of hierarchic transformations and multiple coordinate spaces. Each component in MT4j has its own coordinate space which is described by a transformation matrix, called "local" matrix. By changing this transformation matrix, we can move (translate), rotate and scale this coordinate space and thus the component itself. Everything drawn by this component will be always be transformed by this transformation matrix. So if we for example move a component's coordinate space 5 units to the right and the component then draws a point at position P=(0,0,0), P will actually appear at P'=(5,0,0). If we now attach a child to this transformed component, the parent's local transform will also affect the child. A point drawn by the child component will then be transformed by the childs local transform and the parent's local transform. The local transformations multiplied together from the component itself up to its highest parent make up the so called "global" or "world" transform matrix of the component. It is called global transform matrix because it describes where in our virtual world a point drawn by our component will finally appear. If a component has no parents, the local matrix is identical to the global matrix. Coordinate spacesIn MT4j we differentiate between 3 coordinate spaces: Local space: The local space (sometimes called object or model space) is the component's coordiante system without any transformation applied to it yet. Every component in MT4j has its own three dimensional coordinates space. If we define points in this local object space, they will be relative to the component's local origin. If we for example create a line with two vertices at (0,0,0) and (10,0,0) these vertices will always be at this position in local space so if we call getCenterPointLocal() on that line it will always return the vector (0,5,0) even if we moved the component or one of its parents around. The local object space stays the same. If we create components we define their points, locations or dimensions relative to this local space.
Global Space: The global space (also called world space) is where our components finally appear in our virtual world (viewed from the camera). We can transform a vector defined in the local object coordiante space of a component into global space by applying the component's global matrix to it (which is the accumulation of all local transforms, from the component up to the top most parent). If all components share the same ancestor (usually our scene's canvas object) they all share the same global space. So if we define points in global space, they will be relative to the canvases coordinate space origin. Transformation ChainTo sum it up, the following steps take place everytime a component is drawn. This chain shows what factors determine where a component finally appears on the screen. ==> Drawing commands of the component (untransformed Local Space) Transforming componentsWhen we want to transform components, we have to specify the coordinate system which we want the transform to be relative to. Sometimes the name of the method implies the coordinate space to be used, sometimes we have to specify the coordinate space as an argument. The enumeration TransformSpace, is often used to specify the coordinate space to use in a method. It constists of the three constants:
Moving componentsWe can shift everything drawn by a component (and its children) in the direction and by the amount of a vector by translating it. Example: component.translate(new Vector3D(10,0,0), TransformSpace.LOCAL); This will move the component 10 units in the positive direction of the Xaxis, relative to the component's local space. This first transforms the translation vector into the components local space before applying the translation. Relevant methods:
Rotating componentsComponents can be rotated about each of the three axis. Example: component.rotateZ(new Vector3D(10,10,0), 45, TransformSpace.GLOBAL); This would rotate the component 45 degrees around the ZAxis going through the specified point vector in global space coordiantes. Relevant methods:
Scaling componentsExample: component.scale(1, 1, 2, new Vector3D(0,0,0), TransformSpace.RELATIVE_TO_PARENT); This would scale the component's coordiante system's Zaxis by 2. The center of the scaling would be the origin of the component's parent's local space. Relevant methods:
Transforming pointsOften we need to transform vectors or vertices to be relative to another coordinate space. If we want to, for example check the distance between a vector (point) defined in the local space of one component and a local vector of another component we would transform them both into global space first so they are relative to the same coordiante space where we can then do the distance test. The distance will then of course also be relative to the global space. The MTComponent class offers methods to transform points from one coordinate space to the other: Relevant methods:
We can also transform a vector using an arbitrary matrix. The Vector3D class provides the transform(Matrix matrix) method for this. Vector3D localCompPoint = new Vector3D(25,80,0); localCompPoint.transform(someComponent.getLocalMatrix()); This would transform the point vector of a component's local space into the component parent's local space. So this would have the same effect as the localToParent() method, whith the exception that the transform() method doesent create a copy of the specified vector first. Transforming direction vectorsVectors can represent both, a point in space or a direction. If we want to transform points, we can use the above mentioned methods, but if we are dealing with direction vectors, we have to use other methods. So if we have a direction vector in global space that we want to transform to be relative to a component's local space, we would use the transformDirectionVector method of the Vector3D class. Vector3D direction = new Vector3D(100,150,0); direction.transformDirectionVector(someComponent.getGlobalInverseMatrix()); This would transform the direction vector from global space into someComponent's local space. Relevant methods:
Further readingThe concept of these different coordinate spaces, matrices and vectors/vertices takes a bit to get used to and understand. The following resources may help getting a grasp of it.
