Добромир обнови решението на 20.11.2018 19:29 (преди 9 месеца)
+package main
+
+import (
+ "github.com/fmi/go-homework/geom"
+ "math"
+)
+
+type triangle struct {
+ a, b, c geom.Vector
+}
+
+type quad struct {
+ a, b, c, d geom.Vector
+}
+
+type sphere struct {
+ center geom.Vector
+ radius float64
+}
+
+func NewTriangle(a, b, c geom.Vector) geom.Intersectable {
+ return triangle{a, b, c}
+}
+
+func (tr triangle) Intersect(ray geom.Ray) bool {
+ normal := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(tr.c, tr.a))
+
+ nDotProductDir := dotProduct(normal, ray.Direction)
+ if nDotProductDir == 0 {
+ return false
+ }
+
+ d := dotProduct(normal, tr.a)
+ t := (d - dotProduct(normal, ray.Origin)) / nDotProductDir
+
+ // So point is behind ray's origin?
+ if t < 0 {
+ return false
+ }
+
+ // Intersection point
+ p := addVectors(ray.Origin, scalarMultiply(ray.Direction, t))
+
+ vertex := crossProduct(subtractVectors(tr.b, tr.a), subtractVectors(p, tr.a))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ vertex = crossProduct(subtractVectors(tr.c, tr.b), subtractVectors(p, tr.b))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ vertex = crossProduct(subtractVectors(tr.a, tr.c), subtractVectors(p, tr.c))
+ if dotProduct(vertex, normal) <= 0 {
+ return false
+ }
+
+ return true
+}
+
+func NewQuad(a, b, c, d geom.Vector) geom.Intersectable {
+ return quad{a, b, c, d}
+}
+
+func (q quad) Intersect(ray geom.Ray) bool {
+ return NewTriangle(q.a, q.b, q.d).Intersect(ray) ||
+ NewTriangle(q.d, q.b, q.c).Intersect(ray)
Напиши си няколко теста за този случай. Но наистина няколко, не само вариация на един и същи тест. По какво могат да се различават четириъгълниците?
+}
+
+func NewSphere(center geom.Vector, radius float64) geom.Intersectable {
+ return sphere{center, radius}
+}
+
+func (s sphere) Intersect(ray geom.Ray) bool {
+ L := subtractVectors(s.center, ray.Origin)
+ tca := dotProduct(L, ray.Direction)
Струва ми се, че неявно предполагаш ray.Direction
за единичен вектор.
+
+ d2 := dotProduct(L, L) - tca*tca
+ if d2 > s.radius {
+ return false
+ }
+
+ thc := math.Sqrt(s.radius - d2)
+ t0 := tca - thc
+ t1 := tca + thc
+ if t0 > t1 {
+ t0, t1 = t1, t0
+ }
+
+ if t0 < 0 || t1 < 0 {
+ return false
+ }
+
+ return true
+}
+
+func dotProduct(a geom.Vector, b geom.Vector) float64 {
+ return a.X*b.X + a.Y*b.Y + a.Z*b.Z
+}
+
+func crossProduct(a geom.Vector, b geom.Vector) geom.Vector {
+ return geom.NewVector(
+ a.Y*b.Z-a.Z*b.Y,
+ a.Z*b.X-a.X*b.Z,
+ a.X*b.Y-a.Y*b.X)
+}
+
+func addVectors(a, b geom.Vector) geom.Vector {
+ return geom.NewVector(a.X+b.X, a.Y+b.Y, a.Z+b.Z)
+}
+
+func subtractVectors(a, b geom.Vector) geom.Vector {
+ return geom.NewVector(a.X-b.X, a.Y-b.Y, a.Z-b.Z)
+}
+
+func scalarMultiply(vector geom.Vector, b float64) geom.Vector {
+ return geom.NewVector(vector.X*b, vector.Y*b, vector.Z*b)
+}