aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--src/camera.c80
-rw-r--r--src/camera.h23
-rw-r--r--src/main.c262
4 files changed, 206 insertions, 163 deletions
diff --git a/Makefile b/Makefile
index 4e2382d..99a2459 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/src/main.c b/src/main.c
index d0ce19b..7b41a48 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
Feel free to download, copy and edit any repo