OpenGL 学习笔记 02 —— 图形的平移和旋转及窗口边界检查

在上一篇笔记中, 我们已经实现了一个简单三角形的绘制. 本文将介绍图形移动的两种实现方式及图形的旋转, 以及在移动过程中对窗口边界的检查, 以免图形移动到窗口外部.

图形的移动

绘制图形

在上一篇笔记中, 我们绘制了一个三角形. 为了方便观察, 本文中将三角形改为四边形.

// 四边形边长
GLfloat length = 0.1f;
// 设置四边形顶点位置, 设置为全局变量, 方便改变坐标实现移动
GLfloat verts[] = {
    -length, -length, 0.0f,
    length, -length, 0.0f,
    length, length, 0.0f,
    -length, length, 0.0f,
};

void setupRC() {
    // 设置清屏颜色
    glClearColor(0.0f,0.0f,1.0f,1.0f);
    // 初始化管线
    shaderManager.InitializeStockShaders();
    // 开始绘制
    triangleBatch.Begin(GL_POLYGON, 4);
    triangleBatch.CopyVertexData3f(verts);
    triangleBatch.End();
}
复制代码

监听键盘事件

在 main 函数中, 注册监听事件

// 注册特殊函数
glutSpecialFunc(specialKeys);
复制代码

方法一: 直接改变顶点的位置

void specialKeys(int key, int x, int y) {
    GLfloat stepLength = 0.025f;

    // 获取左上角顶点的坐标值
    GLfloat originX = verts[0];
    GLfloat originY = verts[10];

    // 判断按下的是哪个键
    if (key == GLUT_KEY_UP) {
        originY += stepLength;
    } else if (key == GLUT_KEY_DOWN) {
        originY -= stepLength;
    } else if (key == GLUT_KEY_LEFT) {
        originX -= stepLength;
    } else {
        originX += stepLength;
    }

    // 修改各个点的坐标
    verts[0] = originX;
    verts[1] = originY - length * 2;
    verts[3] = originX + length * 2;
    verts[4] = originY - length * 2;
    verts[6] = originX + length * 2;
    verts[7] = originY;
    verts[9] = originX;
    verts[10] = originY;

    // 刷新顶点坐标
    triangleBatch.CopyVertexData3f(verts);
    // 重新渲染
    glutPostRedisplay();
}
复制代码

至此, 便实现了使用上下左右键控制四边形移动.

窗口边界检查

使用上述方法实现四边形移动后, 会存在这样一个问题: 当四边形移动到窗口边沿后, 继续移动将会移出窗口范围, 最终消失不见.

为了防止此类问题出现, 需要在移动过程中对窗口边界进行判断.

// 在判断按键并改变顶点坐标值后进行触碰到边界(4个边界)的处理
// 当正方形移动超过最左边的时候
if (originX < -1.0f) {
    originX = -1.0f;
}
// 当正方形移动到最右边时
// 1.0 - length * 2 = 总边长 - 正方形的边长 = 最左边点的位置
if (originX > (1.0 - length * 2)) {
    originX = 1.0f - length * 2;
}
// 当正方形移动到最下面时
// -1.0 - length * 2 = Y(负轴边界) - 正方形边长 = 最下面点的位置
if (originY < -1.0f + length * 2 ) {
    originY = -1.0f + length * 2;
}
// 当正方形移动到最上面时
if (originY > 1.0f) {
    originY = 1.0f;
}
复制代码

此时, 四边形移动到窗口边界时就不会出界了.

方法二: 使用矩阵实现移动

定义 x, y 轴上的偏移量

//x轴上移动的距离
GLfloat offsetX =0.0f;
//y轴上移动的距离
GLfloat offsetY =0.0f;
复制代码

specialKeys 中设置偏移量

// 判断按下的是哪个键
if (key == GLUT_KEY_UP) {
    offsetY += stepLength;
} else if (key == GLUT_KEY_DOWN) {
    offsetY -= stepLength;
} else if (key == GLUT_KEY_LEFT) {
    offsetX -= stepLength;
} else {
    offsetX += stepLength;
}

//触碰到边界(4个边界)的处理
if(offsetX < -1.0f + length) {
    offsetX = -1.0f + length;
}
if(offsetX > 1.0f - length) {
    offsetX = 1.0f - length;
}
if(offsetY < -1.0f + length) {
    offsetY = -1.0f + length;
}
if(offsetY > 1.0f - length) {
    offsetY = 1.0f - length;
}
复制代码

renderScene 在重新渲染

//利用矩阵帮助移动
//finalMatrix 结果矩阵
//transformMatrix 平移矩阵
//rotationMatrix  旋转矩阵
M3DMatrix44f finalMatrix, transformMatrix, rotationMatrix;

//平移 x,y,z,w(缩放因子 = 1)
//3D中平移的原理与矩阵之间关系
/*
 参数1:矩阵
 参数2、3、4:X,Y,Z上平移距离
 */
m3dTranslationMatrix44(transformMatrix, offsetX, offsetY, 0.0f);

//平面着色器
/*
 1.平移矩阵 transformMatrix 与 每个顶点 相乘 -> 新顶点 (顶点着色器
 2.将片元着色红色 (片元着色器)
 */
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, redColor);

triangleBatch.Draw();
复制代码

图形旋转

在平移的基础上, 使用矩阵实现边移动边旋转.

// 设置平移属性
static float degree = 0.0f;

/*
 参数1:矩阵
 参数2:弧度
 参数3:X:1,0 1:围绕X轴旋转,0不围绕X轴旋转
 参数4:Y:1,0
 参数5:Z:1,0
 */
m3dRotationMatrix44(rotationMatrix, m3dDegToRad(degree), 0.0f, 0.0f, 1.0f);

// 修改旋转度数
degree +=5.0f;

// 结合2个矩阵的结果 平移矩阵 * 旋转矩阵 = 最终结果矩阵
m3dMatrixMultiply44(finalMatrix, transformMatrix, rotationMatrix);

shaderManager.UseStockShader(GLT_SHADER_FLAT, finalMatrix, redColor);
复制代码

运行结果:

Talk is cheap, show me the code.

Demo 下载地址

转载于:https://juejin.im/post/5a8068175188257a7f1da5ea

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值