示例#1
0
func TestBoundingBoxSplit(t *testing.T) {
	box := &BoundingBox{
		MinVolume: [3]float64{-3.18, -3.96, -1.77},
		MaxVolume: [3]float64{4.58, 1.74, 4.56},
	}

	ray := &ray.Ray{
		Start:     *maths.NewVec3(4.49, -7.3, 5.53),
		Direction: *maths.NewVec3(-0.60, 0.5, -0.62),
	}
	ray.Init()

	if !box.Intersect(ray) {
		t.Error("ray should intersect big box")
	}

	left, right := box.Split(2, 1.39)

	assertEqualVectors(t, maths.NewVec3(-3.18, -3.96, -1.77), maths.NewVec3Array(left.MinVolume))
	assertEqualVectors(t, maths.NewVec3(-3.18, -3.96, 1.39), maths.NewVec3Array(right.MinVolume))
	assertEqualVectors(t, maths.NewVec3(4.58, 1.74, 1.39), maths.NewVec3Array(left.MaxVolume))
	assertEqualVectors(t, maths.NewVec3(4.58, 1.74, 4.56), maths.NewVec3Array(right.MaxVolume))

	if box.IntersectWall(2, 1.39, ray) {
		t.Error("ray shouldn't intersect the wall")
	}

	if right.Intersect(ray) {
		t.Error("ray shouldn't intersect right")
	}

	if !left.Intersect(ray) {
		t.Error("ray should intersect left")
	}
}
示例#2
0
// IntersectTriangle checks if the bounding box intersects with a triangle
// 1) To have a vertex in the box
// 2) The edge of the triangle intersects with the box
// 3) The middle of the triangle to be inside the box, while the vertices aren't
func (b *BoundingBox) IntersectTriangle(A, B, C *maths.Vec3) bool {
	if b.Inside(A) || b.Inside(B) || b.Inside(C) {
		return true
	}
	// we construct the ray from A->B, A->C, etc and check whether it intersects with the box
	triangle := [3]*maths.Vec3{A, B, C}
	ray := &ray.Ray{}
	for rayStart := 0; rayStart < 3; rayStart++ {
		for rayEnd := rayStart + 1; rayEnd < 3; rayEnd++ {
			ray.Start = *(triangle[rayStart])
			ray.Direction = *maths.MinusVectors(triangle[rayEnd], triangle[rayStart])
			ray.Init()
			// Check if there's intersection between AB and the box (example)
			if b.Intersect(ray) {
				// we check whether there's intersection between BA and the Box too
				// to be sure the edge isn't outside the box
				//    _____
				//    |    | <----AB there is intersection, but BA----->
				//    |____|
				ray.Start = *triangle[rayEnd]
				ray.Direction = *maths.MinusVectors(triangle[rayStart], triangle[rayEnd])
				ray.Init()
				if b.Intersect(ray) {
					return true
				}
			}
		}
	}
	// we have to check if the inside of the triangle intersects with the box
	AB := maths.MinusVectors(B, A)
	AC := maths.MinusVectors(C, A)
	ABxAC := maths.CrossProduct(AB, AC)
	distance := maths.DotProduct(A, ABxAC)
	rayEnd := &maths.Vec3{}

	for edgeMask := 0; edgeMask < 7; edgeMask++ {
		for axis := uint(0); axis < 3; axis++ {
			if edgeMask&(1<<axis) != 0 {
				continue
			}

			if edgeMask&1 != 0 {
				ray.Start.X = b.MaxVolume[0]
			} else {
				ray.Start.X = b.MinVolume[0]
			}

			if edgeMask&2 != 0 {
				ray.Start.Y = b.MaxVolume[1]
			} else {
				ray.Start.Y = b.MinVolume[1]
			}

			if edgeMask&4 != 0 {
				ray.Start.Z = b.MaxVolume[2]
			} else {
				ray.Start.Z = b.MinVolume[2]
			}

			*rayEnd = ray.Start
			rayEnd.SetDimension(int(axis), b.MaxVolume[axis])

			if (maths.DotProduct(&ray.Start, ABxAC)-distance)*(maths.DotProduct(rayEnd, ABxAC)-distance) <= 0 {
				ray.Direction = *maths.MinusVectors(rayEnd, &ray.Start)
				ray.Init()
				intersected, distance := IntersectTriangle(ray, A, B, C)
				if intersected && distance < 1.0000001 {
					return true
				}
			}
		}
	}

	return false
}