Beispiel #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(),
	}}
}
Beispiel #2
0
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]),
	}
}
Beispiel #3
0
func (t *Triangle) Contains(p *gnr.Vector3f) bool {
	tp := t.ToPlane()
	na := (&Triangle{
		Points: [3]*gnr.Vector3f{t.Points[0], t.Points[1], p},
	}).ToPlane().Normal
	nb := (&Triangle{
		Points: [3]*gnr.Vector3f{t.Points[1], t.Points[2], p},
	}).ToPlane().Normal
	nc := (&Triangle{
		Points: [3]*gnr.Vector3f{t.Points[2], t.Points[0], p},
	}).ToPlane().Normal

	denom := math.Pow(tp.Normal.Magnitude(), 2)
	ba := gnr.VectorProduct(tp.Normal, na) / denom
	bb := gnr.VectorProduct(tp.Normal, nb) / denom
	bc := gnr.VectorProduct(tp.Normal, nc) / denom

	return ba >= 0 && ba <= 1 && bb >= 0 && bb <= 1 && bc >= 0 && bc <= 1
}
func (aab *AxisAlignedBox) RayInteraction(r *gnr.Ray) []*gnr.InteractionResult {
	planes := []gnr.Object{
		&Plane{
			Normal:   &gnr.Vector3f{-1, 0, 0},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{-1, 0, 0}, aab.Min),
		},
		&Plane{
			Normal:   &gnr.Vector3f{1, 0, 0},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{1, 0, 0}, aab.Max),
		},
		&Plane{
			Normal:   &gnr.Vector3f{0, -1, 0},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{0, -1, 0}, aab.Min),
		},
		&Plane{
			Normal:   &gnr.Vector3f{0, 1, 0},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{0, 1, 0}, aab.Max),
		},
		&Plane{
			Normal:   &gnr.Vector3f{0, 0, -1},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{0, 0, -1}, aab.Min),
		},
		&Plane{
			Normal:   &gnr.Vector3f{0, 0, 1},
			Distance: -gnr.VectorProduct(&gnr.Vector3f{0, 0, 1}, aab.Max),
		},
	}
	irs := gnr.ObjectSlice(planes).AggregateSliceInteractionResult(func(irs []*gnr.InteractionResult, o gnr.Object) []*gnr.InteractionResult {
		newIrs := o.RayInteraction(r)
		p := o.(*Plane)
		newIrs = gnr.InteractionResultSlice(newIrs).SelectInteractionResult(func(ir *gnr.InteractionResult) *gnr.InteractionResult {
			// Correct for IEEE754 errors by aligning PoIs with sides of box
			if math.Abs(p.Normal.X) == 1 {
				ir.PointOfImpact.X = -p.Distance * p.Normal.X
			}
			if math.Abs(p.Normal.Y) == 1 {
				ir.PointOfImpact.Y = -p.Distance * p.Normal.Y
			}
			if math.Abs(p.Normal.Z) == 1 {
				ir.PointOfImpact.Z = -p.Distance * p.Normal.Z
			}
			return ir
		})
		return append(irs, newIrs...)
	})
	irs = gnr.InteractionResultSlice(irs).Where(func(ir *gnr.InteractionResult) bool {
		return aab.Contains(ir.PointOfImpact)
	})
	return irs
}
Beispiel #5
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
}
Beispiel #6
0
func (p *Plane) DistanceToPoint(pt *gnr.Vector3f) float64 {
	n := gnr.CopyVector3f(p.Normal).Normalize()
	return math.Abs(gnr.VectorProduct(n, pt) + p.Distance)
}