Example #1
0
func TestCollideBoxBox(t *testing.T) {
	a, b, cons := NewBody(NewBox(0.5, 0.5, 0.5)), NewBody(NewBox(1, 1, 1)), newManifold()
	if _, _, cs := collideBoxBox(a, b, cons); len(cs) == 0 || cs[0].depth != -1.58 ||
		dumpV3(cs[0].point) != "{-1.0 0.5 0.5}" || dumpV3(cs[0].normal) != "{-1.0 -0.0 -0.0}" {
		depth, point, norm := cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal)
		t.Errorf("Boxes should collide since one is inside the other %f %s %s", depth, point, norm)
	}

	// just inside of contact range.
	a.World().Loc.SetS(0, 0, 1.49)
	if _, _, cs := collideBoxBox(a, b, cons); len(cs) != 4 || !lin.Aeq(cs[0].depth, -0.09) ||
		dumpV3(cs[0].point) != "{0.5 0.5 1.0}" || dumpV3(cs[0].normal) != "{0.0 0.0 1.0}" {
		depth, point, norm := cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal)
		t.Errorf("Boxes should collide %f %s %s", depth, point, norm)
	}
	a.World().Loc.SetS(0, 1.49, 0)
	if _, _, cs := collideBoxBox(a, b, cons); len(cs) != 4 || !lin.Aeq(cs[0].depth, -0.09) ||
		dumpV3(cs[0].point) != "{0.5 1.0 0.5}" || dumpV3(cs[0].normal) != "{0.0 1.0 0.0}" {
		depth, point, norm := cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal)
		t.Errorf("Boxes should collide %f %s %s", depth, point, norm)
	}
	a.World().Loc.SetS(1.49, 0, 0)
	if _, _, cs := collideBoxBox(a, b, cons); len(cs) != 4 || !lin.Aeq(cs[0].depth, -0.09) ||
		dumpV3(cs[0].point) != "{1.0 0.5 0.5}" || dumpV3(cs[0].normal) != "{1.0 0.0 0.0}" {
		depth, point, norm := cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal)
		t.Errorf("Boxes should collide %f %s %s", depth, point, norm)
	}

	// just outside of contact range.
	a.World().Loc.SetS(0, 0, 1.6)
	if _, _, cs := collideBoxBox(a, b, cons); len(cs) != 0 {
		t.Errorf("Boxes should not collide")
	}
}
Example #2
0
func TestRoundTrip(t *testing.T) {
	cam, _, _ := initScene()
	cx, cy, cz := 0.0, 0.0, 14.0 // camera location to
	cam.SetLocation(cx, cy, cz)  // ...point directly at 0, 0, 0

	// Create the matricies to go between clip and world space.
	toClip := lin.NewM4().Mult(cam.vm, cam.pm)
	toWorld := lin.NewM4().Mult(cam.ipm, cam.ivm)
	if !lin.NewM4().Mult(toClip, toWorld).Aeq(lin.M4I) {
		t.Errorf("Invalid world<->clip matricies")
	}

	// start with world coordinates carefully chosen to give x=1, y=1 clip values
	px, py := 6.002062, 3.751289
	pnt := lin.NewV4().SetS(px, py, 0, 1)
	pnt.MultMv(toClip, pnt)
	if !lin.Aeq(pnt.X/pnt.W, 1) || !lin.Aeq(pnt.Y/pnt.W, 1) {
		t.Errorf("%f %f gave clip %f %f %f, expected (1 1 -0.071429)", px, py, pnt.X, pnt.Y, pnt.Z)
	}

	// now reverse back to world coordinates.
	pnt.MultMv(toWorld, pnt)
	if !lin.Aeq(pnt.X, px) || !lin.Aeq(pnt.Y, py) {
		t.Errorf("got point %f %f %f, expected x=%f y=%f", pnt.X, pnt.Y, pnt.Z, px, py)
	}
}
Example #3
0
func TestCastRaySphere(t *testing.T) {
	r := newBody(NewRay(0.70710678, 0.70710678, 0.70710678)) // 45 degrees from each axis.
	s := newBody(NewSphere(1))                               // sphere of radius 1
	s.World().Loc.SetS(20, 20, 20)
	hit, x, y, z := castRaySphere(r, s)
	cx, cy, cz := 19.4226497, 19.4226497, 19.4226497 // expected contact location.
	if !hit || !lin.Aeq(x, cx) || !lin.Aeq(y, cy) || !lin.Aeq(z, cz) {
		t.Errorf("%t Expected ray-plane hit at %2.7f %2.7f %2.7f, got %2.7f %2.7f %2.7f", hit, cx, cy, cz, x, y, z)
	}
}
Example #4
0
func TestCastRotatedRayPlane(t *testing.T) {
	r := newBody(NewRay(0, 0.70710678, -0.70710678)) // ray at origin pointing down +Y -Z
	r.World().Loc.SetS(0, 0, 20)                     // move ray origin +20 on Z axis.
	p := newBody(NewPlane(0, 0, -1))                 // plane at origin with normal -Z
	hit, x, y, z := castRayPlane(r, p)
	cx, cy, cz := 0.0, 20.0, 0.0 // expected contact location.
	if !hit || !lin.Aeq(x, cx) || !lin.Aeq(y, cy) || !lin.Aeq(z, cz) {
		t.Errorf("%t Expected ray-plane hit at %f %f %f, got %f %f %f", hit, cx, cy, cz, x, y, z)
	}
}
Example #5
0
func TestCastRayPlane(t *testing.T) {
	r := newBody(NewRay(0, 0.70710678, 0.70710678)) // ray at origin pointing down +Y +Z
	p := newBody(NewPlane(0, 0, 1))                 // normal +Z
	p.World().Loc.SetS(0, 0, 20)                    // move plane 20 +Z
	hit, x, y, z := castRayPlane(r, p)
	cx, cy, cz := 0.0, 20.0, 20.0 // expected contact location.
	if !hit || !lin.Aeq(x, cx) || !lin.Aeq(y, cy) || !lin.Aeq(z, cz) {
		t.Errorf("%t Expected ray-plane hit at %f %f %f, got %f %f %f", hit, cx, cy, cz, x, y, z)
	}
}
Example #6
0
// Test a ray cast with perspective inverse and angled view inverse.
func TestAngledRay(t *testing.T) {
	cam, ww, wh := initScene()
	cam.AdjustPitch(45)
	cam.SetLocation(0, -15, 15)
	rx, ry, rz := cam.Ray(ww/2, wh/2, ww, wh) // center of screen.
	ex, ey, ez := 0.0, 0.7071068, -0.7071068
	if !lin.Aeq(rx, ex) || !lin.Aeq(ry, ey) || !lin.Aeq(rz, ez) {
		t.Errorf("Expected %f %f %f got %f %f %f", ex, ey, ez, rx, ry, rz)
	}
}
Example #7
0
func TestCastRotatedRaySphere(t *testing.T) {
	r := newBody(NewRay(0, 0.70710678, -0.70710678)) // ray at origin pointing down +Y -Z
	r.World().Loc.SetS(0, 0, 20)                     // move ray origin +20 on Z axis.
	s := newBody(NewSphere(1))                       // sphere of radius 1.
	s.World().Loc.SetS(0, 20, 0)                     // put sphere up the y-axis.
	hit, x, y, z := castRaySphere(r, s)
	cx, cy, cz := 0.0, 19.2928932, 0.7071068 // expected contact location.
	if !hit || !lin.Aeq(x, cx) || !lin.Aeq(y, cy) || !lin.Aeq(z, cz) {
		t.Errorf("%t Expected ray-plane hit at %2.7f %2.7f %2.7f, got %2.7f %2.7f %2.7f", hit, cx, cy, cz, x, y, z)
	}
}
Example #8
0
func (c *cam) update(camera vu.Camera) {
	fraction := 0.25
	pitch := camera.Pitch()
	if !lin.Aeq(pitch, c.pitch) {
		pitch = (c.pitch-pitch)*fraction + pitch
		camera.SetPitch(pitch)
	}
	yaw := camera.Yaw()
	if !lin.Aeq(yaw, c.yaw) {
		yaw = (c.yaw-yaw)*fraction + yaw
		camera.SetYaw(yaw)
	}
}
Example #9
0
// TestChildWorldTransform checks that a child object can calculate its
// world space location.
func TestChildWorldTransform(t *testing.T) {
	eng := newEngine(nil)
	parent := eng.Root().NewPov().SetLocation(0, -8, 0).SetScale(4, 4, 4)
	parent.Spin(-90, 0, 0)
	child := parent.NewPov().SetLocation(0, 0.78, 0.01).SetScale(0.1, 0.1, 0.1)

	// call placeModels to initialize the model transform matrix needed by World.
	eng.placeModels(eng.root(), lin.M4I) // update all transforms.
	if x, y, z := child.World(); !lin.Aeq(x, 0) || !lin.Aeq(y, -7.96) || !lin.Aeq(z, -3.12) {
		t.Errorf("Expecting %f %f %f, got %f, %f %f", 0.0, -7.96, -3.12, x, y, z)
	}
	if eng != nil {
		eng.Shutdown()
	}
}
Example #10
0
func TestSphereProperties(t *testing.T) {
	b := newBody(NewSphere(1)).SetMaterial(0.5, 0.8).(*body)
	if b.movable != true || !lin.Aeq(b.imass, 2) {
		t.Errorf("Expecting movable body with mass %f", b.imass)
	}
	if dumpV3(b.iit) != "{5.0 5.0 5.0}" {
		t.Errorf("Expecting initial inverse inertia %s", dumpV3(b.iit))
	}
}
Example #11
0
File: draw.go Project: toophy/vu
func (d draws) Less(i, j int) bool {
	di, dj := d[i].(*draw), d[j].(*draw)
	if di.bucket != dj.bucket {
		return di.bucket < dj.bucket // First sort into buckets.
	}
	if di.bucket == TRANSPARENT {
		if !lin.Aeq(di.tocam, dj.tocam) {
			return di.tocam > dj.tocam // Sort transparent by distance to camera.
		}
	}
	return di.tag < dj.tag // Sort by eid.
}
Example #12
0
// Tests that the narrowphase collision lookup finds the algorithm that flips
// the box-sphere to be sphere-box.
func TestCollideBoxSphere(t *testing.T) {
	box, sphere, c, cons := newBody(NewBox(1, 1, 1)), newBody(NewSphere(1)), newCollider(), newManifold()
	sphere.World().Loc.SetS(0, 2, 0)
	algorithm := c.algorithms[box.shape.Type()][sphere.shape.Type()]
	i, j, cs := algorithm(box, sphere, cons)
	ii, jj := i.(*body), j.(*body)
	if ii.shape.Type() != SphereShape || jj.shape.Type() != BoxShape {
		t.Error("Should have flipped the objects into Sphere, Box")
	}
	if !lin.Aeq(cs[0].depth, -margin) || dumpV3(cs[0].point) != "{0.0 1.0 0.0}" || dumpV3(cs[0].normal) != "{0.0 1.0 0.0}" {
		t.Errorf("Contact info should be the same %f %s %s", cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal))
	}
}
Example #13
0
func TestCollideBoxBox1(t *testing.T) {
	slab := newBody(NewBox(50, 50, 50)).setMaterial(0, 0)
	slab.World().Loc.SetS(0, -50, 0)
	box := newBody(NewBox(1, 1, 1)).setMaterial(1, 0)
	box.World().Loc.SetS(-5.000000, 1.388000, -3.000000)
	box.World().Rot.SetS(0.182574, 0.365148, 0.547723, 0.730297)
	wantPoint, wantDepth := lin.NewV3S(-5.2, -0.1, -4.0), -0.108
	_, _, cs := collideBoxBox(slab, box, newManifold())
	if !lin.Aeq(cs[0].depth, wantDepth) || dumpV3(cs[0].point) != dumpV3(wantPoint) {
		t.Errorf("Got point %s wanted %s. Got depth %f wanted %f",
			dumpV3(cs[0].point), dumpV3(wantPoint), cs[0].depth, wantDepth)
	}
}
Example #14
0
func TestCollideSphereBox(t *testing.T) {
	a, b, cons := NewBody(NewSphere(1)), NewBody(NewBox(1, 1, 1)), newManifold()
	if _, _, cs := collideSphereBox(a, b, cons); cs[0].depth != -2.04 ||
		dumpV3(cs[0].point) != "{1.0 0.0 0.0}" || dumpV3(cs[0].normal) != "{1.0 0.0 0.0}" {
		t.Errorf("Sphere touching box at point A %f %s %s", cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal))
	}
	a.World().Loc.SetS(0, 2, 0)
	if _, _, cs := collideSphereBox(a, b, cons); !lin.Aeq(cs[0].depth, -margin) ||
		dumpV3(cs[0].point) != "{0.0 1.0 0.0}" || dumpV3(cs[0].normal) != "{0.0 1.0 0.0}" {
		t.Errorf("Sphere touching box at point %f %s %s", cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal))
	}
	a.World().Loc.SetS(0, 0, 2.15)
	if _, _, cs := collideSphereBox(a, b, cons); len(cs) != 0 {
		t.Errorf("Sphere not touching box %f %s %s", cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal))
	}

	// close enough to be considered in contact.
	a.World().Loc.SetS(0, 0, 2.1)
	if _, _, cs := collideSphereBox(a, b, cons); !lin.Aeq(cs[0].depth, 0.06) ||
		dumpV3(cs[0].point) != "{0.0 0.0 1.0}" || dumpV3(cs[0].normal) != "{0.0 0.0 1.0}" {
		t.Errorf("Sphere close to touching box %f %s %s", cs[0].depth, dumpV3(cs[0].point), dumpV3(cs[0].normal))
	}
}
Example #15
0
func TestSphereVolume(t *testing.T) {
	sp := Shape(NewSphere(1.25))
	if !lin.Aeq(sp.Volume(), 6.13592315) {
		t.Errorf("Expected sphere mass 6.13592315, got %2.8f", sp.Volume())
	}
}
Example #16
0
func TestRayWithSpin(t *testing.T) {
	cam, _, _ := initScene()
	cx, cy, cz := 0.0, -10.0, 14.0             // camera location to
	cam.SetLocation(cx, cy, cz)                // ...point directly at 0, 0, 0
	cam.SetPitch(lin.Deg(math.Atan(-cy / cz))) // 35.53768 degrees
	plane := NewPlane(0, 0, -1)

	ww, wh := 1280, 800
	rx, ry, rz := cam.Ray(0, 0, ww, wh)
	ray := NewRay(rx, ry, rz)
	ray.World().SetLoc(cx, cy, cz)
	hit, hx, hy, hz := Cast(ray, plane)
	ex, ey, ez := -6.191039, -4.755119, 0.0
	if !hit || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) {
		t.Errorf("Hit %t %f %f %f, expected %f %f %f", hit, hx, hy, hz, ex, ey, ez)
	}

	rx, ry, rz = cam.Ray(0, wh, ww, wh)
	ray = NewRay(rx, ry, rz)
	ray.World().SetLoc(cx, cy, cz)
	hit, hx, hy, hz = Cast(ray, plane)
	ex, ey, ez = -9.121797, 7.006131, 0.0
	if !hit || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) {
		t.Errorf("Hit %t %f %f %f, expected %f %f %f", hit, hx, hy, hz, ex, ey, ez)
	}

	rx, ry, rz = cam.Ray(ww, 0, ww, wh)
	ray = NewRay(rx, ry, rz)
	ray.World().SetLoc(cx, cy, cz)
	hit, hx, hy, hz = Cast(ray, plane)
	ex, ey, ez = 6.191039, -4.755119, 0.0
	if !hit || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) {
		t.Errorf("Hit %t %f %f %f, expected %f %f %f", hit, hx, hy, hz, ex, ey, ez)
	}

	rx, ry, rz = cam.Ray(ww, wh, ww, wh)
	ray = NewRay(rx, ry, rz)
	ray.World().SetLoc(cx, cy, cz)
	hit, hx, hy, hz = Cast(ray, plane)
	ex, ey, ez = 9.121797, 7.006131, 0.0
	if !hit || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) || !lin.Aeq(hx, ex) {
		t.Errorf("Hit %t %f %f %f, expected %f %f %f", hit, hx, hy, hz, ex, ey, ez)
	}
}