#include // must come before glfw3 #include #include #include #include #define MAP_HEIGHT 10 #define MAP_WIDTH 10 //int height_map[MAP_WIDTH][MAP_HEIGHT] = { // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, // {0, 1, 3, 3, 3, 3, 3, 3, 1, 0}, // {0, 1, 3, 5, 5, 5, 5, 3, 1, 0}, // {0, 1, 3, 5, 8, 8, 5, 3, 1, 0}, // {0, 1, 3, 5, 8, 8, 5, 3, 1, 0}, // {0, 1, 3, 5, 5, 5, 5, 3, 1, 0}, // {0, 1, 3, 3, 3, 3, 3, 3, 1, 0}, // {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //}; bool draw_grid = true; int height_map[MAP_WIDTH][MAP_HEIGHT] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, -1, -2, 0, 0}, {0, 0, 0, 0, 0, 0, 0, -1, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 2, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; // TODO: move into dedicated camera struct // Define the perspective projection matrix void perspective(float fov, float aspect, float near, float far, float *mat) { float f = 1.0f / tan(fov * 0.5f); mat[0] = f / aspect; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f; mat[4] = 0.0f; mat[5] = f; mat[6] = 0.0f; mat[7] = 0.0f; mat[8] = 0.0f; mat[9] = 0.0f; mat[10] = (far + near) / (near - far); mat[11] = -1.0f; mat[12] = 0.0f; mat[13] = 0.0f; mat[14] = (2.0f * far * near) / (near - far); mat[15] = 0.0f; } float camera_pos_x = 0.0f; float camera_pos_y = 0.0f; float camera_pos_z = 0.0f; float camera_yaw = 0.0f; // rotation around y-axis float camera_pitch = 0.0f; // rotation aroudn x-axis void renderHeightMap() { float colors[3][3] = { {0.0f, 1.0f, 0.0f}, // default green {0.0f, 0.0f, 1.0f}, // blue {0.5f, 1.0f, 0.5f} // light green }; float scale_factor = 1.0f; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-camera_pos_x, -camera_pos_y, -camera_pos_z); glRotatef(-camera_pitch, 1.0f, 0.0f, 0.0f); glRotatef(-camera_yaw, 0.0f, 1.0f, 0.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-10.0, 10.0, -10.0, 10.0, -20.0, 20.0); for (int x = 0; x < MAP_WIDTH - 1; x++) { // Adjusted loop bounds glBegin(GL_TRIANGLE_STRIP); for (int y = 0; y < MAP_HEIGHT; y++) { float x0 = x; float y0 = height_map[x][y] * scale_factor; float z0 = y; float x1 = x + 1; // Adjusted x1 float y1 = height_map[x+1][y] * scale_factor; // Adjusted indexing float z1 = y; float* color = colors[0]; if (y0 > 0.5f) { color = colors[2]; } if (y0 < -0.5f) { color = colors[1]; } glColor3fv(color); glVertex3f(x0, y0, z0); glVertex3f(x1, y1, z1); } glEnd(); } // draw grid if(draw_grid) { glColor3f(0.0f, 0.0f, 0.0f); glLineWidth(1.0f); glBegin(GL_LINES); // Draw vertical grid lines for (int x = 0; x <= MAP_WIDTH; x++) { for (int y = 0; y < MAP_HEIGHT; y++) { glVertex3f(x, height_map[x][y] * scale_factor, y); glVertex3f(x, height_map[x][y + 1] * scale_factor, y + 1); } } // Draw horizontal grid lines for (int y = 0; y <= MAP_HEIGHT; y++) { for (int x = 0; x < MAP_WIDTH; x++) { glVertex3f(x, height_map[x][y] * scale_factor, y); glVertex3f(x + 1, height_map[x + 1][y] * scale_factor, y); } } } glEnd(); } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { const float camera_speed = 0.5f; if (key == GLFW_KEY_W && (action == GLFW_PRESS || action == GLFW_REPEAT)) { height_map[5][4] += 1; } else if (key == GLFW_KEY_S && (action == GLFW_PRESS || action == GLFW_REPEAT)) { height_map[5][4] -= 1; } else if (key == GLFW_KEY_A && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_pos_x -= camera_speed; } else if (key == GLFW_KEY_D && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_pos_x += camera_speed; } else if (key == GLFW_KEY_Q && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_pitch -= camera_speed; } else if (key == GLFW_KEY_E && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_pitch += camera_speed; } else if (key == GLFW_KEY_Z && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_yaw -= camera_speed; } else if (key == GLFW_KEY_C && (action == GLFW_PRESS || action == GLFW_REPEAT)) { camera_yaw += camera_speed; } else if (key == GLFW_KEY_X && (action == GLFW_PRESS || action == GLFW_REPEAT)) { draw_grid = !draw_grid; } } int main(int argc, char *argv[]) { GLFWwindow* window; // initiate glfw library if (!glfwInit()){ printf("Failed to initiate GLFW.\n"); return -1; } // create glfw window GLFWmonitor* primary = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(primary); window = glfwCreateWindow(mode->width, mode->height, "raycaster", primary, NULL); if (!window){ printf("Failed to create GLFW window.\n"); glfwTerminate(); return -1; } // make window current glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { printf("GLEW init error"); return -1; } // enable depth testing glEnable(GL_DEPTH_TEST); glfwSetKeyCallback(window, key_callback); while (!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); renderHeightMap(); glfwSwapBuffers(window); // Swap buffers to display the rendered image // Poll for and process events, wait for events if none are pending glfwWaitEventsTimeout(0.01); // Add a slight delay to reduce CPU usage } printf("Terminating GLFW...\n"); glfwTerminate(); return 0; }