diff --git a/CMakeLists.txt b/CMakeLists.txt index 0872c3b..692bf2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,10 @@ set(CMAKE_C_STANDARD 99) add_executable(miniRT main.c include/minirt.h src/window.c src/parser.c src/init.c src/exit.c src/scene.c - src/object.c src/vec/t_vec_new.c src/vec/t_vec_ops.c src/vec/t_vec_products.c) + src/object.c src/vec/t_vec_new.c src/vec/t_vec_ops.c src/vec/t_vec_products.c + src/vec/ray.c + src/colors.c + src/shader.c) add_custom_target(makebuild COMMAND make -C ${mytest_SOURCE_DIR} CLION_EXE_DIR=${PROJECT_BINARY_DIR}) \ No newline at end of file diff --git a/Makefile b/Makefile index 83608cf..bb350bd 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ NAME = miniRT all: $(NAME) $(NAME): $(OBJ) + @cd mlx && make @make bonus -C $(LIBFTDIR) @cp $(LIBFTDIR)/$(LIBFT) . $(CC) $(CPPFLAGS) $(OBJ) $(LIBFT) mlx/libmlx.a -lXext -lX11 -o $(NAME) -lm @@ -28,6 +29,7 @@ clean: fclean: clean $(RM) $(NAME) + @cd mlx && make clean re: fclean $(NAME) diff --git a/ados.rt b/ados.rt index 649ce90..b87d992 100644 --- a/ados.rt +++ b/ados.rt @@ -1,5 +1,5 @@ A 0.3 255,255,255 -C 0,0,40 0,0,1 85 +C 0,0,40 0,0,-1 85 L 0,0,20 0.8 255,255,255 pl 0,-10,0 0,1,0 0,0,150 diff --git a/basic.rt b/basic.rt index f085b1a..81422aa 100644 --- a/basic.rt +++ b/basic.rt @@ -1,5 +1,5 @@ -A .5 125,125,125 +A .8 255,255,225 C 0,0,1 0,0,1 70 -L -10,0,1 .5 255,255,255 -sp 0.0,0.0,20.6 12.6 10,0,255 -pl 0.0,0.0,-10.0 0.0,1.0,0.0 0,0,225 \ No newline at end of file +L -1,0,1 .8 255,255,255 +sp 0.0,0.0,20.6 12.6 10,0,255 +pl 0.0,0.0,53.0 0.0,0.0,-1.0 25,125,25 diff --git a/box.rt b/box.rt index 6bc7db5..9d6676e 100644 --- a/box.rt +++ b/box.rt @@ -1,6 +1,6 @@ -A 0.2 255,255,255 +A 0.5 255,255,255 C 0,0,5 0,0,-1 60 -L -1,2.5,2 0.7 255,255,255 +L -1,2.5,5 0.7 255,255,255 pl 0,-1,0 0,1,0 100,100,100 @@ -13,3 +13,5 @@ pl -3,0,0 1,0,0 255,0,0 pl 3,0,0 -1,0,0 0,0,255 sp 0,0,0 1.0 0,255,0 + +cy 0,0,0 0,1,0 .5 2 140,118,206 diff --git a/cylindre.rt b/cylindre.rt index 166cc9f..c5e5e68 100644 --- a/cylindre.rt +++ b/cylindre.rt @@ -1,4 +1,6 @@ A .5 125,125,125 -L 40,-75,100 .8 255,255,255 -C 1,-10,8 0,0.3,-1 60 -cy 0,-3,-1 0,1,0 4 8 140,118,206 +L 0,0,305 .5 255,255,255 +C 0,0,12 0,0,-1 60 +#cy 0,0,0 0,1,0 2 8 140,118,206 +# cy 0,0,0 0,1,0 2 8 140,118,206 +cy 0,0,0 0,1,0 2 8 140,118,206 \ No newline at end of file diff --git a/include/minirt.h b/include/minirt.h index ad5e5e8..f946d02 100644 --- a/include/minirt.h +++ b/include/minirt.h @@ -6,7 +6,7 @@ /* By: aevstign +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/09 14:39:27 by voparkan #+# #+# */ -/* Updated: 2025/05/21 16:07:04 by aevstign ### ########.fr */ +/* Updated: 2025/06/07 22:02:51 by voparkan ### ########.fr */ /* */ /* ************************************************************************** */ @@ -154,35 +154,6 @@ typedef struct s_spbag t_vec oc; } t_spbag; -typedef struct s_cybag -{ - int i; - float t1; - float t2; - float radius; - float a_f; - float b_f; - float c_f; - float discriminant; - float sqrt_disc; - float t_candidates[2]; - float height; - float ti; - float denom; - float t_cap; - float crb; - t_vec sub; - t_vec oc; - t_vec nor_cyl; - t_vec a; - t_vec b; - t_vec p; - t_vec p_b; - t_vec cap_center; - t_vec mul; - t_vec lp; -} t_cybag; - typedef struct s_hit_record { float t; @@ -190,8 +161,70 @@ typedef struct s_hit_record t_vec normal; t_shapes *object; bool hit; + bool is_cap; } t_hit_record; +typedef struct s_cybag +{ + int i; + float t1; + float t2; + float radius; + float a_f; + float b_f; + float c_f; + float discriminant; + float sqrt_disc; + float t_candidates[2]; + float height; + float ti; + float denom; + float t_cap; + float t_body; + float crb; + float sign; + float half_h; + t_vec sub; + t_vec oc; + t_vec nor_cyl; + t_vec a; + t_vec b; + t_vec p; + t_vec p_b; + t_vec cap_center; + t_vec mul; + t_vec lp; + t_hit_record rec_body; + t_hit_record rec_cap; + t_vec to_point; + t_vec projection; +} t_cybag; + +typedef struct s_cap_bag +{ + t_vec cap_center; + t_vec dist; + t_vec lp; + t_vec cap_normal; + t_vec sub; + float t_cap; + float half_h; + float denom; + int i; + float r2; + float bias; + float sign; +} t_cap_bag; + +typedef struct s_cap_hit_ctx +{ + t_cap_bag *cb; + t_cybag *b; + t_shapes *shp; + t_ray ray; + t_hit_record *hit; +} t_cap_hit_ctx; + void do_j_bzero(t_obag *ob); void init_tobag(t_obag *obag); @@ -252,19 +285,20 @@ void iter_pl(t_data *data, char *tmp, t_shapes *pl_shape); void iter_sp(t_data *data, char *tmp, t_shapes *sp_shape); void iter_cy(t_data *data, char *tmp, t_shapes *cy_shape); void move_cp_buf(char *tmp, t_obag *ob); -float process_cy_cap(t_cybag b, t_shapes *shp, t_ray ray); +float process_cy_cap(t_cybag b, t_shapes *shp, t_ray ray, t_hit_record *rec); float process_cy_body(t_cybag b, t_shapes *shp, t_ray ray); /*rays*/ t_ray shoot_ray(int x, int y, t_data *data); bool ray_inter_sp(t_ray ray, t_shapes *shp, float *t); bool ray_inter_pl(t_ray ray, t_shapes *shp, float *t); -bool ray_inter_cy(t_ray ray, t_shapes *shp, float *t); +bool ray_inter_cy(t_ray ray, t_shapes *shp, float *t, t_hit_record *rec); void cast_rays(t_data *data); /*hit*/ bool hit_objects(t_data *data, t_ray ray, t_hit_record *rec); bool is_in_shadow(t_data *data, t_vec point, t_vec light_pos, t_vec normal); +void resolve_hit(t_hit_record *rec, float t, t_ray ray, t_shapes *shp); /*colors*/ int make_color(t_rgb rgb); @@ -273,6 +307,8 @@ t_rgb shader(t_rgb color, t_data *data, t_hit_record *rec); t_rgb calculate_diffuse(t_data *data, t_vec dir, t_rgb color, t_hit_record *rec); t_rgb calculate_ambient(t_data *data, t_shapes *shp); +t_sbag colors_in_shadow(t_rgb *color, t_data *data, t_hit_record *rec, + t_sbag *sb); /*validator*/ bool check_line(char *line, t_obag *bag); @@ -289,4 +325,10 @@ bool validate_cylindr(char **tokens, const int count); bool validate_rgb(const char *token); bool validate_orientation(const char *tokens); +void remove_comment(char *line); + +/*cy_utils*/ +void calculate_cy_bag(t_cybag *b, t_shapes *shp, t_ray ray); +void handle_cy_body(t_cybag *b, t_shapes *shp, t_ray ray); + #endif diff --git a/include/mlx_utils.h b/include/mlx_utils.h index c84ec17..2a6d66c 100644 --- a/include/mlx_utils.h +++ b/include/mlx_utils.h @@ -19,10 +19,16 @@ # define KEY_ESC 65307 # define A_KEY_UP 237 # define A_KEY_DWN 233 -# define L_KEY_A_L 97 -# define L_KEY_D_R 100 -# define L_KEY_S_B 115 -# define L_KEY_W_U 119 + +# define C_ORI_A_L 97 +# define C_ORI_D_R 100 +# define C_ORI_S_B 115 +# define C_ORI_W_U 119 + +# define L_KEY_A_L 106 +# define L_KEY_D_R 108 +# define L_KEY_S_B 107 +# define L_KEY_W_U 105 # define L_KEY_X_F 120 # define L_KEY_Y_B 121 # define C_KEY_UP 65362 diff --git a/main.c b/main.c index 8d143bc..ce90a94 100644 --- a/main.c +++ b/main.c @@ -37,14 +37,12 @@ void do_hit(t_ray ray, t_hit_record *rec, float *closest_t, t_shapes *shp) *closest_t = t; resolve_hit(rec, t, ray, shp); rec->normal = normalize(shp->axis); + if (vec_dot(&rec->normal, &ray.dir) > 0.0f) + rec->normal = scale(rec->normal, -1.0f); } if ((ft_strncmp(shp->identifier, "cy", 2) == 0) - && (ray_inter_cy(ray, shp, &t) && t < *closest_t)) - { + && (ray_inter_cy(ray, shp, &t, rec) && t < *closest_t)) *closest_t = t; - resolve_hit(rec, t, ray, shp); - rec->normal = normalize(vec_sub(rec->point, shp->cords)); - } } bool hit_objects(t_data *data, t_ray ray, t_hit_record *rec) @@ -104,11 +102,13 @@ int main(int argc, char *argv[]) if (init_mlx_window(data) == -1) exit(-1); cast_rays(data); - mlx_key_hook(data->win_ptr, &key_mapping, (void *)data); + mlx_hook(data->win_ptr, 2, 1L << 0, &key_mapping, data); mlx_hook(data->win_ptr, 33, 1L << 17, &mlx_loop_end, data->mlx_ptr); mlx_loop(data->mlx_ptr); + mlx_destroy_image(data->mlx_ptr, data->scene_img[data->frame % 2]->ptr); mlx_destroy_window(data->mlx_ptr, data->win_ptr); mlx_destroy_display(data->mlx_ptr); + free(data->mlx_ptr); free_data(data); return (0); } diff --git a/multiobject.rt b/multiobject.rt index 11275d4..1d5acd6 100644 --- a/multiobject.rt +++ b/multiobject.rt @@ -1,10 +1,9 @@ A 0.5 255,255,255 -C 0.0,-2.0,8.0 0,0,1 70 -L 40,-75,100 0.8 255,255,255 +C 0.0,-2.0,8.0 0,0,-1 70 +L 40,-75,10 0.8 255,255,255 sp 2,-1,0 1.8 216,56,136 sp 2,-0.2,0 1.8 140,118,206 sp 0,2,0 1.4 216,56,136 -sq -1,0,-0.5 1,0,0 4 0,176,240 -sq 2,0,-0.5 1,0,0 4 0,176,240 cy 0,-2,0 0,1,0 0.8 4 255,204,0 -cy -3,0.6,0 1,0,0 0.8 7 255,204,0 \ No newline at end of file +cy -3,0.6,0 1,0,0 0.8 7 255,204,0 +# \ No newline at end of file diff --git a/multiobject2.rt b/multiobject2.rt index 7439fe3..a6ae77c 100644 --- a/multiobject2.rt +++ b/multiobject2.rt @@ -8,8 +8,5 @@ sp 0,2,0 1.4 216,56,136 pl 0,-2,0 0,1,0 140,118,206 -sq -1,0,-0.5 1,0,0 4 0,176,240 -sq 2,0,-0.5 1,0,0 4 0,176,240 - -cy 0,-1,0 0,2,0 0.8 4 255,204,0 -cy 0,0.6,0 1,2,0 0.8 7 255,204,0 \ No newline at end of file +cy 0,-1,0 0,1,0 0.8 4 255,204,0 +cy 0,0.6,0 1,0,0 0.8 7 255,204,0 \ No newline at end of file diff --git a/src/colors.c b/src/colors.c index 9841060..207bd62 100644 --- a/src/colors.c +++ b/src/colors.c @@ -1,3 +1,15 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* colors.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: voparkan +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/06/07 12:28:10 by voparkan #+# #+# */ +/* Updated: 2025/06/07 14:33:25 by voparkan ### ########.fr */ +/* */ +/* ************************************************************************** */ + /* ************************************************************************** */ /* */ /* ::: :::::::: */ @@ -54,6 +66,8 @@ bool is_in_shadow(t_data *data, t_vec point, t_vec light_pos, t_vec normal) t_hit_record tmp; double hit_dist; + if (data->scene->ambi.ratio == 1) + return (false); to_light = vec_sub(light_pos, point); light_dist = vec_length(to_light); shadow_ray.origin = add(point, scale(normal, 1e-3)); diff --git a/src/exit.c b/src/exit.c index 32351a0..e0ae68a 100644 --- a/src/exit.c +++ b/src/exit.c @@ -12,15 +12,6 @@ #include "../include/minirt.h" -void free_imgs(void *shp) -{ - t_shapes *shape; - - shape = (t_shapes *)shp; - if (shape->img.mlx_ptr != NULL) - free(shape->img.ptr); -} - void free_lines(char **lines) { int i; @@ -47,6 +38,26 @@ void free_data(t_data *data) ft_lstclear(&data->shapes, &free); if (data->scene) free(data->scene); - close(data->scenefd); + if (data->scenefd != -1) + { + close(data->scenefd); + data->scenefd = -1; + } free(data); } + +int min(int a, int b) +{ + if (a < b) + return (a); + else + return (b); +} + +int max(int a, int b) +{ + if (a > b) + return (a); + else + return (b); +} diff --git a/src/init.c b/src/init.c index 63d94b2..1426be6 100644 --- a/src/init.c +++ b/src/init.c @@ -54,15 +54,18 @@ int init_program(t_data *data, int argc, char **argv) if (argc != 2) { perror("You must provide a file name of scene"); + free_data(data); return (-1); } data->filename = argv[1]; - data->frame = 1; + data->frame = 0; check_filename(data); check_file_empty(data); init_scene(data); data->scene_img[0] = malloc(sizeof(t_img)); + check_scene_alloc(data, data->scene_img[0]); data->scene_img[1] = malloc(sizeof(t_img)); + check_scene_alloc(data, data->scene_img[1]); init_objects(data); printf("INIT data->frame: %d\n", data->frame); return (0); diff --git a/src/parser.c b/src/parser.c index 58bc342..b40ecb3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -12,7 +12,7 @@ #include "../include/minirt.h" -bool process_line(char *line, t_obag *bag, char ***lines) +bool process_line(char *line, t_obag *bag, char **lines, int *line_idx) { char *dup; @@ -21,8 +21,8 @@ bool process_line(char *line, t_obag *bag, char ***lines) dup = ft_strdup(line); if (!dup) return (false); - **lines = dup; - (*lines)++; + lines[*line_idx] = dup; + (*line_idx)++; return (true); } @@ -49,64 +49,62 @@ int read_next_line(int fd, char *line_buf, int *i) return (bytes_read); } -static void cleanup_and_exit(t_data *data, char **current, - char **start, char *error_message) +void cleanup_and_exit(t_data *data, char **lines, char *msg) { - *current = NULL; - free_lines(start); + free_lines(lines); free_data(data); - exit_error(error_message); + exit_error(msg); } // bag is used here to store camera, ambient and light counts -void do_lines(t_data *data, char ***lines) +void do_lines(t_data *data, char **lines) { char line[1024]; t_obag bag; int i; - char **current; + int line_idx; int read_state; i = 0; bag = (t_obag){0}; - current = *lines; + line_idx = 0; while (true) { read_state = read_next_line(data->scenefd, line, &i); - if (read_state == 0) + if (read_state == -1) + cleanup_and_exit(data, lines, "Couldn't read scene"); + if (read_state == 0 && i == 0) break ; - else if (read_state == -1) - cleanup_and_exit(data, current, *lines, "Couldn't read scene"); - if (i == 0) + remove_comment(line); + if (line[0] == '\0') continue ; - if (!process_line(line, &bag, ¤t)) - cleanup_and_exit(data, current, *lines, "Invalid scene line"); + if (!process_line(line, &bag, lines, &line_idx)) + cleanup_and_exit(data, lines, "Invalid scene line"); } + lines[line_idx] = NULL; if (!handle_identifiers(bag.i, bag.j, bag.k)) - cleanup_and_exit(data, current, *lines, "Invalid scene line"); - *current = NULL; + cleanup_and_exit(data, lines, "Invalid scene line"); } void init_scene(t_data *data) { char **lines; - char **tmp; int lc; lc = line_count(data->filename); - lines = malloc((lc + 1) * sizeof(char *)); - lines[lc] = NULL; + lines = malloc((lc + 2) * sizeof(char *)); + check_scene_alloc(data, lines); + lines[0] = NULL; data->scenefd = open(data->filename, O_RDONLY); if (data->scenefd == -1) { - free(data); + free(lines); + free_data(data); exit_error("Error opening file"); } - check_scene_alloc(data, lines); - tmp = lines; - do_lines(data, &lines); + do_lines(data, lines); close(data->scenefd); - data->lines = tmp; - print_lines(&tmp); + data->lines = lines; + print_lines(&lines); construct_scene(data); } diff --git a/src/shader.c b/src/shader.c index b2da791..781e0ac 100644 --- a/src/shader.c +++ b/src/shader.c @@ -26,40 +26,36 @@ t_rgb shader(t_rgb color, t_data *data, t_hit_record *rec) t_sbag sb; sb.l_dir = normalize(vec_sub(data->scene->lght.cords, rec->point)); - sb.factor = fmax(0.0, vec_dot(&rec->normal, &sb.l_dir)); + if (ft_strncmp(rec->object->identifier, "cy", 2)) + sb.factor = fmin(0.5, vec_dot(&rec->normal, &sb.l_dir)); + else + sb.factor = 1.0f; sb.mix_color = calculate_ambient(data, rec->object); if (is_in_shadow(data, rec->point, data->scene->lght.cords, rec->normal)) - { - sb.softness = 0.2f + 0.5f * fmax(0.0, vec_dot(&rec->normal, &sb.l_dir)); - sb.visibility = 0.2f; - sb.factor *= sb.visibility; - sb.diffuse = calculate_diffuse(data, sb.l_dir, color, rec); - sb.diffuse.r *= sb.softness; - sb.diffuse.g *= sb.softness; - sb.diffuse.b *= sb.softness; - } + sb = colors_in_shadow(&color, data, rec, &sb); else sb.diffuse = calculate_diffuse(data, sb.l_dir, color, rec); - sb.mix_color.r = min(sb.mix_color.r * 0.4f + sb.diffuse.r * sb.factor, 255); - sb.mix_color.g = min(sb.mix_color.g * 0.4f + sb.diffuse.g * sb.factor, 255); - sb.mix_color.b = min(sb.mix_color.b * 0.4f + sb.diffuse.b * sb.factor, 255); + sb.mix_color.r = min(sb.mix_color.r * data->scene->ambi.ratio + + sb.diffuse.r * sb.factor, 255); + sb.mix_color.g = min(sb.mix_color.g * data->scene->ambi.ratio + + sb.diffuse.g * sb.factor, 255); + sb.mix_color.b = min(sb.mix_color.b * data->scene->ambi.ratio + + sb.diffuse.b * sb.factor, 255); return (sb.mix_color); } -int min(int a, int b) +t_sbag + colors_in_shadow(t_rgb *color, t_data *data, t_hit_record *rec, t_sbag *sb) { - if (a < b) - return (a); - else - return (b); -} - -int max(int a, int b) -{ - if (a > b) - return (a); - else - return (b); + (*sb).softness = 0.2f + 0.5f * fmin(0.2, + vec_dot(&rec->normal, &(*sb).l_dir)); + (*sb).visibility = 0.9f; + (*sb).factor *= (*sb).visibility; + (*sb).diffuse = calculate_diffuse(data, (*sb).l_dir, (*color), rec); + (*sb).diffuse.r *= (*sb).softness; + (*sb).diffuse.g *= (*sb).softness; + (*sb).diffuse.b *= (*sb).softness; + return (*sb); } void mrt_put_pixel(t_img *img, int x, int y, int color) diff --git a/src/validate.c b/src/validate.c index d377b15..8216b1f 100644 --- a/src/validate.c +++ b/src/validate.c @@ -51,8 +51,7 @@ bool handle_identifiers(int camera_count, int light_count, int ambient_count) bool is_valid_identifier(const char *id) { return (!strcmp(id, "A") || !strcmp(id, "C") || !strcmp(id, "L") - || !strcmp(id, "sp") || !strcmp(id, "pl") || !strcmp(id, "cy") - || !strcmp(id, "#")); + || !strcmp(id, "sp") || !strcmp(id, "pl") || !strcmp(id, "cy")); } bool validate_tokens(char **tokens) diff --git a/src/validate_params.c b/src/validate_params.c index 95ae7f7..e2c8023 100644 --- a/src/validate_params.c +++ b/src/validate_params.c @@ -91,3 +91,12 @@ bool validate_ambient(char **tokens, const int count) } return (true); } + +void remove_comment(char *line) +{ + char *hash; + + hash = strchr(line, '#'); + if (hash) + *hash = '\0'; +} diff --git a/src/vec/cy_utils.c b/src/vec/cy_utils.c index 41e5ba5..c1aec63 100644 --- a/src/vec/cy_utils.c +++ b/src/vec/cy_utils.c @@ -1,43 +1,70 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ray.c :+: :+: :+: */ +/* cy_utils.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: aevstign +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/05/11 11:29:07 by aevstign #+# #+# */ -/* Updated: 2025/05/14 19:13:33 by aevstign ### ########.fr */ +/* Created: 2025/05/31 13:12:32 by voparkan #+# #+# */ +/* Updated: 2025/05/31 14:15:30 by voparkan ### ########.fr */ /* */ /* ************************************************************************** */ #include "../../include/vec.h" #include "../../include/minirt.h" -float process_cy_cap(t_cybag b, t_shapes *shp, t_ray ray) +static void check_cy_cap_hit(t_cap_hit_ctx ctx) { - b.i = 0; - while (b.i < 2) + ctx.cb->cap_center = add(ctx.shp->cords, + scale(ctx.b->nor_cyl, ctx.cb->sign * ctx.cb->half_h)); + ctx.cb->denom = vec_dot(&ctx.ray.dir, &ctx.b->nor_cyl); + if (fabs(ctx.cb->denom) < 0.00001f) + return ; + ctx.cb->sub = vec_sub(ctx.cb->cap_center, ctx.ray.origin); + ctx.cb->t_cap = vec_dot(&ctx.cb->sub, &ctx.b->nor_cyl) / ctx.cb->denom; + if (ctx.cb->t_cap < 0.0f) + return ; + ctx.cb->lp = add(ctx.ray.origin, scale(ctx.ray.dir, ctx.cb->t_cap)); + ctx.cb->dist = vec_sub(ctx.cb->lp, ctx.cb->cap_center); + if (vec_dot(&ctx.cb->dist, &ctx.cb->dist) > ctx.cb->r2 + || ctx.cb->t_cap >= ctx.hit->t) + return ; + ctx.cb->cap_normal = normalize(scale(ctx.b->nor_cyl, ctx.cb->sign)); + if (vec_dot(&ctx.ray.dir, &ctx.cb->cap_normal) > 0.0f) + ctx.cb->cap_normal = scale(ctx.cb->cap_normal, -1.0f); + ctx.hit->t = ctx.cb->t_cap; + ctx.hit->normal = ctx.cb->cap_normal; + ctx.hit->point = add(ctx.cb->lp, scale(ctx.cb->cap_normal, ctx.cb->bias)); + ctx.hit->is_cap = true; + ctx.hit->object = ctx.shp; + ctx.hit->hit = true; +} + +float process_cy_cap(t_cybag b, t_shapes *shp, t_ray ray, t_hit_record *hit) +{ + t_cap_bag cb; + t_cap_hit_ctx ctx; + int i; + + cb.r2 = (shp->diameter * 0.5f) * (shp->diameter * 0.5f); + cb.bias = 0.0001f; + cb.half_h = shp->height * 0.5f; + b.nor_cyl = normalize(shp->axis); + hit->t = FLT_MAX; + hit->hit = false; + ctx = (t_cap_hit_ctx){&cb, &b, shp, ray, hit}; + i = 0; + while (i < 2) { - b.cap_center = add(shp->cords, scale(b.nor_cyl, b.i * shp->height)); - b.denom = vec_dot(&ray.dir, &b.nor_cyl); - if (fabs(b.denom) < EPSILON) - { - b.i++; - continue ; - } - b.sub = vec_sub(b.cap_center, ray.origin); - b.t_cap = vec_dot(&b.sub, &b.nor_cyl) / b.denom; - if (b.t_cap < 0) - { - b.i++; - continue ; - } - b.mul = scale(ray.dir, b.t_cap); - b.lp = add(ray.origin, b.mul); - if (vec_length(vec_sub(b.lp, b.cap_center)) <= b.radius) - return (b.t_cap); - b.i++; + if (i == 0) + cb.sign = -1.0f; + else + cb.sign = 1.0f; + check_cy_cap_hit(ctx); + i++; } + if (hit->hit) + return (hit->t); return (-1.0f); } @@ -55,9 +82,38 @@ float process_cy_body(t_cybag b, t_shapes *shp, t_ray ray) b.p = add(ray.origin, scale(ray.dir, b.ti)); b.p_b = vec_sub(b.p, shp->cords); b.height = vec_dot(&b.p_b, &b.nor_cyl); - if (b.height >= 0 && b.height <= shp->height) + if (b.height >= -shp->height / 2.0f && b.height <= shp->height / 2.0f) return (b.ti); ++b.i; } return (-1.0f); } + +void calculate_cy_bag(t_cybag *b, t_shapes *shp, t_ray ray) +{ + b->t_body = -1.0f; + b->t_cap = -1.0f; + b->radius = shp->diameter / 2.0f; + b->nor_cyl = normalize(shp->axis); + b->oc = vec_sub(ray.origin, shp->cords); + b->a = vec_sub(ray.dir, scale(b->nor_cyl, vec_dot(&ray.dir, &b->nor_cyl))); + b->b = vec_sub(b->oc, scale(b->nor_cyl, vec_dot(&b->oc, &b->nor_cyl))); + b->a_f = vec_dot(&b->a, &b->a); + b->b_f = 2.0f * vec_dot(&b->a, &b->b); + b->c_f = vec_dot(&b->b, &b->b) - b->radius * b->radius; + b->discriminant = b->b_f * b->b_f - 4 * b->a_f * b->c_f; +} + +void handle_cy_body(t_cybag *b, t_shapes *shp, t_ray ray) +{ + t_vec to_point; + t_vec projection; + + b->t_body = process_cy_body(*b, shp, ray); + if (b->t_body <= 0.0f) + return ; + resolve_hit(&b->rec_body, b->t_body, ray, shp); + to_point = vec_sub(b->rec_body.point, shp->cords); + projection = scale(b->nor_cyl, vec_dot(&to_point, &b->nor_cyl)); + b->rec_body.normal = normalize(vec_sub(to_point, projection)); +} diff --git a/src/vec/ray.c b/src/vec/ray.c index 54c6118..337c91c 100644 --- a/src/vec/ray.c +++ b/src/vec/ray.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ray.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: aevstign +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/05/11 11:29:07 by aevstign #+# #+# */ -/* Updated: 2025/05/14 19:13:33 by aevstign ### ########.fr */ +/* Created: 2025/05/31 13:12:32 by voparkan #+# #+# */ +/* Updated: 2025/05/31 15:57:10 by voparkan ### ########.fr */ /* */ /* ************************************************************************** */ @@ -73,41 +73,36 @@ bool ray_inter_pl(t_ray ray, t_shapes *shp, float *t) return (*t > 0.001f); } -void calculate_cy_bag(t_cybag *b, t_shapes *shp, t_ray ray) +void prepare_cy_intersect(t_cybag *b, t_shapes *shp, t_ray ray) { - b->radius = shp->diameter / 2; - b->oc = vec_sub(ray.origin, shp->cords); - b->nor_cyl = normalize(shp->cords); - b->a = vec_sub(ray.dir, scale(b->nor_cyl, vec_dot(&ray.dir, &b->nor_cyl))); - b->b = vec_sub(b->oc, scale(b->nor_cyl, vec_dot(&b->oc, &b->nor_cyl))); - b->a_f = vec_dot(&b->a, &b->a); - b->b_f = 2.0f * vec_dot(&b->a, &b->b); - b->c_f = vec_dot(&b->b, &b->b) - b->radius * b->radius; - b->discriminant = b->b_f * b->b_f - 4 * b->a_f * b->c_f; + calculate_cy_bag(b, shp, ray); + if (b->discriminant < 0.0f) + return ; + b->sqrt_disc = sqrtf(b->discriminant); + b->t1 = (-b->b_f - b->sqrt_disc) / (2.0f * b->a_f); + b->t2 = (-b->b_f + b->sqrt_disc) / (2.0f * b->a_f); + b->t_candidates[0] = b->t1; + b->t_candidates[1] = b->t2; } -bool ray_inter_cy(t_ray ray, t_shapes *shp, float *t) +bool ray_inter_cy(t_ray ray, t_shapes *shp, float *t, t_hit_record *rec) { t_cybag b; - calculate_cy_bag(&b, shp, ray); - if (b.discriminant < 0) - return (false); - b.sqrt_disc = sqrtf(b.discriminant); - b.t1 = (-b.b_f - b.sqrt_disc) / (2 * b.a_f); - b.t2 = (-b.b_f + b.sqrt_disc) / (2 * b.a_f); - b.t_candidates[0] = b.t1; - b.t_candidates[1] = b.t2; - b.crb = process_cy_body(b, shp, ray); - if (b.crb > 0) + prepare_cy_intersect(&b, shp, ray); + if (b.discriminant >= 0.0f) + handle_cy_body(&b, shp, ray); + b.t_cap = process_cy_cap(b, shp, ray, &b.rec_cap); + if (b.t_body > 0.0f && (b.t_cap < 0.0f || b.t_body < b.t_cap)) { - *t = b.crb; + *rec = b.rec_body; + *t = b.t_body; return (true); } - b.crb = process_cy_cap(b, shp, ray); - if (b.crb > 0) + if (b.t_cap > 0.0f) { - *t = b.crb; + *rec = b.rec_cap; + *t = b.t_cap; return (true); } return (false); diff --git a/src/window.c b/src/window.c index 327c146..8dedb5d 100644 --- a/src/window.c +++ b/src/window.c @@ -18,6 +18,7 @@ int init_mlx_window(t_data *data) if (!data->mlx_ptr) { perror("Error mlx_init()\n"); + free_data(data); return (-1); } data->win_ptr = mlx_new_window(data->mlx_ptr, WIN_WIDTH, WIN_HEIGHT, @@ -25,6 +26,7 @@ int init_mlx_window(t_data *data) if (!data->win_ptr) { perror("Error mlx_new_window()\n"); + free_data(data); return (-1); } return (0); @@ -34,7 +36,10 @@ void resolve_light_move(t_data *data, int key, bool *cast) { if (key == L_KEY_A_L || key == L_KEY_D_R || key == L_KEY_S_B || key == L_KEY_W_U) + { *cast = true; + data->frame++; + } if (key == L_KEY_A_L) data->scene->lght.cords.x -= 1; if (key == L_KEY_D_R) @@ -45,6 +50,39 @@ void resolve_light_move(t_data *data, int key, bool *cast) data->scene->lght.cords.y += 1; } +static void make_cam_move(t_data *data, int key) +{ + if (key == C_ORI_W_U) + data->scene->cam.cords.z -= 0.1f; + if (key == C_ORI_S_B) + data->scene->cam.cords.z += 0.1f; + if (key == C_ORI_A_L) + data->scene->cam.cords.x += 0.1f; + if (key == C_ORI_D_R) + data->scene->cam.cords.x -= 0.1f; + if (key == C_KEY_UP) + data->scene->cam.orient.y += 0.1f; + if (key == C_KEY_DOWN) + data->scene->cam.orient.y -= 0.1f; + if (key == C_KEY_LEFT) + data->scene->cam.orient.x -= 0.1f; + if (key == C_KEY_RIGHT) + data->scene->cam.orient.x += 0.1f; +} + +void resolve_camera_move(t_data *data, int key, bool *cast) +{ + if (key == C_KEY_UP || key == C_KEY_DOWN || key == C_KEY_LEFT + || key == C_KEY_RIGHT || key == C_ORI_W_U || key == C_ORI_S_B + || key == C_ORI_A_L || key == C_ORI_D_R || key == 92 || key == 121) + { + *cast = true; + data->frame++; + } + make_cam_move(data, key); + data->scene->cam.orient = normalize(data->scene->cam.orient); +} + int key_mapping(int key, void *params) { bool cast; @@ -55,15 +93,10 @@ int key_mapping(int key, void *params) data = (t_data *) params; frame_n = data->frame % 2; if (key == KEY_ESC || key == 17 || key == 53) - { - mlx_destroy_image(data->mlx_ptr, data->scene_img[frame_n]->ptr); - mlx_destroy_window(data->mlx_ptr, data->win_ptr); - mlx_destroy_display(data->mlx_ptr); - free(data->mlx_ptr); - free_data(data); - exit(0); - } + mlx_loop_end(data->mlx_ptr); resolve_light_move(data, key, &cast); + resolve_camera_move(data, key, &cast); + printf("key: %d\n", key); if (cast) { cast_rays(data); diff --git a/test1.rt b/test1.rt index abbe99e..9a57250 100644 --- a/test1.rt +++ b/test1.rt @@ -1,4 +1,4 @@ A 0.5 255,255,255 L 0,4,4 0.1 255,255,255 C 0,0,8 0,0,-1 100 -sp 0,0,0 8 216,56,136 \ No newline at end of file +sp 0,0,0 4 216,56,136 \ No newline at end of file