aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvech <jmvalenciae@unal.edu.co>2022-08-29 15:35:03 -0500
committerjvech <jmvalenciae@unal.edu.co>2022-08-29 15:35:03 -0500
commit61edf5b3a7eee3b4ff6db3664e638b17bf91ebc1 (patch)
tree5116bb20d5bf49afbb1bfb22b5f5cfb77ee39fb5
parentd7bd9a3dbd3486a4b0615dc9f30a890ff6d04ec6 (diff)
feat: Camera and movement implemented
-rw-r--r--TODO2
-rw-r--r--src/linear.c110
-rw-r--r--src/linear.h48
-rw-r--r--src/main.c119
4 files changed, 178 insertions, 101 deletions
diff --git a/TODO b/TODO
index c6eeaeb..2607dc9 100644
--- a/TODO
+++ b/TODO
@@ -7,7 +7,7 @@ General
- define a format for 3D objects
- Render a set of vertices loaded from a file
-- Implement Camera movement
+* Implement Camera movement
Linear
- Implement the Inverse function of mat4
diff --git a/src/linear.c b/src/linear.c
index 4a4c958..c38c297 100644
--- a/src/linear.c
+++ b/src/linear.c
@@ -4,12 +4,12 @@
#include <stdarg.h>
#include <math.h>
-mat4
-linearLookAt(vec3 position, vec3 target, vec3 world_up)
+Mat4
+linearLookAt(Vec3 position, Vec3 target, Vec3 world_up)
{
- mat4 out = linearMat4Identity(1.0);
- mat4 translate;
- vec3 cam_dir, cam_right, cam_up;
+ Mat4 out = linearMat4Identity(1.0);
+ Mat4 translate;
+ Vec3 cam_dir, cam_right, cam_up;
/* position - target */
cam_dir = linearVec3Add(position, linearVec3ScalarMulp(target, -1.0));
cam_dir = linearVec3Normalize(cam_dir);
@@ -31,13 +31,13 @@ linearLookAt(vec3 position, vec3 target, vec3 world_up)
return linearMat4Mul(out, translate);
}
-mat4
+Mat4
linearPerspective(float FoV, float ratio, float near, float far)
{
- mat4 out = linearMat4Fill(0.0);
+ Mat4 out = linearMat4Fill(0.0);
float FoV_radians = FoV * M_PI / 180;
- float width = near * tanf(FoV_radians);
- float height = near * tanf(FoV_radians) * ratio;
+ float width = near * tanf(FoV_radians) * ratio;
+ float height = near * tanf(FoV_radians);
out.matrix[0][0] = near / width;
out.matrix[1][1] = near / height;
@@ -47,43 +47,43 @@ linearPerspective(float FoV, float ratio, float near, float far)
return out;
}
-mat4
+Mat4
linearTranslate(float T_x, float T_y, float T_z)
{
- mat4 out = linearMat4Identity(1.0);
+ Mat4 out = linearMat4Identity(1.0);
out.matrix[0][3] = T_x;
out.matrix[1][3] = T_y;
out.matrix[2][3] = T_z;
return out;
}
-mat4
-linearTranslatev(vec3 T)
+Mat4
+linearTranslatev(Vec3 T)
{
return linearTranslate(T.vector[0], T.vector[1], T.vector[2]);
}
-mat4
+Mat4
linearScale(float S_x, float S_y, float S_z)
{
- mat4 out = linearMat4Identity(1.0);
+ Mat4 out = linearMat4Identity(1.0);
out.matrix[0][0] = S_x;
out.matrix[1][1] = S_y;
out.matrix[2][2] = S_z;
return out;
}
-mat4
-linearScalev(vec3 S)
+Mat4
+linearScalev(Vec3 S)
{
return linearScale(S.vector[0], S.vector[1], S.vector[2]);
}
-mat4
-linearRotatev(float degree, vec3 R_xyz)
+Mat4
+linearRotatev(float degree, Vec3 R_xyz)
{
- mat4 out = linearMat4Identity(1.0);
- vec3 R_xyz_normalized = linearVec3Normalize(R_xyz);
+ Mat4 out = linearMat4Identity(1.0);
+ Vec3 R_xyz_normalized = linearVec3Normalize(R_xyz);
float radians = degree * M_PI/180.0;
float Rx = R_xyz_normalized.vector[0];
float Ry = R_xyz_normalized.vector[1];
@@ -105,17 +105,17 @@ linearRotatev(float degree, vec3 R_xyz)
return out;
}
-mat4
+Mat4
linearRotate(float degree, float Rx, float Ry, float Rz)
{
return linearRotatev(degree, linearVec3(Rx, Ry, Rz));
}
-mat4
+Mat4
linearMat4Fill(float value)
{
int i, j;
- mat4 out;
+ Mat4 out;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
out.matrix[i][j] = value;
@@ -124,11 +124,11 @@ linearMat4Fill(float value)
return out;
}
-mat4
+Mat4
linearMat4Identity(float value)
{
int i, j;
- mat4 out;
+ Mat4 out;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (i == j) out.matrix[i][j] = value;
@@ -138,10 +138,10 @@ linearMat4Identity(float value)
return out;
}
-mat4
-linearMat4Transpose(mat4 x)
+Mat4
+linearMat4Transpose(Mat4 x)
{
- mat4 out;
+ Mat4 out;
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
@@ -151,10 +151,10 @@ linearMat4Transpose(mat4 x)
return out;
}
-mat4
-linearMat4Mul(mat4 x1, mat4 x2)
+Mat4
+linearMat4Mul(Mat4 x1, Mat4 x2)
{
- mat4 out;
+ Mat4 out;
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
@@ -166,10 +166,10 @@ linearMat4Mul(mat4 x1, mat4 x2)
return out;
}
-mat4
+Mat4
linearMat4Muln(int n, ...)
{
- mat4 out;
+ Mat4 out;
if (n <= 0) {
fprintf(stderr, "linearMat4Muln() Error: the specified number of args must be a positive integer greater than 0\n");
@@ -177,21 +177,21 @@ linearMat4Muln(int n, ...)
va_list(ap);
va_start(ap, n);
- out = va_arg(ap, mat4);
+ out = va_arg(ap, Mat4);
int i;
for (i = 1; i < n; i++) {
- out = linearMat4Mul(out, va_arg(ap, mat4));
+ out = linearMat4Mul(out, va_arg(ap, Mat4));
}
va_end(ap);
return out;
}
-mat4
-linearMat4Add(mat4 x1, mat4 x2)
+Mat4
+linearMat4Add(Mat4 x1, Mat4 x2)
{
int i, j;
- mat4 out;
+ Mat4 out;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
out.matrix[i][j] = x1.matrix[i][j] + x2.matrix[i][j];
@@ -201,15 +201,15 @@ linearMat4Add(mat4 x1, mat4 x2)
}
float
-linearMat4Det(mat4 x)
+linearMat4Det(Mat4 x)
{
return 0.0;
}
-vec3
-linearVec3ScalarMulp(vec3 x, float scalar)
+Vec3
+linearVec3ScalarMulp(Vec3 x, float scalar)
{
- vec3 out;
+ Vec3 out;
int i;
for (i = 0; i < 3; i++) {
out.vector[i] = scalar * x.vector[i];
@@ -217,20 +217,20 @@ linearVec3ScalarMulp(vec3 x, float scalar)
return out;
}
-vec3
+Vec3
linearVec3(float x, float y, float z)
{
- vec3 out;
+ Vec3 out;
out.vector[0] = x;
out.vector[1] = y;
out.vector[2] = z;
return out;
}
-vec3
-linearVec3Add(vec3 x, vec3 y)
+Vec3
+linearVec3Add(Vec3 x, Vec3 y)
{
- vec3 out;
+ Vec3 out;
int i;
for (i = 0; i < 3; i++) {
out.vector[i] = x.vector[i] + y.vector[i];
@@ -238,10 +238,10 @@ linearVec3Add(vec3 x, vec3 y)
return out;
}
-vec3
-linearVec3Normalize(vec3 x)
+Vec3
+linearVec3Normalize(Vec3 x)
{
- vec3 out;
+ Vec3 out;
float norm = sqrtf(linearVec3DotProduct(x, x));
int i;
if (norm == 0) return x;
@@ -251,10 +251,10 @@ linearVec3Normalize(vec3 x)
return out;
}
-vec3
-linearVec3CrossProduct(vec3 x, vec3 y)
+Vec3
+linearVec3CrossProduct(Vec3 x, Vec3 y)
{
- vec3 out;
+ Vec3 out;
out.vector[0] = x.vector[1] * y.vector[2] - x.vector[2] * y.vector[1];
out.vector[1] = - x.vector[0] * y.vector[2] + x.vector[2] * y.vector[0];
out.vector[2] = x.vector[0] * y.vector[1] - x.vector[1] * y.vector[0];
@@ -262,7 +262,7 @@ linearVec3CrossProduct(vec3 x, vec3 y)
}
float
-linearVec3DotProduct(vec3 x, vec3 y)
+linearVec3DotProduct(Vec3 x, Vec3 y)
{
float out = 0;
int i;
diff --git a/src/linear.h b/src/linear.h
index c5f40aa..4ed2298 100644
--- a/src/linear.h
+++ b/src/linear.h
@@ -7,34 +7,34 @@
typedef struct {
float matrix[4][4];
-} mat4;
+} Mat4;
typedef struct {
float vector[3];
-} vec3;
+} Vec3;
-mat4 linearTranslatev(vec3 translate_vector);
-mat4 linearRotatev(float degree, vec3 rotation_axis);
-mat4 linearScalev(vec3 scale_vector);
-mat4 linearTranslate(float translate_x, float translate_y, float translate_z);
-mat4 linearScale(float scale_x, float scale_y, float scale_z);
-mat4 linearRotate(float degree, float rotate_x, float rotate_y, float rotate_z);
-mat4 linearPerspective(float FoV, float ratio, float near, float far);
-mat4 linearLookAt(vec3 position, vec3 target, vec3 up);
+Mat4 linearTranslatev(Vec3 translate_vector);
+Mat4 linearRotatev(float degree, Vec3 rotation_axis);
+Mat4 linearScalev(Vec3 scale_vector);
+Mat4 linearTranslate(float translate_x, float translate_y, float translate_z);
+Mat4 linearScale(float scale_x, float scale_y, float scale_z);
+Mat4 linearRotate(float degree, float rotate_x, float rotate_y, float rotate_z);
+Mat4 linearPerspective(float FoV, float ratio, float near, float far);
+Mat4 linearLookAt(Vec3 position, Vec3 target, Vec3 up);
-mat4 linearMat4Fill(float value);
-mat4 linearMat4Identity(float value);
-mat4 linearMat4Mul(mat4 x1, mat4 x2);
-mat4 linearMat4Muln(int n, ...);
-mat4 linearMat4Transpose(mat4 x);
-mat4 linearMat4Inv(mat4 x); //TODO
-mat4 linearMat4Add(mat4 x1, mat4 x2); //TODO
-float linearMat4Det(mat4 x); //TODO
+Mat4 linearMat4Fill(float value);
+Mat4 linearMat4Identity(float value);
+Mat4 linearMat4Mul(Mat4 x1, Mat4 x2);
+Mat4 linearMat4Muln(int n, ...);
+Mat4 linearMat4Transpose(Mat4 x);
+Mat4 linearMat4Inv(Mat4 x); //TODO
+Mat4 linearMat4Add(Mat4 x1, Mat4 x2); //TODO
+float linearMat4Det(Mat4 x); //TODO
-vec3 linearVec3(float x, float y, float z);
-vec3 linearVec3Normalize(vec3 vector);
-vec3 linearVec3Add(vec3 vector1, vec3 vector2);
-vec3 linearVec3ScalarMulp(vec3 vector, float scalar);
-vec3 linearVec3CrossProduct(vec3 vector1, vec3 vector2);
-float linearVec3DotProduct(vec3 vector1, vec3 vector2);
+Vec3 linearVec3(float x, float y, float z);
+Vec3 linearVec3Normalize(Vec3 vector);
+Vec3 linearVec3Add(Vec3 vector1, Vec3 vector2);
+Vec3 linearVec3ScalarMulp(Vec3 vector, float scalar);
+Vec3 linearVec3CrossProduct(Vec3 vector1, Vec3 vector2);
+float linearVec3DotProduct(Vec3 vector1, Vec3 vector2);
#endif
diff --git a/src/main.c b/src/main.c
index 7cded68..0994746 100644
--- a/src/main.c
+++ b/src/main.c
@@ -13,6 +13,12 @@
#include "linear.h"
#include "shader.h"
+struct Camera {
+ Vec3 position;
+ Vec3 front;
+ Vec3 up;
+};
+
float vertices[] = {
-0.5,-0.5,-0.5, 1.0, 1.0, 1.0,
0.5,-0.5,-0.5, 1.0, 1.0, 0.0,
@@ -47,8 +53,7 @@ unsigned int indices[] = {
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 void linearPrintMat4(mat4 x);
+static Mat4 processCameraInput(GLFWwindow *window, struct Camera *cameraObj, float deltaTime);
void
userError(const char *msg, const char *detail)
@@ -78,17 +83,81 @@ processInput(GLFWwindow *window)
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
}
-void
-linearPrintMat4(mat4 x)
+Mat4
+processCameraInput(GLFWwindow *window, struct Camera *camObj, float deltaTime)
{
- int i, j;
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- printf("%f ", x.matrix[i][j]);
- }
- printf("\n");
+ /*
+ * Keyboard Input
+ */
+ Vec3 tmp;
+ float speed = 2.0f * deltaTime;
+ 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);
+ }
+
+ /*
+ * 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;
}
- printf("\n");
+
+ 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);
}
int main()
@@ -110,6 +179,7 @@ int main()
glfwSetFramebufferSizeCallback(window, glfw_size_callback);
glfwMakeContextCurrent(window);
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
GLubyte glewErrno = glewInit();
if (glewErrno != GLEW_OK) {
@@ -143,11 +213,18 @@ int main()
unsigned int shaderProgram = shaderCreateProgram("shaders/vertex.vsh",
"shaders/fragment.fsh");
+ struct Camera mainCamera;
+ mainCamera.position = linearVec3(0.0, 0.0, -3.0);
+ mainCamera.front = linearVec3(0.0, 0.0, 0.0);
+ mainCamera.up = linearVec3(0.0, 1.0, 0.0);
+
unsigned int modelLoc, viewLoc, projLoc;
- mat4 model, view, proj;
- mat4 T, S, R;
+ Mat4 model, view, proj;
+ Mat4 T, S, R;
- float t;
+ float dt, t, t0;
+ int width, height;
+ t0 = 0;
while (!glfwWindowShouldClose(window)) {
processInput(window);
@@ -155,18 +232,19 @@ int main()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
t = (float)glfwGetTime();
+ dt = t - t0;
+ t0 = t;
+
T = linearTranslate(0.0, 0.0, 0.0);
R = linearRotate(180 * t / M_PI, 0.0, 1.0, 0.0);
S = linearScale(1.0, 1.0, 1.0);
model = linearMat4Muln(3, T, R, S);
- T = linearTranslate(0.0, -0.0, -80);
- R = linearRotate(60, 1, 0, 0);
-
- view = linearMat4Muln(2, T, R);
+ view = processCameraInput(window, &mainCamera, dt);
- proj = linearPerspective(35, 4 / 3.0, 0.1, 100);
+ glfwGetWindowSize(window, &width, &height);
+ proj = linearPerspective(35, width / (float)height, 0.1, 100);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
@@ -176,10 +254,9 @@ int main()
projLoc = glGetUniformLocation(shaderProgram, "proj");
glUniformMatrix4fv(modelLoc, 1, GL_TRUE, model.matrix[0]);
- glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glUniformMatrix4fv(viewLoc, 1, GL_TRUE, view.matrix[0]);
- glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glUniformMatrix4fv(projLoc, 1, GL_TRUE, proj.matrix[0]);
+
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
Feel free to download, copy and edit any repo