官术网_书友最值得收藏!

Transform matrix

We've briefly touched on the fact that our math library multiplies matrices in a left to right order. But what exactly does this mean? When we multiply two matrices, we combine their linear transformations into one matrix. The first transformation applied is the one on the far left, then the one to its right, and so on.

For example, let's take two matrices, one that translates an object by 10 units on its X axis and one that rotates it by 45 degrees on its Y axis:

mat4 transform1 = Translate(10, 0, 0) * RotateY(45);
mat4 transform2 = RotateY(45) * Translate(10, 0, 0);

Because matrix multiplication is not cumulative Transform matrix, transform1, and transform2 are not the same! transform1 will move the object to (10, 0, 0), and then rotate the object at that position:

Transform matrix

transform2, on the other hand, will rotate the object by 45 degrees on its Y axis, and then translate it by 10 units on its local X axis:

Transform matrix

Getting ready

The multiplication order is highly dependent on the conventions you are using and what makes sense to you. For the context of our physics engine we want to scale first, rotate second, and translate last. This order is a fairly common convention in most games. We're going to make a helper function that takes scale, rotation, and translation and returns a full transform matrix.

We have two ways to create a rotation matrix, using Euler angles or using the axis angle representation. We are going to implement two versions of the Transform function, one for each representation.

How to do it…

Follow these steps to create a composite matrix given scale, rotation, and translation:

  1. Add the declaration for the Transform function to matrices.h:
    mat4 Transform(const vec3& scale, const vec3& eulerRotation,
       const vec3& translate);
    mat4 Transform(const vec3& scale, constvec3& rotationAxis,
       float rotationAngle, const vec3& translate);
  2. Implement the Euler angle version of the Transform function in matrices.cpp:
    mat4 Transform(const vec3& scale, const vec3& eulerRotation,
       const vec3& translate) {
          return Scale(scale) *
          Rotation(eulerRotation.x, 
                   eulerRotation.y, 
                   eulerRotation.z) *
          Translation(translate);
    }
  3. Implement the axis angle version of the Transform function in matrices.cpp:
    mat4 Transform(const vec3& scale, const vec3& rotationAxis,
       float rotationAngle, const vec3& translate) {
          return Scale(scale) * 
          AxisAngle(rotationAxis, rotationAngle) * 
          Translation(translate);
    }

How it works…

Generally, to create a three-dimensional transform, we want to scale first, rotate second, and translate last. If this order of transformations seems arbitrary, that's because it absolutely is.

We scale first to avoid the scaling matrix interfering with the rotation matrix. Then, we want to rotate before translating. In this way, the position of the object is intuitively where we tell the translation to be. Also, the rotation will happen in the world axis. Because we multiply from left to right, we can express a transformation from left to right:

Transform = Scale(1, 2, 1)      * 
            Rotation(0, 30, 0)  * 
            Translation(10, 0, 0);
主站蜘蛛池模板: 四子王旗| 英超| 江油市| 桦甸市| 闽清县| 河间市| 呼图壁县| 崇礼县| 南川市| 武川县| 康乐县| 新巴尔虎左旗| 达尔| 庄河市| 肥西县| 临清市| 平谷区| 秦安县| 兴仁县| 水城县| 三原县| 乳源| 仲巴县| 娄底市| 贵溪市| 安徽省| 曲周县| 三亚市| 新蔡县| 梅河口市| 兴安县| 澄城县| 防城港市| 壶关县| 海门市| 铜鼓县| 青龙| 合阳县| 稻城县| 平潭县| 咸丰县|