Как заставить C++ OpenGL Camera смотреть влево и вправо?

В этом проекте я сделал 3d куб и добавил камеру. Мы можем двигаться вперед, назад, вправо или влево с помощью клавиш W, A, S, D, но мы не можем повернуть направо или налево. Например, я хочу увидеть обратную сторону куба, но не могу ее увидеть. На самом деле это простая задача и ее решение простое, но мой уровень математики недостаточен, будет лучше, если кто-нибудь объяснит мне это. расскажу вам мой код и то, что я пробовал ниже.

#include <Windows.h>

#include <gl/GL.h>
#include <gl/GLU.h>
#include <GLFW/glfw3.h>

#include <cstdio>
#include <iostream>
#include <cmath>
#include <math.h>

int width = 1280;
int height = 720;

float camera_z = 5;
float camera_y = 0;
float camera_x = 0;

float fov = 60;

GLFWwindow* window;

float speed = 0.01;


GLfloat vertices[] = {
    -1, -1, -1,   -1, -1,  1,   -1,  1,  1,   -1,  1, -1,
    1, -1, -1,    1, -1,  1,    1,  1,  1,    1,  1, -1,
    -1, -1, -1,   -1, -1,  1,    1, -1,  1,    1, -1, -1,
    -1,  1, -1,   -1,  1,  1,    1,  1,  1,    1,  1, -1,
    -1, -1, -1,   -1,  1, -1,    1,  1, -1,    1, -1, -1,
    -1, -1,  1,   -1,  1,  1,    1,  1,  1,    1, -1,  1
};

GLfloat colors[] = {
    1, 1, 0,   1, 1, 0,   0, 1, 0,   0, 1, 0,
    1, 1, 0,   1, 1, 0,   0, 1, 0,   0, 1, 0,
    1, 1, 0,   1, 1, 0,   0, 1, 0,   0, 1, 0,
    1, 1, 0,   1, 1, 0,   0, 1, 0,   0, 1, 0,
    1, 1, 0,   0, 1, 1,   0, 1, 0,   0, 1, 0,
    1, 1, 0,   0, 1, 1,   0, 1, 0,   0, 1, 0
};



void keyboard() {

    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {

        glfwSetWindowShouldClose(window, GL_TRUE);

    }
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {

        camera_z = camera_z - speed;

    }
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {

        camera_x = camera_x - speed;

    }
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {

        camera_z = camera_z + speed;

    }
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {

        camera_x = camera_x + speed;
    }
    if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {

        camera_y = camera_y + speed;
    }
    if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {

        camera_y = camera_y - speed;
    }

    

    if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {

        // need help
       
    }
    if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
       
        // need help
    }

   
}
       




void drawCube() {

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, colors);
    
    glDrawArrays(GL_QUADS, 0, 24);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

}



