Created
November 12, 2025 19:10
-
-
Save gstreetmedia/3eb43b6f95ffc43f93039134edd56198 to your computer and use it in GitHub Desktop.
ThreeJS Box3 subtract Method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Subtract boxB from boxA, returning the remaining non-overlapping regions | |
| * This properly handles Box3 subtraction by breaking the result into slices | |
| * @param boxA - The box to subtract from | |
| * @param boxB - The box to subtract | |
| * @returns Array of Box3 objects representing the remaining volume after subtraction | |
| */ | |
| export function subtractBox3(boxA: Box3, boxB: Box3): Box3[] { | |
| const result: Box3[] = []; | |
| // Check if boxes actually intersect | |
| const intersection = new Box3(); | |
| intersection.copy(boxA); | |
| // Manually check intersection without modifying boxes | |
| if (boxA.max.x <= boxB.min.x || boxA.min.x >= boxB.max.x || | |
| boxA.max.y <= boxB.min.y || boxA.min.y >= boxB.max.y || | |
| boxA.max.z <= boxB.min.z || boxA.min.z >= boxB.max.z) { | |
| // No intersection, return original box | |
| return [boxA.clone()]; | |
| } | |
| // Calculate actual intersection bounds | |
| const intMin = { | |
| x: Math.max(boxA.min.x, boxB.min.x), | |
| y: Math.max(boxA.min.y, boxB.min.y), | |
| z: Math.max(boxA.min.z, boxB.min.z) | |
| }; | |
| const intMax = { | |
| x: Math.min(boxA.max.x, boxB.max.x), | |
| y: Math.min(boxA.max.y, boxB.max.y), | |
| z: Math.min(boxA.max.z, boxB.max.z) | |
| }; | |
| // Bottom slice (min Y) | |
| if (boxA.min.y < intMin.y) { | |
| result.push(new Box3( | |
| new Vector3(boxA.min.x, boxA.min.y, boxA.min.z), | |
| new Vector3(boxA.max.x, intMin.y, boxA.max.z) | |
| )); | |
| } | |
| // Top slice (max Y) | |
| if (boxA.max.y > intMax.y) { | |
| result.push(new Box3( | |
| new Vector3(boxA.min.x, intMax.y, boxA.min.z), | |
| new Vector3(boxA.max.x, boxA.max.y, boxA.max.z) | |
| )); | |
| } | |
| // Left slice (min X) - only in the intersection Y/Z region | |
| if (boxA.min.x < intMin.x) { | |
| result.push(new Box3( | |
| new Vector3(boxA.min.x, intMin.y, boxA.min.z), | |
| new Vector3(intMin.x, intMax.y, boxA.max.z) | |
| )); | |
| } | |
| // Right slice (max X) - only in the intersection Y/Z region | |
| if (boxA.max.x > intMax.x) { | |
| result.push(new Box3( | |
| new Vector3(intMax.x, intMin.y, boxA.min.z), | |
| new Vector3(boxA.max.x, intMax.y, boxA.max.z) | |
| )); | |
| } | |
| // Front slice (min Z) - only in the intersection X/Y region | |
| if (boxA.min.z < intMin.z) { | |
| result.push(new Box3( | |
| new Vector3(intMin.x, intMin.y, boxA.min.z), | |
| new Vector3(intMax.x, intMax.y, intMin.z) | |
| )); | |
| } | |
| // Back slice (max Z) - only in the intersection X/Y region | |
| if (boxA.max.z > intMax.z) { | |
| result.push(new Box3( | |
| new Vector3(intMin.x, intMin.y, intMax.z), | |
| new Vector3(intMax.x, intMax.y, boxA.max.z) | |
| )); | |
| } | |
| return result; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment