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

  • 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.

主站蜘蛛池模板: 宝应县| 池州市| 兰考县| 和田县| 正镶白旗| 青川县| 临潭县| 镇康县| 安福县| 远安县| 香格里拉县| 禹城市| 常德市| 达州市| 湖北省| 射阳县| 东乌| 清苑县| 错那县| 南宫市| 江达县| 思南县| 亳州市| 嘉黎县| 兴安盟| 彰化市| 五大连池市| 武山县| 尚志市| 武宁县| 修武县| 牟定县| 浪卡子县| 疏勒县| 报价| 仲巴县| 西青区| 长治县| 米林县| 郧西县| 威海市|