aboutsummaryrefslogtreecommitdiff
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
parent1e77295876e20702d5ccb477b2f01df980723f04 (diff)
feat - Add several entities
-rw-r--r--color.go4
-rw-r--r--hitable.go50
-rw-r--r--main.go10
3 files changed, 50 insertions, 14 deletions
diff --git a/color.go b/color.go
index 1ac8141..b8776ca 100644
--- a/color.go
+++ b/color.go
@@ -16,8 +16,8 @@ func LinearBlend(color1 Color, color2 Color, param float64) Color {
}
}
-func RayColor(ray Ray, hitable Hitable) Color {
- hit := hitable.Hit(ray)
+func RayColor(ray Ray, hitable_list HitableList) Color {
+ hit := hitable_list.Hit(ray, T_MIN, T_MAX)
if hit.time > 0.0 {
vec := AddVec3D(hit.normal, Vec3D{1.0, 1.0, 1.0})
return LinearBlend(Color{vec.x, vec.y, vec.z}, Color{0.0, 0.0, 0.0}, 0.5)
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{}
}
diff --git a/main.go b/main.go
index a1cb2c9..daf2718 100644
--- a/main.go
+++ b/main.go
@@ -2,19 +2,25 @@ package main
const HEIGHT = 100
const WIDTH = 200
+const T_MIN = 0.001
+const T_MAX = 1000
func main() {
LOWER_LEFT_CORNER := Vec3D{-2.0, -1.0, -1.0}
ORIGIN := Vec3D{0.0, 0.0, 0.0}
HORIZONTAL := Vec3D{4.0, 0.0, 0.0}
VERTICAL := Vec3D{0.0, 2.0, 0.0}
- SPHERE := Sphere{Vec3D{0.0, 0.0, -1.0}, .5}
+
+ SPHERE := Sphere{Vec3D{0.0, 0.0, -1.0}, 0.5}
+ EARTH := Sphere{Vec3D{0.0, -100.5, -1.0}, 100.0}
+
+ WORLD := HitableList{EARTH, SPHERE}
frame := Frame{}
for x := 0; x < HEIGHT; x++ {
for y := 0; y < WIDTH; y++ {
u, v := float64(y)/float64(WIDTH), float64(x)/float64(HEIGHT)
ray := Ray{ORIGIN, AddVec3D(AddVec3D(LOWER_LEFT_CORNER, ScalarProduct(u, HORIZONTAL)), ScalarProduct(v, VERTICAL))}
- color := RayColor(ray, SPHERE)
+ color := RayColor(ray, WORLD)
frame[HEIGHT-1-x][y] = color.ToPixel()
}
}