OpenGL и клавиатура

252
20 июня 2018, 20:50

Есть проект, на C++ с OpenGL - просто камера, которой можно управлять с помощью клавиатуры. Но когда включена русская раскладка, то камера не перемещается, а при отпускании клавиши приложение завершается с ошибкой. (Выводится сообщение от Windows что прекращена работа программы). проект включает в себя ещё 4 файла (Camera.h, Camera.cpp, Vector3.h, Vector3.cpp), если надо, то могу скинуть их содержимое. Заранее спасибо.

main.cpp:

#include "Camera.h"
#include "Vector3.h"
#include <GL/glut.h>
#include <math.h>
#include <vector>
#include <algorithm>
using namespace std;
int HWND;
float WIN_WIDTH = 640, WIN_HEIGHT = 480;
float CAM_MOVE_SPEED = 2, CAM_ROT_SPEED = 2;
Camera cam = Camera();
vector<char> keys;
static long double d2r(long double d) {return (d / 180.0) * ((long double) M_PI);}
void drawMap()
{
    int m[] = {
    1, 0, 0, 0, 0,
    0, 1, 0, 1, 0,
    0, 0, 0, 0, 0,
    1, 0, 0, 0, 1,
    0, 1, 1, 1, 0,
    };
    for (int y=0; y<5; y++)
    {
        for (int x=0; x<5; x++)
        {
            if (m[x*5+y] == 1)
            {
                glutWireCube(20);
            }
            glTranslatef(-20, 0, 0);
        }
        glTranslatef(100, 0, 20);
    }
}
void draw()
{
    glClear(GL_COLOR_BUFFER_BIT);
    drawMap();
    cam.updateMatrix();
    glutSwapBuffers();
}
void timer(int)
{
    glutPostRedisplay();
    glutTimerFunc(50, timer, 0);
}
void keyTimer(int)
{
    if (find(keys.begin(), keys.end(), 'w') != keys.end()) cam.move(-sin(d2r(cam.rot.y)*CAM_MOVE_SPEED), 0, cos(d2r(cam.rot.y))*CAM_MOVE_SPEED);
    if (find(keys.begin(), keys.end(), 's') != keys.end()) cam.move(sin(d2r(cam.rot.y)*CAM_MOVE_SPEED), 0, -cos(d2r(cam.rot.y))*CAM_MOVE_SPEED);
    if (find(keys.begin(), keys.end(), 'a') != keys.end()) cam.move(cos(d2r(cam.rot.y)*CAM_MOVE_SPEED), 0, sin(d2r(cam.rot.y))*CAM_MOVE_SPEED);
    if (find(keys.begin(), keys.end(), 'd') != keys.end()) cam.move(-cos(d2r(cam.rot.y)*CAM_MOVE_SPEED), 0, -sin(d2r(cam.rot.y))*CAM_MOVE_SPEED);
    if (find(keys.begin(), keys.end(), 'q') != keys.end()) cam.move(0, -CAM_ROT_SPEED, 0);
    if (find(keys.begin(), keys.end(), 'z') != keys.end()) cam.move(0, CAM_ROT_SPEED, 0);
    if (find(keys.begin(), keys.end(), 'u') != keys.end()) cam.rotate(-CAM_ROT_SPEED, 0, 0);
    if (find(keys.begin(), keys.end(), 'j') != keys.end()) cam.rotate(CAM_ROT_SPEED, 0, 0);
    if (find(keys.begin(), keys.end(), 'h') != keys.end()) cam.rotate(0, -CAM_ROT_SPEED, 0);
    if (find(keys.begin(), keys.end(), 'k') != keys.end()) cam.rotate(0, CAM_ROT_SPEED, 0);
    glutTimerFunc(50, keyTimer, 0);
}
void reshape(int w, int h)
{
    WIN_WIDTH = w; WIN_HEIGHT = h;
    glMatrixMode(GL_PROJECTION);
    glViewport(0, 0, w, h);
    glLoadIdentity();
    gluPerspective(60, WIN_WIDTH/WIN_HEIGHT, 0.1, 400.0);
    glMatrixMode(GL_MODELVIEW);
}
/// x cos(x)*cos(y)
/// z sin(x)*cos(y)
/// y sin(y)
void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27:
        glutDestroyWindow(HWND);
        exit(0);
        break;
    case 'w': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 's': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'a': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'd': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'q': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'z': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'u': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'j': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'h': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    case 'k': if (find(keys.begin(), keys.end(), (char)key) != keys.end()) keys.push_back((char)key); break;
    }
}
void keyboardUp(unsigned char key, int x, int y)
{
    switch (key)
    {
        case 'w': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 's': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'a': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'd': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'q': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'z': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'u': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'j': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'h': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
        case 'k': keys.erase(std::find(keys.begin(), keys.end(), (char)key)); break;
    }
}
void init()
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, WIN_WIDTH/WIN_HEIGHT, 0.1, 400.0);
    glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
    glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
    glutInitWindowPosition(100, 200);
    HWND = glutCreateWindow("Game");
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutTimerFunc(50, timer, 0);
    glutTimerFunc(50, keyTimer, 0);
    glutFullScreen();
    init();
    glutMainLoop();
    return 0;
}
Answer 1

Видимо тут проблема в реализации keyboardUp, если отпускается неизвестная клавиша, то поиск вернет итератор конца вектора, что будет нарушением инварианта для vector::erase, который требует валидный и разименуемый итератор. Кроме того, вся эта копипаста в свиче явно ни к чему. Можно сократить до:

void keyboardUp(unsigned char key, int x, int y)
{
    keys.erase(std::remove(keys.begin(), keys.end(), (char)key), keys.end());
}
READ ALSO
Сортировка бинарного дерева

Сортировка бинарного дерева

Есть вот такая вот программа которая входящие данные забивает в бинарное дерево, а потом считает количество обращений к элементамНужно после...

233
Замена подстроки в строке с++

Замена подстроки в строке с++

Есть в котором встречаются <i> и </i>Заменить каждое вхождение <i> на <курсив>, а каждое вхождение </i> на <конец курсив>

178
Проверка числа на n-значность числа

Проверка числа на n-значность числа

Программа запрашивает у пользователя шестизначное числоВывести на экран, соблюдал ли он правила

301