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) 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) DistanceToPoint(pt *gnr.Vector3f) float64 { n := gnr.CopyVector3f(p.Normal).Normalize() return math.Abs(gnr.VectorProduct(n, pt) + p.Distance) }