Ocaml strikes back

Grr – I got angry with my trusty old O’Caml’s back again.

It all started with my hobby physics engine project (I’ll talk about this more at some later post*) that I’ve been putting together in my free time – I wanted to visualize how well my first draft of joint-friction works; Should be easy with a powerful language, no sweat, right? Well almost. 🙂

*) Actually now that I think about it, I’ll probably never dedicate a whole post to explaining it, but you, my loyal reader, can gather bits and pieces of it from various future posts, or something. 🙂

I already had most of the dummy code for my test-case written (point-particle on a sine-curve)

Parameters:

type state = { x : float; y : float; vx : float; vy : float; lambda : float };;
let h = 0.02;;
let g = 10.0;;
let mass = 1.0;;
let fricCoef1 = 0.1;;

Then some update code (manully solving the constraint equation for phi(x,y) = y + sin x = 0 etc. and then the fun part:

Visualizing the slide!

Grab google and O’Caml reference manual (http://caml.inria.fr/distrib/ocaml-3.09/ocaml-3.09-refman.pdf) and we have all we need:

(In case you are on Linux (more on that later 🙂 type something like ocaml graphics.cma to get the interpreter with X11 support)

Open Graphics module, create default window surface and resize it to (1024×768):

open Graphics;;
open_graph "";;
resize_window 1024 768;;

Then define starting point on window (lower right being 0,0!), with which factor to scale the gfx and draw the basic coordinate axles (x = 0 and y = 0)

let scale = 100.0;;
let x0 = 100;;
let y0 = 400;;


let drawAxis () =
set_color (rgb 0 0 0);
set_line_width 2;
moveto x0 10;
let w = size_x () in
let h = size_y () in
lineto x0 (h-11);
moveto 10 y0;
lineto (w -11) y0;
;;

Easy, no?

Then just define the functions needed to draw the sine-curve, then the whole background and ultimate the whole state:


let pixelcoordX x = x0 + int_of_float (scale *. x);;
let pixelcoordY y = y0 + int_of_float (scale *. y);;

let drawCurve () =
let nPoints = 50 in
set_color (rgb 120 120 120);
set_line_width 1;
let first = ref true in
for i = 0 to nPoints do
let x = -.0.7 +. (float_of_int i) *.
9.6 /. (float_of_int nPoints) in
let y = -.(sin x) in
let drawCall =
if !first then
moveto
else
lineto
in
drawCall (pixelcoordX x) (pixelcoordY y);
first := false
done;
;;


(* drawCurve ();; *)


let drawBackGround () =
clear_graph();
drawAxis();
drawCurve()
;;


let drawState state =
let x = state.x in
let y = state.y in
set_color (rgb 220 20 120);
set_line_width 3;
draw_circle (pixelcoordX x) (pixelcoordY y) 6
;;

Almost there! Only thing missing is some loop to render the frames – what this means, is that I need to just draw my graphics to the windowing-system backbuffer, post that to the frontbuffer and wait a while to get smooth animation – preferrably so that the the time used to compute physics step and draw the graphics is comparable to physics-stepsize.

But wait, there’s no sane way to wait in O’Caml!!! The Unix-module has wait-function for complete seconds only! So – I can’t wait 0.02 seconds which is my physics-stepsize. Unix-select could apparently also be used, but for some reason Unix.select [] [] [] 0.02 causes an exception (The system-call is pre-empted by an interrupt apparently). So what is the solution? Apparently there isn’t any? How is one supposed to code this thing? I mean, these are preeeettyyy basic OS-services that should be always available. Well – after googling and trying out desperate things for an hour or so, I deviced an elegant solution: The busy-loop – here we go:


let drawFrame state =
auto_synchronize false;
drawBackGround();
(* ignore (Unix.select [] [] [] 0.01); *)
(* ignore (Unix.sleep 1); *)
(*GRRRRRRRRRRRRRRRRRRRR OCAML SUCCCCCCCKKKKKSSSSSSSS!!!!!!! NO WAY TO
SLEEEEEEEEEEEEEEPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP!!!!!!!!!!!!!!!*)
for i = 1 to 90009 do (); done;
drawState state;
synchronize();
auto_synchronize true;
;;


let runNFrames n state =
let s = ref state in
for i = 0 to n do
drawFrame !s;
s := fricstep !s
done
;;


runNFrames 1000 s;;

Beautiful, isn’t it? Well, with this trickery I was able to play my smoooth animation and verify that visually the quality is ok and that the test-particle stops quite nicely to the bottom of the hill.

Advertisements

3 Responses to “Ocaml strikes back”

  1. […] in my post on an O’Caml rant, I was complaining how O’Caml made it impossible for me to do the “simplest of all […]

  2. […] About Coulombic Friction models So I have been lately somewhat involved in modeling Coulombic friction in my (perhaps game-) physics simulations project, as you can see from my post on writing test code and the first O’Caml rant. […]

  3. Great Post!…

    […] I found your entry interesting thus I’ve added a Trackback to it on my weblog 🙂 […]…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: