OpenGL超级宝典(第7版)笔记18 位移、旋转、缩放、观察、透视矩阵 代码实现
前言
上一篇我们介绍了缩放矩阵、旋转矩阵、位移矩阵、观察矩阵、透视矩阵,我们介绍了这个流程中每个矩阵的用处,以及简单的推导了一下矩阵是如何来的,这里我们要把这些计算添加到我们自己的c++类中去,我们将基础的四维向量(3维同理不再过多介绍)、4*4矩阵都封装到类中,之后定义一个粗略的摄像机把那一大堆矩阵都放进去,试着生成3D的图形。
1 向量和矩阵
首先是向量和矩阵类的声明:
#ifndef BASIC_RA
#define BASIC_RA
#include<iostream>
#include<Windows.h>
#include<math.h>
#define GLEW_STATIC
#include<glew.h>
#include<glfw3.h>
#include<math.h>
#endif //!BASIC_RA
#ifndef VEC3F_H
#define VEC3F_H
class vec3f
{
public:
vec3f();
vec3f(GLfloat a, GLfloat b, GLfloat c);
public:
vec3f Front_cross(vec3f& a);//前叉乘,a在前的叉乘,不能连乘,右/左手定则
vec3f Back_cross(vec3f& a);//后叉乘,a在后的叉乘,不能连乘,右/左手定则
GLfloat Dot(vec3f& a);//点乘,不能连乘
vec3f mult(GLfloat a);//乘
void To_one();//单位化,变成长度为1的向量
public://运算符重载
vec3f operator+(const vec3f& a);//不能连加
void operator+=(const vec3f a);
vec3f operator-(const vec3f& a);//不能连减
void operator-=(const vec3f a);
vec3f& operator=(const vec3f a);//应该可以连等赋值
GLfloat operator*(const vec3f a);//点乘,不能连乘
GLfloat& operator[](int i);
public:
void print();
public:
GLfloat x;
GLfloat y;
GLfloat z;
};
#endif // !VEC3F_H
#ifndef VEC4F_H
#define VEC4F_H
class vec4f
{
public:
vec4f();
vec4f(GLfloat a, GLfloat b, GLfloat c, GLfloat d);
public:
GLfloat& operator[](int i);
vec4f operator=(vec4f a);
public:
void print();
public:
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
};
#endif // !VEC4F_H
#ifndef MAT4F_H
#define MAT4F_H
class mat4f{
public:
mat4f();
mat4f(GLfloat in);
~mat4f();
public:
void input_f_front(GLfloat *data,int number);//从头写入
void input_f_back(GLfloat *data,int number);//从尾部写入
void input_f(GLfloat data,int loc);//修改某个位置的值
void input_3vs(vec3f *v,int number);//从头写入vec3f拷贝的位置
void input_3v(vec3f v,int loc);
void input_4vs(vec4f *v,int number);//从头写入
void input_4v(vec4f v,int loc);
public:
mat4f build_rotation(GLfloat rx,GLfloat ry,GLfloat rz);//生成绕x,y,z的旋转矩阵
vec3f rotation(vec3f a);//把a向量经过本矩阵进行旋转
public:
mat4f operator*(const mat4f a);
vec4f operator*(vec4f a);
mat4f operator=(const mat4f a);
public:
void clear();//清零
void clear_to_one();
void print();
public:
GLfloat m_mat4f[16]={
0};
};
#endif //!MAT4F_H
声明中包含了成员变量,初始化函数,赋值函数,特殊计算函数,运算符重载,还有一些辅助函数(print clear)
声明中值得特别提起的就三个函数:
第一个是vec3f中的Front_cross和Back_cross他们分别对应前后叉乘,使用的时候要注意选择(因为叉乘的顺序不同,最后产生的方向就不一样)。
第二个是vec3f中的To_one,这是一个把向量单位化的函数,我们会经常使用该函数,尤其是在摄像机视角移动的时候
第三个是mat4f中的build_rotation,我们可以通过向它输入三个弧度值,最终得到欧拉角的旋转矩阵
这里只放几个重要的函数代码(要不然太长了),完整版看我的资源(免费的资源):
#include "vec34_mat4.h"
#pragma region vec3f
vec3f vec3f::Front_cross(vec3f& a) {
vec3f temp;
temp.x = a.y * this->z - a.z * this->y;
temp.y = -a.z * this->x + a.x * this->z;
temp.z = a.x * this->y - a.y * this->x;
return temp;
}
vec3f vec3f::Back_cross(vec3f& a) {
vec3f temp;
temp.x = a.z * this->y - a.y * this