commit 4a1aba8a71da1fb3d3ec248a50b5116620c3e6c5 Author: Alexandre Date: Sun Jun 30 16:28:02 2024 +0200 Initial commit diff --git a/a.out b/a.out new file mode 100755 index 0000000..d4a9451 Binary files /dev/null and b/a.out differ diff --git a/display.c b/display.c new file mode 100644 index 0000000..f1831d6 --- /dev/null +++ b/display.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void updateRenderer(SDL_Renderer* renderer) { + //printf("E"); + SDL_RenderPresent(renderer); +} + +void resetRenderer(SDL_Renderer* renderer) { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); +} + +void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A) { + SDL_SetRenderDrawColor(renderer, R, G, B, A); + SDL_RenderFillRect(renderer, rect); +} + +void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A) { + SDL_Rect rect; + rect.x = X; + rect.y = Y; + rect.w = W; + rect.h = H; + SDL_SetRenderDrawColor(renderer, R, G, B, A); + SDL_RenderFillRect(renderer, &rect); +} \ No newline at end of file diff --git a/display.cmi b/display.cmi new file mode 100644 index 0000000..7461930 Binary files /dev/null and b/display.cmi differ diff --git a/display.cmo b/display.cmo new file mode 100644 index 0000000..627d725 Binary files /dev/null and b/display.cmo differ diff --git a/display.ml b/display.ml new file mode 100644 index 0000000..832f83b --- /dev/null +++ b/display.ml @@ -0,0 +1,471 @@ +open Graphics ;; +open Tsdl ;; + +Random.self_init () ;; + +(* + +ocamlfind ocamlc -linkpkg -package unix -linkpkg -package graphics -linkpkg -package tsdl -thread -package threads -linkpkg display.ml + +*) + +ignore (Sdl.init Sdl.Init.everything) ;; + +let p = Sdl.fill_rect ;; + +let matrix_mult m1 m2 = + let n = Array.length m1 + and p = Array.length m1.(0) + and r = Array.length m2 + and s = Array.length m2.(0) in + + let mres = Array.make_matrix n s 0 in + + if p <> r then + failwith "ERROR : matrixes cannot be multipied, maybe try with reversed inputs ?\n" + else begin + for i = 0 to n-1 do + for j = 0 to s-1 do + for k = 0 to p do + mres.(i).(j) <- mres.(i).(j) + m1.(i).(k) + m2.(k).(j) + done + done + done + end; + mres ;; + +let abs x = if x >= 0 then x else -x ;; +let absf x = if x >= 0. then x else -.(x) ;; + +(* ------------------------------------------------------------- *) + +type pt_3d = {mutable x : float ; mutable y : float ; mutable z : float} ;; +type pt_2d = {mutable x : float ; mutable y : float} ;; + +(* ------------------------------------------------------------- *) +let camera_xyz = {x = 0.0 ; y = 0.0 ; z = 0.0} ;; +let camera_angle = ref 0 ;; (* in degrees *) +(* ------------------------------------------------------------- *) + +(* +let should_be_drawn (pt : pt_3d) = + let translated = {x = pt.x -. camera_xyz.x; y = pt.y -. camera_xyz.y; z = pt.z +. camera_xyz.z} in + (translated.z *. Float.cos ((float_of_int !camera_angle) *. 3.14159255358 /. 180.) -. translated.x *. Float.sin ((float_of_int !camera_angle) *. 3.14159255358 /. 180.)) > 0. ;; +*) + +let should_be_drawn_gr (pt : pt_3d) = + pt.z > 0.1 ;; + +let sign x = + if x >= 0. then 1. else -. (1.) ;; + +let is_cube_behind_camera (cube : pt_3d array) = + let res = ref true in + for i = 0 to (Array.length cube) -1 do + () + done; + !res ;; + +let debug_1 (smth : pt_3d array) = + for i = 0 to Array.length smth -1 do + Printf.printf "(%f, %f, %f)" smth.(i).x smth.(i).y smth.(i).z; + Stdlib.print_endline ";" + done ; + Stdlib.print_endline " " ;; + +let to_graphics (flat : pt_2d array) screen_wd screen_ht = + let res = Array.make (Array.length flat) (0, 0) in + for k = 0 to (Array.length flat -1) do + let proj_x = int_of_float ((float_of_int screen_wd) *. (1. +. flat.(k).x) /. 2.) + and proj_y = int_of_float ((float_of_int screen_ht) *. (1. +. flat.(k).y) /. 2.) in + (*Printf.printf "Converting to (%d %d)" proj_x proj_y; + Stdlib.print_endline " ";*) + res.(k) <- (proj_x, proj_y); + done; + res ;; + +let draw_pts_2d (flat : pt_2d array) screen_wd screen_ht = + set_color black; + set_line_width 4; + for k = 0 to (Array.length flat -1) do + if absf flat.(k).x <= 1.01 && absf flat.(k).y <= 1.01 then begin + let proj_x = int_of_float ((float_of_int screen_wd) *. (1. +. flat.(k).x) /. 2.) + and proj_y = int_of_float ((float_of_int screen_ht) *. (1. +. flat.(k).y) /. 2.) in + (*Printf.printf "Printing at (%d %d)" proj_x proj_y; + Stdlib.print_endline " ";*) + fill_circle proj_x proj_y 10 + end + done ;; + +let project (shape : pt_3d array) screen_wd screen_ht fov = + let res = Array.make (Array.length shape) {x = 0. ; y = 0.} in + for k = 0 to (Array.length shape -1) do + res.(k) <- {x = 2. ; y = 2.} + done; + let ar = (float_of_int screen_wd) /. (float_of_int screen_ht) in + for k = 0 to (Array.length shape -1) do + if should_be_drawn_gr shape.(k) then begin + res.(k).x <- shape.(k).x /. (ar *. shape.(k).z *. Float.tan (((float_of_int fov) *. 3.14159265358 /. 180.) /. 2.)); + res.(k).y <- shape.(k).y /. (shape.(k).z *. Float.tan (((float_of_int fov) *. 3.14159265358 /. 180.) /. 2.)) + end + else begin + res.(k).x <- (absf shape.(k).x) /. (ar *. (0.1 *. (sign shape.(k).x)) *. Float.tan (((float_of_int fov) *. 3.14159265358 /. 180.) /. 2.)); + res.(k).y <- (absf shape.(k).y) /. ((0.1 *. (sign shape.(k).y)) *. Float.tan (((float_of_int fov) *. 3.14159265358 /. 180.) /. 2.)) + end; + (*Printf.printf "added (%f %f)" res.(k).x res.(k).y; + Stdlib.print_endline " ";*) + done; + res ;; + +let adjust_to_camera (shape : pt_3d array) = + let res = Array.make (Array.length shape) {x = 0.0 ; y = 0.0; z = 0.0} in + for i = 0 to Array.length shape -1 do + res.(i) <- {x = shape.(i).x +. camera_xyz.x ; y = shape.(i).y +. camera_xyz.y ; z = shape.(i).z -. camera_xyz.z} + done; + let res2 = Array.make (Array.length shape) {z =0.0 ; x =0.0 ; y =0.0} in + for i = 0 to Array.length shape -1 do + res2.(i) <- { + x = res.(i).x *. Float.cos ((float_of_int !camera_angle) *. 3.14159255358 /. 180.) +. res.(i).z *. Float.sin ((float_of_int !camera_angle) *. 3.14159255358 /. 180.); + y = res.(i).y; + z = res.(i).z *. Float.cos ((float_of_int !camera_angle) *. 3.14159255358 /. 180.) -. res.(i).x *. Float.sin ((float_of_int !camera_angle) *. 3.14159255358 /. 180.) + } + done; + (*debug_1 res2 ;*) + res2 ;; + +let sq x = x *. x ;; + +let dist_from_camera (p : pt_3d) = + Float.sqrt ((sq (p.x +. camera_xyz.x)) +. (sq (p.y +. camera_xyz.y)) +. (sq (p.z -. camera_xyz.z))) ;; + +let farthest_pt (p1 : pt_3d) (p2 : pt_3d) = + max (dist_from_camera p1) (dist_from_camera p2) ;; + +let swap arr i j = + let temp = arr.(i) in + arr.(i) <- arr.(j); + arr.(j) <- temp ;; + +let draw_cube_p (cube : pt_3d array) screen_wd screen_ht fov r g b = + let proj = project (adjust_to_camera cube) screen_wd screen_ht fov in + + let graphed = to_graphics proj screen_wd screen_ht in + set_color (rgb 192 192 192); + + let distances = [| + max (farthest_pt cube.(0) cube.(1)) (farthest_pt cube.(2) cube.(3)); + max (farthest_pt cube.(4) cube.(5)) (farthest_pt cube.(6) cube.(7)); + max (farthest_pt cube.(0) cube.(1)) (farthest_pt cube.(5) cube.(4)); + max (farthest_pt cube.(1) cube.(2)) (farthest_pt cube.(6) cube.(5)); + max (farthest_pt cube.(2) cube.(3)) (farthest_pt cube.(7) cube.(6)); + max (farthest_pt cube.(3) cube.(0)) (farthest_pt cube.(4) cube.(7)); + |] in + + let order = [| + [|graphed.(0); graphed.(1); graphed.(2); graphed.(3); graphed.(0)|]; + [|graphed.(4); graphed.(5); graphed.(6); graphed.(7); graphed.(4)|]; + [|graphed.(0); graphed.(1); graphed.(5); graphed.(4); graphed.(0)|]; + [|graphed.(1); graphed.(2); graphed.(6); graphed.(5); graphed.(1)|]; + [|graphed.(2); graphed.(3); graphed.(7); graphed.(6); graphed.(2)|]; + [|graphed.(3); graphed.(0); graphed.(4); graphed.(7); graphed.(3)|]; + |] in + + (* Note : edge orders must be as following : + 7--------6 + /| /| + / | / | + 4--------5 | + | | | | + | 3-----|--2 + | / | / + |/ |/ + 0--------1 + *) + + for i = 0 to 5 do + let cur_max = ref distances.(i) in + let idmax = ref i in + for j = i to 5 do + if distances.(j) > !cur_max then begin + cur_max := distances.(j); + idmax := j + end + done; + swap distances i !idmax; + swap order i !idmax; + done; + (*Printf.printf "| "; + for i = 0 to 5 do + Printf.printf "%f " distances.(i) + done; + Stdlib.print_endline "|";*) + set_line_width 5; + for i = 0 to 5 do + let light = max (0.) (1. -. (distances.(i)) /. 7.5) in + 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); + set_color black; + draw_poly_line order.(i); + done ;; + +let sum_x (poly : pt_3d array) = + let res = ref 0. in + for i = 0 to (Array.length poly -1) do + res := !res +. poly.(i).x + done; + !res /. (float_of_int (Array.length poly));; + +let sum_y (poly : pt_3d array) = + let res = ref 0. in + for i = 0 to (Array.length poly -1) do + res := !res +. poly.(i).y + done; + !res /. (float_of_int (Array.length poly));; + +let sum_z (poly : pt_3d array) = + let res = ref 0. in + for i = 0 to (Array.length poly -1) do + res := !res +. poly.(i).z + done; + !res /. (float_of_int (Array.length poly)) ;; + +let cube_dist (c : pt_3d array) = + let mid_pt = { + x = sum_x c; + y = sum_y c; + z = sum_z c + } + in dist_from_camera mid_pt ;; + +let draw_multiples_cubes (cubes : pt_3d array array) screen_wd screen_ht fov = + let n = Array.length cubes in + let new_arr = Array.make n cubes.(0) in + let distances = Array.make n 0. in + for i = 0 to n-1 do + new_arr.(i) <- cubes.(i); + distances.(i) <- cube_dist cubes.(i) + done ; + for i = 0 to n-1 do + let cur_max = ref distances.(i) in + let idmax = ref i in + for j = i to n-1 do + if distances.(j) > !cur_max then begin + cur_max := distances.(j); + idmax := j + end + done; + swap distances i !idmax; + swap new_arr i !idmax; + done; + for i = 0 to n-1 do + draw_cube_p new_arr.(i) screen_wd screen_ht fov 192 192 192 + done ;; + +let draw_multiples_cubes_colored (cubes : pt_3d array array) maxlen rs gs bs screen_wd screen_ht fov = + let n = maxlen in + + let new_arr = Array.make n cubes.(0) + and distances = Array.make n 0. + and reds = Array.make n 0 + and greens = Array.make n 0 + and blues = Array.make n 0 in + + for i = 0 to n-1 do + new_arr.(i) <- cubes.(i); + distances.(i) <- cube_dist cubes.(i); + reds.(i) <- rs.(i); + greens.(i) <- gs.(i); + blues.(i) <- bs.(i) + done ; + for i = 0 to n-1 do + let cur_max = ref distances.(i) in + let idmax = ref i in + for j = i to n-1 do + if distances.(j) > !cur_max then begin + cur_max := distances.(j); + idmax := j; + end + done; + swap distances i !idmax; + swap new_arr i !idmax; + swap reds i !idmax; + swap greens i !idmax; + swap blues i !idmax; + done; + for i = 0 to n-1 do + (*Printf.printf "drawing cube (%f, %f, %f) with distance %f" new_arr.(i).(0).x new_arr.(i).(0).y new_arr.(i).(0).z distances.(i); + Stdlib.print_endline "...";*) + draw_cube_p new_arr.(i) screen_wd screen_ht fov reds.(i) greens.(i) blues.(i) + done ;; + +let create_cube x0' y0' z0' sz' = + let x0 = float_of_int x0' + and y0 = float_of_int y0' + and z0 = float_of_int z0' + and s = float_of_int sz' in + let res = [| + {x = x0 ; y = y0 ; z = z0}; + {x = x0 +. s ; y = y0 ; z = z0}; + {x = x0 +. s ; y = y0 +. s ; z = z0}; + {x = x0 ; y = y0 +. s ; z = z0}; + {x = x0 ; y = y0 ; z = z0 +. s}; + {x = x0 +. s ; y = y0 ; z = z0 +. s}; + {x = x0 +. s ; y = y0 +. s ; z = z0 +. s}; + {x = x0 ; y = y0 +. s ; z = z0 +. s} + |] + in res ;; + +let cube = [| + {x = -1.; y = 1.; z = 1.}; + {x = -2.; y = 1.; z = 1.}; + {x = -2.; y = 2.; z = 1.}; + {x = -1.; y = 2.; z = 1.}; + {x = -1.; y = 1.; z = 2.}; + {x = -2.; y = 1.; z = 2.}; + {x = -2.; y = 2.; z = 2.}; + {x = -1.; y = 2.; z = 2.} +|] ;; + +let cube2 = [| + {x = 1.; y = 1.; z = 1.}; + {x = 2.; y = 1.; z = 1.}; + {x = 2.; y = 2.; z = 1.}; + {x = 1.; y = 2.; z = 1.}; + {x = 1.; y = 1.; z = 2.}; + {x = 2.; y = 1.; z = 2.}; + {x = 2.; y = 2.; z = 2.}; + {x = 1.; y = 2.; z = 2.} +|] ;; + +let cube3 = [| + {x = 1.; y = 1.; z = 2.}; + {x = 2.; y = 1.; z = 2.}; + {x = 2.; y = 2.; z = 2.}; + {x = 1.; y = 2.; z = 2.}; + {x = 1.; y = 1.; z = 3.}; + {x = 2.; y = 1.; z = 3.}; + {x = 2.; y = 2.; z = 3.}; + {x = 1.; y = 2.; z = 3.} +|] ;; + +let cube4 = [| + {x = 1.; y = 0.; z = 2.}; + {x = 2.; y = 0.; z = 2.}; + {x = 2.; y = -1.; z = 2.}; + {x = 1.; y = -1. ; z = 2.}; + {x = 1.; y = 0.; z = 3.}; + {x = 2.; y = 0.; z = 3.}; + {x = 2.; y = -1.; z = 3.}; + {x = 1.; y = -1.; z = 3.} +|] ;; + +let fov = 90 ;; + +let hehe () = + open_graph " 1500x1000" ; + set_window_title "3D" ; + + camera_xyz.z <- 0.8; + for i = 0 to 488 do + open_graph " 1500x1000" ; + draw_multiples_cubes [|cube ; cube4 ; cube2 ; cube3|] 1500 1000 fov ; + camera_xyz.z <- camera_xyz.z -. 0.1; + Stdlib.print_endline "-"; + Stdlib.print_endline "-"; + Unix.sleepf 0.15 + done; + + Unix.sleepf 1.0; + close_graph () ;; + +let get1char () = + let termio = Unix.tcgetattr Unix.stdin in + let () = + Unix.tcsetattr Unix.stdin Unix.TCSADRAIN + { termio with Unix.c_icanon = false } in + let res = input_char stdin in + Unix.tcsetattr Unix.stdin Unix.TCSADRAIN termio; + res ;; + +(* ---------------------------------------------------- *) +(* ---------------------------------------------------- *) + +type tile = Free | Wall | Crate | Exit | Craxit | Camera ;; + +let width = 5 +and height = 5 +and depth = 5 ;; +(* dimensions *) + +let laby = Array.make width [|[||]|] ;; +for i = 0 to width -1 do + laby.(i) <- Array.make_matrix height depth Wall +done ;; + +let n_walls = ref (width*height*depth) ;; + +let convert_laby laby = + let width = Array.length laby + and height = Array.length laby.(0) + and depth = Array.length laby.(0).(0) in + + let cubes = Array.make (width*height*depth) [||] + and reds = Array.make (width*height*depth) 0 + and greens = Array.make (width*height*depth) 0 + and blues = Array.make (width*height*depth) 0 in + + let index = ref 0 in + for w = 0 to width-1 do + for h = 0 to height-1 do + for d = 0 to depth-1 do + if laby.(w).(h).(d) <> Free then begin + (*Printf.printf "added (%d, %d, %d)" w h d; + Stdlib.print_endline " ";*) + cubes.(!index) <- create_cube w h d 1; + reds.(!index) <- 212; + greens.(!index) <- 212; + blues.(!index) <- 212; + incr index + end + done + done + done; + (cubes, reds, greens, blues) ;; + +let cheesify laby = + let width = Array.length laby + and height = Array.length laby.(0) + and depth = Array.length laby.(0).(0) in + + for w = 0 to width-1 do + for h = 0 to height-1 do + for d = 0 to depth-1 do + let rand_w = Random.int width + and rand_h = Random.int height + and rand_d = Random.int depth in + (*Printf.printf "chose (%d, %d, %d)" rand_w rand_h rand_d; + Stdlib.print_endline " ";*) + if laby.(rand_w).(rand_h).(rand_d) <> Free then begin + laby.(rand_w).(rand_h).(rand_d) <- Free; + decr n_walls + end + done + done + done;; + +cheesify laby ;; + +let (cs, rs, gs, bs) = convert_laby laby ;; + +camera_xyz.z <- -. (2.) ;; +camera_xyz.x <- -. (float_of_int width) /. 2. ;; +camera_xyz.y <- -. (float_of_int height) /. 2. ;; +while true do + open_graph " 1500x1000"; + draw_multiples_cubes_colored cs !n_walls rs gs bs 1500 1000 fov ; + camera_xyz.z <- camera_xyz.z +. 1.; + Unix.sleepf 1.25 +done ;; \ No newline at end of file diff --git a/display.mli b/display.mli new file mode 100644 index 0000000..9b8277f --- /dev/null +++ b/display.mli @@ -0,0 +1,52 @@ +val p : 'a +val matrix_mult : int array array -> int array array -> int array array +val abs : int -> int +val absf : float -> float +type pt_3d = { mutable x : float; mutable y : float; mutable z : float; } +type pt_2d = { mutable x : float; mutable y : float; } +val camera_xyz : pt_3d +val camera_angle : int ref +val should_be_drawn_gr : pt_3d -> bool +val sign : float -> float +val is_cube_behind_camera : pt_3d array -> bool +val debug_1 : pt_3d array -> unit +val to_graphics : pt_2d array -> int -> int -> (int * int) array +val draw_pts_2d : pt_2d array -> int -> int -> unit +val project : pt_3d array -> int -> int -> int -> pt_2d array +val adjust_to_camera : pt_3d array -> pt_3d array +val sq : float -> float +val dist_from_camera : pt_3d -> float +val farthest_pt : pt_3d -> pt_3d -> float +val swap : 'a array -> int -> int -> unit +val draw_cube_p : + pt_3d array -> int -> int -> int -> int -> int -> int -> unit +val sum_x : pt_3d array -> float +val sum_y : pt_3d array -> float +val sum_z : pt_3d array -> float +val cube_dist : pt_3d array -> float +val draw_multiples_cubes : pt_3d array array -> int -> int -> int -> unit +val draw_multiples_cubes_colored : + pt_3d array array -> + int -> int array -> int array -> int array -> int -> int -> int -> unit +val create_cube : int -> int -> int -> int -> pt_3d array +val cube : pt_3d array +val cube2 : pt_3d array +val cube3 : pt_3d array +val cube4 : pt_3d array +val fov : int +val hehe : unit -> 'a +val get1char : unit -> char +type tile = Free | Wall | Crate | Exit | Craxit | Camera +val width : int +val height : int +val depth : int +val laby : tile array array array +val n_walls : int ref +val convert_laby : + tile array array array -> + pt_3d array array * int array * int array * int array +val cheesify : tile array array array -> unit +val cs : pt_3d array array +val rs : int array +val gs : int array +val bs : int array