Ива обнови решението на 21.11.2018 14:01 (преди 9 месеца)
+package main
+
+import "github.com/fmi/go-homework/geom"
+import "math"
+
+type Vector struct {
+ X, Y, Z float64
+}
+
+type Ray struct {
+ Origin Vector
+ Direction Vector
+}
+
+type Intersectable interface {
+ Intersect(ray Ray) bool
+}
+
+type Triangle struct {
+ a, b, c geom.Vector
+}
+type Sphere struct {
+ radius float64
+ origin geom.Vector
+}
+
+type Quad struct {
+ a, b, c, d geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ if geom.Len(a)+geom.Len(b) > geom.Len(c) && geom.Len(b)+geom.Len(c) > geom.Len(a) && geom.Len(a)+geom.Len(c) > geom.Len(b) {
+ return Triangle{a, b, c}
+ } else {
+ return Triangle{geom.NewVector(0, 0, 0), geom.NewVector(0, 0, 0), geom.NewVector(0, 0, 0)}
+ }
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{a, b, c, d}
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{r, origin}
+}
+
+func (tr Triangle) Intersect(ray geom.Ray) bool {
+ var n geom.Vector
+ originNorm := geom.NewVector(0, 0, 0)
+
+ n = geom.Cross(geom.Sub(tr.b, tr.a), geom.Sub(tr.c, tr.a))
+ d := math.Abs(geom.Dot(n, geom.NewVector(ray.Direction.X, ray.Direction.Y, ray.Direction.Z)))
+
+ if d > 0.0000001 {
+ t := geom.Dot(geom.Sub(originNorm, geom.NewVector(ray.Origin.X, ray.Origin.Y, ray.Origin.Z)), n) / d
+ return (t >= 0)
+ } else {
+ return false
+ }
+}
+
+
+func (s Sphere) Intersect(ray geom.Ray) bool {
+ area := NewTriangle(geom.NewVector(s.radius, 0, 0), geom.NewVector(0, s.radius, 0), geom.NewVector(0, 0, s.radius))
+ secondarea := NewTriangle(geom.NewVector(s.radius, s.radius, 0), geom.NewVector(0, s.radius, s.radius), geom.NewVector(s.radius, 0, s.radius))
+
+ n := geom.Cross(geom.Sub(area.b, area.a), geom.Sub(area.c, area.a))
+ p := geom.Cross(geom.Sub(secondarea.b, secondarea.a), geom.Sub(secondarea.c, secondarea.a))
+
+ tvalue := geom.Dot(geom.Sub(ray.Origin, ray.Origin), n) / geom.Dot(ray.Direction, n)
+ tsecvalue := geom.Dot(geom.Sub(ray.Origin, ray.Origin), p) / geom.Dot(ray.Direction, p)
+
+ if area.Intersect(ray) {
+ vect := geom.Sub(geom.Add(ray.Origin, geom.Mul(ray.Direction, tvalue)), ray.Origin)
+ return (math.Sqrt(geom.Dot(vect, vect)) <= s.radius)
+ } else if secondarea.Intersect(ray) {
+ vect := geom.Sub(geom.Add(ray.Origin, geom.Mul(ray.Direction, tsecvalue)), ray.Origin)
+ return (math.Sqrt(geom.Dot(vect, vect)) <= s.radius)
+ } else {
+ return false
+ }
+}
+
+func (q Quad) Intersect(ray geom.Ray) bool {
+ triangle := NewTriangle(q.a, q.b, q.c)
+ opositeTriangle := NewTriangle(q.b, q.c, q.d)
+ if triangle.Intersect(ray) || opositeTriangle.Intersect(ray) {
+ return true
+ } else {
+ return false
+ }
+}