cvmath 0.0.8

Computer Graphics Vector Math Library
Documentation
use super::*;

#[test]
fn test_trace_capsule_body_entry() {
	let capsule = Capsule3(Point3(0.0, 0.0, 0.0), Vec3(4.0, 0.0, 0.0), 1.0);
	let ray = Ray3 {
		origin: Point3(2.0, -3.0, 0.0),
		direction: Vec3(0.0, 1.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	let hit = ray.trace(&capsule).expect("Ray should hit the capsule body");
	assert_eq!(hit.distance, 2.0);
	assert_eq!(hit.point, Point3(2.0, -1.0, 0.0));
	assert_eq!(hit.normal, Vec3(0.0, -1.0, 0.0));
	assert_eq!(hit.side, HitSide::Entry);
	assert_eq!(ray.inside(&capsule), false);
}

#[test]
fn test_trace_capsule_cap_exit_from_inside() {
	let capsule = Capsule3(Point3(0.0, 0.0, 0.0), Vec3(4.0, 0.0, 0.0), 1.0);
	let ray = Ray3 {
		origin: Point3(0.0, 0.0, 0.0),
		direction: Vec3(-1.0, 0.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	let hit = ray.trace(&capsule).expect("Ray should exit through the start cap");
	assert_eq!(hit.distance, 1.0);
	assert_eq!(hit.point, Point3(-1.0, 0.0, 0.0));
	assert_eq!(hit.normal, Vec3(1.0, 0.0, 0.0));
	assert_eq!(hit.side, HitSide::Exit);
	assert_eq!(ray.inside(&capsule), true);
}

#[test]
fn test_trace_capsule_parallel_miss() {
	let capsule = Capsule3(Point3(0.0, 0.0, 0.0), Vec3(4.0, 0.0, 0.0), 1.0);
	let ray = Ray3 {
		origin: Point3(-2.0, 2.0, 0.0),
		direction: Vec3(1.0, 0.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	assert!(ray.trace(&capsule).is_none(), "Parallel ray outside the cylinder radius should miss");
}

#[test]
fn test_trace_capsule_degenerate_matches_sphere() {
	let capsule = Capsule3(Point3(1.0, -1.0, 2.0), Vec3::ZERO, 2.0);
	let sphere = Sphere(Point3(1.0, -1.0, 2.0), 2.0);
	let ray = Ray3 {
		origin: Point3(-4.0, -1.0, 2.0),
		direction: Vec3(1.0, 0.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	let capsule_hit = ray.trace(&capsule).expect("Degenerate capsule should trace like a sphere");
	let sphere_hit = ray.trace(&sphere).expect("Sphere should be hit");

	assert_eq!(capsule_hit.distance, sphere_hit.distance);
	assert_eq!(capsule_hit.point, sphere_hit.point);
	assert_eq!(capsule_hit.normal, sphere_hit.normal);
	assert_eq!(capsule_hit.side, sphere_hit.side);
}

#[test]
fn test_trace_capsule_boundary_start_moving_away() {
	let capsule = Capsule3(Point3(0.0, 0.0, 0.0), Vec3(4.0, 0.0, 0.0), 1.0);
	let ray = Ray3 {
		origin: Point3(2.0, -1.0, 0.0),
		direction: Vec3(0.0, -1.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	assert!(ray.trace(&capsule).is_none(), "Ray starting on the boundary and moving away should not self-hit");
}

#[test]
fn test_trace_capsule_zero_radius_matches_line_behavior() {
	let capsule = Capsule3(Point3(0.0, 0.0, 0.0), Vec3(4.0, 0.0, 0.0), 0.0);
	let line = Line3(Point3(0.0, 0.0, 0.0), Point3(4.0, 0.0, 0.0));
	let ray = Ray3 {
		origin: Point3(2.0, -3.0, 0.0),
		direction: Vec3(0.0, 1.0, 0.0),
		distance: Interval(0.0, f64::INFINITY),
	};

	assert_eq!(ray.trace(&capsule), ray.trace(&line));
	assert_eq!(capsule.inside(ray.origin), false);
}

#[test]
fn test_lerp() {
	let capsule = lerp(
		Capsule3(Point3(1.0, 2.0, 3.0), Vec3(4.0, 5.0, 6.0), 7.0),
		Capsule3(Point3(5.0, 6.0, 7.0), Vec3(8.0, 9.0, 10.0), 11.0),
		0.5,
	);
	assert_eq!(capsule, Capsule3(Point3(3.0, 4.0, 5.0), Vec3(6.0, 7.0, 8.0), 9.0));
}