本案例将使用 OpenGL 在 Mac 环境在窗口中心绘制一个正方形, 监听键盘的上, 下, 左, 右按键, 实现每次平移的同时旋转5度, 由于工具版本比较低, Xcode 我版本高, 第一次启动时会有个小bug, 但是并不影响后边的探索, 图形会先在左下角, 拖动一下窗口, 就到屏幕中间了. 主要包括两部分, 绘制流程图和主要代码, 环境请自己搭建. 如有需要可联系本人提供对应的工具.
一.绘制流程图
-
绘制正方形平移旋转流程图.jpg
-
二.代码
如有不懂的代码, 请参考三角形绘制中注释
1. 头文件
#include "GLTools.h"
#include <GLUT/GLUT.h>
2. 全局变量
//定义一个,着色管理器
GLShaderManager shaderManager;
//简单的批次容器,是GLTools的一个简单的容器类。
GLBatch triangleBatch;
//blockSize 边长
GLfloat blockSize = 0.1f;
//正方形的4个点坐标
GLfloat vVerts[] = {
-blockSize,-blockSize,0.0f,
blockSize,-blockSize,0.0f,
blockSize,blockSize,0.0f,
-blockSize,blockSize,0.0f
};
// 正方形平移的偏移量 x / y 方向
GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;
// 正方形旋转角度累计
GLfloat yRot = 0.0f;
3. main 函数
int main(int argc,char *argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
glutInitWindowSize(800, 600);
glutCreateWindow("Triangle")
glutReshapeFunc(changeSize);
glutDisplayFunc(RenderScene);
//注册特殊键位监听函数
glutSpecialFunc(SpecialKeys);
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
setupRC();
glutMainLoop();
return 0;
}
4. SetupRC 函数
void setupRC()
{
glClearColor(0.8f, 0.9f, 0.9f, 1.0f);
shaderManager.InitializeStockShaders();
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
5. changeSize 函数
- 初始化时调用一次
- 当窗口大小改变时, 会调用此函数, 比如拖动改变窗口大小.
/*
在窗口大小改变时,接收新的宽度&高度。
*/
void changeSize(int w,int h)
{
glViewport(0, 0, w, h);
}
6. RenderSence 函数
- 初始化时调用一次
- 重新绘制时, 会调用此函数
void RenderScene(void)
{
//1.清除一个或者一组特定的缓存区
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f,0.0f,0.0f,0.0f};
// 定义矩阵
M3DMatrix44f mFinalTransform, mTransfromMatrix, mRotationMartix;
//平移
m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);
//旋转
m3dRotationMatrix44(mRotationMartix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
//将旋转和移动的矩阵结果 合并到 mFinalTransform (矩阵相乘)
m3dMatrixMultiply44(mFinalTransform, mTransfromMatrix, mRotationMartix);
//将矩阵结果 提交给固定着色器(平面着色器)中绘制
shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);
triangleBatch.Draw();
//执行交换缓存区
glutSwapBuffers();
}
7.上下左右 键位监听
void SpecialKeys(int key, int x, int y){
// 旋转
yRot += 5.0f;
// 平移步长
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;
}
// 手动调用 RenderSence 函数进行重绘
glutPostRedisplay();
}
网友评论