本文主要是介绍3D数学 矩阵和线性变换之镜像,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
矩阵和线性变换之镜像
1. 什么是镜像变换?
在2D中镜像变换就如下图所示,沿着某条轴发生对称现象就叫镜像变换。在3D中同理可以得到沿着某个平面发生对称的现象。
2. 镜像变换的矩阵是怎样的?
我们想来看简单的,沿着x轴、y轴或z轴发生镜像变换(注意是“沿着”轴的镜像,而不是“关于”轴对称),原理很简单,只需要让x、y或z变为相反数即可。所以我们分别只需令单位矩阵上第一列、第二列或第三列的1变为-1,就分别得到沿着x轴、y轴或z轴发生镜像变换的矩阵。
再来看复杂的,沿着任意轴发生镜像变换,需要用到下面这个矩阵(该轴给出的方向向量一定要是单位向量)(数学证明暂时不给出,详见《3D数学基础 图形与游戏开发》)。
3. 镜像矩阵编程示例
void Matrix3X3::setReflect(E_Axis axis)
{m11 = 1; m12 = 0; m13 = 0;m21 = 0; m22 = 1; m23 = 0;m31 = 0; m32 = 0; m33 = 1;switch(axis){case Axis_x:{m11 = -1;break;}case Axis_y:{m22 = -1;break;}case Axis_z:{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;
}
4. 镜像矩阵编程完整程序示例
//MathUtil.h#pragma once#include <math.h>enum E_Axis{Axis_x,Axis_y,Axis_z};
const float Pi = 3.14159;
//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);
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)
{m11 = 1; m12 = 0; m13 = 0;m21 = 0; m22 = 1; m23 = 0;m31 = 0; m32 = 0; m33 = 1;switch(axis){case Axis_x:{m11 = -1;break;}case Axis_y:{m22 = -1;break;}case Axis_z:{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;
}
#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.setReflect(Axis_x);print_v(a);b = a * M;print_v(b);Vector3 n(0,0,1);M.setReflect(n);b = a * M;print_v(b);system("pause");return 0;
}
5. 代码运行结果
[ 10, 20, 30 ][ -10, 20, 30 ][ 10, 20, -30 ]
这篇关于3D数学 矩阵和线性变换之镜像的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!