В этом проекте я сделал 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?
главным образом, что сложнее рассчитать параметры?
хотя я вижу, что вы смотрите в фиксированном направлении, так что, возможно, вы уже поняли, что вам нужно сделать, чтобы использовать его. Подсказка: sin(угол) и cos(угол) вычисляют точку на окружности (в радианах)
Спасибо, не могли бы вы добавить код? Мои познания в математике немного ниже. Я знаю, что это проблема, программирование и математика как братья. Заранее извиняюсь.
Чтобы выполнить это с помощью lookat, вам в значительной степени нужно вычислить матрицу вращения, применить ее к отдельным векторам, а затем заставить lookat восстановить матрицу вращения из этих векторов. Это очень окольный способ добиться этого. Прекратите использовать lookat, за исключением случаев, когда камера и точка, за которой вы хотите, чтобы она следовала, действительно независимы.
см. Понимание матриц гомогенного преобразования 4x4 особенно ссылки в конце ...
Вам нужно построить матрицу преобразования. Преобразование обычно представляет собой комбинацию перемещения, масштабирования и поворота.
Где вы сначала вращаете, затем масштабируете, а затем переводите (фактический порядок вычислений - умножение - обратный):
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)? Имеют ли для вас какое-либо значение термины вектор и матрица, если да, то каков ваш уровень знаний? Если вы дадите нам подсказку, мы сможем указать вам в нужном направлении. Это не так сложно, как кажется на первый взгляд (в зависимости от вашего визуального воображения, даже очень интуитивного).
Я не знаю линейной алгебры, но знаю векторы.
Великолепно, это хорошее начало. Знаете ли вы, что значит взять точечное или перекрестное произведение двух векторов? Изучив эти две темы, перейдите к Переводу и Вращению , тогда вы в основном закончили. Я также очень рекомендую Сущность линейной алгебры от 3Blue1Brown.
Приложение: так как нет никакого способа обойти Матричное умножение, подсказка от меня, что в основном упускается из виду: если вы усвоили геометрический смысл скалярного произведения и после того, как вы поняли, что геометрический смысл строк и столбцов матрица, то вы также должны заметить, что каждый компонент результирующей матрицы является результатом скалярного произведения строки и вектора-столбца, визуализируйте это и усвойте.
Не «попробую», а «сделаю»! Начните с серии видео, которую я предложил. Пара видео по 10 минут, и вам не придется смотреть их все сразу. Начните с первых 5 и глав 9, 10, 11 (1 ч. вашей жизни), после этого для более глубокого понимания читайте остальные статьи. Я гарантирую, что в течение недели обучения вы сможете построить свою систему камер (на основе реальных знаний, а не уже пойманной рыбы).
Вам может быть проще, если вы не используете gluLookAt