From: Seth Long Date: Fri, 22 Nov 2024 02:25:19 +0000 (-0800) Subject: Added solver X-Git-Url: https://isoptera.lcsc.edu/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=example_engine%2F.git Added solver --- diff --git a/Makefile b/Makefile index 66a3e1d..c53694b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -OBJS = main.o stb_image.o helpers.o tiny_obj_loader.o baseclass.o old_objects.o geometric_objects.o hud.o door.o vehicle.o -CXXFLAGS = -g -Wall +OBJS = main.o stb_image.o helpers.o tiny_obj_loader.o baseclass.o old_objects.o geometric_objects.o hud.o door.o vehicle.o maze.o +CXXFLAGS = -g -Wall -std=c++20 LDFLAGS = -lGL -lglfw -lGLEW -pthread -g # For FreeBSD (doesn't seem to hurt anything on Linux) @@ -16,4 +16,4 @@ test: all ./a.out ${OBJS} : game.h -main.o : projectiles.h activation_area.h turret.h tile_floor.h old_objects.h moving_platform.h geometric_objects.h hud.h door.h vehicle.h +main.o : projectiles.h activation_area.h turret.h tile_floor.h old_objects.h moving_platform.h geometric_objects.h hud.h door.h vehicle.h maze.h diff --git a/brick_2.png b/brick_2.png new file mode 100644 index 0000000..fa50d7c Binary files /dev/null and b/brick_2.png differ diff --git a/game.h b/game.h index e49caab..1f97d94 100644 --- a/game.h +++ b/game.h @@ -33,6 +33,8 @@ GLuint make_shader(const char* filename, GLenum shaderType); float randvel(float speed); void init_helpers(); void free_helpers(); +glm::vec3 get_look_at_point(); +ssize_t is_empty(glm::vec3 position, float distance = 0.2f); class gameobject { public: @@ -128,4 +130,3 @@ EXTERN size_t vehicle_index INIT(0); #include "hud.h" EXTERN hud main_hud; - diff --git a/geometric_objects.cpp b/geometric_objects.cpp index abf1543..01737b8 100644 --- a/geometric_objects.cpp +++ b/geometric_objects.cpp @@ -216,26 +216,29 @@ void sphere::addsphere(glm::vec3 location, float radius, glm::vec3 up, glm::vec3 } void rollsphere::roll_to(size_t index, glm::vec3 new_location, float speed){ + data_mutex.lock(); speeds[index] = speed; new_locations[index] = new_location; new_locations[index].y = locations[index].y; float angular_velocity = speed / radii[index]; glm::vec3 axis = glm::cross(new_locations[index] - locations[index], glm::vec3(0, 1, 0)); - main_hud.lprintf(0, "Angular Velocity: %f, axis %f, %f, %f\n", angular_velocity, axis.x, axis.y, axis.z); rotation_matrices[index] = glm::rotate(glm::mat4(1.0f), -angular_velocity, axis); + data_mutex.unlock(); } void rollsphere::move(int elapsed_time){ + data_mutex.lock(); for(size_t i = 0; i < locations.size(); i++){ if(speeds[i] > 0.0001){ glm::vec3 direction = glm::normalize(new_locations[i] - locations[i]); locations[i] += speeds[i] * direction; ups[i] = rotation_matrices[i] * ups[i]; forwards[i] = rotation_matrices[i] * forwards[i]; - if(glm::length(new_locations[i] - locations[i]) < 0.01) + if(glm::length(new_locations[i] - locations[i]) < speeds[i]) speeds[i] = 0.0f; } } + data_mutex.unlock(); } void rollsphere::addsphere(glm::vec3 location, float radius, glm::vec3 up, glm::vec3 forward){ diff --git a/helpers.cpp b/helpers.cpp index 85f9a67..c40fb19 100644 --- a/helpers.cpp +++ b/helpers.cpp @@ -24,6 +24,14 @@ void free_helpers() { free(general_buffer); } +glm::vec3 get_look_at_point(){ + glm::vec3 look_at_point = player_position; + look_at_point.x += cosf(player_elevation) * sinf(player_heading); + look_at_point.y += sinf(player_elevation); + look_at_point.z += cosf(player_elevation) * cosf(player_heading); + return look_at_point; +} + float randvel(float speed){ long min = -100; long max = 100; diff --git a/loaded_object_vertex_shader.glsl b/loaded_object_vertex_shader.glsl index 0e92338..f3a83c3 100644 --- a/loaded_object_vertex_shader.glsl +++ b/loaded_object_vertex_shader.glsl @@ -7,7 +7,6 @@ in vec3 in_vertex; in vec2 in_texcoord; uniform mat4 vp; out vec2 frag_texcoord; -out vec4 gl_Position; void main(void) { gl_Position = vp * models[gl_InstanceID] * vec4(in_vertex, 1.0); diff --git a/main.cpp b/main.cpp index 0c2f507..01a06b4 100644 --- a/main.cpp +++ b/main.cpp @@ -14,6 +14,7 @@ #include "geometric_objects.h" #include "door.h" #include "vehicle.h" +#include "maze.h" std::mutex grand_mutex; @@ -29,6 +30,7 @@ std::vector objects; projectile ice_balls; wall_block spawned_blocks("cube.obj", "projectile.jpg", glm::vec3(2, 2, 2)); fragment brick_fragments; +maze_solver round_maze_solver; class target : public loaded_object, public block_object { public: @@ -42,14 +44,13 @@ class target : public loaded_object, public block_object { }; -ssize_t is_empty(glm::vec3 position, float distance = 0.2f){ +ssize_t is_empty(glm::vec3 position, float distance){ for(gameobject* o : objects) { ssize_t collide_index = o->collision_index(position, distance); if(collide_index != -1) return false; } return true; - } void fire(bool burst = false){ @@ -120,6 +121,8 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod player_platform = 0; } } + if(GLFW_KEY_V == key && 0 == action) + round_maze_solver.launch(-100); } int shutdown_engine = 0; @@ -437,6 +440,12 @@ int main(int argc, char** argv) { test_sphere.addsphere(glm::vec3(-30, 10, 530), 20); objects.push_back(&test_sphere); + maze test_maze; + test_maze.start_location = glm::vec3(0, -100, 600); + test_maze.load_from_file("maze_map"); + objects.push_back(&test_maze); + objects.push_back(&round_maze_solver); + /* Initialize game objects */ for(gameobject* o : objects){ if(o->init()){ @@ -476,10 +485,8 @@ int main(int argc, char** argv) { /* Where are we? A: player_position * What are we looking at? */ - glm::vec3 look_at_point = player_position; - look_at_point.x += cosf(player_elevation) * sinf(player_heading); - look_at_point.y += sinf(player_elevation); - look_at_point.z += cosf(player_elevation) * cosf(player_heading); + + glm::vec3 look_at_point = get_look_at_point(); glm::mat4 view = glm::lookAt(player_position, look_at_point, glm::vec3(0, 1, 0)); glm::mat4 projection = glm::perspective(45.0f, width / height, 0.1f, 10000.0f); glm::mat4 vp = projection * view; diff --git a/maze.cpp b/maze.cpp new file mode 100644 index 0000000..1a03e0a --- /dev/null +++ b/maze.cpp @@ -0,0 +1,73 @@ +#include "game.h" +#include "maze.h" + +bool maze::load_from_file(const char* filename){ + FILE *infile = fopen(filename, "r"); + if(!infile){ + printf(RED("Maze file %s could not be opened").c_str(), filename); + return false; + } + char *line; + size_t linesize = 0; + ssize_t readlen; + glm::vec3 place = start_location; + while(0 < (readlen = getline(&line, &linesize, infile))){ + for(char *c = line; *c && (*c == '#' || *c == ' '); c++) { + if(*c == '#') + locations.push_back(place); + place.x += 8; + } + place.x = start_location.x; + place.z += 8; + } + fclose(infile); + return true; +} + +void maze_solver::launch(float maze_height){ + glm::vec3 lap = get_look_at_point(); + data_mutex.lock(); + sphere::addsphere(lap, 3.5); + float height_change = player_position.y - maze_height; + lap -= player_position; + lap *= height_change / lap.y; + lap = player_position - lap; + lap = glm::vec3(8.0f * roundf(lap.x / 8.0f), maze_height, 8.0f * roundf(lap.z / 8.0f)); + new_locations.push_back(lap); + main_hud.lprintf(0, "Solver sent to: %f, %f, %f", lap.x, lap.y, lap.z); + speeds.push_back(0.1f); + rotation_matrices.push_back(glm::mat4(1.0f)); + visiteds.push_back(std::set()); + stacks.push_back(std::vector()); + data_mutex.unlock(); +} + +void maze_solver::move(int elapsed_time) { + for(size_t i = 0; i < locations.size(); i++){ + bool found_next = false; + if(speeds[i] < 0.001){ + for(auto &n : intpoint(locations[i]).neighbors()){ + if(!is_empty(n.vec3(), 0.0f)) + continue; + if(visiteds[i].contains(n)) + continue; + visiteds[i].insert(n); + stacks[i].push_back(n); + found_next = true; + roll_to(i, n.vec3(), solve_speed); + main_hud.lprintf(0, "Going to %d, %d, %d", n.x, n.y, n.z); + break; // We found somewhere new to go! + } + if(!found_next){ // Backtrack + if(stacks[i].size()){ + roll_to(i, stacks[i].back().vec3(), solve_speed); + main_hud.lprintf(0, "Backtrack to %f, %f, %f", new_locations[i].x, new_locations[i].y, new_locations[i].z); + stacks[i].pop_back(); + } else { // We can't backtrack, because the stack is empty + visiteds[i].clear(); // Maybe just start over? + } + } + } + } + rollsphere::move(elapsed_time); +} diff --git a/maze.h b/maze.h new file mode 100644 index 0000000..1529c21 --- /dev/null +++ b/maze.h @@ -0,0 +1,49 @@ +#pragma once + +#include "geometric_objects.h" +#include + +class maze : public wall_block { +public: + glm::vec3 start_location; + maze() : wall_block("cube.obj", "brick_2.png", glm::vec3(4, 4, 4)) { + scale = 4.0f; + } + + bool load_from_file(const char* filename); +}; + +class maze_solver : public rollsphere { + struct intpoint { + int x, y, z; + intpoint(glm::vec3 p) { + x = roundf(p.x); + y = roundf(p.y); + z = roundf(p.z); + } + intpoint(int nx, int ny, int nz) : x(nx), y(ny), z(nz) {} + bool operator== (const intpoint &other) const { + return other.x == x && other.y == y && other.z == z; + } + bool operator<(const intpoint &other) const { + return (x << 20) + (y << 10) + z < (other.x << 20) + (other.y << 10) + other.z; + } + std::vector neighbors(){ + std::vector retval; + retval.push_back(intpoint(x - 8, y, z)); + retval.push_back(intpoint(x + 8, y, z)); + retval.push_back(intpoint(x, y, z - 8)); + retval.push_back(intpoint(x, y, z + 8)); + return retval; + } + glm::vec3 vec3(){ + return glm::vec3(x, y, z); + } + }; +public: + float solve_speed = 0.01f; + std::vector> visiteds; + std::vector> stacks; + void launch(float maze_height); + void move(int elapsed_time) override; +}; diff --git a/maze_map b/maze_map new file mode 100644 index 0000000..a99957b --- /dev/null +++ b/maze_map @@ -0,0 +1,20 @@ +######### ########## +# # # ## +# # #### # # ## ## +# ## # # # +# ################ +# # ## ## +##### #### # # # +# ### # # ## # +##### ### # # +# # ######### # ## +# ### # # +# # ############ +####### # # ## # +# # # # +#### #### ########## +## ### ### # +# ####### # # +# ## ### ## # +# # # +####################