blob: ac5e9968a9b8730361d5952c9204c2c4e1964f73 (
plain)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
package main
import (
maths "math"
)
//HitRecord
type HitRecord struct {
Valid bool
P Vec3
N Vec3
T float64
F bool
Mat Material
}
func (rec *HitRecord) SetFaceNormal(r Ray, out_n Vec3) {
rec.F = r.Direction.Dot(out_n) < 0;
if rec.F {
rec.N = out_n;
} else {
rec.N = out_n.Neg();
}
}
//Hittable
type Hittable interface {
Hit(r Ray, ray_t Interval) (rec HitRecord)
}
//Sphere < Hittable
type Sphere struct {
Origin Vec3
Radius float64
Mat Material
}
func (s Sphere) Hit(r Ray, ray_t Interval) (rec HitRecord) {
oc := s.Origin.Sub(r.Origin);
a := r.Direction.MagSqr();
h := r.Direction.Dot(oc);
c := oc.MagSqr() - maths.Pow(s.Radius, 2);
disc := maths.Pow(h, 2) - a*c;
if disc < 0 {
return;
}
sqrtd := maths.Sqrt(disc);
root := (h - sqrtd) / a;
if !ray_t.Surround(root) {
root = (h + sqrtd) / a;
if !ray_t.Surround(root) {
return;
}
}
rec.T = root;
rec.P = r.At(rec.T);
out_n := rec.P.Sub(s.Origin).Div(SplatVec3(s.Radius));
rec.SetFaceNormal(r, out_n);
rec.Mat = s.Mat;
rec.Valid = true;
return;
}
//Hittables < Hittable
type Hittables struct {
Objects []Hittable
}
func (l *Hittables) Add(o Hittable) {
l.Objects = append(l.Objects, o);
}
func (l Hittables) Hit(r Ray, ray_t Interval) (rec HitRecord) {
closest_so_far := ray_t.Max;
for _, o := range l.Objects {
temp_rec := o.Hit(r, Interval{ray_t.Min, closest_so_far});
if temp_rec.Valid {
rec = temp_rec;
closest_so_far = rec.T;
}
}
return;
}
|