c++ - 无法使用 opengl 正确旋转 2D 对象
问题描述
我正在使用 opengl、glfw 和 glew。当用户分别按下左右箭头时,我想旋转飞船的尖端而不移动整个飞船。我试过使用 gltransform glrotate,它确实会旋转,但它也会移动我的宇宙飞船。空间运动的输出
objects objects::rotateSpaceship(GLFWwindow * window, objects & sp)
{
GLfloat spaceship_angle = sp.getAngle();
GLfloat newAngle = sp.getAngle() + 0.5;
sp.setAngle(newAngle);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
GLfloat spaceShipRightLine[] =
{
x, y + 80, 0,
x - 50, y - 50, 0
};
GLfloat spaceShipLeftLine[] = {
x, y + 80, 0,
x + 50, y - 50, 0
};
GLfloat spaceShipMiddleLine[] = {
sp.x - 30 ,sp.y,0,
sp.x + 35,sp.y,0
};
glPushMatrix();
glTranslatef(0.0, 0.01, 0.0); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(0.0, 0.01, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return sp;
}
解决方案
请注意,由glBegin
/glEnd
序列绘制和固定函数矩阵堆栈自几十年以来已被弃用。阅读Fixed Function Pipeline并查看Vertex Specification and Shader了解最先进的渲染方式。
我想在不移动整个飞船的情况下旋转飞船的尖端 [...]
首先,您必须定义枢轴,即宇宙飞船的“尖端”:
float pivot_x = sp.x;
float pivot_y = sp.y + 80.0f;
要围绕枢轴旋转,您必须定义一个模型矩阵,该矩阵由反转的枢轴置换,然后旋转 ( glRotatef
) 并最终转换回枢轴 ( glTranslate
):
glTranslatef(pivot_x, pivot_y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-pivot_x, -pivot_y, 0);
最终代码可能如下所示:
float pivot_x = x;
float pivot_y = y + 80.0f;
glPushMatrix();
glTranslatef(pivot_x, pivot_y, 0 ); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(-pivot_x, -pivot_y, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
推荐阅读
- javascript - 用户向下滚动页面时使用 Javascipt 预加载/延迟加载图像
- json - 如何配置验证器以尊重 JSON 验证中已经存在的 $type 类型名称?
- python - 无法访问来自 Xpath 的 Python 中的数组元素
- android - 在 Android TV 上记录/保存语音识别意图中的音频
- ffmpeg - 如何为 ffmpeg HLS 导出的文件夹提供自定义文件夹名称?
- c - 通过在 VS Code 中引入函数来重构 C 代码。参数值和指针语法
- typescript - 迭代对象的通用属性,验证它是对象的属性而不是任何字符串(我收到来自编译器的错误)
- html - 导致宽度居中的垂直线是问题
- visual-studio-extensions - 有没有办法将 EnvDTE Project 全局变量保存到 vcxproj.user 文件而不是 .vcxproj 文件?
- azure-devops - 预测 Azure Devops 中一组大小工作项的交付日期