Last active
January 17, 2019 13:35
-
-
Save ympbyc/0e83949bf1c5efd6c005709b0cdea2b8 to your computer and use it in GitHub Desktop.
Easily composable signed distance functions for CEPL. Mostly untested.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defpackage :distance-fns | |
(:use :cl :cepl :rtg-math :vari) | |
(:nicknames :df)) | |
(in-package :df) | |
(defun-g rand ((co :vec2)) | |
(fract (* (sin (dot co (v! 12.98 78.23))) 43758.54))) | |
;; Signed Distance functions | |
(defun-g sdf-sphere ((p :vec3) (r :float)) | |
(- (length p) r)) | |
(defun-g sdf-box ((p :vec3) (b :vec3)) | |
(let ((d (- (abs p) b))) | |
(+ (min (max (x d) (max (y d) (z d))) 0.0) | |
(length (max d 0.0))))) | |
(defun-g sdf-torus ((p :vec3) (r :vec2)) | |
(let ((q (v! (- (length (swizzle p :xz)) (x r)) | |
(y p)))) | |
(- (length q) (y r)))) | |
(defun-g sdf-cylinder ((p :vec3) (c :vec3)) | |
(- (length (- (swizzle p :xz) (swizzle c :xy))) | |
(z c))) | |
(defun-g sdf-cone ((p :vec3) (c :vec2)) | |
(let ((q (length (swizzle p :xy)))) | |
(dot c (v! q (z p))))) | |
(defun-g sdf-plane ((p :vec3) (n :vec4)) | |
(+ (dot p (swizzle n :xyz)) | |
(w n))) | |
(defun-g sdf-hex-prism ((p :vec3) (h :vec2)) | |
(let ((q (abs p))) | |
(max (- (z q) (y h)) | |
(- (max (+ (* (x q) 0.866025) | |
(* (y q) 0.5)) | |
(y q)) | |
(x h))))) | |
(defun-g sdf-ellipsoid ((p :vec3) (r :vec3)) | |
(* (- (length (/ p r)) 1.0) | |
(min (min (x r) (y r)) (z r)))) | |
(defun-g sdf-U ((d1 :float) (d2 :float)) | |
(min d1 d2)) | |
(defun-g sdf-S ((d1 :float) (d2 :float)) | |
(max (- d1) d2)) | |
(defun-g sdf-I ((d1 :float) (d2 :float)) | |
(max d1 d2)) | |
(defun-g sdf-rep ((p :vec3) (c :vec3)) | |
(let ((q (v! (mod (x p) (x c)) | |
(mod (y p) (y c)) | |
(mod (z p) (z c))))) | |
(- q (* c 0.5)))) | |
(defun-g sdf-tx ((p :vec3) (m :mat4)) | |
(let ((v (* (inverse m) (v! (x p) (y p) (z p) 1.0)))) | |
(swizzle v :xyz))) | |
(defun-g sdf-displace ((dist1 :float) (dist2 :float)) | |
(+ dist1 dist2)) | |
(defun-g sdf-smin ((a :float) (b :float) (k :float)) | |
(let ((h (max (- k (abs (- a b))) 0.0))) | |
(- (min a b) | |
(/ (* h h 0.25) k)))) | |
(defun-g sdf-blend ((d1 :float) (d2 :float)) | |
(sdf-smin d1 d2 0.6)) | |
(defun-g sdf-bend ((p :vec3) (k :float)) | |
(let* ((c (cos (* k (y p)))) | |
(s (sin (* k (y p)))) | |
(m (m! c (- s) s c)) | |
(q (v! (* m (swizzle p :xy)) (z p)))) | |
q)) | |
;;API | |
(defmacro sdf-api (name &rest params) | |
(let ((f-n (intern (concatenate 'string "SDF-" (symbol-name name))))) | |
`(defmacro-g ,(intern (concatenate 'string (symbol-name name))) | |
,params | |
(let ((p (gensym))) | |
`(lambda ((,p :vec3)) | |
(,',f-n | |
,p | |
,,@params)))))) | |
(defmacro sdf-api* (name) | |
(let ((f-n (intern (concatenate 'string "SDF-" (symbol-name name))))) | |
`(defmacro-g ,(intern (concatenate 'string (symbol-name name))) | |
(df1 df2) | |
(let ((p (gensym))) | |
`(lambda ((,p :vec3)) | |
(,',f-n | |
(funcall ,df1 ,p) | |
(funcall ,df2 ,p))))))) | |
(defmacro sdf-api** (name param) | |
(let ((f-n (intern (concatenate 'string "SDF-" (symbol-name name))))) | |
`(defmacro-g ,(intern (concatenate 'string (symbol-name name))) | |
(,param df) | |
(let ((p (gensym))) | |
`(lambda ((,p :vec3)) | |
(funcall ,df | |
(,',f-n ,p ,,param))))))) | |
(export (sdf-api sphere r)) | |
(export (sdf-api box size)) | |
(export (sdf-api torus r)) | |
(export (sdf-api cylinder c)) | |
(export (sdf-api cone c)) | |
(export (sdf-api plane n)) | |
(export (sdf-api hex-prism h)) | |
(export (sdf-api ellipsoid r)) | |
(export (sdf-api* U)) | |
(export (sdf-api* S)) | |
(export (sdf-api* I)) | |
(export (sdf-api* displace)) | |
(export (sdf-api* blend)) | |
(export (sdf-api** rep v)) | |
(export (sdf-api** tx v)) | |
(export (sdf-api** bend k)) | |
(defmacro-g move (v df) | |
(let* ((sym (gensym))) | |
`(lambda ((,sym :vec3)) | |
(let* ((m (m! 1.0 0.0 0.0 0.0 | |
0.0 1.0 0.0 0.0 | |
0.0 0.0 1.0 0.0 | |
(x ,v) (y ,v) (z ,v) 1.0)) | |
(p (* (inverse m) (v! (x ,sym) (y ,sym) (z ,sym) 1.0)))) | |
(funcall ,df (swizzle p :xyz)))))) | |
(defmacro-g rotate-x (tt df) | |
(let* ((sym (gensym))) | |
`(lambda ((,sym :vec3)) | |
(let* ((m (m! 1.0 0.0 0.0 0.0 | |
0.0 (cos ,tt) (- (sin ,tt)) 0.0 | |
0.0 (sin ,tt) (cos ,tt) 0.0 | |
0.0 0.0 0.0 1.0)) | |
(p (* (inverse m) (v! (x ,sym) (y ,sym) (z ,sym) 1.0)))) | |
(funcall ,df (swizzle p :xyz)))))) | |
(defmacro-g rotate-y (tt df) | |
(let* ((sym (gensym))) | |
`(lambda ((,sym :vec3)) | |
(let* ((m (m! (cos ,tt) 0.0 (sin ,tt) 0.0 | |
0.0 1.0 0.0 0.0 | |
(- (sin ,tt)) 0.0 (cos ,tt) 0.0 | |
0.0 0.0 0.0 1.0)) | |
(p (* (inverse m) (v! (x ,sym) (y ,sym) (z ,sym) 1.0)))) | |
(funcall ,df (swizzle p :xyz)))))) | |
(defmacro-g rotate-z (tt df) | |
(let* ((sym (gensym))) | |
`(lambda ((,sym :vec3)) | |
(let* ((m (m! (cos ,tt) (- (sin ,tt)) 0.0 0.0 | |
(sin ,tt) (cos ,tt) 0.0 0.0 | |
0.0 0.0 1.0 0.0 | |
0.0 0.0 0.0 1.0)) | |
(p (* (inverse m) (v! (x ,sym) (y ,sym) (z ,sym) 1.0)))) | |
(funcall ,df (swizzle p :xyz)))))) | |
(export 'move) | |
(export 'rotate-x) | |
(export 'rotate-y) | |
(export 'rotate-z) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;just compose it like you would in Libfive Studio | |
(df:blend (df:move (V! 1 0 0) (df:sphere 1)) | |
(df:box 1 (v! 2 2 2)) | |
;;-> gives you back a signed distance function (lambda (:vec3) :float) you can use with raymarcher |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment