-
Notifications
You must be signed in to change notification settings - Fork 0
/
tri.lisp~
50 lines (49 loc) · 1.73 KB
/
tri.lisp~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
(defclass tri (surfer)
((v1 :accessor tri-v1
:initarg :v1
:initform '(1 1 0))
(v2 :accessor tri-v2
:initarg :v2
:initform '(2 1 0))
(v3 :accessor tri-v3
:initarg :v3
:initform '(1 2 0))))
(defmethod tri-verts ((a tri))
(list (tri-v1 a) (tri-v2 a) (tri-v3 a)))
(defmethod intersect ((a tri) pt dir)
(let ((amount (to-plane pt dir (tri-verts a))))
(if amount
(let ((testp (vplus pt (vs* amount dir))))
(multiple-value-bind (x y)
(transform-to-tri-coords testp (tri-v1 a) (tri-v2 a) (tri-v3 a))
(if (and (and (< 0 x) (< 0 y))
(and (> 1 (+ x y))))
testp
nil)))
nil)))
(defun to-plane (pt dir ls)
"Calculate intersection multiplier in the parametrization of the ray"
(let* ((n (plane-normal ls))
(denom (vdot dir n)))
(if (= denom 0) ; ray and plane-normal can't be perpendicular, points can't be in a line
nil ; signal that they don't intersect anywhere
; (or they do everywhere mwah ha ha)
(/ (vdot (vdif '(0 0 0) (vdif pt (first ls))) n)
denom))))
(defun plane-normal (verts)
"Calc a unit vector normal of the plane that contains the given vertices."
;; As of now, you could give a list of n verts, but it only uses the first 3
;; They better not be in a line
(let ((vhat (vdif (second verts) (first verts)))
(uhat (vdif (third verts) (first verts))))
(unitize (vcross vhat uhat))))
(defun transform-to-tri-coords (pt a b c)
"Transform the given point to new basis"
(let* ((u (vdif b a))
(v (vdif c a))
(z (vcross u v)))
(let ((sloop (minv (apply #'mat (mapcan #'list u v z)))))
(let ((params (m* sloop (apply #'vec3 pt))))
(values (vx params) (vy params))))))
(defmethod normal ((toon tri) pt)
(plane-normal (tri-verts toon)))