Added ray casting to significantly improve frame rate

This commit is contained in:
Alexandre 2024-07-03 12:55:57 +02:00
parent 2585ec0556
commit c70cd64e29
7 changed files with 174 additions and 68 deletions

BIN
a.out

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
display.cmx Normal file

Binary file not shown.

View File

@ -5,9 +5,27 @@ Random.self_init () ;;
let __width__ = 1500
and __height__ = 1000 ;;
type tile = Free | Wall | Crate | Exit | Craxit | Camera ;;
let width = 15
and height = 15
and depth = 15 ;;
(* dimensions *)
let render_distance = 7 ;;
let chunk_dist = 2 ;;
let chunk_size = 4 ;;
let chunk_size_f = float_of_int chunk_size ;;
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
(*
ocamlfind ocamlc -linkpkg -package unix -linkpkg -package graphics -thread -package threads -linkpkg display.ml
ocamlfind ocamlopt -linkpkg -package unix -linkpkg -package graphics -thread -package threads -linkpkg display.ml
*)
@ -111,7 +129,7 @@ let parse_texture filename =
tex
| exn -> close_in ptr ; raise exn ;;
let stone = parse_texture "texture404.txt" ;;
let stone = parse_texture "output.txt" ;;
(* ------------------------------------------------------------- *)
(* ------------------------------------------------------------- *)
@ -249,6 +267,14 @@ let adjust_to_camera (shape : pt_3d array) =
(*debug_1 res2 ;*)
res2 ;;
let adjust_pt (pt : pt_3d) =
let tpt = {x = pt.x +. camera_xyz.x ; y = pt.y +. camera_xyz.y ; z = pt.z -. camera_xyz.z} in
{
x = tpt.x *. Float.cos ((float_of_int !camera_angle_y) *. 3.14159255358 /. 180.) +. tpt.z *. Float.sin ((float_of_int !camera_angle_y) *. 3.14159255358 /. 180.);
y = tpt.y;
z = tpt.z *. Float.cos ((float_of_int !camera_angle_y) *. 3.14159255358 /. 180.) -. tpt.x *. Float.sin ((float_of_int !camera_angle_y) *. 3.14159255358 /. 180.)
} ;;
let sq x = x *. x ;;
let dist_from_camera (p : pt_3d) =
@ -282,34 +308,150 @@ let convex_pt (p1 : int * int) (p2 : int * int) theta maxtheta =
and mid_y = int_of_float ((1. -. ratio) *. (float_of_int (snd p1)) +. ratio *. (float_of_int (snd p2))) in
(mid_x, mid_y) ;;
let convex_3d (p1 : pt_3d) (p2 : pt_3d) theta maxtheta =
let ratio = (float_of_int theta) /. (float_of_int maxtheta) in
{
x = (1. -. ratio) *. p1.x +. ratio *. p2.x;
y = (1. -. ratio) *. p1.y +. ratio *. p2.y;
z = (1. -. ratio) *. p1.z +. ratio *. p2.z
} ;;
(*
----\\ WARNING : THIS BIT YIELDS A SEGMENTATION FAULT //-----
exception Out_of_bounds ;;
let get_single_pt pt =
try
Graphics.point_color (fst pt) (snd pt)
with
| Graphics.Graphic_failure _ -> raise Out_of_bounds ;;
let is_hidden (rect : (int * int) array) =
try
let midpt = ((fst rect.(0) + fst rect.(1) + fst rect.(2) + fst rect.(3))/4, (snd rect.(0) + snd rect.(1) + snd rect.(2) + snd rect.(3))/4) in
let color_BL = get_single_pt rect.(0)
and color_BR = get_single_pt rect.(1)
and color_TL = get_single_pt rect.(2)
and color_TR = get_single_pt rect.(3)
and color_C = get_single_pt midpt in
(color_BL = 0) || (color_BR = 0) || (color_TL = 0) || (color_TR = 0) || (color_C = 0)
with
| Out_of_bounds -> false ;;
*)
let ctc_one x =
if x >= 0 then
x / chunk_size
else
x / chunk_size -1 ;;
let ctcf_one x =
if x >= 0. then
int_of_float (x /. chunk_size_f)
else
int_of_float (x /. chunk_size_f) -1 ;;
let coords_to_chunk x y z =
(ctc_one x, ctc_one y, ctc_one z) ;;
let coords_to_chunk_f x y z =
(ctcf_one x, ctcf_one y, ctcf_one z) ;;
(* -------------------------------------------------------------------------------------- *)
let is_in_cube (pt : pt_3d) (cube : pt_3d array) =
(* cube and pt are relative to the camera *)
(*Printf.printf " comparing with cube : (%f, %f, %f)" cube.(0).x cube.(0).y cube.(0).z;
Stdlib.print_endline " ";*)
(cube.(0).x <= pt.x) &&
(cube.(0).y <= pt.y) &&
(cube.(0).z <= pt.z) &&
(cube.(6).x >= pt.x) &&
(cube.(6).y >= pt.y) &&
(cube.(6).z >= pt.z) ;;
let seg_len (p1 : pt_3d) (p2 : pt_3d) =
Float.sqrt ((sq (p1.x -. p2.x)) +. (sq (p1.y -. p2.y)) +. (sq (p1.z -. p2.z))) ;;
exception ReturnBool of bool ;;
let is_visible (pt0 : pt_3d) (hash : (int * int * int, coloredCube dynamic) Hashtbl.t) =
try
let pt = pt0 in
(*Printf.printf " current pt : (%f, %f, %f)\n" pt.x pt.y pt.z;
Printf.printf " camera pt : (%f, %f, %f)\n" (-. camera_xyz.x) (-. camera_xyz.y) camera_xyz.z;*)
let segment_length = dist_from_camera pt in
let n_iter = int_of_float (segment_length /. 1.7) in
(*Printf.printf " distance : %f\n" segment_length;
Printf.printf " n_iter : %d" n_iter;
Stdlib.print_endline " ";*)
for i = 1 to n_iter -1 do
let cur_pt = convex_3d pt {x = -. camera_xyz.x ; y = -. camera_xyz.y ; z = camera_xyz.z} i n_iter in
let (ch_x, ch_y, ch_z) = coords_to_chunk_f cur_pt.x cur_pt.y cur_pt.z in
(*Printf.printf " regarding pt : (%f, %f, %f) in chunk (%d, %d, %d)" cur_pt.x cur_pt.y cur_pt.z ch_x ch_y ch_z;
Stdlib.print_endline " ";*)
let cubes = Hashtbl.find hash (ch_x, ch_y, ch_z) in
for c = 0 to cubes.len -1 do
if is_in_cube cur_pt cubes.tab.(c).cube then
raise (ReturnBool false)
done
done;
(*Stdlib.print_endline " No collision detected";*)
true
with
| Not_found -> (*Stdlib.print_endline " EMPTY"; *)true
| ReturnBool b -> (*Printf.printf " Aborted to %b" b ; Stdlib.print_endline " "; *)b ;;
let is_visible_cube (cube : pt_3d array) (hash : (int * int * int, coloredCube dynamic) Hashtbl.t) =
(*Printf.printf "cube (%f, %f, %f)" cube.(0).x cube.(0).y cube.(0).z;
Printf.printf "[of length %d]" (Array.length cube);
Stdlib.print_endline " ";*)
let res = ref false in
for i = 0 to Array.length cube -1 do
res := !res || (is_visible cube.(i) hash)
done;
(*Printf.printf "yielding %b" !res;
Stdlib.print_endline " "; *)
!res ;;
let draw_texture (rect : (int * int) array) (text : texture) light =
(*set_color white;
fill_poly rect ;;*)
for i = 0 to text.width -1 do
for j = 0 to text.height -1 do
let face_R = int_of_float ((float_of_int text.arr_red.(i).(j)) *. light)
and face_G = int_of_float ((float_of_int text.arr_green.(i).(j)) *. light)
and face_B = int_of_float ((float_of_int text.arr_blue.(i).(j)) *. light) in
set_color (rgb face_R face_G face_B);
if true then begin
let face_R = int_of_float ((float_of_int text.arr_red.(i).(j)) *. light)
and face_G = int_of_float ((float_of_int text.arr_green.(i).(j)) *. light)
and face_B = int_of_float ((float_of_int text.arr_blue.(i).(j)) *. light) in
set_color (rgb face_R face_G face_B);
let pt_a = convex_pt rect.(0) rect.(1) i text.width
and pt_b = convex_pt rect.(0) rect.(1) (i+1) text.width
let pt_a = convex_pt rect.(0) rect.(1) i text.width
and pt_b = convex_pt rect.(0) rect.(1) (i+1) text.width
and pt_e = convex_pt rect.(3) rect.(2) (i+1) text.width
and pt_f = convex_pt rect.(3) rect.(2) i text.width in
and pt_e = convex_pt rect.(3) rect.(2) (i+1) text.width
and pt_f = convex_pt rect.(3) rect.(2) i text.width in
let bot_left = convex_pt pt_a pt_f j text.height
and bot_right = convex_pt pt_b pt_e j text.height
and top_left = convex_pt pt_a pt_f (j+1) text.height
and top_right = convex_pt pt_b pt_e (j+1) text.height in
fill_poly [|bot_left; bot_right; top_right; top_left|]
let bot_left = convex_pt pt_a pt_f j text.height
and bot_right = convex_pt pt_b pt_e j text.height
and top_left = convex_pt pt_a pt_f (j+1) text.height
and top_right = convex_pt pt_b pt_e (j+1) text.height in
fill_poly [|bot_left; bot_right; top_right; top_left|]
end
done
done ;;
let draw_cube_p (cube : pt_3d array) screen_wd screen_ht fov r g b =
let draw_cube_p (cube : pt_3d array) (hash : (int * int * int, coloredCube dynamic) Hashtbl.t) screen_wd screen_ht fov r g b =
let adjusted = adjust_to_camera cube in
let (draw_faces, draw_cube) = are_faces_behind adjusted in
if draw_cube then begin
if draw_cube && (is_visible_cube cube hash) then begin
(*Printf.printf "drawing cube (%f, %f, %f)" cube.(0).x cube.(0).y cube.(0).z ;
Stdlib.print_endline " ";*)
let proj = project adjusted screen_wd screen_ht fov in
let graphed = to_graphics proj screen_wd screen_ht in
@ -358,16 +500,16 @@ let draw_cube_p (cube : pt_3d array) screen_wd screen_ht fov r g b =
swap order i !idmax;
swap draw_faces i !idmax;
done;
set_line_width 5;
set_line_width 2;
for i = 0 to 5 do
if draw_faces.(i) then begin
let light = max (0.) (1. -. (distances.(i)) /. 12.5) in
let face_R = int_of_float ((float_of_int r) *. light)
(*let face_R = int_of_float ((float_of_int r) *. light)
and face_G = int_of_float ((float_of_int g) *. light)
and face_B = int_of_float ((float_of_int b) *. light) in
set_color (rgb face_R face_G face_B);
fill_poly order.(i);
(*draw_texture order.(i) stone light ;*)
fill_poly order.(i);*)
draw_texture order.(i) stone light ;
set_color black;
draw_poly_line order.(i);
end
@ -403,7 +545,7 @@ let cube_dist (c : pt_3d array) =
}
in dist_from_camera mid_pt ;;
let draw_multiples_cubes_colored (cubes : pt_3d array dynamic) rs gs bs screen_wd screen_ht fov render_dist =
let draw_multiples_cubes_colored (cubes : pt_3d array dynamic) rs gs bs hash screen_wd screen_ht fov render_dist =
let n = cubes.len in
let distances = Array.make n 0. in
@ -426,11 +568,11 @@ let draw_multiples_cubes_colored (cubes : pt_3d array dynamic) rs gs bs screen_w
done;
for i = 0 to n-1 do
if distances.(i) <= (float_of_int render_dist) then begin
draw_cube_p cubes.tab.(i) screen_wd screen_ht fov rs.tab.(i) gs.tab.(i) bs.tab.(i)
draw_cube_p cubes.tab.(i) hash screen_wd screen_ht fov rs.tab.(i) gs.tab.(i) bs.tab.(i)
end
done ;;
let draw_multiples_cubes_colored_hash (dyna : coloredCube dynamic) screen_wd screen_ht fov =
let draw_multiples_cubes_colored_hash (dyna : coloredCube dynamic) (hash : (int * int * int, coloredCube dynamic) Hashtbl.t) screen_wd screen_ht fov =
let n = dyna.len in
(*Printf.printf ">> %d <<" n;
@ -457,7 +599,7 @@ let draw_multiples_cubes_colored_hash (dyna : coloredCube dynamic) screen_wd scr
for i = 0 to n-1 do
(*Printf.printf "drawing (%f, %f, %f)" (dyna.tab.(i).cube.(0).x) (dyna.tab.(i).cube.(0).y) (dyna.tab.(i).cube.(0).z);
Stdlib.print_endline " ";*)
draw_cube_p (dyna.tab.(i).cube) screen_wd screen_ht fov (dyna.tab.(i).red) (dyna.tab.(i).green) (dyna.tab.(i).blue)
draw_cube_p (dyna.tab.(i).cube) hash screen_wd screen_ht fov (dyna.tab.(i).red) (dyna.tab.(i).green) (dyna.tab.(i).blue)
done ;;
let create_cube x0' y0' z0' sz' =
@ -519,24 +661,6 @@ let get1char () =
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
type tile = Free | Wall | Crate | Exit | Craxit | Camera ;;
let width = 15
and height = 15
and depth = 15 ;;
(* dimensions *)
let render_distance = 7 ;;
let chunk_dist = 2 ;;
let chunk_size = 4 ;;
let chunk_size_f = float_of_int chunk_size ;;
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
(* -------------------------------------------------------------------------------------------------------- *)
let laby = Array.make width [|[||]|] ;;
for i = 0 to width -1 do
laby.(i) <- Array.make_matrix height depth Wall
@ -544,24 +668,6 @@ done ;;
let n_walls = ref (width*height*depth) ;;
let ctc_one x =
if x >= 0 then
x / chunk_size
else
x / chunk_size -1 ;;
let ctcf_one x =
if x >= 0. then
int_of_float (x /. chunk_size_f)
else
int_of_float (x /. chunk_size_f) -1 ;;
let coords_to_chunk x y z =
(ctc_one x, ctc_one y, ctc_one z) ;;
let coords_to_chunk_f x y z =
(ctcf_one x, ctcf_one y, ctcf_one z) ;;
let is_collision_cube (cam_coords : pt_3d) (cube : pt_3d array) =
cube.(0).x <= (-. cam_coords.x) &&
cube.(0).y <= (-. cam_coords.y) &&
@ -775,7 +881,7 @@ let cheesify (laby : tile array array array) =
done
done
done;;
(*
(* z q s d for movement, p to go up, m to go down, a to rotate left, e to rotate right *)
let rec move_cam (cubes : pt_3d array array) b c =(* Printf.printf "[%b]" b; Stdlib.print_endline " " ; *)match c with
| 'z' ->
@ -821,7 +927,7 @@ let play laby =
fill_poly [|(0, 0); (1500, 0); (1500, 1000); (0, 1000); (0, 0)|];
set_color white;
draw_multiples_cubes_colored cs rs gs bs __width__ __height__ fov render_distance ;
draw_multiples_cubes_colored cs rs gs bs hash __width__ __height__ fov render_distance ;
auto_synchronize true;
@ -830,7 +936,7 @@ let play laby =
let usr_input = get1char () in
move_cam cs.tab true usr_input
done ;;
done ;;*)
let rec move_cam_hash (cubes : coloredCube dynamic) b c =(* Printf.printf "[%b]" b; Stdlib.print_endline " " ; *)match c with
| 'z' ->
@ -936,7 +1042,7 @@ let rec move_cam_hash_2 hash cx cy cz b c =(* Printf.printf "[%b]" b; Stdlib.pri
let manage_unexisting_chunk hash ch_x ch_y ch_z screen_wd screen_ht fov =
try
draw_multiples_cubes_colored_hash (Hashtbl.find hash (ch_x, ch_y, ch_z)) screen_wd screen_ht fov
draw_multiples_cubes_colored_hash (Hashtbl.find hash (ch_x, ch_y, ch_z)) hash screen_wd screen_ht fov
with
| Not_found -> () ;;
@ -952,6 +1058,7 @@ let render_chunks hash camx camy camz ch_distance screen_wd screen_ht fov =
done
done;
let sort_fct elt1 elt2 =
(*- (snd (snd elt2)) + (snd (snd elt1))*)
(snd (snd elt2)) - (snd (snd elt1))
in
@ -987,7 +1094,6 @@ let play_dos laby =
let (ch_x, ch_y, ch_z) = coords_to_chunk_f (-. camera_xyz.x) (-. camera_xyz.y) camera_xyz.z in
(*draw_multiples_cubes_colored_hash (Hashtbl.find hash (ch_x, ch_y, ch_z)) __width__ __height__ fov ;*)
render_chunks hash ch_x ch_y ch_z chunk_dist __width__ __height__ fov ;
auto_synchronize true;

BIN
display.o Normal file

Binary file not shown.

View File

@ -1,3 +1,3 @@
2 2
250,0,250 0,0,0
0,0,0 250,0,250
250,0,250 2,2,2
2,2,2 250,0,250