矩阵和线性变换之切变
1. 什么是切变?
我们来看一幅图片。下面的图片,随着y增大,x的偏移会越来越大。这种类型的变换就叫切换。我们可以得到下图的公式x’ = x + sy。该公式转换成矩阵就得到了切变矩阵。
2. 切变效果的矩阵是怎样的?
在3D中,同样的道理,有如下右边三个矩阵,分别是随着z增大,x和y发生切变。随着y增大,x和z发生切变。随着z增大,x和y发生切变。
3. 切变矩阵示例代码
void Matrix3X3::setShear(E_Axis axis, float s, float t)
{
switch(axis)
{
case Axis_x:
{
m11 = 1; m12 = s; m13 = t;
m21 = 0; m22 = 1; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_y:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = s; m22 = 1; m23 = t;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_z:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = 1; m23 = 0;
m31 = s; m32 = t; m33 = 1;
break;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
4. 切变矩阵程序完整示例代码
//MathUtil.h
#pragma once
#include <math.h>
enum E_Axis{Axis_x,Axis_y,Axis_z};
const float Pi = 3.14159f;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
//Vector3.h
#pragma once
class Vector3{
public:
Vector3();
Vector3(float X,float Y,float Z);
//变为零向量
void Zero();
//求负向量
Vector3 operator-() const;
//求向量大小(长度或模)
float Length() const;
//标准化该向量
void Normal();
//向量的加法
Vector3 operator+(Vector3 &rhs) const;
Vector3& operator+=(Vector3 &rhs);
//向量的减法
Vector3 operator-(Vector3 &rhs) const;
Vector3& operator-=(Vector3 &rhs);
//向量乘标量
Vector3 operator*(float scalar);
//向量乘等于标量
Vector3& operator*=(float scalar);
//向量除以等于标量
Vector3& operator/=(float scalar);
//向量除以标量
Vector3 operator/(float scalar);
//距离公式
float Distance(Vector3 &vec) const;
//向量点乘
float operator*(Vector3 &rhs) const;
//向量叉积
Vector3 CrossProduct(Vector3& vec) const;
public:
float x,y,z;
};
//标量乘向量
Vector3 operator*(float scalar, Vector3& vec);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
//Vector3.cpp
#include "Vector3.h"
#include <cmath>
Vector3::Vector3():x(0.0),y(0.0),z(0.0)
{
}
Vector3::Vector3(float X,float Y,float Z):x(X),y(Y),z(Z)
{
}
void Vector3::Zero()
{
x = y = z = 0;
}
Vector3 Vector3::operator-() const
{
return Vector3(-x,-y,-z);
}
float Vector3::Length() const
{
return sqrt(x*x+y*y+z*z);
}
Vector3 Vector3::operator*(float scalar)
{
return Vector3(this->x * scalar, this->y * scalar, this->z * scalar);
}
Vector3& Vector3::operator*=(float scalar)
{
return *this = *this * scalar;
}
Vector3& Vector3::operator/=(float scalar)
{
return *this = *this / scalar;
}
Vector3 operator*(float scalar, Vector3& vec)
{
return vec*scalar;
}
Vector3 Vector3::operator/(float scalar)
{
float temp = 1/ scalar;
return *this * temp;
}
void Vector3::Normal()
{
//计算机计算乘法的速度比除法快
float temp = 1 / Length();
x *= temp;
y *= temp;
z *= temp;
}
Vector3 Vector3::operator+(Vector3& rhs) const
{
return Vector3(x+rhs.x,y+rhs.y,z+rhs.z);
}
Vector3& Vector3::operator+=(Vector3& rhs)
{
*this = *this + rhs;
return *this;
}
Vector3 Vector3::operator-(Vector3& rhs) const
{
return Vector3(x-rhs.x,y-rhs.y,z-rhs.z);
}
Vector3& Vector3::operator-=(Vector3& rhs)
{
*this = *this - rhs;
return *this;
}
float Vector3::Distance(Vector3& vec) const
{
return (*this - vec).Length();
}
float Vector3::operator*(Vector3& rhs) const
{
return this->x * rhs.x + this->y * rhs.y + this->z * rhs.z;
}
Vector3 Vector3::CrossProduct(Vector3& vec) const
{
return Vector3(this->y * vec.z - this->z * vec.y,
this->z * vec.x - this->x * vec.z,
this->x * vec.y - this->y * vec.x);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
//Matrix3X3.h
#pragma once
#include "MathUtil.h"
#include "Vector3.h"
class Matrix3X3
{
public:
//矩阵相乘
Matrix3X3 operator*(Matrix3X3& rhs);
//矩阵乘等矩阵
Matrix3X3& operator*=(Matrix3X3& rhs);
void setRotate(E_Axis axis,float theta);
void setScale(Vector3 &vec);
void setOrthProject(Vector3 &vec);
void setReflect(E_Axis axis);
void setReflect(Vector3 &vec);
void setShear(E_Axis axis, float s, float t);
public:
float m11,m12,m13;
float m21,m22,m23;
float m31,m32,m33;
};
//向量乘以矩阵
Vector3 operator*(Vector3& vec,Matrix3X3& mat);
//向量乘等矩阵
Vector3& operator*=(Vector3& vec,Matrix3X3& mat);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
//Matrix3X3.cpp
#include "Matrix3X3.h"
#include <assert.h>
Matrix3X3 Matrix3X3::operator*(Matrix3X3& rhs)
{
Matrix3X3 tempMat;
tempMat.m11 = this->m11 * rhs.m11 + this->m12 * rhs.m21 + this->m13 * rhs.m31;
tempMat.m12 = this->m11 * rhs.m12 + this->m12 * rhs.m22 + this->m13 * rhs.m32;
tempMat.m13 = this->m11 * rhs.m13 + this->m12 * rhs.m23 + this->m13 * rhs.m33;
tempMat.m21 = this->m21 * rhs.m11 + this->m22 * rhs.m21 + this->m23 * rhs.m31;
tempMat.m22 = this->m21 * rhs.m12 + this->m22 * rhs.m22 + this->m23 * rhs.m32;
tempMat.m23 = this->m21 * rhs.m13 + this->m22 * rhs.m23 + this->m23 * rhs.m33;
tempMat.m31 = this->m31 * rhs.m11 + this->m32 * rhs.m21 + this->m33 * rhs.m31;
tempMat.m32 = this->m31 * rhs.m12 + this->m32 * rhs.m22 + this->m33 * rhs.m32;
tempMat.m33 = this->m31 * rhs.m13 + this->m32 * rhs.m23 + this->m33 * rhs.m33;
return tempMat;
}
Matrix3X3& Matrix3X3::operator*=(Matrix3X3& rhs)
{
*this = *this * rhs;
return *this;
}
Vector3 operator*(Vector3& vec,Matrix3X3& mat)
{
Vector3 tempVec;
tempVec.x = vec.x * mat.m11 + vec.y * mat.m21 + vec.z * mat.m31;
tempVec.y = vec.x * mat.m12 + vec.y * mat.m22 + vec.z * mat.m32;
tempVec.z = vec.x * mat.m13 + vec.y * mat.m23 + vec.z * mat.m33;
return tempVec;
}
Vector3& operator*=(Vector3& vec,Matrix3X3& mat)
{
vec = vec * mat;
return vec;
}
void Matrix3X3::setRotate(E_Axis axis,float theta)
{
float sinValue,cosValue;
sinValue = sin(theta);
cosValue = cos(theta);
switch(axis)
{
case Axis_x:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = cosValue; m23 = sinValue;
m31 = 0; m32 = -sinValue; m33 = cosValue;
break;
}
case Axis_y:
{
m11 = cosValue; m12 = 0; m13 = -sinValue;
m21 = 0; m22 = 1; m23 = 0;
m31 = sinValue; m32 = 0; m33 = cosValue;
break;
}
case Axis_z:
{
m11 = cosValue; m12 = sinValue; m13 = 0;
m21 = -sinValue; m22 = cosValue; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
break;
}
default:
assert(false);
}
}
void Matrix3X3::setScale(Vector3& vec)
{
m11 = vec.x; m12 = 0; m13 = 0;
m21 = 0; m22 = vec.y; m23 = 0;
m31 = 0; m32 = 0; m33 = vec.z;
}
void Matrix3X3::setOrthProject(Vector3 &vec)
{
assert(fabs(vec*vec) - 1 < 0.01f);
m11 = 1 - vec.x*vec.x;
m12 = m21 = -vec.x * vec.y;
m13 = m31 = -vec.x * vec.z;
m22 = 1 - vec.y * vec.y;
m23 = m32 = -vec.y * vec.z;
m33 = 1 - vec.z * vec.z;
}
void Matrix3X3::setReflect(E_Axis axis)
{
switch(axis)
{
case Axis_x:
{
m11 = -1; m12 = 0; m13 = 0;
m21 = 0; m22 = 1; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_y:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = -1; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_z:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = 1; m23 = 0;
m31 = 0; m32 = 0; m33 = -1;
break;
}
}
}
void Matrix3X3::setReflect(Vector3 &vec)
{
assert(fabs(vec*vec) - 1 < 0.01f);
m11 = 1 - 2 * vec.x * vec.x;
m12 = m21 = - 2 * vec.x * vec.y;
m13 = m13 = -2 * vec.x * vec.z;
m22 = 1 - 2 * vec.y * vec.y;
m23 = m32 = -2 * vec.y * vec.z;
m33 = 1 - 2 * vec.z * vec.z;
}
void Matrix3X3::setShear(E_Axis axis, float s, float t)
{
switch(axis)
{
case Axis_x:
{
m11 = 1; m12 = s; m13 = t;
m21 = 0; m22 = 1; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_y:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = s; m22 = 1; m23 = t;
m31 = 0; m32 = 0; m33 = 1;
break;
}
case Axis_z:
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = 1; m23 = 0;
m31 = s; m32 = t; m33 = 1;
break;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
#include <iostream>
#include "Vector3.h"
#include "Matrix3X3.h"
using namespace std;
float ToZero(float num)
{
return (abs(num) < 0.0001 ? 0 : num);
}
void print_v(Vector3 v)
{
cout << "[ " << ToZero(v.x) << ", "
<< ToZero(v.y) << ", "
<< ToZero(v.z) << " ]" << endl;
cout << endl;
}
void print_m(Matrix3X3 m)
{
cout << m.m11 << "\t" << m.m12 << "\t" << m.m13 << endl;
cout << m.m21 << "\t" << m.m22 << "\t" << m.m23 << endl;
cout << m.m31 << "\t" << m.m32 << "\t" << m.m33 << endl;
cout << endl;
}
int main()
{
Vector3 a(10,20,30),b;
Matrix3X3 M;
M.setShear(Axis_x,1,2);
print_m(M);
print_v(a);
b = a * M;
print_v(b);
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
5. 程序运行结果
1 1 2
0 1 0
0 0 1
[ 10, 20, 30 ]
[ 10, 30, 50 ]