【问题标题】:How to correctly translate mouse coords to opengl coords?如何正确地将鼠标坐标转换为 opengl 坐标?
【发布时间】: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 轴的宽度,中心在中间

标签: c++ opengl freeglut


【解决方案1】:

我注意到的第一件事是你的方法 move_ship() 中有一些神奇的数字。你的回调 resize() 能够改变宽度和高度,所以在 move_ship() 中使用常量对我来说似乎是一个错误。

【讨论】:

  • 是的,我知道这是一个残酷的黑客攻击,但现在我只想让鼠标移动到点,我也不打算调整窗口大小。如果我得到正确的鼠标并且在截止日期之前有足够的时间,我肯定会以正确的方式做:) 而且我这些“神奇的数字”是问题的原因,因为我无法 100% 测量这些尺寸对。
  • 好吧 46 和 48,我们不知道这些数字是从哪里来的。我猜他们应该是 MaxPlayerPositionXY/2 ?
  • 没错,班上没有人告诉我们为什么应该是这些数字(不同的)。这些数字是我经过反复试验得到的,在屏幕边缘它们脱落了,所以我无法到达边缘。在网络上的任何地方,我都能看到从 -1 到 1 的 OpenGL 坐标,而这里我有 46 个等等。
  • 好吧,我们永远无法解决这里的难题。你在学习游戏编程吗?无论如何,主要问题似乎是你只是复制粘贴你还不理解的代码,甚至是概念。我建议阅读有关 openhl 中使用的各种矩阵的 somr 在线文档。确保您了解世界、相机和投影矩阵的概念。你很幸运,你的游戏只是一个 2d 平台游戏,所以不涉及 3d 或投影,这会让事情变得更容易。并命名你的变量和函数,它会得到回报。祝你好运!
  • 不,我不复制粘贴。该公式在课堂上有效,我知道这些数字在那里意味着什么,我之前已经描述过。刚才,当我创建一个新项目并且没有从第一个项目中复制它并尝试以正确的方式进行时,我并没有 100% 工作
【解决方案2】:

公式应该是

void mouseToGl(
    double& x, double& y, // output GL coords
    double mx, double my, // mouse coords in pixels (0,0 is top left)
    double W, double H)   // screen dimension width, height
{
    x = 2.0 * (mx / W) - 1.0;
    y = 2.0 * ((my - W + 1) / W) - 1.0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多