Kamera
Camera/View space
1. Camera pozíció
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
2. Camera nézőirány
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
3. Jobb (Right) tengely
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
4. Up tengely
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);
Look At
\begin{equation*} LookAt = \begin{bmatrix} \color{red}{R_x} & \color{red}{R_y} & \color{red}{R_z} & 0 \\ \color{green}{U_x} & \color{green}{U_y} & \color{green}{U_z} & 0 \\ \color{blue}{D_x} & \color{blue}{D_y} & \color{blue}{D_z} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} * \begin{bmatrix} 1 & 0 & 0 & -\color{purple}{P_x} \\ 0 & 1 & 0 & -\color{purple}{P_y} \\ 0 & 0 & 1 & -\color{purple}{P_z} \\ 0 & 0 & 0 & 1 \end{bmatrix} \end{equation*}
glm::mat4 view;
view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
A kamera mozgatása
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
A LookAt mátrixot a következő képpen számítjuk:
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
...
float cameraSpeed = 0.05f; // adjust accordingly
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPos += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPos -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
Mozgás sebessége
Ehhez vezessünk be két globális változót:
float deltaTime = 0.0f; // Time between current frame and last frame
float lastFrame = 0.0f; // Time of last frame
A render ciklus elején számítsuk ki az eltelt időt:
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
Majd skálázzuk a sebességet:
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
float cameraSpeed = 2.5f * deltaTime;
...
}
Körbenézés a kamerával (look around)
Euler szögek
direction.y = sin(glm::radians(pitch)); // Note that we convert the angle to radians first
direction.z = cos(glm::radians(pitch));
A yaw érték esetén a következő eredményt kapjuk:
direction.x = cos(glm::radians(yaw));
direction.y = sin(glm::radians(pitch));
direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
Egér kezelés
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
glfwSetCursorPosCallback(window, mouse_callback);
- Az egér elmozdulásának a kiszámítása az előző pozíció és a mostani alapján
- A yaw és a pitch értékek frissítése az offsetek alapján
- Megszorítás hozzáadása a pitch értékhez (ne tudjun túl le vagy fel nézni a user)
- Az új nézőirány vektor kiszámítása
float lastX = 400, lastY = 300;
A mouse_callback-ben kiszámítjuk az offsetet, amit skálázunk egy érzékenységet definiáló változóval:
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // reversed since y-coordinates range from bottom to top
lastX = xpos;
lastY = ypos;
float sensitivity = 0.05f;
xoffset *= sensitivity;
yoffset *= sensitivity;
Következő lépésben frissítjük a yaw és a pitch értékeket:
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
cameraFront = glm::normalize(front);
if(firstMouse) { // this bool variable is initially set to true
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
A teljes egérkezelő kód:
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
if(firstMouse) {
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.05;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
}
Zoom
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
if(fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
if(fov <= 1.0f)
fov = 1.0f;
if(fov >= 45.0f)
fov = 45.0f;
}
projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);