diff --git a/build/main b/build/main index 85722bb..33d3add 100755 Binary files a/build/main and b/build/main differ diff --git a/level.cpp b/level.cpp new file mode 100644 index 0000000..36886e8 --- /dev/null +++ b/level.cpp @@ -0,0 +1,142 @@ +int load_sectors(const char *path) { + // Sector 0 is usually reserved/null + state.sectors.n = 1; + state.walls.n = 0; + + FILE *f = fopen(path, "r"); + if (!f) { + printf("Could not open file: %s\n", path); + return -1; + } + + enum { SCAN_SECTOR, SCAN_WALL, SCAN_NONE } ss = SCAN_NONE; + char line[1024]; + + while (fgets(line, sizeof(line), f)) { + char *p = line; + // Trim leading whitespace + while (isspace(*p)) + p++; + + // Skip comments and empty lines + if (!*p || *p == '#') + continue; + + // Check for section headers like [SECTOR] + if (*p == '[') { + if (strstr(p, "[SECTOR]")) + ss = SCAN_SECTOR; + else if (strstr(p, "[WALL]")) + ss = SCAN_WALL; + continue; + } + + // Parse data based on current section + if (ss == SCAN_SECTOR) { + struct Sector *s = &state.sectors.arr[state.sectors.n++]; + // Format: ID, FirstWallIndex, NumWalls, FloorZ, CeilZ + if (sscanf(p, "%d %zu %zu %f %f", &s->id, &s->firstwall, &s->nwalls, + &s->floor, &s->ceil) != 5) { + fclose(f); + return -5; + } + } else if (ss == SCAN_WALL) { + struct Wall *w = &state.walls.arr[state.walls.n++]; + // Format: x1, y1, x2, y2, PortalID + if (sscanf(p, "%f %f %f %f %d", &w->v1.x, &w->v1.y, &w->v2.x, &w->v2.y, + &w->portalID) != 5) { + fclose(f); + return -4; + } + } + } + + fclose(f); + return 0; // Success +} +void build_sector_flats(struct Sector *s) { + // We need at least 3 walls to make a floor (a triangle) + if (s->nwalls < 3) + return; + + // 1. Pick a pivot point (the start of the first wall) + struct Wall *first_w = &state.walls.arr[s->firstwall]; + glm::vec3 pivot_floor = + glm::vec3((float)first_w->v1.x, s->floor, (float)first_w->v1.y); + glm::vec3 pivot_ceil = + glm::vec3((float)first_w->v1.x, s->ceil, (float)first_w->v1.y); + + // 2. Loop through the rest of the walls to create a "fan" of triangles + for (size_t i = 1; i < s->nwalls - 1; i++) { + struct Wall *w1 = &state.walls.arr[s->firstwall + i]; + struct Wall *w2 = &state.walls.arr[s->firstwall + i + 1]; + + glm::vec3 p1_f = glm::vec3((float)w1->v1.x, s->floor, (float)w1->v1.y); + glm::vec3 p2_f = glm::vec3((float)w2->v1.x, s->floor, (float)w2->v1.y); + + glm::vec3 p1_c = glm::vec3((float)w1->v1.x, s->ceil, (float)w1->v1.y); + glm::vec3 p2_c = glm::vec3((float)w2->v1.x, s->ceil, (float)w2->v1.y); + + // FLOOR TRIANGLE (Facing Up) + // Winding: Pivot -> P1 -> P2 (Counter-Clockwise) + map_mesh.push_back({pivot_floor, {pivot_floor.x, pivot_floor.z}}); + map_mesh.push_back({p1_f, {p1_f.x, p1_f.z}}); + map_mesh.push_back({p2_f, {p2_f.x, p2_f.z}}); + + // CEILING TRIANGLE (Facing Down) + // Winding: Pivot -> P2 -> P1 (Clockwise from top, CCW from bottom) + map_mesh.push_back({pivot_ceil, {pivot_ceil.x, pivot_ceil.z}}); + map_mesh.push_back({p2_c, {p2_c.x, p2_c.z}}); + map_mesh.push_back({p1_c, {p1_c.x, p1_c.z}}); + } +} +void push_wall_quad(glm::vec2 a, glm::vec2 b, float y_low, float y_high) { + float length = glm::distance(a, b); + float height = y_high - y_low; + + // Vertex data: Position(x, y, z), TexCoords(u, v) + // Triangle 1 + map_mesh.push_back({{a.x, y_low, a.y}, {0.0f, 0.0f}}); + map_mesh.push_back({{b.x, y_low, b.y}, {length, 0.0f}}); + map_mesh.push_back({{b.x, y_high, b.y}, {length, height}}); + + // Triangle 2 + map_mesh.push_back({{a.x, y_low, a.y}, {0.0f, 0.0f}}); + map_mesh.push_back({{b.x, y_high, b.y}, {length, height}}); + map_mesh.push_back({{a.x, y_high, a.y}, {0.0f, height}}); +} +void build_map_mesh() { + map_mesh.clear(); + + // Loop through sectors starting from 1 + for (size_t i = 1; i < state.sectors.n; i++) { + struct Sector *s = &state.sectors.arr[i]; + + // Loop through the walls assigned to this sector + for (size_t j = 0; j < s->nwalls; j++) { + struct Wall *w = &state.walls.arr[s->firstwall + j]; + + // Map coordinates directly from the wall struct + // We cast to float because sscanf read them as ints + glm::vec2 pA = glm::vec2((float)w->v1.x, (float)w->v1.y); + glm::vec2 pB = glm::vec2((float)w->v2.x, (float)w->v2.y); + + if (w->portalID == 0) { + // It's a solid wall: draw from floor to ceiling + push_wall_quad(pA, pB, s->floor, s->ceil); + } else { + // It's a portal: draw the upper/lower differences + struct Sector *neighbor = &state.sectors.arr[w->portalID]; + + // Draw lower "step" if neighbor floor is higher + if (neighbor->floor > s->floor) + push_wall_quad(pA, pB, s->floor, neighbor->floor); + + // Draw upper "overhang" if neighbor ceiling is lower + if (neighbor->ceil < s->ceil) + push_wall_quad(pA, pB, neighbor->ceil, s->ceil); + } + } + build_sector_flats(s); + } +} diff --git a/level.hpp b/level.hpp new file mode 100644 index 0000000..e69de29 diff --git a/main.cpp b/main.cpp index 2abe0f7..c94f872 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -21,53 +22,180 @@ float deltaTime = 0.0f; // Time between current frame and last frame float lastFrame = 0.0f; // Time of last frame float lastX = 600 / 2.0f; float lastY = 800 / 2.0f; -Camera camera(glm::vec3(1.0f, 0.0f, 1.0f)); +Camera camera(glm::vec3(1.0f, 1.0f, 1.0f)); bool firstMouse = true; -const int MAP_WIDTH = 20; -const int MAP_HEIGHT = 20; -int worldMap[MAP_WIDTH][MAP_HEIGHT] = { - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 0, 1, 0, 2, 2, 2, 2, 0, 1, 0, 2, 2, 2, 0, 1}, - {1, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 2, 0, 1}, - {1, 0, 2, 2, 2, 0, 1, 0, 2, 2, 2, 2, 0, 1, 0, 2, 2, 2, 0, 1}, - {1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1}, - {1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1}, - {1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1}, - {1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1}, - {1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 0, 2, 2, 2, 2, 2, 2, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 0, 1}, - {1, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 1}, - {1, 0, 2, 0, 0, 0, 0, 2, 0, 1, 1, 0, 2, 0, 0, 0, 0, 2, 0, 1}, - {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; +struct Sector { + int id; + float floor, ceil; + size_t firstwall, nwalls; +}; -bool collision_check(float newX, float newZ) { - float playerRadius = 0.2f; - // We check the four corners of the player's "hitbox" - for (float offset_x = -playerRadius; offset_x <= playerRadius; - offset_x += playerRadius * 2) { - for (float offset_z = -playerRadius; offset_z <= playerRadius; - offset_z += playerRadius * 2) { - int gridX = (int)(newX + offset_x); - int gridZ = (int)(newZ + offset_z); +struct Wall { + glm::vec2 v1, v2; // Index of the vertices + int portalID; // -1 if solid, else the ID of the sector on the other side +}; - // 1. Check map boundaries - if (gridX < 0 || gridX >= MAP_WIDTH || gridZ < 0 || gridZ >= MAP_HEIGHT) - return false; +struct { + struct { + struct Sector arr[32]; + size_t n; + } sectors; + struct { + struct Wall arr[128]; + size_t n; + } walls; - // 2. Check if the tile is a wall - if (worldMap[gridX][gridZ] > 0) - return false; +} state; + +struct MapVertex { + glm::vec3 pos; + glm::vec2 tex; +}; + +std::vector map_mesh; + +static int load_sectors(const char *path) { + // Sector 0 is usually reserved/null + state.sectors.n = 1; + state.walls.n = 0; + + FILE *f = fopen(path, "r"); + if (!f) { + printf("Could not open file: %s\n", path); + return -1; + } + + enum { SCAN_SECTOR, SCAN_WALL, SCAN_NONE } ss = SCAN_NONE; + char line[1024]; + + while (fgets(line, sizeof(line), f)) { + char *p = line; + // Trim leading whitespace + while (isspace(*p)) + p++; + + // Skip comments and empty lines + if (!*p || *p == '#') + continue; + + // Check for section headers like [SECTOR] + if (*p == '[') { + if (strstr(p, "[SECTOR]")) + ss = SCAN_SECTOR; + else if (strstr(p, "[WALL]")) + ss = SCAN_WALL; + continue; + } + + // Parse data based on current section + if (ss == SCAN_SECTOR) { + struct Sector *s = &state.sectors.arr[state.sectors.n++]; + // Format: ID, FirstWallIndex, NumWalls, FloorZ, CeilZ + if (sscanf(p, "%d %zu %zu %f %f", &s->id, &s->firstwall, &s->nwalls, + &s->floor, &s->ceil) != 5) { + fclose(f); + return -5; + } + } else if (ss == SCAN_WALL) { + struct Wall *w = &state.walls.arr[state.walls.n++]; + // Format: x1, y1, x2, y2, PortalID + if (sscanf(p, "%f %f %f %f %d", &w->v1.x, &w->v1.y, &w->v2.x, &w->v2.y, + &w->portalID) != 5) { + fclose(f); + return -4; + } } } - return true; + + fclose(f); + return 0; // Success +} +void build_sector_flats(struct Sector *s) { + // We need at least 3 walls to make a floor (a triangle) + if (s->nwalls < 3) + return; + + // 1. Pick a pivot point (the start of the first wall) + struct Wall *first_w = &state.walls.arr[s->firstwall]; + glm::vec3 pivot_floor = + glm::vec3((float)first_w->v1.x, s->floor, (float)first_w->v1.y); + glm::vec3 pivot_ceil = + glm::vec3((float)first_w->v1.x, s->ceil, (float)first_w->v1.y); + + // 2. Loop through the rest of the walls to create a "fan" of triangles + for (size_t i = 1; i < s->nwalls - 1; i++) { + struct Wall *w1 = &state.walls.arr[s->firstwall + i]; + struct Wall *w2 = &state.walls.arr[s->firstwall + i + 1]; + + glm::vec3 p1_f = glm::vec3((float)w1->v1.x, s->floor, (float)w1->v1.y); + glm::vec3 p2_f = glm::vec3((float)w2->v1.x, s->floor, (float)w2->v1.y); + + glm::vec3 p1_c = glm::vec3((float)w1->v1.x, s->ceil, (float)w1->v1.y); + glm::vec3 p2_c = glm::vec3((float)w2->v1.x, s->ceil, (float)w2->v1.y); + + // FLOOR TRIANGLE (Facing Up) + // Winding: Pivot -> P1 -> P2 (Counter-Clockwise) + map_mesh.push_back({pivot_floor, {pivot_floor.x, pivot_floor.z}}); + map_mesh.push_back({p1_f, {p1_f.x, p1_f.z}}); + map_mesh.push_back({p2_f, {p2_f.x, p2_f.z}}); + + // CEILING TRIANGLE (Facing Down) + // Winding: Pivot -> P2 -> P1 (Clockwise from top, CCW from bottom) + map_mesh.push_back({pivot_ceil, {pivot_ceil.x, pivot_ceil.z}}); + map_mesh.push_back({p2_c, {p2_c.x, p2_c.z}}); + map_mesh.push_back({p1_c, {p1_c.x, p1_c.z}}); + } +} +void push_wall_quad(glm::vec2 a, glm::vec2 b, float y_low, float y_high) { + float length = glm::distance(a, b); + float height = y_high - y_low; + + // Vertex data: Position(x, y, z), TexCoords(u, v) + // Triangle 1 + map_mesh.push_back({{a.x, y_low, a.y}, {0.0f, 0.0f}}); + map_mesh.push_back({{b.x, y_low, b.y}, {length, 0.0f}}); + map_mesh.push_back({{b.x, y_high, b.y}, {length, height}}); + + // Triangle 2 + map_mesh.push_back({{a.x, y_low, a.y}, {0.0f, 0.0f}}); + map_mesh.push_back({{b.x, y_high, b.y}, {length, height}}); + map_mesh.push_back({{a.x, y_high, a.y}, {0.0f, height}}); +} +void build_map_mesh() { + map_mesh.clear(); + + // Loop through sectors starting from 1 + for (size_t i = 1; i < state.sectors.n; i++) { + struct Sector *s = &state.sectors.arr[i]; + + // Loop through the walls assigned to this sector + for (size_t j = 0; j < s->nwalls; j++) { + struct Wall *w = &state.walls.arr[s->firstwall + j]; + + // Map coordinates directly from the wall struct + // We cast to float because sscanf read them as ints + glm::vec2 pA = glm::vec2((float)w->v1.x, (float)w->v1.y); + glm::vec2 pB = glm::vec2((float)w->v2.x, (float)w->v2.y); + + if (w->portalID == 0) { + // It's a solid wall: draw from floor to ceiling + push_wall_quad(pA, pB, s->floor, s->ceil); + } else { + // It's a portal: draw the upper/lower differences + struct Sector *neighbor = &state.sectors.arr[w->portalID]; + + // Draw lower "step" if neighbor floor is higher + if (neighbor->floor > s->floor) + push_wall_quad(pA, pB, s->floor, neighbor->floor); + + // Draw upper "overhang" if neighbor ceiling is lower + if (neighbor->ceil < s->ceil) + push_wall_quad(pA, pB, neighbor->ceil, s->ceil); + } + } + build_sector_flats(s); + } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { @@ -99,7 +227,7 @@ void mouse_callback(GLFWwindow *window, double xpos, double ypos) { camera.ProcessMouseMovement(xoffset, yoffset); } -void updatePhysics(float deltaTime) { +void updatePhysics(float deltaTime, float floor) { // 1. Apply gravity to velocity (Velocity = Acceleration * Time) if (!camera.isGrounded) { camera.verticalVelocity += camera.gravity * deltaTime; @@ -110,8 +238,8 @@ void updatePhysics(float deltaTime) { // 3. Ground Collision (The Floor) // If the floor is at y = 0 - if (camera.Position.y <= 0.0f) { - camera.Position.y = 0.0f; + if (camera.Position.y <= floor) { + camera.Position.y = floor; camera.verticalVelocity = 0.0f; camera.isGrounded = true; } @@ -136,11 +264,33 @@ void processInput(GLFWwindow *window) { camera.ProcessKeyboard(LEFT, deltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, deltaTime); - if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && camera.isGrounded) { camera.verticalVelocity = camera.jumpForce; camera.isGrounded = false; } } +int get_sector_at(float x, float z) { + // Start from 1 (skipping null sector) + for (size_t i = 1; i < state.sectors.n; i++) { + struct Sector *s = &state.sectors.arr[i]; + int inside = 0; + + for (size_t j = 0; j < s->nwalls; j++) { + struct Wall *w = &state.walls.arr[s->firstwall + j]; + + // Check if player position is between the Y-bounds of the wall + if (((w->v1.y > z) != (w->v2.y > z)) && + (x < (float)(w->v2.x - w->v1.x) * (z - (float)w->v1.y) / + (float)(w->v2.y - w->v1.y) + + (float)w->v1.x)) { + inside = !inside; + } + } + if (inside) + return (int)i; + } + return -1; // Outside the map +} int main() { @@ -164,9 +314,10 @@ int main() { glfwWindowHint(GLFW_FLOATING, GLFW_TRUE); // This makes the window float glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_TRUE); + glfwWindowHintString(GLFW_WAYLAND_APP_ID, "opengl"); GLFWwindow *window = - glfwCreateWindow(800, 600, "testing open gl", NULL, NULL); + glfwCreateWindow(1000, 600, "testing open gl", NULL, NULL); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetCursorPosCallback(window, mouse_callback); @@ -231,20 +382,29 @@ int main() { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // cube one -0.5f, 0.5f, -0.5f, 0.0f, 1.0f // cube one }; - glm::vec3 cubePositions[] = { + if (load_sectors("../map.txt") != 0) { + printf("loaded %zu sectors and %zu walls", state.sectors.n, state.walls.n); + printf("Failed to parse map file!\n"); + return -1; + } + build_map_mesh(); - glm::vec3(0.0f, 0.0f, 0.0f), - glm::vec3(2.0f, 5.0f, -15.0f), - glm::vec3(-1.5f, -2.2f, -2.5f), - glm::vec3(-3.8f, -2.0f, -12.3f), - glm::vec3(2.4f, -0.4f, -3.5f), - glm::vec3(-1.7f, 3.0f, -7.5f), - glm::vec3(1.3f, -2.0f, -2.5f), - glm::vec3(1.5f, 2.0f, -2.5f), - glm::vec3(1.5f, 0.2f, -1.5f), - glm::vec3(-1.3f, 1.0f, -1.5f) + unsigned int mapVAO, mapVBO; + glGenVertexArrays(1, &mapVAO); + glGenBuffers(1, &mapVBO); - }; + glBindVertexArray(mapVAO); + glBindBuffer(GL_ARRAY_BUFFER, mapVBO); + glBufferData(GL_ARRAY_BUFFER, map_mesh.size() * sizeof(MapVertex), + map_mesh.data(), GL_STATIC_DRAW); + + // Position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MapVertex), (void *)0); + glEnableVertexAttribArray(0); + // TexCoord attribute + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(MapVertex), + (void *)offsetof(MapVertex, tex)); + glEnableVertexAttribArray(2); unsigned int EBO; glGenBuffers(1, &EBO); @@ -388,9 +548,27 @@ int main() { float gravity = -9.81f; while (!glfwWindowShouldClose(window)) { float currentFrame = glfwGetTime(); + float ground = 1.0f; deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - updatePhysics(deltaTime); + int current_sector_id = get_sector_at(camera.Position.x, camera.Position.z); + + if (current_sector_id != -1) { + struct Sector *s = &state.sectors.arr[current_sector_id]; + + // The "target" height is floor + player height (e.g., 2.0 units) + float target_y = s->floor + 1.0f; + ground = target_y; + + // Smoothly interpolate (lerp) to the target height so you don't + // "teleport" up stairs + if (camera.isGrounded) { + float lerpSpeed = 10.0f; // Adjust this for "snappiness" + camera.Position.y = + glm::mix(camera.Position.y, target_y, lerpSpeed * deltaTime); + } + } + updatePhysics(deltaTime, ground); processInput(window); ballVelocity.y += gravity * deltaTime; @@ -425,7 +603,7 @@ int main() { ourshader.use(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture2); + glBindTexture(GL_TEXTURE_2D, texture1); // model = glm::translate( // model, glm::vec3(0.0f, sin(glfwGetTime() * 2) * 10e-4f, 0.0f)); @@ -444,75 +622,10 @@ int main() { glBindVertexArray(sphereVAO); glDrawElements(GL_TRIANGLES, sphereIndices.size(), GL_UNSIGNED_INT, 0); - glBindVertexArray(wallVAO); - - for (int x = 0; x < MAP_WIDTH; x++) { - for (int y = 0; y < MAP_HEIGHT; y++) { - if (worldMap[x][y] > 0) { - // Set Texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture2); - if (y + 1 < MAP_HEIGHT && worldMap[x][y + 1] == 0) { - glm::mat4 model = glm::mat4(1.0f); - model = glm::translate( - model, glm::vec3(x, 0.0f, y + 0.5f)); // Move to edge - // No rotation needed if the plane naturally faces Z - ourshader.setMat4("mvp", projection * view * model); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - } - - // Check East neighbor: if it's empty, draw the East face - if (x + 1 < MAP_WIDTH && worldMap[x + 1][y] == 0) { - glm::mat4 model = glm::mat4(1.0f); - model = glm::translate(model, glm::vec3(x + 0.5f, 0.0f, y)); - model = glm::rotate(model, glm::radians(90.0f), - glm::vec3(0.0f, 1.0f, 0.0f)); - ourshader.setMat4("mvp", projection * view * model); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - } - - if (y - 1 < MAP_HEIGHT && worldMap[x][y - 1] == 0) { - glm::mat4 model = glm::mat4(1.0f); - model = glm::translate( - model, glm::vec3(x, 0.0f, y - 0.5f)); // Move to edge - // No rotation needed if the plane naturally faces Z - ourshader.setMat4("mvp", projection * view * model); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - } - - if (x - 1 < MAP_WIDTH && worldMap[x - 1][y] == 0) { - glm::mat4 model = glm::mat4(1.0f); - model = glm::translate(model, glm::vec3(x - 0.5f, 0.0f, y)); - model = glm::rotate(model, glm::radians(90.0f), - glm::vec3(0.0f, 1.0f, 0.0f)); - ourshader.setMat4("mvp", projection * view * model); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - } - - } else { - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture1); - // Draw Floor - glm::mat4 floorModel = glm::mat4(1.0f); - floorModel = - glm::translate(floorModel, glm::vec3((float)x, -0.5f, (float)y)); - floorModel = glm::rotate(floorModel, glm::radians(90.0f), - glm::vec3(1.0f, 0.0f, 0.0)); - ourshader.setMat4("mvp", projection * view * floorModel); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - - // Draw Ceiling - glm::mat4 cielModel = glm::mat4(1.0f); - cielModel = - glm::translate(cielModel, glm::vec3((float)x, 0.5f, (float)y)); - cielModel = glm::rotate(cielModel, glm::radians(90.0f), - glm::vec3(1.0f, 0.0f, 0.0)); - ourshader.setMat4("mvp", projection * view * cielModel); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - } - } - } + glBindTexture(GL_TEXTURE_2D, texture2); + ourshader.setMat4("mvp", projection * view * glm::mat4(1.0f)); + glBindVertexArray(mapVAO); + glDrawArrays(GL_TRIANGLES, 0, map_mesh.size()); glBindVertexArray(0); diff --git a/map.txt b/map.txt new file mode 100644 index 0000000..1d35029 --- /dev/null +++ b/map.txt @@ -0,0 +1,34 @@ +[SECTOR] +1 0 8 0.0 5.0 +2 8 3 1.0 4.0 +3 11 4 0.2 6.0 +4 15 5 0.0 3.0 + +[WALL] +# SECTOR 1: 0..7 +4 1 2 1 0 +5 2 4 1 0 +5 3 5 2 0 +4 4 5 3 3 +2 4 4 4 0 +1 3 2 4 2 +1 2 1 3 0 +2 1 1 2 0 + +# SECTOR 2: 8..10 +2 4 1 3 1 +1 5 2 4 0 +1 3 1 5 0 + +# SECTOR 3: 11..14 +5 3 4 4 1 +6 5 5 3 0 +6 7 6 5 4 +4 4 6 7 0 + +# SECTOR 4: 15..19 +7 4 6 5 0 +8 5 7 4 0 +8 7 8 5 0 +6 7 8 7 0 +6 5 6 7 3 diff --git a/physics.hpp b/physics.hpp new file mode 100644 index 0000000..e69de29