예제 #1
0
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(),
	}}
}
예제 #2
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
}
예제 #3
0
func (p *Plane) DistanceToPoint(pt *gnr.Vector3f) float64 {
	n := gnr.CopyVector3f(p.Normal).Normalize()
	return math.Abs(gnr.VectorProduct(n, pt) + p.Distance)
}