-
Notifications
You must be signed in to change notification settings - Fork 3
/
plane.go
66 lines (60 loc) · 1.67 KB
/
plane.go
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package main
import (
"fmt"
)
type Plane struct {
q Vec3 // A point on the plane
normal Vec3 // A vector normal to the plane
}
type PlaneObject struct {
*Plane `json:"-"`
Mat *Material `json:"-"`
V1, V2, V3 Vec3
MatName string `json:"mat"`
}
func (p *PlaneObject) Initialize(materials map[string]*Material) error {
m, ok := materials[p.MatName]
if !ok {
return fmt.Errorf("Cannot find material %s", p.MatName)
}
p.Mat = m
// Construct two vectors, v2v1 and v3v1; their cross product is normal
// to the plane.
l1 := p.V2.Sub(p.V1)
l2 := p.V3.Sub(p.V1)
p.Plane = &Plane{
q: p.V1,
normal: l1.Cross(l2),
}
return nil
}
// Intersect determines the intersection of r with p.
//
// A point p is on the plane if normal·(p - q) = 0.
// Points on the ray are of the form P(t) = ray.V + t*ray.D for t >= 0.
// Thus intersections have the solution
// normal · (q - ray.V)
// t = ---------------------
// ray.D · normal
// If t < 0, then the intersection is behind the vantage point and doesn't count.
func (p *PlaneObject) Intersect(r Ray) (float64, *Material, Vec3, Vec3, bool) {
denom := r.D.Dot(p.normal)
if denom == 0 {
// Ray is parallel to the plane
return 0, nil, Vec3{}, Vec3{}, false
}
num := p.normal.Dot(p.q.Sub(r.V))
t := num / denom
if t < minDistance {
// Intersection is behind the vantage point.
return 0, nil, Vec3{}, Vec3{}, false
}
normal := p.normal
if denom > 0 {
// If the ray is less than 90 degrees from the normal line
// (dot product > 0), we're hitting the 'back' of the plane
// and we want to return the opposite normal.
normal = p.normal.Mul(-1)
}
return t, p.Mat, r.At(t), normal, true
}