diff --git a/a.out b/a.out index 3aecaa0..3a5581b 100755 Binary files a/a.out and b/a.out differ diff --git a/display.cmi b/display.cmi index cac5f6a..b86063e 100644 Binary files a/display.cmi and b/display.cmi differ diff --git a/display.cmo b/display.cmo index eb1af1b..ac33f45 100644 Binary files a/display.cmo and b/display.cmo differ diff --git a/display.ml b/display.ml index 2a38f0e..f28baf8 100644 --- a/display.ml +++ b/display.ml @@ -1,14 +1,42 @@ open Graphics ;; -open Tsdl ;; Random.self_init () ;; +let __width__ = 1500 +and __height__ = 1000 ;; + (* -ocamlfind ocamlc -linkpkg -package unix -linkpkg -package graphics -linkpkg -package tsdl -thread -package threads -linkpkg display.ml +ocamlfind ocamlc -linkpkg -package unix -linkpkg -package graphics -thread -package threads -linkpkg display.ml *) +(* ------------------------------------------------------------- *) +(* ------------------------------------------------------------- *) + +type 'a dynamic = {mutable tab : 'a array ; mutable len : int ; mutable memlen : int} ;; + +let dyn_create i = + {tab = Array.make 10 i ; len = 0 ; memlen = 10} ;; + +let dyn_append arr elt = + let fct x = + if x < arr.len then + arr.tab.(x) + else + arr.tab.(0) + in + if arr.len = arr.memlen then begin + let newarr = Array.init (2 * arr.memlen) fct in + arr.memlen <- 2 * arr.memlen; + arr.tab <- newarr + end; + arr.tab.(arr.len) <- elt; + arr.len <- arr.len + 1 ;; + +(* ------------------------------------------------------------- *) +(* ------------------------------------------------------------- *) + let matrix_mult m1 m2 = let n = Array.length m1 and p = Array.length m1.(0) @@ -155,6 +183,92 @@ let are_faces_behind (cube : pt_3d array) = res.(5) <- (should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(4)) || (should_be_drawn_gr cube.(7)); (res, res.(0) || res.(1) || res.(2) || res.(3) || res.(4) || res.(5)) ;; +let are_faces_behind_rev (cube : pt_3d array) = + let res = Array.make 6 false in + res.(0) <- + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(2))) && + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(3))) && + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(1))) && + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(2))) && + ((should_be_drawn_gr cube.(2)) || (should_be_drawn_gr cube.(3))) && + ((should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(0))) ; + res.(1) <- + ((should_be_drawn_gr cube.(4)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(5)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(4)) || (should_be_drawn_gr cube.(5))) && + ((should_be_drawn_gr cube.(5)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(6)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(7)) || (should_be_drawn_gr cube.(4))) ; + res.(2) <- + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(5))) && + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(4))) && + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(1))) && + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(5))) && + ((should_be_drawn_gr cube.(5)) || (should_be_drawn_gr cube.(4))) && + ((should_be_drawn_gr cube.(4)) || (should_be_drawn_gr cube.(0))) ; + res.(3) <- + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(2)) || (should_be_drawn_gr cube.(5))) && + ((should_be_drawn_gr cube.(1)) || (should_be_drawn_gr cube.(2))) && + ((should_be_drawn_gr cube.(2)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(6)) || (should_be_drawn_gr cube.(5))) && + ((should_be_drawn_gr cube.(5)) || (should_be_drawn_gr cube.(1))) ; + res.(4) <- + ((should_be_drawn_gr cube.(2)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(2)) || (should_be_drawn_gr cube.(3))) && + ((should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(7)) || (should_be_drawn_gr cube.(6))) && + ((should_be_drawn_gr cube.(6)) || (should_be_drawn_gr cube.(2))) ; + res.(5) <- + ((should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(4))) && + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(3)) || (should_be_drawn_gr cube.(0))) && + ((should_be_drawn_gr cube.(0)) || (should_be_drawn_gr cube.(4))) && + ((should_be_drawn_gr cube.(4)) || (should_be_drawn_gr cube.(7))) && + ((should_be_drawn_gr cube.(7)) || (should_be_drawn_gr cube.(3))) ; + (res, res.(0) || res.(1) || res.(2) || res.(3) || res.(4) || res.(5)) ;; + +let are_edges_behind (cube : pt_3d array) = + let res = Array.make 6 [||] in + res.(0) <- [| + (should_be_drawn_gr cube.(0)) && (should_be_drawn_gr cube.(1)); + (should_be_drawn_gr cube.(1)) && (should_be_drawn_gr cube.(2)); + (should_be_drawn_gr cube.(2)) && (should_be_drawn_gr cube.(3)); + (should_be_drawn_gr cube.(3)) && (should_be_drawn_gr cube.(0)) + |]; + res.(1) <- [| + (should_be_drawn_gr cube.(4)) && (should_be_drawn_gr cube.(5)); + (should_be_drawn_gr cube.(5)) && (should_be_drawn_gr cube.(6)); + (should_be_drawn_gr cube.(6)) && (should_be_drawn_gr cube.(7)); + (should_be_drawn_gr cube.(7)) && (should_be_drawn_gr cube.(4)) + |]; + res.(2) <- [| + (should_be_drawn_gr cube.(0)) && (should_be_drawn_gr cube.(1)); + (should_be_drawn_gr cube.(1)) && (should_be_drawn_gr cube.(5)); + (should_be_drawn_gr cube.(5)) && (should_be_drawn_gr cube.(4)); + (should_be_drawn_gr cube.(4)) && (should_be_drawn_gr cube.(0)) + |]; + res.(3) <- [| + (should_be_drawn_gr cube.(1)) && (should_be_drawn_gr cube.(2)); + (should_be_drawn_gr cube.(2)) && (should_be_drawn_gr cube.(6)); + (should_be_drawn_gr cube.(6)) && (should_be_drawn_gr cube.(5)); + (should_be_drawn_gr cube.(5)) && (should_be_drawn_gr cube.(1)) + |]; + res.(4) <- [| + (should_be_drawn_gr cube.(2)) && (should_be_drawn_gr cube.(3)); + (should_be_drawn_gr cube.(3)) && (should_be_drawn_gr cube.(7)); + (should_be_drawn_gr cube.(7)) && (should_be_drawn_gr cube.(6)); + (should_be_drawn_gr cube.(6)) && (should_be_drawn_gr cube.(2)) + |]; + res.(5) <- [| + (should_be_drawn_gr cube.(3)) && (should_be_drawn_gr cube.(0)); + (should_be_drawn_gr cube.(0)) && (should_be_drawn_gr cube.(4)); + (should_be_drawn_gr cube.(4)) && (should_be_drawn_gr cube.(7)); + (should_be_drawn_gr cube.(7)) && (should_be_drawn_gr cube.(3)) + |]; + res ;; + let draw_cube_p (cube : pt_3d array) 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 @@ -222,6 +336,138 @@ let draw_cube_p (cube : pt_3d array) screen_wd screen_ht fov r g b = done end ;; +let draw_cube_p_rev (cube : pt_3d array) screen_wd screen_ht fov r g b = + let adjusted = adjust_to_camera cube in + let (draw_faces, draw_cube) = are_faces_behind_rev adjusted in + if draw_cube then begin + let proj = project adjusted 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; + swap draw_faces i !idmax; + done; + set_line_width 5; + for i = 0 to 5 do + if draw_faces.(i) then begin + 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); + end + done + end ;; + +let draw_cube_hollow_p (cube : pt_3d array) 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 + let draw_edges = are_edges_behind adjusted in + if draw_cube then begin + let proj = project adjusted 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; + swap draw_faces i !idmax; + swap draw_edges i !idmax + done; + set_line_width 5; + set_color (rgb r g b); + for i = 0 to 5 do + for j = 0 to 3 do + if draw_edges.(i).(j) then begin + draw_poly_line [|order.(i).(j) ; order.(i).((j+1) mod 4)|]; + end + done + done + end ;; + let sum_x (poly : pt_3d array) = let res = ref 0. in for i = 0 to (Array.length poly -1) do @@ -251,46 +497,15 @@ let cube_dist (c : pt_3d array) = } 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 draw_multiples_cubes_colored (cubes : pt_3d array dynamic) rs gs bs screen_wd screen_ht fov render_dist = + let n = cubes.len 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) + distances.(i) <- cube_dist cubes.tab.(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 render_dist = - 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 @@ -301,16 +516,12 @@ let draw_multiples_cubes_colored (cubes : pt_3d array array) maxlen rs gs bs scr end done; swap distances i !idmax; - swap new_arr i !idmax; - swap reds i !idmax; - swap greens i !idmax; - swap blues i !idmax; + swap cubes.tab 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 "...";*) - if distances.(i) <= (float_of_int render_dist) then - draw_cube_p new_arr.(i) screen_wd screen_ht fov reds.(i) greens.(i) blues.(i) + 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) + end done ;; let create_cube x0' y0' z0' sz' = @@ -330,69 +541,8 @@ let create_cube x0' y0' z0' sz' = |] 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 () ;; - (* 7--------6 /| /| @@ -470,40 +620,46 @@ let is_collision_cube (cam_coords : pt_3d) (cube : pt_3d array) = let is_collision (cam_coords : pt_3d) (cubes : pt_3d array array) = let res = ref false in let n = !n_walls in + + let distances = Array.make n 0. in + for i = 0 to n-1 do - if not !res then + distances.(i) <- cube_dist cubes.(i); + done ; + + for i = 0 to n-1 do + if not !res && distances.(i) < 2. then res := is_collision_cube cam_coords cubes.(i) done; !res ;; + 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 cubes = dyn_create (create_cube 0 0 0 0) + and reds = dyn_create 0 + and greens = dyn_create 0 + and blues = dyn_create 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 + dyn_append cubes (create_cube w h d 1); + dyn_append reds 212; + dyn_append greens 212; + dyn_append blues 212; end done done done; (cubes, reds, greens, blues) ;; -let cheesify laby = +let cheesify (laby : tile array array array) = let width = Array.length laby and height = Array.length laby.(0) and depth = Array.length laby.(0).(0) in @@ -577,7 +733,7 @@ let play laby = fill_poly [|(0, 0); (1500, 0); (1500, 1000); (0, 1000); (0, 0)|]; set_color white; - draw_multiples_cubes_colored cs !n_walls rs gs bs 1500 1000 fov render_distance ; + draw_multiples_cubes_colored cs rs gs bs __width__ __height__ fov render_distance ; auto_synchronize true; @@ -585,20 +741,7 @@ let play laby = Stdlib.print_endline " "; let usr_input = get1char () in - move_cam cs true usr_input - done ;; - -let test1 laby = - cheesify laby ; - let (cs, rs, gs, bs) = convert_laby laby in - camera_xyz.z <- -. (1.5) ; - 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 render_distance ; - camera_xyz.z <- camera_xyz.z +. 1.; - Unix.sleepf 1.25 + move_cam cs.tab true usr_input done ;; play laby ;; \ No newline at end of file