; Copyright (C) 2010 Dave Griffiths : See LICENCE file (include "../maths/vec.sc") (include "line.sc") (include "../maths/intersection.sc") ; i can't decide if we need a vertex structure here... (define (triangle a b c) (let ((n (calc-normal a b c))) (list 'triangle a b c n n n))) (define (triangle-with-normals a b c na nb nc) (list 'triangle a b c na nb nc)) (define (triangle? t) (eq? (car t) 'triangle)) (define (triangle-a t) (list-ref t 1)) (define (triangle-b t) (list-ref t 2)) (define (triangle-c t) (list-ref t 3)) (define (triangle-na t) (list-ref t 4)) (define (triangle-nb t) (list-ref t 5)) (define (triangle-nc t) (list-ref t 6)) (define (calc-normal a b c) (vnorm (vcross (vsub b c) (vsub a b)))) (define (bary-interpolate va vb vc b) (vadd (vadd (vmul va (vx b)) (vmul vb (vy b))) (vmul vc (vz b)))) (define (triangle/line-dist t l) 0) (define (triangle/line-intersect? t l) (let ((bary (triangle/line-intersect->bary t l))) (if bary #t #f))) (define (triangle/line-intersect t l) (let ((tb (triangle/line-intersect->bary t l))) (cond (tb (let ((tt (car tb)) (bary (cadr tb))) (intersection tt (bary-interpolate (triangle-a t) (triangle-b t) (triangle-c t) bary) (bary-interpolate (triangle-na t) (triangle-nb t) (triangle-nc t) bary)))) (else #f)))) (define (triangle/line-intersect->bary t l) (let* ((u (vsub (triangle-a t) (triangle-c t))) (v (vsub (triangle-b t) (triangle-c t))) (n (vcross v u)) (start (line-start l)) (end (line-end l))) (cond ((zero? (vmag n)) #f) (else (let* ((ray (vsub end start)) (w0 (vsub start (triangle-c t))) (a (- (vdot n w0))) (b (vdot n ray))) ; if b is small, ray is parallel (cond ((zero? b) #f) (else (let ((r (/ a b))) (cond ((< r 0) #f) ((> r 1) #f) (else (let* ((I (vadd start (vmul ray r))) (uu (vdot u u)) (uv (vdot u v)) (vv (vdot v v)) (w (vsub I (triangle-c t))) (wu (vdot w u)) (wv (vdot w v)) (D (- (* uv uv) (* uu vv))) (baryx (/ (- (* uv wv) (* vv wu)) D))) (cond ((or (< baryx 0) (> baryx 1)) #f) (else (let ((baryy (/ (- (* uv wu) (* uu wv)) D))) (cond ((or (< baryy 0) (> baryy 1)) #f) (else (let ((baryz (- 1 (+ baryx baryy)))) (cond ((or (< baryz 0) (> baryz 1)) #f) (else (list r (vector baryx baryy baryz)))))))))))))))))))))