OpenGL(五)-矩阵变换

关键函数讲解

平移

1
2
3
4
5
6
7
8
9
10
11
12
//创建单元矩阵 
M3DMatrix44f m3;
m3dLoadIdentity44(m3);

/*
m3dTranslationMatrix44(M3DMatrix44f m, float x, float y, float z)
参数1:结果矩阵,平移之后的结果矩阵
参数2:沿着X轴移动多少,正数\负数
参数3:沿着Y轴移动多少,正数\负数
参数4:沿着Z轴移动多少,正数\负数
*/
m3dTranslationMatrix44(m3, 0.0f, 10.0f, 0.0f);

旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    /*
m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z);
参数1:结果矩阵,旋转之后的结果矩阵
参数2:旋转多少弧度
参数3:是否围绕X轴旋转,是(1),不是(0)
参数4:是否围绕Y轴旋转,是(1),不是(0)
参数5:是否围绕Z轴旋转,是(1),不是(0)
*/
m3dRotationMatrix44(m3, m3dDegToRad(45.0f), 1.0f, 0.0f, 0.0f);
```
### 缩放
```objc
/*
void m3dScaleMatrix44(M3DMatrix44f m, float xScale, float yScale, float zScale)
参数1:结果矩阵
参数2:围绕X轴放大\缩小;放大x>1,缩小:0.5f
参数3:围绕Y轴放大\缩小;放大x>1,缩小:0.5f
参数4:围绕Z轴放大\缩小;放大x>1,缩小:0.5f
*/
m3dScaleMatrix44(m3, 1.0f, 10.0f, 1.0f);

案例1 : 利用矩阵的平移、旋转、综合变化等, 实现矩阵的移动.

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
GLBatch	squareBatch;
GLfloat blockSize = 0.1f;
GLfloat vVerts[] = {
-blockSize, -blockSize, 0.0f,
blockSize, -blockSize, 0.0f,
blockSize, blockSize, 0.0f,
-blockSize, blockSize, 0.0f};

GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;

void SetupRC()
{
//背景颜色
glClearColor(0.0f, 0.0f, 1.0f, 1.0f );

shaderManager.InitializeStockShaders();

// 加载矩形
squareBatch.Begin(GL_TRIANGLE_FAN, 4);
squareBatch.CopyVertexData3f(vVerts);
squareBatch.End();
}

//移动(移动只是计算了X,Y移动的距离,以及碰撞检测)
void SpecialKeys(int key, int x, int y)
{
GLfloat stepSize = 0.025f;


if(key == GLUT_KEY_UP)
yPos += stepSize;

if(key == GLUT_KEY_DOWN)
yPos -= stepSize;

if(key == GLUT_KEY_LEFT)
xPos -= stepSize;

if(key == GLUT_KEY_RIGHT)
xPos += stepSize;

// 碰撞检测
if(xPos < (-1.0f + blockSize)) xPos = -1.0f + blockSize;

if(xPos > (1.0f - blockSize)) xPos = 1.0f - blockSize;

if(yPos < (-1.0f + blockSize)) yPos = -1.0f + blockSize;

if(yPos > (1.0f - blockSize)) yPos = 1.0f - blockSize;

// 每次操作方向键之后, 重新调用RenderScene进行新的场景渲染
glutPostRedisplay();
}

void RenderScene(void)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };

//!!!矩阵变化 - 关键代码!!!
M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationMatrix;

//平移 xPos,yPos
m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);

// 每次重绘时,旋转5度
static float yRot = 0.0f;
yRot += 5.0f;
m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);

//将旋转和移动的结果合并到mFinalTransform 中
m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);

//将矩阵结果提交到固定着色器(平面着色器)中。
shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);

//!!!矩形重新绘制, 即会出现一个既平移了方向又旋转了角度的新矩形
squareBatch.Draw();

// 执行缓冲区交换
glutSwapBuffers();
}

void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
}


int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("Move Block with Arrow Keys");

GLenum err = glewInit();
if (GLEW_OK != err)
{

fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return 1;
}


glutReshapeFunc(ChangeSize);//设置视口大小
glutDisplayFunc(RenderScene);//渲染场景
glutSpecialFunc(SpecialKeys);//键盘方向键操作

SetupRC();

glutMainLoop();
return 0;
}

效果图:

注: 本例是键盘的上下左右方向键来控制矩形的旋转平移, 具体代码参见上面
利用矩阵变换实现模型变化.gif

案例2 : 利用模型视图矩阵和投影矩阵让一个球体旋转

绘制球体
1
2
3
gltMakeSphere(torusBatch, 0.4f, 10, 20);

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
设置模型视图矩阵 和 投影矩阵
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
//建立一个基于时间变化的动画
static CStopWatch rotTimer;

//当前时间 * 60s
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//矩阵变量
M3DMatrix44f mTranlate,mRotate,mModelView,mModelViewProjection;

//将圆球像Z轴负方向移动2.5个单位长度
m3dTranslationMatrix44(mTranlate, 0.0f , 0.0f,-2.5f);

//旋转
m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);

//将平移和旋转的矩阵进行叉乘,产生一个新的矩阵mModelView
m3dMatrixMultiply44(mModelView, mTranlate, mRotate);

//模型视图矩阵 和 投影矩阵
//将投影矩阵 与 模型视图矩阵进行叉乘 ,将变化最终结果通过矩阵叉乘的方式应用到mModelViewProjection中来
m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(), mModelView);

GLfloat vBlack[] = {0.0f,0.0f,0.0f,1.0f};

//平面着色器来渲染图像
shaderManager.UseStockShader(GLT_SHADER_FLAT,mModelViewProjection,vBlack);

//开始绘图
torusBatch.Draw();

glutSwapBuffers();
glutPostRedisplay();
效果图

ModelViewProjection.gif

谢谢你赏我糖果吃