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

  • Game Physics Cookbook
  • Gabor Szauer
  • 900字
  • 2021-04-02 20:27:32

Vector matrix multiplication

We have now implemented translation, scaling, and rotation in terms of matrices. These matrices become useful when we can apply their transformations to vectors. How do we apply a matrix transformation to a vector? The same way we do to a matrix: using matrix multiplication!

To multiply a vector and a matrix, we need to think of a vector as a matrix that has only one row or column. This leaves us with an important question, is a vec3 a matrix with one column and three rows, or three columns and one row?

If the vector is on the left side of the matrix, it's a 1 X 3 Row Vector. With a row vector, we use Pre Multiplication.

If the vector is on the right side of the matrix, it's a 3 X 1 Column Vector. With column vectors we use Post Multiplication.

The naming is intuitive, with pre multiplication the vector is placed before the matrix, with post multiplication the vector is placed after the matrix. This convention must be followed because the inner dimensions of matrices being multiplied have to match.

We have to decide if our vectors are row or column vectors. This decision comes down to whether we want to use pre or post multiplication. Multiplying two matrices using our row major library is already left to right. By using row vectors we can multiply vectors and matrices left to right as well. This should help make vector matrix multiplication feel more intuitive.

This takes care of 3 X 3 matrices, but what about a 4 X 4 matrix? We can't multiply a vec3 by a mat4, the inner dimensions for matrix multiplication must match! We actually need to use a data type we don't have, a vec4. This is where the W component we briefly discussed in Chapter 1, Vectors, becomes important. In our final physics engine, a vector will represent one of two things, a point in space, or a direction and a magnitude.

What's the difference? Multiplying a point in space by a matrix will change its position. Multiplying a vector can't change its position, it has none! Only the direction and magnitude of the vector can change.

  • A vector is a 1 X 4 matrix with a W component of 0.
  • A point is a 1 X 4 matrix with a W component of anything other than 0.

Getting ready

Because a vec3 could potentially represent a point or a vector, we're not going to overload the multiplication operator. Instead, we are going to make two new functions, MultiplyPoint and MultiplyVector. There are two ways we can implement these functions.

We could create a temp float array with four elements; filling the first three with the X, Y, and Z components of the vector and the W component with 0 or 1, depending on whether we have a point or a vector. Then, we could use the generic Multiply function on this array.

The other option is to hard-code the dot product between row i of the vector and column j of the matrix. This way, we can hard-code the W component within the dot product to 0 or 1. We're going to implement both the MultiplyPoint and MultiplyVector functions in this manner.

How to do it…

Follow these steps to multiply vectors and matrices:

  1. Add the MultiplyPoint and MultiplyVector declarations to matrices.h:
    vec3 MultiplyPoint(const vec3& vec, const mat4& mat);
    vec3 MultiplyVector(const vec3& vec, const mat4& mat);
    vec3 MultiplyVector(const vec3& vec, const mat3& mat);
  2. Implement the MultiplyPoint function in matrices.cpp. Hard-code 1 where the W component would be:
    vec3 MultiplyPoint(const vec3& vec, const mat4& mat) {
       vec3 result;
       result.x = vec.x * mat._11 + vec.y * mat._21 + 
                  vec.z * mat._31 + 1.0f  * mat._41;
       result.y = vec.x * mat._12 + vec.y * mat._22 + 
                  vec.z * mat._32 + 1.0f  * mat._42;
       result.z = vec.x * mat._13 + vec.y * mat._23 + 
                  vec.z * mat._33 + 1.0f  * mat._43;
       return result;
    }
  3. Implement the MultiplyVector in matrices.cpp. Hard code 0 where the W component should be:
    vec3 MultiplyVector(const vec3& vec, const mat4& mat) {
       vec3 result;
       result.x = vec.x * mat._11 + vec.y * mat._21 + 
                  vec.z * mat._31 + 0.0f  * mat._41;
       result.y = vec.x * mat._12 + vec.y * mat._22 + 
                  vec.z * mat._32 + 0.0f  * mat._42;
       result.z = vec.x * mat._13 + vec.y * mat._23 + 
                  vec.z * mat._33 + 0.0f  * mat._43;
       return result;
    }
  4. Implement the mat3 version of MultiplyVector in matrices.cpp. In this function, we actually use the dot product, instead of hand-coding the whole thing.
    vec3 MultiplyVector(const vec3& vec, const mat3& mat) {
       vec3 result;
       result.x = Dot(vec, vec3(mat._11, mat._21, mat._31));
       result.y = Dot(vec, vec3(mat._12, mat._22, mat._32));
       result.z = Dot(vec, vec3(mat._13, mat._23, mat._33));
       return result;
    }

How it works…

We have to choose between row or column vectors because we can only multiply matrices together if their inner dimensions match. Let's explore why a W component of 1 will turn a vector into a point.

Translation is stored in elements 41, 42, and 43 of a matrix. When we take the dot product of a four-component vector and the column of a 4 X 4 matrix, the elements in the translation row of the matrix get multiplied by the W component. A W of 1 means the translation remains untouched. A W of 0 cancels out the translation.

主站蜘蛛池模板: 盘锦市| 哈尔滨市| 南平市| 洛川县| 乡城县| 错那县| 光山县| 安乡县| 云龙县| 九寨沟县| 北票市| 青龙| 梓潼县| 鲁山县| 昌乐县| 东山县| 石屏县| 长汀县| 大余县| 图们市| 乐平市| 文山县| 喀喇沁旗| 六盘水市| 高邑县| 遂平县| 雅安市| 稷山县| 湖口县| 伽师县| 乌拉特中旗| 中宁县| 秦皇岛市| 浮梁县| 潢川县| 德钦县| 南木林县| 邢台市| 彭水| 桃园县| 霍州市|