aboutsummaryrefslogtreecommitdiff
path: root/hitable.go
diff options
context:
space:
mode:
authorMartin Lehoux <martin@lehoux.net>2020-04-04 17:53:48 -0700
committerMartin Lehoux <martin@lehoux.net>2020-04-04 17:53:48 -0700
commitf230ab264adebce9868d088ea408445d66254963 (patch)
treea7c4635e80b1d905b32e7bd02e372897bff2e905 /hitable.go
parent1e77295876e20702d5ccb477b2f01df980723f04 (diff)
feat - Add several entities
Diffstat (limited to 'hitable.go')
-rw-r--r--hitable.go50
1 files changed, 40 insertions, 10 deletions
diff --git a/hitable.go b/hitable.go
index ed18a5d..bc9f9bc 100644
--- a/hitable.go
+++ b/hitable.go
@@ -9,8 +9,25 @@ type HitRecord struct {
}
type Hitable interface {
- Hit(ray Ray) HitRecord
- Normal(point Vec3D) Vec3D
+ Hit(ray Ray, t_min float64, t_max float64) HitRecord
+ Normal(point Vec3D, ray Ray) Vec3D
+}
+
+type HitableList []Hitable
+
+func (hitable_list HitableList) Hit(ray Ray, t_min float64, t_max float64) HitRecord {
+ closest_hit := HitRecord{T_MAX, Vec3D{}, Vec3D{}}
+ for _, hitable := range hitable_list {
+ hit := hitable.Hit(ray, t_min, closest_hit.time)
+ if hit.time > 0 {
+ closest_hit = hit
+ }
+ }
+ if closest_hit.time < T_MAX {
+ return closest_hit
+ } else {
+ return HitRecord{}
+ }
}
type Sphere struct {
@@ -18,20 +35,33 @@ type Sphere struct {
radius float64
}
-func (sphere Sphere) Normal(point Vec3D) Vec3D {
- return SubVec3D(point, sphere.center).Unit()
+func (sphere Sphere) Normal(point Vec3D, ray Ray) Vec3D {
+ out_normal := SubVec3D(point, sphere.center).Unit()
+ if DotProduct(ray.direction, out_normal) < 0.0 {
+ return out_normal
+ } else {
+ return out_normal.Invert()
+ }
}
-func (sphere Sphere) Hit(ray Ray) HitRecord {
+func (sphere Sphere) Hit(ray Ray, t_min float64, t_max float64) HitRecord {
oc := SubVec3D(ray.origin, sphere.center)
a := DotProduct(ray.direction, ray.direction)
b := 2.0 * DotProduct(oc, ray.direction)
c := DotProduct(oc, oc) - sphere.radius*sphere.radius
discriminant := b*b - 4*a*c
- if discriminant < 0 {
- return HitRecord{}
+ if discriminant > 0 {
+ root := math.Sqrt(discriminant)
+ time := (-b - root) / (2.0 * a)
+ if t_min < time && time < t_max {
+ point := ray.PointAt(time)
+ return HitRecord{time, point, sphere.Normal(point, ray)}
+ }
+ time = (-b + root) / (2.0 * a)
+ if t_min < time && time < t_max {
+ point := ray.PointAt(time)
+ return HitRecord{time, point, sphere.Normal(point, ray)}
+ }
}
- time := (-b - math.Sqrt(discriminant)) / (2.0 * a)
- point := ray.PointAt(time)
- return HitRecord{time, point, sphere.Normal(point)}
+ return HitRecord{}
}