Павел обнови решението на 21.11.2018 13:21 (преди 9 месеца)
+package main
+
+import (
+ "math"
+ "github.com/fmi/go-homework/geom"
+)
+
+type Triangle struct {
+ A, B, C geom.Vector
+}
+
+func NewTriangle(a, b, c geom.Vector) Triangle {
+ return Triangle{A: a, B: b, C: c}
+}
+
+type Quad struct {
+ A, B, C, D geom.Vector
+}
+
+func NewQuad(a, b, c, d geom.Vector) Quad {
+ return Quad{A: a, B: b, C: c, D: d}
+}
+
+type Sphere struct {
+ Origin geom.Vector
+ R float64
+}
+
+func NewSphere(origin geom.Vector, r float64) Sphere {
+ return Sphere{Origin: origin, R: r}
+}
+
+func (triangle Triangle) Intersect(ray geom.Ray) bool {
+ // Describing the triangle's plane - ax + by + cz = d
+ AB := geom.Sub(triangle.B, triangle.A)
+ BC := geom.Sub(triangle.C, triangle.B)
+ n := geom.Cross(AB, BC) // normal vector
+ d := geom.Dot(n, triangle.A) // same for triangle.B and triangle.C
+
+ denom := geom.Dot(n, ray.Direction)
+
+ if math.Abs(d - denom) < 0.0000001 { // check if line is in the plane
+ return true
+ }
+
+ if math.Abs(denom) < 0.0000001 { // check if line is parallel to the plane
+ return false
+ }
+
+ distance := geom.Dot(n, geom.Sub(triangle.A, ray.Origin)) // the distance from the
+ P := geom.Add(ray.Origin, geom.Mul(ray.Direction, distance)) // the intersection point
+
+ edge0 := geom.Sub(triangle.B, triangle.A)
+ edge1 := geom.Sub(triangle.C, triangle.B)
+ edge2 := geom.Sub(triangle.A, triangle.C)
+
+ c0 := geom.Sub(P, triangle.A)
+ c1 := geom.Sub(P, triangle.B)
+ c2 := geom.Sub(P, triangle.C)
+
+ if (geom.Dot(n, geom.Cross(edge0, c0)) > 0.0000001 &&
+ geom.Dot(n, geom.Cross(edge1, c1)) > 0.0000001 &&
+ geom.Dot(n, geom.Cross(edge2, c2)) > 0.0000001) {
+ return true;
+ }
+
+ return false
+}
+
+func (quad Quad) Intersect(ray geom.Ray) bool {
+ // TODO
+ return true
+}
+
+func (sphere Sphere) Intersect(ray geom.Ray) bool {
+ originSub := geom.Sub(ray.Origin, sphere.Origin)
+ originSubSquared := geom.Dot(originSub, originSub)
+ originSubRayDirectionDot := geom.Dot(originSub, ray.Direction)
+ determinant := math.Pow(originSubRayDirectionDot, 2) - originSubSquared - math.Pow(sphere.R, 2)
+ if determinant >= 0 {
+ return true // if determinant is 0, the ray touches the sphere, if larger it goes through it.
+ }
+ return false
+}