Skip to content

Commit acc03cc

Browse files
authored
Octree: Add Box3 interface. (#32343)
1 parent 47e0b18 commit acc03cc

File tree

1 file changed

+131
-1
lines changed

1 file changed

+131
-1
lines changed

examples/jsm/math/Octree.js

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ const _point2 = new Vector3();
1717
const _plane = new Plane();
1818
const _line1 = new Line3();
1919
const _line2 = new Line3();
20+
const _box = new Box3();
2021
const _sphere = new Sphere();
2122
const _capsule = new Capsule();
23+
const _center = new Capsule();
2224

2325
const _temp1 = new Vector3();
2426
const _temp2 = new Vector3();
@@ -373,6 +375,61 @@ class Octree {
373375

374376
}
375377

378+
/**
379+
* Computes the intersection between the given bounding box and triangle.
380+
*
381+
* @param {Box3} box - The bounding box to test.
382+
* @param {Triangle} triangle - The triangle to test.
383+
* @return {Object|false} The intersection object. If no intersection
384+
* is detected, the method returns `false`.
385+
*/
386+
triangleBoxIntersect( box, triangle ) {
387+
388+
// cheap check
389+
390+
if ( Math.max( triangle.a.x, triangle.b.x, triangle.c.x ) < box.min.x ||
391+
Math.min( triangle.a.x, triangle.b.x, triangle.c.x ) > box.max.x ||
392+
Math.max( triangle.a.y, triangle.b.y, triangle.c.y ) < box.min.y ||
393+
Math.min( triangle.a.y, triangle.b.y, triangle.c.y ) > box.max.y ||
394+
Math.max( triangle.a.z, triangle.b.z, triangle.c.z ) < box.min.z ||
395+
Math.min( triangle.a.z, triangle.b.z, triangle.c.z ) > box.max.z ) {
396+
397+
return false;
398+
399+
}
400+
401+
// expensive check
402+
403+
if ( ! box.intersectsTriangle( triangle ) ) return false;
404+
405+
// there is an intersection, now compute collision data
406+
407+
triangle.getPlane( _plane );
408+
409+
// determine which corner of the box is "deepest" into the plane
410+
411+
_v1.x = ( _plane.normal.x > 0 ) ? box.min.x : box.max.x;
412+
_v1.y = ( _plane.normal.y > 0 ) ? box.min.y : box.max.y;
413+
_v1.z = ( _plane.normal.z > 0 ) ? box.min.z : box.max.z;
414+
415+
// Calculate the distance from the plane to that corner (the distance will be negative
416+
// because of the intersection)
417+
418+
const distance = _plane.distanceToPoint( _v1 );
419+
420+
const intersection = {
421+
depth: - distance, // Flip sign so depth is positive
422+
normal: _plane.normal.clone(),
423+
point: _v1.clone()
424+
};
425+
426+
// project the point onto the triangle surface
427+
intersection.point.addScaledVector( intersection.normal, distance );
428+
429+
return intersection;
430+
431+
}
432+
376433
/**
377434
* Computes the intersection between the given sphere and triangle.
378435
*
@@ -455,6 +512,38 @@ class Octree {
455512

456513
}
457514

515+
/**
516+
* Computes the triangles that potentially intersect with the given bounding box.
517+
*
518+
* @param {Box3} box - The bounding box.
519+
* @param {Array<Triangle>} triangles - The target array that holds the triangles.
520+
*/
521+
getBoxTriangles( box, triangles ) {
522+
523+
for ( let i = 0; i < this.subTrees.length; i ++ ) {
524+
525+
const subTree = this.subTrees[ i ];
526+
527+
if ( ! box.intersectsBox( subTree.box ) ) continue;
528+
529+
if ( subTree.triangles.length > 0 ) {
530+
531+
for ( let j = 0; j < subTree.triangles.length; j ++ ) {
532+
533+
if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] );
534+
535+
}
536+
537+
} else {
538+
539+
subTree.getBoxTriangles( box, triangles );
540+
541+
}
542+
543+
}
544+
545+
}
546+
458547
/**
459548
* Computes the triangles that potentially intersect with the given capsule.
460549
*
@@ -487,6 +576,47 @@ class Octree {
487576

488577
}
489578

579+
/**
580+
* Performs a bounding box intersection test with this Octree.
581+
*
582+
* @param {Box3} box - The bounding box to test.
583+
* @return {Object|boolean} The intersection object. If no intersection
584+
* is detected, the method returns `false`.
585+
*/
586+
boxIntersect( box ) {
587+
588+
_box.copy( box );
589+
590+
const triangles = [];
591+
let result, hit = false;
592+
593+
this.getBoxTriangles( box, triangles );
594+
595+
for ( let i = 0; i < triangles.length; i ++ ) {
596+
597+
if ( result = this.triangleBoxIntersect( _box, triangles[ i ] ) ) {
598+
599+
hit = true;
600+
601+
_box.translate( result.normal.multiplyScalar( result.depth ) );
602+
603+
}
604+
605+
}
606+
607+
if ( hit ) {
608+
609+
const collisionVector = _box.getCenter( _center ).sub( box.getCenter( _v1 ) );
610+
const depth = collisionVector.length();
611+
612+
return { normal: collisionVector.normalize(), depth: depth };
613+
614+
}
615+
616+
return false;
617+
618+
}
619+
490620
/**
491621
* Performs a bounding sphere intersection test with this Octree.
492622
*
@@ -558,7 +688,7 @@ class Octree {
558688

559689
if ( hit ) {
560690

561-
const collisionVector = _capsule.getCenter( new Vector3() ).sub( capsule.getCenter( _v1 ) );
691+
const collisionVector = _capsule.getCenter( _center ).sub( capsule.getCenter( _v1 ) );
562692
const depth = collisionVector.length();
563693

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

0 commit comments

Comments
 (0)