Как заставить 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 в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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

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

Erdal Küçük 19.02.2023 16:33

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

Erdal Küçük 19.02.2023 19:37

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