From b6b83e9328d8c58c3bffd9a5dc1b80efc5b0e6a8 Mon Sep 17 00:00:00 2001 From: Erik Cowley Date: Fri, 13 Oct 2023 01:13:57 -0400 Subject: [PATCH] Add ghosts --- Makefile | 7 +++- ghost.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++ ghost.h | 27 +++++++++++++ ghostfragshader.glsl | 15 ++++++++ ghostland.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++-- ghostshader.glsl | 21 ++++++++++ 6 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 ghost.cpp create mode 100644 ghost.h create mode 100644 ghostfragshader.glsl create mode 100644 ghostshader.glsl diff --git a/Makefile b/Makefile index 8ca8bbf..6aa8420 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ CC := g++ CFLAGS := -std=c++17 -O3 LDFLAGS := -ldl -lglfw -ghostland: glad.o ghostland.o stb_image.o collisions.o player.o shader.o - $(CC) -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o shader.o $(LDFLAGS) $(CFLAGS) +ghostland: glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o + $(CC) -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o $(LDFLAGS) $(CFLAGS) glad.o: glad.c $(CC) -c -o glad.o glad.c $(CFLAGS) @@ -23,5 +23,8 @@ player.o: player.cpp player.h shader.o: shader.cpp shader.h $(CC) -c -o shader.o shader.cpp $(CFLAGS) +ghost.o: ghost.cpp ghost.h + $(CC) -c -o ghost.o ghost.cpp $(CFLAGS) + clean: rm -f *.o ghostland diff --git a/ghost.cpp b/ghost.cpp new file mode 100644 index 0000000..c8131b8 --- /dev/null +++ b/ghost.cpp @@ -0,0 +1,90 @@ +#include +#include +#include + +#include "ghost.h" + +int counter = 0; + +Ghost::Ghost(float xmin, float xmax, float zmin, float zmax) { + + ghost_id = counter; + counter++; + + this->xmin = xmin; + this->xmax = xmax; + this->zmin = zmin; + this->zmax = zmax; + + pos.x = rand_float(xmin, xmax); + pos.y = 2.5; + pos.z = rand_float(zmin, zmax); + + y_offset = rand_float(0.0, 3.14); + yawr = rand_float(0.0, 6.28); + + first_frame = false; + +} + +void Ghost::apply_movement() { + + float curr_time = static_cast(glfwGetTime()); + + if (!first_frame) { + first_frame = true; + prev_move_time = curr_time; + return; + } + + float diff_time = curr_time - prev_move_time; + prev_move_time = curr_time; + + glm::vec3 moved; + moved.x = pos.x + (-sin(yawr) + cos(yawr)) * diff_time; + moved.y = 2.5 + sin(curr_time + y_offset); + moved.z = pos.z + (cos(yawr) + sin(yawr)) * diff_time; + + bool reset_yaw = false; + + if (moved.x < xmin) { + reset_yaw = true; + moved.x = xmin; + } else if (moved.x > xmax) { + reset_yaw = true; + moved.x = xmax; + } + + if (moved.z < zmin) { + reset_yaw = true; + moved.z = zmin; + } else if (moved.z > zmax) { + reset_yaw = true; + moved.z = zmax; + } + + if (reset_yaw) { + yawr = rand_float(0.0, 6.28); + } else { + yawr += rand_float(-0.3, 0.3); + } + + pos = moved; + +} + +glm::mat4 Ghost::get_model(glm::vec3 &camera_pos) { + + glm::mat4 ghost_model = glm::mat4(1.0f); + ghost_model = glm::translate(ghost_model, pos); + glm::vec3 ghost_direction = pos - camera_pos; + ghost_model = glm::rotate(ghost_model, atan2f(ghost_direction.x, ghost_direction.z), glm::vec3(0.0f, 1.0f, 0.0f)); + return ghost_model; + +} + +float rand_float(float rmin, float rmax) { + float rdiff = rmax - rmin; + float res = (float)rand()/(float)RAND_MAX; + return res * rdiff + rmin; +} diff --git a/ghost.h b/ghost.h new file mode 100644 index 0000000..fd1e4c0 --- /dev/null +++ b/ghost.h @@ -0,0 +1,27 @@ +#ifndef GHOST_H +#define GHOST_H + +#include + +class Ghost { + public: + Ghost(float xmin, float xmax, float zmin, float zmax); + void apply_movement(); + glm::mat4 get_model(glm::vec3 &camera_pos); + + private: + int ghost_id; + bool first_frame; + glm::vec3 pos; + float yawr; + float xmin; + float xmax; + float zmin; + float zmax; + float y_offset; + float prev_move_time; +}; + +float rand_float(float rmin, float rmax); + +#endif diff --git a/ghostfragshader.glsl b/ghostfragshader.glsl new file mode 100644 index 0000000..e8985a3 --- /dev/null +++ b/ghostfragshader.glsl @@ -0,0 +1,15 @@ +#version 460 core + +out vec4 FragColor; + +in vec3 FragPos; +in vec3 Normal; +in vec2 TexCoord; + +uniform sampler2D texture0; + +void main() { + vec4 outcolor = texture(texture0, TexCoord); + outcolor.a = outcolor.a * 0.3; + FragColor = outcolor; +} diff --git a/ghostland.cpp b/ghostland.cpp index 9f9e370..edd51c8 100644 --- a/ghostland.cpp +++ b/ghostland.cpp @@ -16,6 +16,7 @@ #include "collisions.h" #include "player.h" #include "shader.h" +#include "ghost.h" void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); @@ -87,6 +88,7 @@ int main(int argc, char *argv[]) // num surfaces * 6 (vertices per point) * 6 (floats per point) int num_wall_vertices = num_walls * 6 * 6; wall_vertices = (float *)calloc(sizeof(float), num_wall_vertices); + int xmin_wall, xmax_wall, zmin_wall, zmax_wall; // read walls for (int i = 0; i < num_walls; i++) { for (int j = 0; j < 6; j++) { @@ -104,6 +106,16 @@ int main(int argc, char *argv[]) printf("3rd fscanf failed.\n"); return -1; } + if (wall_vertices[vix] < xmin_wall) { + xmin_wall = wall_vertices[vix]; + } else if (wall_vertices[vix] > xmax_wall) { + xmax_wall = wall_vertices[vix]; + } + if (wall_vertices[vix + 2] < zmin_wall) { + zmin_wall = wall_vertices[vix + 2]; + } else if (wall_vertices[vix + 2] > zmax_wall) { + zmax_wall = wall_vertices[vix + 2]; + } } if (fscanf(fp, "\n") == EOF) { printf("4th fscanf failed.\n"); @@ -145,7 +157,7 @@ int main(int argc, char *argv[]) return -1; } glfwMakeContextCurrent(window); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + //glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); @@ -159,6 +171,9 @@ int main(int argc, char *argv[]) glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + int wall_program = create_shader_program("vertexshader.glsl", "fragmentshader.glsl"); if (wall_program < 0) { glfwTerminate(); @@ -246,6 +261,57 @@ int main(int argc, char *argv[]) int trail_ix = 0; int trail_sz = 0; + // do stuff for ghosts + // create program + int ghost_program = create_shader_program("ghostshader.glsl", "ghostfragshader.glsl"); + if (ghost_program < 0) { + glfwTerminate(); + return -1; + } + // ghost vertices + float ghost_vertices[] = { + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + }; + unsigned int ghostVBO, ghostVAO; + glGenVertexArrays(1, &ghostVAO); + glBindVertexArray(ghostVAO); + glGenBuffers(1, &ghostVBO); + glBindBuffer(GL_ARRAY_BUFFER, ghostVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(ghost_vertices), ghost_vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float))); + glEnableVertexAttribArray(2); + // ghost texture + unsigned int ghost_texture; + glGenTextures(1, &ghost_texture); + glBindTexture(GL_TEXTURE_2D, ghost_texture); + // set the texture wrapping parameters + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + int width, height, numberChannels; + //stbi_set_flip_vertically_on_load(true); + unsigned char *ghost_data = stbi_load("ghost_facing_right.png", &width, &height, &numberChannels, 0); + printf("Num channels: %d\n", numberChannels); + if (!ghost_data) { + printf("Failed to load texture!\n"); + glfwTerminate(); + return -1; + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ghost_data); + glGenerateMipmap(GL_TEXTURE_2D); + stbi_image_free(ghost_data); + // TODO move these into config file?? int time_secI = 0, num_frames = 1; float time_sec; @@ -260,6 +326,11 @@ int main(int argc, char *argv[]) float largecutoff = glm::cos(glm::radians(30.0f)); float smallcutoff = glm::cos(glm::radians(7.5f)); + std::vector ghosts; + for (int i = 0; i < 4000; i++) { + ghosts.push_back(new Ghost(xmin_wall, xmax_wall, zmin_wall, zmax_wall)); + } + while (!glfwWindowShouldClose(window)) { float current_frame = static_cast(glfwGetTime()); @@ -368,10 +439,24 @@ int main(int argc, char *argv[]) model = glm::rotate(model, glm::radians(trail_angles[i]), glm::vec3(0.0f, -1.0f, 0.0f)); set_uniform(trail_program, modelC, model); glBindVertexArray(trailVAO); - glDrawArrays(GL_TRIANGLES, 0, 3 * 3 * 3); } + glUseProgram(ghost_program); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, ghost_texture); + + set_uniform(ghost_program, projectionC, projection); + set_uniform(ghost_program, viewC, view); + for (int i = 0; i < ghosts.size(); i++) { + glm::mat4 ghost_model = ghosts[i]->get_model(camera_pos); + ghosts[i]->apply_movement(); + set_uniform(ghost_program, modelC, ghost_model); + glBindVertexArray(ghostVAO); + glDrawArrays(GL_TRIANGLES, 0, (3 + 3 + 2) * 6); + } + player->apply_movement(); glfwSwapBuffers(window); @@ -389,8 +474,7 @@ int main(int argc, char *argv[]) return 0; } -void framebuffer_size_callback(GLFWwindow* window, int width, int height) -{ +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } diff --git a/ghostshader.glsl b/ghostshader.glsl new file mode 100644 index 0000000..4328a86 --- /dev/null +++ b/ghostshader.glsl @@ -0,0 +1,21 @@ +#version 460 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoord; + +out vec3 FragPos; +out vec3 Normal; +out vec2 TexCoord; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + FragPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(transpose(inverse(model))) * aNormal; + TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); + + gl_Position = projection * view * vec4(FragPos, 1.0); +}