319 lines
8.8 KiB
C
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);
|
|
}
|