func (t *Triangle) ToPlane() *Plane { v1 := gnr.VectorDifference(t.Points[1], t.Points[0]) v2 := gnr.VectorDifference(t.Points[2], t.Points[0]) normal := gnr.VectorCross(v1, v2) return &Plane{ Normal: normal, Distance: -gnr.VectorProduct(normal, t.Points[0]), } }
func (s *Sphere) RayInteraction(r *gnr.Ray) []*gnr.InteractionResult { // Ray: {P | P = r.Origin + t * r.Direction} // Sphere: {P | mag(P - s.Center)^2 - s.Radius^2 = 0} // substitution // mag(r.Origin + t * r.Direction)^2 - s.Radius^2 = 0 d := gnr.VectorDifference(r.Origin, s.Center) p := 2 * gnr.VectorProduct(r.Direction, d) q := math.Pow(d.Magnitude(), 2) - math.Pow(s.Radius, 2) p2 := math.Pow(p, 2) inSqrt := p2/4 - q if inSqrt < 0 { return []*gnr.InteractionResult{} } sqrt := math.Sqrt(inSqrt) t1 := -p/2 + sqrt t2 := -p/2 - sqrt P1 := gnr.VectorSum(r.Origin, gnr.CopyVector3f(r.Direction).ScalarMultiply(t1)) P2 := gnr.VectorSum(r.Origin, gnr.CopyVector3f(r.Direction).ScalarMultiply(t2)) irs := []*gnr.InteractionResult{ {Color: gnr.ColorWhite}, {Color: gnr.ColorWhite}, } irs[0].PointOfImpact = P1 irs[0].Normal = gnr.VectorDifference(P1, s.Center) irs[0].Distance = gnr.VectorDifference(P1, r.Origin).Magnitude() if inSqrt != 0 { irs[1].PointOfImpact = P2 irs[1].Normal = gnr.VectorDifference(P2, s.Center) irs[1].Distance = gnr.VectorDifference(P2, r.Origin).Magnitude() } else { irs = irs[0:1] } return irs }
func (p *Plane) RayInteraction(r *gnr.Ray) []*gnr.InteractionResult { // Ray: {P | P = r.Origin + t * r.Direction} // Plane: {P | P * p.Normal + p.Distance = 0} // Substitute: (r.Origin + t * r.Direction) * p.Normal + p.Distance = 0 t := -(p.Distance + gnr.VectorProduct(r.Origin, p.Normal)) / gnr.VectorProduct(r.Direction, p.Normal) if t < 0 { return []*gnr.InteractionResult{} } impact := gnr.CopyVector3f(r.Direction).ScalarMultiply(t).Add(r.Origin) return []*gnr.InteractionResult{{ Color: gnr.ColorWhite, PointOfImpact: impact, Normal: gnr.CopyVector3f(p.Normal), Distance: gnr.VectorDifference(impact, r.Origin).Magnitude(), }} }
func (s *Sphere) Contains(p *gnr.Vector3f) bool { // TODO: Research if there’s a way to check this without being susceptible // to IEEE 754 rounding errors. return gnr.VectorDifference(p, s.Center).Magnitude()-s.Radius < Epsilon }
func (t *Triangle) Area() float64 { v1 := gnr.VectorDifference(t.Points[1], t.Points[0]) v2 := gnr.VectorDifference(t.Points[2], t.Points[0]) return gnr.VectorCross(v1, v2).Magnitude() / 2 }