目录
一、基础知识
计算机3D图形学最最最基本的目标就是:将构建好的3D物体显示在2D屏幕坐标上;可以先了解一下相关知识。
防丢:下面两篇文章内容我打包到资源中了,可以在我的资源中找到;
要将一个3维图形 在二维界面旋转显示,可以采用旋转矩阵的方式;一个点需要进行三次矩阵点乘,然后把图形所有的顶点全部进行三次点乘就可以获得最终的点坐标
1.矩阵运算
大学唯一挂的科-线性代数;必须先补充一下,链接是讲的比较简单的文章;不用回去翻书。
线性代数- 矩阵运算
2.三维坐标旋转矩阵变换
二维旋转矩阵推导
下面的文章是坐标变换的过程
三维坐标旋转矩阵推导过程(包看懂)
3.三维旋转矩阵
绕X轴旋转 θ \theta θ角度的旋转矩阵Rx(θ)
R x ( θ ) = [ 1 0 0 0 cos θ − sin θ 0 sin θ cos θ ] R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta \\ 0 & \sin\theta & \cos\theta \end{bmatrix} Rx(θ)= 1000cosθsinθ0−sinθcosθ
绕Y轴旋转 θ \theta θ角度的旋转矩阵 Ry(θ)
R y ( θ ) = [ cos θ 0 sin θ 0 1 0 − sin θ 0 cos θ ] R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix} Ry(θ)= cosθ0−sinθ010sinθ0cosθ
绕Z轴旋转 θ \theta θ角度的旋转矩阵Rz(θ)
R z ( θ ) = [ cos θ − sin θ 0 sin θ cos θ 0 0 0 1 ] R_z(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} Rz(θ)= cosθsinθ0−sinθcosθ0001
二、C语言实现
矩阵运算库-C https://github.com/Amoiensis/Matrix_hub
1. 关键函数-C
// 矩阵乘法运算-通用
// a[m][n] * b[n][p] = c[m][p]
// mid = n;
// 序号 = 列数*行索引 + 列索引
// c的元素个数 m*p 序号 : p*(0 -- m-1) + (0 -- p-1)
// a的元素个数 m*n 序号 : n*(0 -- m-1) + (0 -- n-1)
// b的元素个数 n*p 序号 : p*(0 -- n-1) + (0 -- p-1)
float* Matrex_Conv(int l_row,int l_col,int r_row,int r_col, float* martex_l, float* martex_r)// a[m][n] * b[n][p] = c[m][p]
{
int i,j,k,mid;
float* martex_o;
if(l_col != r_row)
{
return NULL;
}
mid = r_row;
for(i = 0; i < l_row;+ i++) //m
{
for(k = 0; k < r_col; k++) //p
{
for (j = 0; j < mid; j++) //n
{
martex_o[i*r_col+k] += martex_l[i*l_col + j] * martex_r[j*r_col+k];// martex_l 行不变 列++ martex_r 列不变 行++
}
}
}
return martex_o;
}
//计算矩阵乘法 - 简化版 因为行列已知
// float a[3] = {x,y.z};
float* Matrex_Conv(float* a, float b[3][3])
{
float res[3];
for(int i = 0; i < 3; i++)
res[i] = b[i][0] * a[0] + b[i][1] * a[1] + b[i][2] * a[2];
for(int i = 0; i < 3; i++)a[i] = res[i];
return a;
}
//x,y,z为弧度制
void rotate(float* obj, float x, float y, float z) //旋转该向量
{
float rx[3][3] = { {1, 0, 0},
{0, cos(y), -sin(y)},
{0, sin(y), cos(y)}};
float ry[3][3] = { {cos(x), 0, sin(x)},
{0, 1, 0},
{-sin(x), 0, cos(x)}};
float rz[3][3] = { {cos(z), -sin(z), 0},
{sin(z), cos(z), 0},
{0, 0, 1}};
obj = Matrex_Conv(obj,rx);
obj = Matrex_Conv(obj,ry);
obj = Matrex_Conv(obj,rz);
}
2.继续简化
实际还能简化
绕x轴旋转时,x坐标不变,转换为2维点旋转,分别进行3次二维点旋转即可。
// 绕y轴旋转x′ = x*cosβ - y*sinβ
// y′ = x*sinβ + y*cosβ
void rotate(float* obj, float pitch, float yow, float roll)
{
float sin_p,cos_p,sin_y,cos_y,sin_r,cos_r;
float xt,yt,zt,x,y,z;
x = obj[0];
y = obj[1];
z = obj[2];
sin_p = sin(pitch);
cos_p = cos(pitch);
sin_y = sin(yow);
cos_y = cos(yow);
sin_r = sin(roll);
cos_r = cos(roll);
//绕x轴旋转;x轴坐标不变
yt = y * cos_p - z * sin_p;
zt = y * sin_p + z * cos_p;
y = yt;
z = zt;
//绕y轴旋转;y轴坐标不变
xt = x * cos_y - z * sin_y;
zt = x * sin_y + z * cos_y;
x = xt;
z = zt;
//绕x轴旋转;z轴坐标不变
xt = x * cos_r - y * sin_r; // finaly rotate around the Z axis
yt = x * sin_r + y * cos_r; // using X and Y
x = xt;
y = yt;
obj[0] = x;
obj[1] = y;
obj[2] = z;
}
3. 旋转图形
有了前面对单个点的旋转后,将图形所有顶点进行旋转后就可以得到整体图形的旋转效果;
常在各种视频中看到旋转的3d立方体,实际上;项目中通常用于模型姿态显示可以说效果会很好。