Skip to content

Commit

Permalink
culling
Browse files Browse the repository at this point in the history
  • Loading branch information
Ib Green committed Jun 12, 2019
1 parent 328f6cd commit e611e32
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 190 deletions.
20 changes: 18 additions & 2 deletions modules/core/test/classes/matrix4.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ test('Matrix4#toRowMajor', t => {
t.end();
});


test('Matrix4#getScale', t => {
const INPUT = INDICES_MATRIX;
const RESULT = [3.7416573867739413, 10.488088481701515, 17.37814719698276];
Expand All @@ -173,7 +172,24 @@ test('Matrix4#getScale', t => {

test('Matrix4#getRotation', t => {
const INPUT = INDICES_MATRIX;
const RESULT = [0.2672612419124244, 0.19069251784911848, 0.17263060129453078, 0, 1.3363062095621219, 0.5720775535473555, 0.4028047363539052, 0, 2.4053511772118195, 0.9534625892455924, 0.6329788714132796, 0, 0, 0, 0, 1 ];
const RESULT = [
0.2672612419124244,
0.19069251784911848,
0.17263060129453078,
0,
1.3363062095621219,
0.5720775535473555,
0.4028047363539052,
0,
2.4053511772118195,
0.9534625892455924,
0.6329788714132796,
0,
0,
0,
0,
1
];

const m = new Matrix4(INPUT).getRotation([...INDICES_MATRIX]);
tapeEquals(t, m, RESULT, 'getRotation gave the right result');
Expand Down
4 changes: 2 additions & 2 deletions modules/core/test/classes/quaternion.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ test('Quaternion#identity', t => {
});

test('Quaternion#add', t => {
const quat = new Quaternion(1, 1, 1, 1).identity();
t.throws(() => quat.add([0, 0, 0, 0], [0, 0, 0, 0]));
const quat = new Quaternion(1, 1, 1, 1).identity();
t.throws(() => quat.add([0, 0, 0, 0], [0, 0, 0, 0]));
tapeEquals(t, quat.add([0, 0, 0, 0]), quat, 'should add quaternion');
t.end();
});
Expand Down
4 changes: 2 additions & 2 deletions modules/core/test/classes/spherical-coordinates.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ test('SphericalCoordinates#import', t => {
test('SphericalCoordinates#constructor', t => {
const spherical = new SphericalCoordinates();
t.ok(spherical, 'SphericalCoordinates default constructor OK');
t.throws(() => new SphericalCoordinates({ bearing: NaN }));
t.throws(() => new SphericalCoordinates({ bearing: 0, pitch: 'a' }));
t.throws(() => new SphericalCoordinates({bearing: NaN}));
t.throws(() => new SphericalCoordinates({bearing: 0, pitch: 'a'}));
t.end();
});

Expand Down
34 changes: 20 additions & 14 deletions modules/culling/src/lib/culling-volume.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class CullingVolume {
// For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value
// represents the case where the object bounding volume is entirely inside the culling volume.
static get MASK_INSIDE() {
return 0xffffffff;
return 0x00000000;
}

// For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value
Expand All @@ -49,8 +49,8 @@ export default class CullingVolume {
let planeIndex = 0;

for (const faceNormal of faces) {
const plane0 = this.planes[planeIndex];
const plane1 = this.planes[planeIndex + 1];
let plane0 = this.planes[planeIndex];
let plane1 = this.planes[planeIndex + 1];

if (!plane0) {
plane0 = this.planes[planeIndex] = new Vector4();
Expand All @@ -60,7 +60,7 @@ export default class CullingVolume {
}

scratchPlaneCenter
.set(faceNormal)
.copy(faceNormal)
.scale(-radius)
.add(center);

Expand All @@ -70,7 +70,7 @@ export default class CullingVolume {
plane0.w = -faceNormal.dot(scratchPlaneCenter);

scratchPlaneCenter
.set(faceNormal)
.copy(faceNormal)
.scale(radius)
.add(center);
plane1.x = -faceNormal.x;
Expand All @@ -82,25 +82,31 @@ export default class CullingVolume {
planeIndex += 2;
}

return result;
return this;
}

// Determines whether a bounding volume intersects the culling volume.
computeVisibility(boundingVolume) {
assert(boundingVolume);
const planes = this.planes;
const intersecting = false;
const intersect = Intersect.INSIDE;
for (const plane of this.planes) {
const result = boundingVolume.intersectPlane(Plane.fromCartesian4(plane, scratchPlane));
if (result === Intersect.OUTSIDE) {
return Intersect.OUTSIDE;
}
if (result === Intersect.INTERSECTING) {
intersecting = true;
const result = boundingVolume.intersectPlane(plane);
switch (result) {
case Intersect.OUTSIDE:
// We are done
return Intersect.OUTSIDE;

case Intersect.INTERSECTING:
// If no other intersection is outside, return INTERSECTING
intersect = Intersect.INTERSECTING;
break;

default:
}
}

return intersecting ? Intersect.INTERSECTING : Intersect.INSIDE;
return intersect;
}

// Determines whether a bounding volume intersects the culling volume.
Expand Down
106 changes: 61 additions & 45 deletions modules/culling/src/lib/oriented-bounding-box.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export default class OrientedBoundingBox {

// eslint-disable-next-line max-statements
distanceSquaredTo(point) {
const offset = Vector3.subtract(point, this.center, scratchOffset);
const offset = scratchOffset.copy(point).subtract(this.center);

const halfAxes = this.halfAxes;
const u = halfAxes.getColumn(0, scratchVectorU);
Expand Down Expand Up @@ -183,101 +183,117 @@ export default class OrientedBoundingBox {
// to position projected onto direction.

// eslint-disable-next-line max-statements
computePlaneDistances(box, position, direction, result = [[], []]) {
computePlaneDistances(position, direction, result = [[], []]) {
let minDist = Number.POSITIVE_INFINITY;
let maxDist = Number.NEGATIVE_INFINITY;

const center = box.center;
const halfAxes = box.halfAxes;
const center = this.center;
const halfAxes = this.halfAxes;

const u = halfAxes.getColumn(0, scratchVectorU);
const v = halfAxes.getColumn(1, scratchVectorV);
const w = halfAxes.getColumn(2, scratchVectorW);

// project first corner
const corner = Vector3.add(u, v, scratchCorner);
Vector3.add(corner, w, corner);
Vector3.add(corner, center, corner);
const corner = scratchCorner
.copy(u)
.add(v)
.add(w)
.add(center);

const toCenter = Vector3.subtract(corner, position, scratchToCenter);
let mag = Vector3.dot(direction, toCenter);
const toCenter = scratchToCenter.copy(corner).subtract(position);
let mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project second corner
Vector3.add(center, u, corner);
Vector3.add(corner, v, corner);
Vector3.subtract(corner, w, corner);
corner
.copy(center)
.add(u)
.add(v)
.subtract(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project third corner
Vector3.add(center, u, corner);
Vector3.subtract(corner, v, corner);
Vector3.add(corner, w, corner);
corner
.copy(center)
.add(u)
.subtract(v)
.add(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project fourth corner
Vector3.add(center, u, corner);
Vector3.subtract(corner, v, corner);
Vector3.subtract(corner, w, corner);
corner
.copy(center)
.add(u)
.subtract(v)
.subtract(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project fifth corner
Vector3.subtract(center, u, corner);
Vector3.add(corner, v, corner);
Vector3.add(corner, w, corner);
center
.copy(corner)
.subtract(u)
.add(v)
.add(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project sixth corner
Vector3.subtract(center, u, corner);
Vector3.add(corner, v, corner);
Vector3.subtract(corner, w, corner);
center
.copy(corner)
.subtract(u)
.add(v)
.subtract(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project seventh corner
Vector3.subtract(center, u, corner);
Vector3.subtract(corner, v, corner);
Vector3.add(corner, w, corner);
center
.copy(corner)
.subtract(u)
.subtract(v)
.add(w);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);

// project eighth corner
Vector3.subtract(center, u, corner);
Vector3.subtract(corner, v, corner);
Vector3.subtract(corner, w, corner);

Vector3.subtract(corner, position, toCenter);
mag = Vector3.dot(direction, toCenter);
center
.copy(corner)
.subtract(u)
.subtract(v)
.subtract(w);

toCenter.copy(corner).subtract(position);
mag = direction.dot(toCenter);

minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Expand Down
17 changes: 17 additions & 0 deletions modules/culling/test/lib/culling-volume.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,28 @@ import {CullingVolume, BoundingSphere, makeBoundingSphereFromPoints} from '@math
// Vector3.UNIT_Y
// );

test('CullingVolume#constructor', t => {
t.doesNotThrow(() => new CullingVolume());
t.ok(CullingVolume.MASK_INSIDE >= 0);
t.ok(CullingVolume.MASK_OUTSIDE >= 0);
t.ok(CullingVolume.MASK_INDETERMINATE >= 0);
t.end();
});

test('CullingVolume#computeVisibility throws without a bounding volume', t => {
t.throws(() => new CullingVolume().computeVisibility());
t.end();
});

test('CullingVolume#fromBoundingSphere', t => {
const sphere = makeBoundingSphereFromPoints([
new Vector3(0, -2.0, -1.5),
new Vector3(0, 0, -1.5)
]);
t.doesNotThrow(() => new CullingVolume().fromBoundingSphere(sphere));
t.end();
});

/*
test('CullingVolume#computeVisibilityWithPlaneMask throws without a bounding volume', t => {
t.throws(() =>
Expand Down
Loading

0 comments on commit e611e32

Please sign in to comment.