diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/camera.c | 80 | ||||
-rw-r--r-- | src/camera.h | 23 | ||||
-rw-r--r-- | src/main.c | 262 |
4 files changed, 206 insertions, 163 deletions
@@ -4,7 +4,7 @@ DLIBS := -lm $(shell pkg-config --libs glfw3 opengl glew) INCLUDE := $(addprefix -I,./include) OBJDIR = objs SRCDIR = src -OBJS = $(addprefix objs/,main.o shader.o linear.o obj.o) +OBJS = $(addprefix objs/,main.o shader.o linear.o obj.o camera.o) BIN = mverse SHADERS_DIR = /usr/share/${BIN} @@ -24,7 +24,7 @@ $(OBJDIR)/%.o: $(SRCDIR)/%.c build: $(OBJS) ${CC} $^ -o ${BIN} ${DLIBS} -run: +run: build ./${BIN} models/cessna.obj install: build diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..f087d83 --- /dev/null +++ b/src/camera.c @@ -0,0 +1,80 @@ +#include "camera.h" +static void cameraUpdateVectors(struct Camera *camera); + +Mat4 +cameraGetViewMatrix(struct Camera camera) +{ + Vec3 target = linearVec3Add(camera.position, camera.front); + return linearLookAt(camera.position, target, camera.up); +} + +void +cameraProcessKeyboard( + struct Camera *camera, + enum CameraMovement direction, + float deltaTime) +{ + float speed = camera->movementSpeed * deltaTime; + Vec3 tmp; + + switch (direction) { + case CAMDIR_FORWARD: + // pos = pos + front * speed + tmp = linearVec3ScalarMulp(camera->front, speed); + camera->position = linearVec3Add(camera->position, tmp); + break; + + case CAMDIR_BACKWARD: + // pos = pos + front * (-speed) + tmp = linearVec3ScalarMulp(camera->front, -speed); + camera->position = linearVec3Add(camera->position, tmp); + break; + + case CAMDIR_LEFT: + // pos = pos + unit|(up x front)| * (speed) + tmp = linearVec3CrossProduct(camera->front, camera->up); + tmp = linearVec3Normalize(tmp); + tmp = linearVec3ScalarMulp(tmp, -speed); + camera->position = linearVec3Add(camera->position, tmp); + break; + + case CAMDIR_RIGHT: + // pos = pos + unit|(up x front)| * (-speed) + tmp = linearVec3CrossProduct(camera->front, camera->up); + tmp = linearVec3Normalize(tmp); + tmp = linearVec3ScalarMulp(tmp, speed); + camera->position = linearVec3Add(camera->position, tmp); + break; + + default: + break; + } +} + +void +cameraProcessMouseMovement(struct Camera *camera, float xoffset, float yoffset) +{ + camera->yaw += camera->mouseSensivity * xoffset; + camera->pitch += camera->mouseSensivity * yoffset; + + if (camera->pitch > 89.0f) + camera->pitch = 89.0f; + else if (camera->pitch < -89.0f) + camera->pitch = - 89.0f; + cameraUpdateVectors(camera); +} + +void +cameraUpdateVectors(struct Camera *camera) +{ + Vec3 tmp; + float rpitch = M_PI / 180 * camera->pitch; + float ryaw = M_PI / 180 * camera->yaw; + + tmp = linearVec3( + cosf(ryaw) * cosf(-rpitch), + sinf(-rpitch), + sinf(ryaw) * cosf(-rpitch)); + camera->front = linearVec3Normalize(tmp); + +} diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..1d16098 --- /dev/null +++ b/src/camera.h @@ -0,0 +1,23 @@ +#ifndef __CAMERA__ +#include <math.h> +#include "linear.h" + +enum CameraMovement { + CAMDIR_FORWARD, + CAMDIR_BACKWARD, + CAMDIR_LEFT, + CAMDIR_RIGHT +}; + +struct Camera { + Vec3 position, front, up; + float yaw; + float pitch; + float movementSpeed; + float mouseSensivity; +}; + +Mat4 cameraGetViewMatrix(struct Camera camera); +void cameraProcessKeyboard(struct Camera *camera, enum CameraMovement direction, float deltaTime); +void cameraProcessMouseMovement(struct Camera *camera, float xoffset, float yoffset); +#endif @@ -35,28 +35,93 @@ #include "linear.h" #include "shader.h" #include "obj.h" +#include "camera.h" -struct Camera { - Vec3 position; - Vec3 front; - Vec3 up; -}; - +static void processCursorPosInput(GLFWwindow *window, struct Camera *camera); +static void processKeyboardInput(GLFWwindow *window, struct Camera *camera, float deltatime); static void loadCLI(int argc, char *argv[], char **vertexPath, char **fragmentPath); static void initOpengl(void); static void initGlfw(void); static void userError(const char *msg, const char *detail); -static void glfw_size_callback(GLFWwindow *window, int width, int height); -static void processInput(GLFWwindow *window); -static Mat4 processCameraInput(GLFWwindow *window, struct Camera *cameraObj, float deltaTime); -static unsigned int loadTexture(char const *path); static void meshSetUp(Mesh *mesh); static void meshDraw(unsigned int shader, Mesh mesh); static void objSetUp(Obj obj); static void objDraw(unsigned int shader, Obj obj); static void usage(int status); -static float cameraSpeed = 2.0; +static void glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods); +static void glfw_size_callback(GLFWwindow *window, int width, int height); + +void +processCursorPosInput(GLFWwindow *window, struct Camera *camera) +{ + static int first_mouse = 1; + double xpos, ypos; + int width, height; + static double lastX, lastY; + float xoffset, yoffset; + glfwGetCursorPos(window, &xpos, &ypos); + glfwGetWindowSize(window, &width, &height); + + if (first_mouse) { + first_mouse = 0; + lastX = width / 2.0; + lastY = height / 2.0; + } + + + xoffset = xpos - lastX; + yoffset = ypos - lastY; + lastX = xpos; + lastY = ypos; + cameraProcessMouseMovement(camera, xoffset, yoffset); +} + +void +processKeyboardInput(GLFWwindow *window, struct Camera *camera, float deltatime) +{ + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + cameraProcessKeyboard(camera, CAMDIR_FORWARD, deltatime); + + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + cameraProcessKeyboard(camera, CAMDIR_BACKWARD, deltatime); + + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + cameraProcessKeyboard(camera, CAMDIR_LEFT, deltatime); + + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + cameraProcessKeyboard(camera, CAMDIR_RIGHT, deltatime); + + if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) + camera->movementSpeed += 0.2; + + if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) + camera->movementSpeed -= 0.2; +} + +void +glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if (action != GLFW_PRESS) return; + + switch (key) { + case GLFW_KEY_ESCAPE: + case GLFW_KEY_Q: + glfwSetWindowShouldClose(window, 1); + break; + case GLFW_KEY_1: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + break; + case GLFW_KEY_2: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + break; + case GLFW_KEY_3: + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + break; + default: + return; + } +} void loadCLI(int argc, char *argv[], char **vertexPath, char **fragmentPath) @@ -119,143 +184,6 @@ glfw_size_callback(GLFWwindow *window, int width, int height) } void -processInput(GLFWwindow *window) -{ - if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS - || glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) - glfwSetWindowShouldClose(window, 1); - - if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) - glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); -} - -Mat4 -processCameraInput(GLFWwindow *window, struct Camera *camObj, float deltaTime) -{ - /* - * Keyboard Input - */ - Vec3 tmp; - float speed = cameraSpeed * deltaTime; - - if (glfwGetKey(window, GLFW_KEY_K)) cameraSpeed += 0.2; - if (glfwGetKey(window, GLFW_KEY_J)) cameraSpeed -= 0.2; - - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - // pos = pos + front * speed - tmp = linearVec3ScalarMulp(camObj->front, speed); - camObj->position = linearVec3Add(camObj->position, tmp); - } - if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - // pos = pos + front * (-speed) - tmp = linearVec3ScalarMulp(camObj->front, -speed); - camObj->position = linearVec3Add(camObj->position, tmp); - } - if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - // pos = pos + unit|(up x front)| * (speed) - tmp = linearVec3CrossProduct(camObj->front, camObj->up); - tmp = linearVec3Normalize(tmp); - tmp = linearVec3ScalarMulp(tmp, speed); - camObj->position = linearVec3Add(camObj->position, tmp); - } - if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - // pos = pos + unit|(up x front)| * (-speed) - tmp = linearVec3CrossProduct(camObj->front, camObj->up); - tmp = linearVec3Normalize(tmp); - tmp = linearVec3ScalarMulp(tmp, -speed); - camObj->position = linearVec3Add(camObj->position, tmp); - } - - if (glfwGetKey(window, GLFW_KEY_DOWN)) scale -= 0.1 * speed; - if (glfwGetKey(window, GLFW_KEY_UP)) scale += 0.1 * speed; - if (glfwGetKey(window, GLFW_KEY_ENTER)) scale = 1; - - /* - * Mouse Input - */ - - static int firstMouse = 1; - float sensibility = 0.1f; - static float yaw = -90.0; - static float pitch = 0.0; - - double xpos, ypos; - static double lastX, lastY; - float xoffset, yoffset; - glfwGetCursorPos(window, &xpos, &ypos); - - if (firstMouse) { - firstMouse = 0; - lastX = xpos; - lastY = ypos; - } - - xoffset = (xpos - lastX) * sensibility; - yoffset = (ypos - lastY) * sensibility; - lastX = xpos; - lastY = ypos; - - yaw += xoffset; - pitch += yoffset; - - if (pitch > 89.0) pitch = 89.0f; - else if (pitch < -89.0) pitch = -89.0f; - float rpitch = M_PI / 180 * pitch; - float ryaw = M_PI / 180 * yaw; - - tmp = linearVec3( - cosf(ryaw) * cosf(-rpitch), - sinf(-rpitch), - sinf(ryaw) * cosf(-rpitch)); - camObj->front = linearVec3Normalize(tmp); - - return linearLookAt(camObj->position, - linearVec3Add(camObj->front, camObj->position), - camObj->up); -} - - -static unsigned int -loadTexture(char const *path) -{ - unsigned int textureID; - glGenTextures(1, &textureID); - - int width, height, channels; - unsigned char *data = stbi_load(path, &width, &height, &channels, 0); - - if (data) { - GLenum format; - if (channels == 1) - format = GL_RED; - if (channels == 3) - format = GL_RED; - if (channels == 4) - format = GL_RGBA; - - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - stbi_image_free(data); - return textureID; - } - char errorMsg[500]; - sprintf(errorMsg, "file %200s not found", path); - userError("loadTexture() Error", errorMsg); - return textureID; -} - - -void meshSetUp(Mesh *mesh) { glGenVertexArrays(1, &(mesh->VAO)); @@ -344,7 +272,9 @@ int main(int argc, char *argv[]) // Window Setup glfwSetFramebufferSizeCallback(window, glfw_size_callback); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetKeyCallback(window, glfw_key_callback); + //glfwSetCursorPosCallback(window, glfw); glfwMakeContextCurrent(window); @@ -353,49 +283,59 @@ int main(int argc, char *argv[]) objSetUp(obj); - struct Camera mainCamera = { - .position = linearVec3(0.0, 0.0, 10.0), - .front = linearVec3(0.0, 0.0, 1.0), - .up = linearVec3(0.0, 1.0, 0.0), + struct Camera camera = { + .position = {{0.0, 0.0, 10.0}}, + .front = {{0.0, 0.0, 1.0}}, + .up = {{0.0, 1.0, 0.0}}, + .yaw = -90.0f, + .pitch = 0.0f, + .mouseSensivity = 0.1f, + .movementSpeed = 2.0f }; Mat4 model, view, proj; Mat4 T, S, R; - float t, t0, dt; + float t0, t, deltatime; int width, height; char title[1024]; t0 = 0; glEnable(GL_DEPTH_TEST); while (!glfwWindowShouldClose(window)) { - processInput(window); glClearColor(0.2f, 0.2f, 0.2f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // handle input glfwGetWindowSize(window, &width, &height); sprintf(title, "mverse: x: %f y: %f z: %f", - mainCamera.front.vector[0] + mainCamera.position.vector[0], - mainCamera.front.vector[1] + mainCamera.position.vector[1], - mainCamera.front.vector[2] + mainCamera.position.vector[2]); + camera.front.vector[0] + camera.position.vector[0], + camera.front.vector[1] + camera.position.vector[1], + camera.front.vector[2] + camera.position.vector[2]); glfwSetWindowTitle(window, title); t = (float)glfwGetTime(); - dt = t - t0; + deltatime = t - t0; t0 = t; + processKeyboardInput(window, &camera, deltatime); + processCursorPosInput(window, &camera); + - view = processCameraInput(window, &mainCamera, dt); + // update + view = cameraGetViewMatrix(camera); proj = linearPerspective(35, (float)width / height, 0.1, 100); T = linearTranslate(0.0, 0.0, 0.0); R = linearRotate(0, 1.0, 0.0, 0.0); S = linearScale(scale, scale, scale); model = linearMat4Muln(3, T, R, S); + // render glUseProgram(shader); shaderSetMatrixfv(shader, "model", model.matrix[0], glUniformMatrix4fv); shaderSetMatrixfv(shader, "proj", proj.matrix[0], glUniformMatrix4fv); shaderSetMatrixfv(shader, "view", view.matrix[0], glUniformMatrix4fv); shaderSetMatrixfv(shader, "rotNormals", R.matrix[0], glUniformMatrix4fv); - shaderSetfv(shader, "viewPos", mainCamera.position.vector, glUniform3fv); + shaderSetfv(shader, "viewPos", camera.position.vector, glUniform3fv); shaderSetfv(shader, "dirLight.direction", vec3(-0.2, -1.0, 0.3), glUniform3fv); shaderSetfv(shader, "dirLight.ambient", vec3(0.1, 0.1, 0.1), glUniform3fv); |