int main(void)
{
    

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(width, height, "C++ OpenGL ", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    

    glEnable(GL_DEPTH_TEST); 

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        glViewport(0, 0, width, height);

        /* Render here */
        glClearColor(0.0, 192/256, 1, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        float aspect = (float)width / (float)height;
        float fov = 60;
        gluPerspective(fov, aspect, 0.1, 1000);
        
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        keyboard();
        
                                                      
        gluLookAt(
            camera_x,
            camera_y,
            camera_z,
            camera_x + 1, // need help
            camera_y + 1, // need help
            camera_z - fov ,
            0,
            1, 
            0
        );

        glTranslatef(0, 0,-3);
        drawCube();



        glFlush();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

Я пробовал использовать переменные camera_eyex, *_eyey, *_eyez. Я добавил их в цикл, чтобы дать камере значение +1. Раньше я увеличивал или уменьшал их, когда хотел пойти влево или вправо, но в этом методе много ошибок. Например, даже если камера поворачивается на 45 градусов, когда я нажимаю клавишу W, она движется прямо, то есть не туда, куда я смотрю. Кроме того, поворот более чем на 90 градусов вправо или влево невозможен. Кроме того, когда я нажимаю левую кнопку, чтобы пойти влево, поворот становится все медленнее и медленнее.

Вам может быть проще, если вы не используете gluLookAt

user253751 17.02.2023 22:38

Какой недостаток у gluLookAt?

Bilal Akol 17.02.2023 22:41

Главным образом, что сложнее рассчитать параметры?

user253751 17.02.2023 22:42

Хотя я вижу, что вы смотрите в фиксированном направлении, так что, возможно, вы уже поняли, что вам нужно сделать, чтобы использовать его. Подсказка: sin(угол) и cos(угол) вычисляют точку на окружности (в радианах)

user253751 17.02.2023 22:43

Спасибо, не могли бы вы добавить код? Мои познания в математике немного ниже. Я знаю, что это проблема, программирование и математика как братья. Заранее извиняюсь.

Bilal Akol 17.02.2023 22:45

Чтобы выполнить это с помощью lookat, вам в значительной степени нужно вычислить матрицу вращения, применить ее к отдельным векторам, а затем заставить lookat восстановить матрицу вращения из этих векторов. Это очень окольный способ добиться этого. Прекратите использовать lookat, за исключением случаев, когда камера и точка, за которой вы хотите, чтобы она следовала, действительно независимы.

Yakov Galka 18.02.2023 05:08

См. Понимание матриц гомогенного преобразования 4x4 особенно ссылки в конце ...

Spektre 18.02.2023 09:15
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
Уроки CSS 6
Уроки CSS 6
Здравствуйте дорогие читатели, я Ферди Сефа Дюзгюн, сегодня мы продолжим с вами уроки css. Сегодня мы снова продолжим с так называемых классов.
Что такое Css? Для чего он используется?
Что такое Css? Для чего он используется?
CSS, или "Каскадные таблицы стилей", - это язык стилей, используемый в веб-страницах. CSS является одним из основных инструментов веб-разработки...
0
7
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно построить матрицу преобразования. Преобразование обычно представляет собой комбинацию перемещения, масштабирования и поворота.

Где вы сначала вращаете, затем масштабируете, а затем переводите (фактический порядок вычислений - умножение - обратный):

translation x scale x rotation

Если вы хотите масштабировать или вращать вокруг определенной точки (поворота или центра), вам нужно перевести в центральную точку и в конце перевести обратно в исходную точку, например:

translation x center x scale x rotation x -center

Алгоритм lookAt задает вращение и перемещение на основе параметров (глаз, цель, вверх), тогда как ваша цель — отделить вращение от перемещения. Поэтому вам нужно построить собственное преобразование, например:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//set the position of the camera
glTranslate(pos);

//set the scale or rotation pivot
//glTranslate(center);

//scale
//glScale(scale);

//rotate around z-axis first
glRotate(z_angle, 0, 0, 1);    

//rotate around y-axis
glRotate(y_angle, 0, 1, 0);

//rotate around x-axis
glRotate(x_angle, 1, 0, 0);

//set the center back, if set before
//glTranslate(-center);

Вы найдете больше информации здесь (связанный с OpenGl, хотя и «современный» OpenGl): https://learnopengl.com/Getting-started/Transformations

Примечание. Возможно, вам придется настроить ввод «W A S D» на измененные оси. Если, например, клавиша «W» регулирует z-компоненту, вы, вероятно, не пойдете «вперед» (по оси z) с приведенной выше настройкой. Чтобы двигаться в соответствии с преобразованными осями, вам понадобится матрица преобразования и извлеките их. Лучше использовать математическую библиотеку, например. глм . Как можно реализовать орбитальную камеру, опять же, посмотрите: https://learnopengl.com/Getting-started/Camera


Создание системы камер требует некоторых теоретических знаний в области линейной алгебры.

Основываясь на разделе комментариев ниже, я перечисляю все соответствующие ссылки здесь:

Кроме того, это может быть ошеломляющим для тех, кто никогда не посещал курс линейной алгебры, поэтому я настоятельно рекомендую Сущность линейной алгебры от 3Blue1Brown.

Замечание о матричном умножении, которое недостаточно подчеркивается и чаще всего упускается из виду: как только кто-то усвоил геометрический смысл скалярного произведения и геометрический смысл строк и столбцов матрицы, следует также отметить, что каждый компонент результирующего матрица является результатом скалярного произведения строки и вектора-столбца, визуализируйте это и усвойте.

@BilalAkol Билал Аркадашим, не сдавайся. Математика севиен недир? Вы когда-нибудь посещали курс линейной алгебры (lineer cebir)? Имеют ли для вас какое-либо значение термины вектор и матрица, если да, то каков ваш уровень знаний? Если вы дадите нам подсказку, мы сможем указать вам в нужном направлении. Это не так сложно, как кажется на первый взгляд (в зависимости от вашего визуального воображения, даже очень интуитивного).

Erdal Küçük 18.02.2023 20:10

Я не знаю линейной алгебры, но знаю векторы.

Bilal Akol 19.02.2023 12:47

Великолепно, это хорошее начало. Знаете ли вы, что значит взять точечное или перекрестное произведение двух векторов? Изучив эти две темы, перейдите к Переводу и Вращению , тогда вы в основном закончили. Я также очень рекомендую Сущность линейной алгебры от 3Blue1Brown.

Erdal Küçük 19.02.2023 16:09

Приложение: так как нет никакого способа обойти Матричное умножение, подсказка от меня, что в основном упускается из виду: если вы усвоили геометрический смысл скалярного произведения и после того, как вы поняли, что геометрический смысл строк и столбцов матрица, то вы также должны заметить, что каждый компонент результирующей матрицы является результатом скалярного произведения строки и вектора-столбца, визуализируйте это и усвойте.

Erdal Küçük 19.02.2023 16:33

Не «попробую», а «сделаю»! Начните с серии видео, которую я предложил. Пара видео по 10 минут, и вам не придется смотреть их все сразу. Начните с первых 5 и глав 9, 10, 11 (1 ч. вашей жизни), после этого для более глубокого понимания читайте остальные статьи. Я гарантирую, что в течение недели обучения вы сможете построить свою систему камер (на основе реальных знаний, а не уже пойманной рыбы).

Erdal Küçük 19.02.2023 19:37

Другие вопросы по теме