Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 131 additions & 1 deletion examples/jsm/math/Octree.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ const _point2 = new Vector3();
const _plane = new Plane();
const _line1 = new Line3();
const _line2 = new Line3();
const _box = new Box3();
const _sphere = new Sphere();
const _capsule = new Capsule();
const _center = new Capsule();

const _temp1 = new Vector3();
const _temp2 = new Vector3();
Expand Down Expand Up @@ -373,6 +375,61 @@ class Octree {

}

/**
* Computes the intersection between the given bounding box and triangle.
*
* @param {Box3} box - The bounding box to test.
* @param {Triangle} triangle - The triangle to test.
* @return {Object|false} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
triangleBoxIntersect( box, triangle ) {

// cheap check

if ( Math.max( triangle.a.x, triangle.b.x, triangle.c.x ) < box.min.x ||
Math.min( triangle.a.x, triangle.b.x, triangle.c.x ) > box.max.x ||
Math.max( triangle.a.y, triangle.b.y, triangle.c.y ) < box.min.y ||
Math.min( triangle.a.y, triangle.b.y, triangle.c.y ) > box.max.y ||
Math.max( triangle.a.z, triangle.b.z, triangle.c.z ) < box.min.z ||
Math.min( triangle.a.z, triangle.b.z, triangle.c.z ) > box.max.z ) {

return false;

}

// expensive check

if ( ! box.intersectsTriangle( triangle ) ) return false;

// there is an intersection, now compute collision data

triangle.getPlane( _plane );

// determine which corner of the box is "deepest" into the plane

_v1.x = ( _plane.normal.x > 0 ) ? box.min.x : box.max.x;
_v1.y = ( _plane.normal.y > 0 ) ? box.min.y : box.max.y;
_v1.z = ( _plane.normal.z > 0 ) ? box.min.z : box.max.z;

// Calculate the distance from the plane to that corner (the distance will be negative
// because of the intersection)

const distance = _plane.distanceToPoint( _v1 );

const intersection = {
depth: - distance, // Flip sign so depth is positive
normal: _plane.normal.clone(),
point: _v1.clone()
};

// project the point onto the triangle surface
intersection.point.addScaledVector( intersection.normal, distance );

return intersection;

}

/**
* Computes the intersection between the given sphere and triangle.
*
Expand Down Expand Up @@ -455,6 +512,38 @@ class Octree {

}

/**
* Computes the triangles that potentially intersect with the given bounding box.
*
* @param {Box3} box - The bounding box.
* @param {Array<Triangle>} triangles - The target array that holds the triangles.
*/
getBoxTriangles( box, triangles ) {

for ( let i = 0; i < this.subTrees.length; i ++ ) {

const subTree = this.subTrees[ i ];

if ( ! box.intersectsBox( subTree.box ) ) continue;

if ( subTree.triangles.length > 0 ) {

for ( let j = 0; j < subTree.triangles.length; j ++ ) {

if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] );

}

} else {

subTree.getBoxTriangles( box, triangles );

}

}

}

/**
* Computes the triangles that potentially intersect with the given capsule.
*
Expand Down Expand Up @@ -487,6 +576,47 @@ class Octree {

}

/**
* Performs a bounding box intersection test with this Octree.
*
* @param {Box3} box - The bounding box to test.
* @return {Object|boolean} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
boxIntersect( box ) {

_box.copy( box );

const triangles = [];
let result, hit = false;

this.getBoxTriangles( box, triangles );

for ( let i = 0; i < triangles.length; i ++ ) {

if ( result = this.triangleBoxIntersect( _box, triangles[ i ] ) ) {

hit = true;

_box.translate( result.normal.multiplyScalar( result.depth ) );

}

}

if ( hit ) {

const collisionVector = _box.getCenter( _center ).sub( box.getCenter( _v1 ) );
const depth = collisionVector.length();

return { normal: collisionVector.normalize(), depth: depth };

}

return false;

}

/**
* Performs a bounding sphere intersection test with this Octree.
*
Expand Down Expand Up @@ -558,7 +688,7 @@ class Octree {

if ( hit ) {

const collisionVector = _capsule.getCenter( new Vector3() ).sub( capsule.getCenter( _v1 ) );
const collisionVector = _capsule.getCenter( _center ).sub( capsule.getCenter( _v1 ) );
const depth = collisionVector.length();

return { normal: collisionVector.normalize(), depth: depth };
Expand Down