diff options
| author | Martin Lehoux <martin@lehoux.net> | 2020-04-04 17:53:48 -0700 |
|---|---|---|
| committer | Martin Lehoux <martin@lehoux.net> | 2020-04-04 17:53:48 -0700 |
| commit | f230ab264adebce9868d088ea408445d66254963 (patch) | |
| tree | a7c4635e80b1d905b32e7bd02e372897bff2e905 /hitable.go | |
| parent | 1e77295876e20702d5ccb477b2f01df980723f04 (diff) | |
feat - Add several entities
Diffstat (limited to 'hitable.go')
| -rw-r--r-- | hitable.go | 50 |
1 files changed, 40 insertions, 10 deletions
@@ -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{} } |
