Polygonizer

Jules Bloomenthal wrote an article about an implicit surface polygonizer. I've ported his C program to Lisp. If you want to execute the polygonizer, you'll need lispbuilder-sdl, cl-opengl and optionally the Infix package for easier entering mathematical formulas.

How it works

The polygonizer calculates the surface of a function. A point is on the surface of a function if the function value for this point is 0. A simple example is a torus:

(defun torus (x y z)
  "a torus"
  (let* ((major 2.5)
         (minor 1.2)
    (x2 (* x x))
         (y2 (* y y))
         (z2 (* z z))
         (a (+ x2 y2 z2 (* major major) (- (* minor minor)))))
    (- (* a a) (* 4.0 (* major major) (+ y2 z2)))))

Then we define a callback function, which is called by the polygonizer for every triangle it creates:

(defun triangle (p1 p2 p3 n1 n2 n3)
  (incf *triangle-count*)
  (gl:begin :triangles)
  (gl:normal (point-x n1) (point-y n1) (point-z n1))
  (gl:vertex (point-x p1) (point-y p1) (point-z p1))
  (gl:normal (point-x n2) (point-y n2) (point-z n2))
  (gl:vertex (point-x p2) (point-y p2) (point-z p2))
  (gl:normal (point-x n3) (point-y n3) (point-z n3))
  (gl:vertex (point-x p3) (point-y p3) (point-z p3))
  (gl:end))

After initializing OpenGL, we call the polygonizer:

(polygonize #'torus 0.10 100 0.0 0.0 0.0 #'triangle TET)

The output:

Torus

For more complex functions, like this one from the paper:

Jack Formula

it is easier to use the Infix package, if you are not a hardcore Lisp programmer, to write it like this:

(defun jack (x y z)
  #I"(1/(x^^2/9+4*y^^2+4*z^^2)^^4
        +1/(y^^2/9+4*x^^2+4*z^^2)^^4
        +1/(z^^2/9+4*y^^2+4*x^^2)^^4
        +1/((4*x/3-4)^^2+16*y^^2/9+16*z^^2/9)^^4
        +1/((4*x/3+4)^^2+16*y^^2/9+16*z^^2/9)^^4
        +1/((4*y/3-4)^^2+16*x^^2/9+16*z^^2/9)^^4
        +1/((4*y/3+4)^^2+16*x^^2/9+16*z^^2/9)^^4)^^(-1/4)-1")

This produces the following surface:

Jack

The source in one file.


17. April 2006, Frank Buß