目的
- 实现正方形绘制
- 键位(↑ ↓ ← →)控制正方形移动
绘制正方形
注:绘制正方形常用的两种方式(1、两个三角形拼接。2、四个顶点数据直接连接)两种方式的区别是图元连接方式不同。今天是通过顶点连接方式绘制正方形
- 首先设置将要绘制的正方形的中心为坐标原点。
正方形的边长 = blockSize * 2;
GLfloat blockSize = 0.1f;
- 设置顶点数据
//正方形四个点的坐标(坐标元素为x、y、z)
GLfloat vVerts[] = {
-blockSize, -blockSize, 0.0f,
blockSize, -blockSize, 0.0f,
blockSize, blockSize, 0.0f,
-blockSize, blockSize, 0.0f,
};
- 设置图元连接方式
//将 GL_TRIANGLES 修改为 GL_TRIANGLE_FAN ,4个顶点
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
重要的绘制步骤已经结束了,接下来就是设置键位控制移动了。
键位移动
- 首先在main函数注册特殊键位函数回调
//注册特殊函数,通过监听键位的回调,实现方法SpecialKeys实现移动
glutSpecialFunc(SpecialKeys);
- 移动正方形有2种方式(1、坐标系移动。2、矩阵移动)
注:1、注意边界问题,不能让正方形越界。2、移动之后记得重新提交渲染(容易忘记。。)
坐标系移动
- 正方形总共有4个顶点,使用其中任意一个顶点的坐标。根据监听移动位置来移动。其他每个顶点也要做相应移动处理,保持正方形形态移动。(缺点:要处理每一个顶点移动的位置,比较繁琐)
- 代码如下(没有什么好解释的,看代码就可以了,直接移动4个顶点坐标)
void SpecialKeys(int key, int x, int y){
GLfloat stepSize = 0.025f;
GLfloat blockX = vVerts[0];
GLfloat blockY = vVerts[10];
if (key == GLUT_KEY_UP) {
blockY += stepSize;
}
if (key == GLUT_KEY_DOWN) {
blockY -= stepSize;
}
if (key == GLUT_KEY_LEFT) {
blockX -= stepSize;
}
if (key == GLUT_KEY_RIGHT) {
blockX += stepSize;
}
//触碰到边界(4个边界)的处理
//当正方形移动超过最左边的时候
if (blockX < -1.0f) {
blockX = -1.0f;
}
//当正方形移动到最右边时
//1.0 - blockSize * 2 = 总边长 - 正方形的边长 = 最左边点的位置
if (blockX > (1.0 - blockSize * 2)) {
blockX = 1.0f - blockSize * 2;
}
//当正方形移动到最下面时
//-1.0 - blockSize * 2 = Y(负轴边界) - 正方形边长 = 最下面点的位置
if (blockY < -1.0f + blockSize * 2 ) {
blockY = -1.0f + blockSize * 2;
}
//当正方形移动到最上面时
if (blockY > 1.0f) {
blockY = 1.0f;
}
// Recalculate vertex positions
vVerts[0] = blockX;
vVerts[1] = blockY - blockSize*2;
printf("(%f,%f)\n",vVerts[0],vVerts[1]);
vVerts[3] = blockX + blockSize*2;
vVerts[4] = blockY - blockSize*2;
printf("(%f,%f)\n",vVerts[3],vVerts[4]);
vVerts[6] = blockX + blockSize*2;
vVerts[7] = blockY;
printf("(%f,%f)\n",vVerts[6],vVerts[7]);
vVerts[9] = blockX;
vVerts[10] = blockY;
printf("(%f,%f)\n",vVerts[9],vVerts[10]);
//更新顶点数据
triangleBatch.CopyVertexData3f(vVerts);
//重新提交渲染(不要忘记写这个。。)
glutPostRedisplay();
}
矩阵移动
- 设置一个矩阵,通过正方形在X/Y轴的移动距离。使得所有顶点一起移动。(优点:通过移动图形,不用所有的顶点数据都去一个一个的设置)
- 要修改2个函数(SpecialKeys、RenderScene)
- 要设置全局变量(要在2个方法中用到)
//记录移动图形时,在x轴上平移的距离
GLfloat xPos = 0.0f;
//记录移动图形时,在y轴上平移的距离
GLfloat yPos = 0.0f;
GLfloat stepSize = 0.025f;
- 修改移动代码(SpecialKeys)
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;
}
//碰撞检测 xPos是平移距离,即移动量
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;
}
glutPostRedisplay();
}
- 修改RenderScene函数
使用平移矩阵
void RenderScene(void)
{
//1.清除一个或者一组特定的缓存区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//1.设置颜色RGBA
GLfloat vRed[] = {1.0,0.0,0.0,1.0f};
//定义矩阵
M3DMatrix44f mTransformMatrix;
//平移矩阵
m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f);
//参数1:存储着色器类型
//参数2:使用什么矩阵变换
//参数3:颜色
shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransformMatrix, vRed);
//提交着色器
triangleBatch.Draw();
glutSwapBuffers();
}
具体流程图等找到比较好用的画图软件在补上。。🤣