From ed6a644b0e91b18583e820e46c237dad8d983f76 Mon Sep 17 00:00:00 2001 From: Lucas Dower Date: Sat, 12 Mar 2022 22:22:20 +0000 Subject: [PATCH] Fixed #28, added testing --- src/ray.ts | 36 ++++++++++++------- test/ray.test.ts | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 test/ray.test.ts diff --git a/src/ray.ts b/src/ray.ts index 4eb948a..adea421 100644 --- a/src/ray.ts +++ b/src/ray.ts @@ -1,5 +1,5 @@ import { Vector3 } from './vector'; -import { Bounds } from './util'; +import { ASSERT, Bounds } from './util'; const EPSILON = 0.0000001; @@ -9,9 +9,21 @@ export enum Axes { } /* eslint-enable */ -interface Ray { +export function axesToDirection(axis: Axes) { + if (axis === Axes.x) { + return new Vector3(1, 0, 0); + } + if (axis === Axes.y) { + return new Vector3(0, 1, 0); + } + if (axis === Axes.z) { + return new Vector3(0, 0, 1); + } + ASSERT(false); +} + +export interface Ray { origin: Vector3, - direction: Vector3, axis: Axes } @@ -40,8 +52,7 @@ function traverseX(rayList: Array, bounds: Bounds) { for (let y = bounds.min.y; y <= bounds.max.y; ++y) { for (let z = bounds.min.z; z <= bounds.max.z; ++z) { rayList.push({ - origin: new Vector3(bounds.min.x, y, z), - direction: new Vector3(1, 0, 0), + origin: new Vector3(bounds.min.x - 1, y, z), axis: Axes.x, }); } @@ -52,8 +63,7 @@ function traverseY(rayList: Array, bounds: Bounds) { for (let x = bounds.min.x; x <= bounds.max.x; ++x) { for (let z = bounds.min.z; z <= bounds.max.z; ++z) { rayList.push({ - origin: new Vector3(x, bounds.min.y, z), - direction: new Vector3(0, 1, 0), + origin: new Vector3(x, bounds.min.y - 1, z), axis: Axes.y, }); } @@ -64,19 +74,19 @@ function traverseZ(rayList: Array, bounds: Bounds) { for (let x = bounds.min.x; x <= bounds.max.x; ++x) { for (let y = bounds.min.y; y <= bounds.max.y; ++y) { rayList.push({ - origin: new Vector3(x, y, bounds.min.z), - direction: new Vector3(0, 0, 1), + origin: new Vector3(x, y, bounds.min.z - 1), axis: Axes.z, }); } } } -export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | void) { +export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) { const edge1 = Vector3.sub(v1, v0); const edge2 = Vector3.sub(v2, v0); - const h = Vector3.cross(ray.direction, edge2); + const rayDirection = axesToDirection(ray.axis); + const h = Vector3.cross(rayDirection, edge2); const a = Vector3.dot(edge1, h); if (a > -EPSILON && a < EPSILON) { @@ -92,7 +102,7 @@ export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vec } const q = Vector3.cross(s, edge1); - const v = f * Vector3.dot(ray.direction, q); + const v = f * Vector3.dot(rayDirection, q); if (v < 0.0 || u + v > 1.0) { return; @@ -101,6 +111,6 @@ export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vec const t = f * Vector3.dot(edge2, q); if (t > EPSILON) { - return Vector3.add(ray.origin, Vector3.mulScalar(ray.direction, t)); + return Vector3.add(ray.origin, Vector3.mulScalar(rayDirection, t)); } } diff --git a/test/ray.test.ts b/test/ray.test.ts new file mode 100644 index 0000000..198c355 --- /dev/null +++ b/test/ray.test.ts @@ -0,0 +1,94 @@ +import { Ray, Axes, rayIntersectTriangle } from '../src/ray'; +import { Vector3 } from '../src/vector'; +import { Triangle } from '../src/triangle'; +import { ASSERT } from '../src/util'; + +test('rayIntersectTriangle x-axis #1', () => { + const ray: Ray = { + origin: new Vector3(-1, 0, 0), + axis: Axes.x, + }; + const tri = new Triangle( + new Vector3(5, -1, -1), + new Vector3(5, 0, 1), + new Vector3(5, 1, -1), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeDefined(); + ASSERT(intersects); + expect(intersects.equals(new Vector3(5, 0, 0))).toEqual(true); +}); + +test('rayIntersectTriangle x-axis #2', () => { + const ray: Ray = { + origin: new Vector3(1, 0, 0), + axis: Axes.x, + }; + const tri = new Triangle( + new Vector3(0, -1, -1), + new Vector3(0, 0, 1), + new Vector3(0, 1, -1), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeUndefined(); +}); + +test('rayIntersectTriangle y-axis #1', () => { + const ray: Ray = { + origin: new Vector3(0, -1, 0), + axis: Axes.y, + }; + const tri = new Triangle( + new Vector3(-1, 6, -1), + new Vector3( 0, 6, 1), + new Vector3( 1, 6, -1), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeDefined(); + ASSERT(intersects); + expect(intersects.equals(new Vector3(0, 6, 0))).toEqual(true); +}); + +test('rayIntersectTriangle y-axis #2', () => { + const ray: Ray = { + origin: new Vector3(0, 1, 0), + axis: Axes.y, + }; + const tri = new Triangle( + new Vector3(-1, 0, -1), + new Vector3( 0, 0, 1), + new Vector3( 1, 0, -1), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeUndefined(); +}); + +test('rayIntersectTriangle z-axis #1', () => { + const ray: Ray = { + origin: new Vector3(0, 0, -1), + axis: Axes.z, + }; + const tri = new Triangle( + new Vector3(-1, -1, 7), + new Vector3( 0, 1, 7), + new Vector3( 1, -1, 7), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeDefined(); + ASSERT(intersects); + expect(intersects.equals(new Vector3(0, 0, 7))).toEqual(true); +}); + +test('rayIntersectTriangle z-axis #2', () => { + const ray: Ray = { + origin: new Vector3(0, 0, 1), + axis: Axes.z, + }; + const tri = new Triangle( + new Vector3(-1, -1, 0), + new Vector3( 0, 1, 0), + new Vector3( 1, -1, 0), + ); + const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2); + expect(intersects).toBeUndefined(); +});