miniRT/src/minirt.c
2026-02-08 22:30:21 +01:00

319 lines
8.8 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* minirt.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: bszilas <bszilas@student.42vienna.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/09/08 16:33:29 by victor #+# #+# */
/* Updated: 2025/05/31 18:22:50 by victor ### ########.fr */
/* */
/* ************************************************************************** */
#include "../minirt.h"
#include <stdio.h>
t_data data = { 0 };
uint ratio_x = 0;
uint ratio_y = 0;
uint max_res_x = 1;
uint max_res_y = 1;
void create_display() {
InitWindow(800, 600, "miniRT");
int monitor = GetCurrentMonitor();
int w = GetMonitorWidth(monitor);
int h = GetMonitorHeight(monitor);
SetWindowSize(w, h);
data.scene.w = w;
data.scene.h = h;
SetTargetFPS(60);
}
void data_destroy_func(void *data_ptr)
{
t_data *data;
data = data_ptr;
#ifndef __EMSCRIPTEN__
data->go = false;
pthread_rwlock_unlock(&data->rwlock);
while (data->thread_count--)
pthread_join(data->threads[data->thread_count].thread, NULL);
pthread_barrier_destroy(&data->barrier);
pthread_rwlock_destroy(&data->rwlock);
#endif /* ifndef __EMSCRIPTEN__ */
UnloadTexture(data->texture);
CloseWindow();
}
t_container *menu_init(t_data *data)
{
t_container *menu;
t_item item;
menu = ft_calloc(16, sizeof(*menu));
lst_memory(menu, free, ADD);
menu[ID_GROUP_MENU_MAIN - 1] = container_create("Main menu", \
NULL, CONTAINER_GRID);
item = container_item_button_create("add sphere", \
NULL, scene_add_sphere_func);
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
item = container_item_button_create("add plane", NULL, \
scene_add_plane_func);
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
item = container_item_button_create("add cylinder", NULL, \
scene_add_cylinder);
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
item = container_item_button_create("add disk", NULL, \
scene_add_disk);
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
item = container_item_button_create("show_help", NULL, help_menu_draw);
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
item = container_item_button_create("Load Scene", NULL, explorer_read_dir);
item.param = (t_param){&data->scene, NULL, PARAM_SCENE};
container_item_add(&menu[ID_GROUP_MENU_MAIN - 1], &item);
return (menu);
}
t_container *menus_create(t_data *data)
{
t_container *menu;
uint i;
menu = menu_init(data);
sphere_menu_create(&menu[ID_GROUP_SPHERE]);
plane_menu_create(&menu[ID_GROUP_PLANE]);
cone_menu_create(&menu[ID_GROUP_CONE]);
disc_menu_create(&menu[ID_GROUP_DISC]);
cylinder_menu_create(&menu[ID_GROUP_CYLINDER]);
i = 0;
while (i < 16)
menu[i++].data = data;
return (menu);
}
void initialize_data(t_data *data, char *path)
{
scene_create(path, &data->scene);
create_display();
data->pixel = pixel_plane_create();
data->func_ptr = help_menu_draw;
data->mouse.data = data;
data->scene.pixel = data->pixel;
data->menu = menus_create(data);
Image img = GenImageColor(data->scene.w, data->scene.h, BLACK);
data->pixel_colors = img.data;
data->texture = LoadTextureFromImage(img);
data->should_rerender = true;
pixels_image_syncronize(data->pixel_colors, data->pixel);
}
char* validate_file_extension(int argc, char **argv)
{
if (argc == 2 && ft_strlen(argv[1]) > 3 && ft_memcmp(&argv[1][ft_strlen(argv[1]) - 3], ".rt\0", 4) == 0)
return argv[1];
ft_fprintf(STDERR_FILENO, "Invalid Argument to Program!\nExiting...\n");
fflush(stderr);
exit(EXIT_FAILURE);
}
void get_key_code(int keys[]) {
uint c = 0;
if (IsKeyPressed(KEY_ESCAPE)) {
keys[c++] = KEY_ESCAPE;
if (c == 3) return;
}
if ((IsKeyPressed(KEY_W) || IsKeyDown(KEY_W))) {
keys[c++] = KEY_W;
if (c == 3) return;
}
if ((IsKeyPressed(KEY_E) || IsKeyDown(KEY_E))) {
keys[c++] = KEY_E;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_Q) || IsKeyDown(KEY_Q))) {
keys[c++] = KEY_Q;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_A) || IsKeyDown(KEY_A))) {
keys[c++] = KEY_A;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_S) || IsKeyDown(KEY_S))) {
keys[c++] = KEY_S;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_D) || IsKeyDown(KEY_D))) {
keys[c++] = KEY_D;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_ENTER)) {
keys[c++] = KEY_ENTER;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_BACKSPACE)) {
keys[c++] = KEY_BACKSPACE;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_SLASH)) {
keys[c++] = KEY_SLASH;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_PERIOD)) {
keys[c++] = KEY_PERIOD;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_M)) {
keys[c++] = KEY_M;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_P)) {
keys[c++] = KEY_P;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_EQUAL)) {
keys[c++] = KEY_EQUAL;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_Y)) {
keys[c++] = KEY_Y;
if (c == 3) return ;
}
if (IsKeyPressed(KEY_MINUS)) {
keys[c++] = KEY_MINUS;
if (c == 3) return ;
}
if (IsKeyDown(KEY_ONE)) {
keys[c++] = KEY_ONE;
if (c == 3) return ;
}
if (IsKeyDown(KEY_TWO)) {
keys[c++] = KEY_TWO;
if (c == 3) return ;
}
if (IsKeyDown(KEY_THREE)) {
keys[c++] = KEY_THREE;
if (c == 3) return ;
}
if (IsKeyDown(KEY_FOUR)) {
keys[c++] = KEY_FOUR;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_UP) || IsKeyDown(KEY_UP))) {
keys[c++] = KEY_UP;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_DOWN) || IsKeyDown(KEY_DOWN))) {
keys[c++] = KEY_DOWN;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_LEFT) || IsKeyDown(KEY_LEFT))) {
keys[c++] = KEY_LEFT;
if (c == 3) return ;
}
if ((IsKeyPressed(KEY_RIGHT) || IsKeyDown(KEY_RIGHT))) {
keys[c++] = KEY_RIGHT;
if (c == 3) return ;
}
}
bool key_was_pressed = false;
void main_loop() {
int keys[3] = { 0 };
Vector2 mouse_pos = GetMousePosition();
if (data.mouse.left_is_pressed || data.mouse.right_is_pressed)
{
mouse_move(mouse_pos.x, mouse_pos.y, &data);
mouse_release(mouse_pos.x, mouse_pos.y, &data);
}
else
mouse_press(mouse_pos.x, mouse_pos.y, &data);
bzero(keys, sizeof(keys));
get_key_code(keys);
for (int i = 0; i < 3; i++)
{
if (keys[i])
{
key_was_pressed = true;
data.should_rerender = true;
#ifdef __EMSCRIPTEN__
data.scene.resolution_x = ratio_x * 2;
data.scene.resolution_y = ratio_y * 2;
#else
data.scene.resolution_x = ratio_x;
data.scene.resolution_y = ratio_y;
#endif /* ifdef __EMSCRIPTEN__ */
key_press(keys[i], &data);
}
}
rendering_loop(&data);
data.scene.resolution_x = max_res_x;
data.scene.resolution_y = max_res_y;
if (key_was_pressed) {
key_was_pressed = false;
} else {
data.should_rerender = false;
data.func_ptr = NULL;
}
}
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main(int argc, char **argv)
{
char *path;
#ifndef __EMSCRIPTEN__
t_thread thread[THREAD_COUNT];
#endif /* ifndef __EMSCRIPTEN__ */
if (argc == 1) {
path = SCENES_PATH"/multilight.rt";
}
else
path = validate_file_extension(argc, argv);
initialize_data(&data, path);
lst_memory(&data, data_destroy_func, ADD);
int divisor = gcd(data.scene.w, data.scene.h);
ratio_x = data.scene.w / divisor;
ratio_y = data.scene.h / divisor;
#ifndef __EMSCRIPTEN__
threads_init(thread, &data);
data.threads = thread;
#endif
#ifdef __EMSCRIPTEN__
max_res_y = ratio_y;
max_res_x = ratio_x;
emscripten_set_main_loop(main_loop, 0, 1);
#else
while(!WindowShouldClose()) {
main_loop();
}
#endif /* ifdef __EMSCRIPTEN__ */
return (0);
}