Help us understand the problem. What is going on with this article?

「プログラムでシダを描画する」をOCaml(OpenGL)で描画する

More than 3 years have passed since last update.

空前のシダ描画ブーム到来!?(^^;)
あなたも得意なプログラミング言語でシダを描画してみよう!

これまでの一覧

OCamlでlablglを利用してOpenGL描いてみました。
OCaml初心者なので、OCaml使いならこう書くなどありましたらコメント等お願いします。

x,yの写像の計算をタプルを使うことで、ベクトルとみなし、一まとめにしたのが、
前回のEmscripten版との違いです。

cedarOpenGL.ml
let dim = ref (500, 500);;

let w1 (x, y) = (0.836 *. x +. 0.044 *. y, (-0.044) *. x +. 0.836 *. y +. 0.169);;
let w2 (x, y) = ((-0.141) *. x +. 0.302 *. y, 0.302 *. x +. 0.141 *. y +. 0.127);;
let w3 (x, y) = (0.141 *. x -. 0.302 *. y, 0.302 *. x +. 0.141 *. y +. 0.169);;
let w4 (x, y) = (0.0, 0.175337 *. y);;

let makeImageBuf p n m init =
    let result = Array.make p (Array.make n (Array.make m init)) in
        for j = 1 to p - 1 do
            result.(j) <- Array.make n (Array.make m init);
            for i = 1 to n - 1 do
                result.(j).(i) <- Array.make m init
            done;
        done;
        result;;


let rec cedar n (x, y) ib =
  if 0 < n then begin
    cedar (n - 1) (w1(x,y)) ib;
    if Random.float 1.0 < 0.3 then begin
      cedar (n - 1) (w2(x,y)) ib;
    end;

    if Random.float 1.0 < 0.3 then begin
      cedar (n - 1) (w3(x,y)) ib;
    end;

    if Random.float 1.0 < 0.3 then begin
      cedar (n - 1) (w4(x,y)) ib;
    end;

    end
  else begin
    let xx = int_of_float (x *. (float (fst !dim)) *. 0.9) + (fst !dim)/2 in
    let yy = int_of_float (y *. (float (snd !dim)) *. 0.9) in
    if xx >= (fst !dim) then () else
       if yy >= (snd !dim) then () else
         ib.(1).(xx).(yy) <- 1.0;
  end;;

let imgBuf = makeImageBuf 3 (fst !dim) (snd !dim) 0.0;;
cedar 20 (0.0,0.0) imgBuf;;

let reshape ~w ~h =
  let w = max 1 w and h = max 1 h in
  dim := (w, h);
  GlDraw.viewport 0 0 w h;
  GlMat.mode `projection;
  GlMat.load_identity ();
  GlMat.ortho ~x:(-1., 1.) ~y:(-1., 1.) ~z:(0., 1.);
  GlMat.mode `modelview;;

let display () =
  let w, h = !dim in
  GlDraw.begins `points;
  for a = 0 to w - 1 do
    for b = 0 to h - 1 do
      let idx_x = int_of_float((float a /. float w) *. float (fst !dim)) in
      let idx_y = int_of_float((float b /. float h) *. float (snd !dim)) in
      GlDraw.color (imgBuf.(0).(idx_x).(idx_y), imgBuf.(1).(idx_x).(idx_y), imgBuf.(2).(idx_x).(idx_y));
      let x = 2. *. float a /. float w -. 1. in
      let y = 2. *. float b /. float h -. 1. in
      GlDraw.vertex ~x ~y ()
    done;
  done;
  GlDraw.ends ();
  Gl.flush ();;


let () =
  let argv' = Glut.init Sys.argv in
  Glut.initWindowSize ~w:(fst !dim) ~h:(snd !dim);
  ignore (Glut.createWindow ~title:"プログラムでシダを描画する");
  Glut.reshapeFunc ~cb:reshape;
  Glut.displayFunc ~cb:display;
  Glut.keyboardFunc ~cb:(fun ~key ~x ~y -> if key=27 then exit 0);
  Glut.mainLoop ();;

ocamlCedar.png

関連投稿

関連記事

kjunichi
WebRubyがきっかけで、mrubyで実装されたhttp2サーバーのtrusterdに絡んだ事をやってみたり、ElectronのIssue眺めたり、手元で動かしたり、node.js関連。WASMも少々。投稿する記事の内容は個人の意見であり、所属する企業の見解を代表するものではありません。
https://abrakatabura.hatenablog.com/
japan-systems
「2019年に50周年を迎えたIT企業です。最先端の技術により全国の企業、官公庁、自治体に多くの実績があります。」
https://www.japan-systems.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away