【发布时间】:2019-11-04 04:54:21
【问题描述】:
我需要为大学的一个项目制作游戏。一切正常,唯一的问题是将鼠标坐标(左上角的 0,0)转换为 openGL 坐标(屏幕中心的 0,0)。
在课堂上,我们得到了这样做的公式: double openglX = ((double)x - [半水平分辨率]) / [水平分辨率] * [水平 opengl 范围]; double openglY = -((double)y - [半垂直分辨率]) / [垂直分辨率] * [垂直 opengl 范围];
#include <iostream>
#include <list>
#include <vector>
#include <cstdlib>
#include <ctime>
#define NDEBUG
#include <GL/freeglut.h>
const int GAME_LOGIC_REFRESH_TIME = 10;
/* GLUT callback Handlers */
void resize(int width, int height)
{
const float ar = (float)width / (float)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
gluLookAt(0, 0, 45, 0, 0, 0, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void gameLogic(int value)
{
if (value == 0)
{
}
else if(value==1)
{
}
}
void move_ship(int x, int y)
{
double openglX = ((double)x - 600) / 1200 * 46;
double openglY = -((double)y - 500) / 1000 * 38;
player.SetPosition(openglX);
}
/* helper functions for settings options and parameters */
void InitGLUTScene(const char* window_name)
{
glutInitWindowSize(1200, 1000);
glutInitWindowPosition(40, 40);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutCreateWindow(window_name);
glClearColor(0, 0, 0, 0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
}
void SetCallbackFunctions()
{
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutTimerFunc(GAME_LOGIC_REFRESH_TIME, gameLogic, 0);
glutMouseFunc(mouse);
glutPassiveMotionFunc(move_ship);
}
void SetObjectsPositions()
{
}
int main(int argc, char *argv[])
{
srand(time(NULL));
glutInit(&argc, argv);
InitGLUTScene("Space Invaders");
SetCallbackFunctions();
SetObjectsPositions();
glutMainLoop();
return 0;
}
move_ship 中的计算在靠近屏幕中心的位置非常好,但在边缘处它们离得太远了,这是一个大问题,玩家无法到达屏幕边缘。
【问题讨论】:
-
该公式将屏幕坐标转换为 OpenGL 剪辑空间,即 x、y 和 z 轴的 [-1, 1]。 (z 轴 -> 深度值)。 (z 轴在您的公式中被忽略。)它不考虑您使用
glFrustum()实现的透视变换。有两种解决方案:3D picking 或将鼠标坐标转换为用于 CPU 侧相交的光束段:How to convert world to screen coordinates and vice versa。 -
这件事让我很困惑。我在任何地方都看到 x 和 y 上的 [-1, 1] 范围,但在大学的每一段代码中,它都有一些奇怪的数字,就像我提供给你的那样。
-
好的,所以我做了正确的事并放弃了一些神奇的数字,但左边两个我不知道如何摆脱
c++ double openglX = ((double)x - glutGet(GLUT_WINDOW_WIDTH) / 2) / glutGet(GLUT_WINDOW_WIDTH) * 46; double openglY = -((double)y - glutGet(GLUT_WINDOW_HEIGHT) / 2) / glutGet(GLUT_WINDOW_HEIGHT) * 38;46 是初始 X 轴的宽度,中心在middle 38 是初始 Y 轴的宽度,中心在中间