aboutsummaryrefslogtreecommitdiff
path: root/hittable.go
diff options
context:
space:
mode:
Diffstat (limited to 'hittable.go')
-rw-r--r--hittable.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/hittable.go b/hittable.go
new file mode 100644
index 0000000..5320a0f
--- /dev/null
+++ b/hittable.go
@@ -0,0 +1,87 @@
+package main
+
+import (
+ maths "math"
+)
+
+//HitRecord
+
+type HitRecord struct {
+ Valid bool
+ P Vec3
+ N Vec3
+ T float64
+}
+
+func (rec *HitRecord) SetFaceNormal(r Ray, out_n Vec3) {
+ if r.Direction.Dot(out_n) < 0 {
+ 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
+}
+
+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(Splat(s.Radius));
+ rec.SetFaceNormal(r, out_n);
+ 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;
+}