Skip to content

Instantly share code, notes, and snippets.

@viperscape
Last active December 25, 2015 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save viperscape/7055130 to your computer and use it in GitHub Desktop.
Save viperscape/7055130 to your computer and use it in GitHub Desktop.
using core.matrix, perform some 3d graphics-related functions lookat, perspective projection, and building translation and rotation matrices; 'left' in the function name specifies left-handed coordinates
;; (ns somenamespace
;; (:refer-clojure :exclude [* - + == /])
;; (:use clojure.core.matrix)
;; (:use clojure.core.matrix.operators)
;; (:gen-class))
(defn inv [n] "returns the inverse, (* -1 n)" (* -1 n))
(defn projection [l r b t, n f, aspect fov]
"builds a perspective-projection matrix"
(let [m (identity-matrix 4)
yscale (float (/ 1 (Math/tan (* (/ fov 2) (/ Math/PI 180)))))
xscale (float (/ yscale aspect))
m (mset m 0 0 xscale);(float (/ (* 2 n) (- r l))))
m (mset m 1 1 yscale);(float (/ (* 2 n) (- t b))))
m (mset m 2 2 (inv (float (/ (+ f n) (- f n)))))
m (mset m 2 3 -1)
m (mset m 3 2 (inv (float (/ (* 2 f n) (- f n)))))
;m (mset m 2 0 (float (/ (+ r l) (- r l))))
;m (mset m 2 1 (float (/ (+ t b) (- t b))))
m (mset m 3 3 0)]
m
))
(defn perspective [fov aspect near far]
"builds a perspective-projection matrix"
(let [half (float (Math/tan (* (/ fov 2) (/ Math/PI 180))))
height (float (* near half))
width (float (* aspect height))]
(projection (inv width) width (inv height) height near far aspect fov)
))
(defn translate-left [v]
"builds a translation matrix, takes a 3d vector"
(let [m (identity-matrix 4)
m (mset m 0 3 (first v))
m (mset m 1 3 (second v))
m (mset m 2 3 (last v))]
m))
(defn rotate-by-left [angle axis]
"returns a rotation matrix, specify angle and axis
TODO: turn this in to a switch statement"
(let [ca (Math/cos angle)
sa (Math/sin angle)]
(if (= :x axis)
(let [m (identity-matrix 4)
m (mset m 1 1 ca)
m (mset m 1 2 (inv sa))
m (mset m 2 1 sa)
m (mset m 2 2 ca)] m)
(if (= :y axis)
(let [m (identity-matrix 4)
m (mset m 0 0 ca)
m (mset m 0 2 sa)
m (mset m 2 0 (inv sa))
m (mset m 2 2 ca)] m)
(if (= :z axis)
(let [m (identity-matrix 4)
m (mset m 0 0 ca)
m (mset m 0 1 (inv sa))
m (mset m 1 0 sa)
m (mset m 1 1 ca)] m))))
))
(defn lookat [eye dir up]
"performs lookat matrix operation, takes 3 vectors of size 3
TODO: prep this properly for right-hand openGL friendly matrix, and run GL_FALSE instead"
(let [f (normalise (- dir eye))
s (normalise (cross up f))
u (cross f s)
mo (identity-matrix 4)
mo (mset mo 0 0 (first s))
mo (mset mo 1 0 (second s))
mo (mset mo 2 0 (last s))
mo (mset mo 0 1 (first u))
mo (mset mo 1 1 (second u))
mo (mset mo 2 1 (last u))
mo (mset mo 0 2 (inv (first f)))
mo (mset mo 1 2 (inv (second f)))
mo (mset mo 2 2 (inv (last f)))]
(transform mo (translate-left [(inv (first eye)) (inv (second eye)) (inv (last eye))]))
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment