3D数学 矩阵和线性变换之切变

来源:互联网 发布:淘宝店铺怎么复制商品 编辑:程序博客网 时间:2024/06/05 15:02

矩阵和线性变换之切变

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;        }    }}

4. 切变矩阵程序完整示例代码

//MathUtil.h#pragma once#include <math.h>enum E_Axis{Axis_x,Axis_y,Axis_z};const float Pi = 3.14159f;
//Vector3.h#pragma onceclass 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);
//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);}
//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);
//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;        }    }}
#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;}

5. 程序运行结果

1       1       20       1       00       0       1[ 10, 20, 30 ][ 10, 30, 50 ]
0 0
原创粉丝点击