Archive for the ‘Graphics’ Category

Running CL-SDL in CLISP

Tuesday, September 9th, 2008

I have been experimenting with ways to do this on and off, but I finally got CL-SDL loaded into CLISP and without the UFFI patches that are on sourceforge.

It is the kind of thing that should not have been hard and, in the end, it really wasn’t. It was just a matter of doing the research. I have learned more about Common Lisp packages, implementations, and FFIs than I would have expected on this little project.

The main thrust is that UFFI does not support CLISP, though CFFI does. Fortunately, CFFI includes a compatibility layer that allows it to use UFFI bindings. While I had read this on cliki.net, it took a great deal more googling to figure out how to use the darn thing. On the lispwannabe blog, the writer shows an asdf package for uffi that loads cffi’s compatibility layer into asdf as uffi. This is important, because a great many other things expect to find uffi there. At this point, using cl-sdl’s example1.lisp works when I used the following code:

(require 'asdf)
(asdf:operate 'asdf:load-op :uffi)
(asdf:operate 'asdf:load-op :sdl)

(load "example1")
(sdl-example1:start)

This, however, does not solve the whole problem in interactive mode. Within cl-sdl, there are a number of places where slightly different code is written for slightly different implementations. This causes a problem as CLISP doesn’t offer any of them in its *features* variable. One answer is to add clisp’s feature to the lists in the bindings, but that takes a good deal of work. Instead, what I found is that if you just push :cmucl onto features, it works.

Where to go from here: get started on the rewrite of Latrunculi’s graphics system, for one. Another would be to try and use this information to use CL-SDL from within ECL which seems, so far as I can tell, to be the CL implementation with the best Windows support.

2D Mouse Picking with OpenGL & GLUT

Wednesday, March 14th, 2007

As I may (or may not) have mentioned, I have been piecing together my own Haskell tutorial that I hope to make available soon (what time is soon? With respect to deadlines, all times are soon). I decided to write the tour de force example program with HOpenGL as I’ve used OpenGL in the past and, I admit, I was a little ticked when the Haskell School of Expression used the Haskell X11/Win32 overlay. The reason being that because I play with sundry operating systems and programming languages I appreciate lessons that are transferable. If this is coding, I appreciate being able to pick up the bindings in another language and make use of it there, rather than using some languages jerry-rigged utility that I can’t use anywhere else.

The thing is, on the other project for which I’ve used OpenGL, I did it in pure 3D, but this example is a simple 2D game. This makes most of the rendering easier (or rather, less verbose), however this combined with the conditions of the game means that I have to redo the mouse picking. I also noticed that there isn’t a lot available on this rather arcane condition: 2D mouse picking in HOpenGL with GLUT. So, post-odyssey, here is the mad computer scientist’s lab report.

OpenGL, being a forward thinking spec, was written with 3D specifically in mind. This is well and good, we like 3D, and, for the most part, it is easy to ignore depth when rendering and get something that is 2D-ish out of the system.

GLUT offers a simple event handler for passive motion (i.e. motion when there is no mouse button pressed). In Haskell, the signature is of the form:

type MotionCallback = Position -> IO ()

Position has the form Position x y, where x and y are expressed in pixels. We can set the new “target” equal to these coordinates, with one problem: OpenGL does not measure its coordinate system in pixels (come to think of it, I haven’t the foggiest notion what it IS based on; I just had to develop something of a feel for it with practice). So we need to convert from pixels to the OpenGL coordinate system. Here is the finished code that accomplishes this:

viewp <- get viewport
pm <- get (matrix $ Just Projection) :: IO (GLmatrix GLdouble)
mvm <- get (matrix $ Just $ Modelview 0) :: IO (GLmatrix GLdouble)

coords@(Vertex3 x1 y1 z1) <- unProject (Vertex3 (fromIntegral x) (fromIntegral y) 0)
pm
mvm
iewp

Providing the Z value in Vertex3 as 0 is important for the 2D aspect of this. If we were doing 3D picking, we would either render the scene to the back-buffer with color coding and read the color of the pixel where the mouse was located (the method used in Latrunculi) or we would use unProject twice: once with Z = 0 and the other time with Z = far plane and use these values to create a pick ray. x1 and y1 are the OpenGL coordinates we will need in 2D–with one caveat. The OpenGL axis is inverted relative to X11/Win32 windowing systems.
The OpenGL FAQ gives the way to do this as taking the WindowHeight – y1. This assumes the integer form of the OpenGL commands which is not present in the current HOpenGL bindings. What I found works is to invert the y1 coordinate in the following manner:

(x1, 0.0 – y1)

Which is, admittedly, the same as multiplying y1 by -1. So we literally invert the Y-Coordinate and presto! we have the coordinates we need.

As usual, the culprits in figuring things like this are the stupid little things: getting the type signatures correct in the first two lines and finding out (or rather, remembering) that the axis needs to be inverted.