Skip to content

Commit

Permalink
Merge pull request #638 from 3DStreet/boxhelper
Browse files Browse the repository at this point in the history
New BoxHelper that take into account the rotation
  • Loading branch information
kfarr authored Jun 18, 2024
2 parents 8b759ee + 3db29f3 commit 122f8c1
Showing 1 changed file with 88 additions and 37 deletions.
125 changes: 88 additions & 37 deletions src/editor/lib/viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,91 @@ import { initRaycaster } from './raycaster';
import Events from './Events';
import { sendMetric } from '../services/ga.js';

// variables used by OrientedBoxHelper
const auxEuler = new THREE.Euler();
const auxPosition = new THREE.Vector3();
const auxLocalPosition = new THREE.Vector3();
const origin = new THREE.Vector3();
const auxScale = new THREE.Vector3();
const auxQuaternion = new THREE.Quaternion();
const identityQuaternion = new THREE.Quaternion();
const auxMatrix = new THREE.Matrix4();
const tempBox3 = new THREE.Box3();
const tempVector3Size = new THREE.Vector3();
const tempVector3Center = new THREE.Vector3();

class OrientedBoxHelper extends THREE.BoxHelper {
constructor(object, color = 0xffff00, fill = false) {
super(object, color);
this.material.linewidth = 3;
if (fill) {
// Mesh with BoxGeometry and Semi-transparent Material
const boxFillGeometry = new THREE.BoxGeometry(1, 1, 1);
const boxFillMaterial = new THREE.MeshBasicMaterial({
color: color,
transparent: true,
opacity: 0.3,
depthTest: false
});
const boxFill = new THREE.Mesh(boxFillGeometry, boxFillMaterial);
this.boxFill = boxFill;
this.add(boxFill);
}
}

update() {
// Bounding box is created axis-aligned AABB.
// If there's any rotation the box will have the wrong size.
// It undoes the local entity rotation and then restores so box has the expected size.
// We also undo the parent world rotation.
if (this.object !== undefined) {
auxEuler.copy(this.object.rotation);
auxLocalPosition.copy(this.object.position);
this.object.rotation.set(0, 0, 0);
this.object.position.set(0, 0, 0);

this.object.parent.matrixWorld.decompose(
auxPosition,
auxQuaternion,
auxScale
);
auxMatrix.compose(origin, identityQuaternion, auxScale);
this.object.parent.matrixWorld.copy(auxMatrix);
if (this.boxFill) {
tempBox3.setFromObject(this.object);
tempBox3.getSize(tempVector3Size);
tempBox3.getCenter(tempVector3Center);
this.boxFill.position.copy(tempVector3Center);
this.boxFill.scale.copy(tempVector3Size);
}
}

super.update();

// Restore rotations.
if (this.object !== undefined) {
this.object.parent.matrixWorld.compose(
auxPosition,
auxQuaternion,
auxScale
);
this.object.rotation.copy(auxEuler);
this.object.position.copy(auxLocalPosition);
this.object.getWorldQuaternion(this.quaternion);
this.object.getWorldPosition(this.position);
this.updateMatrix();
}
}

dispose() {
super.dispose();
if (this.boxFill) {
this.boxFill.geometry.dispose();
this.boxFill.material.dispose();
}
}
}

/**
* Transform controls stuff mostly.
*/
Expand All @@ -27,59 +112,27 @@ export function Viewport(inspector) {
grid.visible = false;
sceneHelpers.add(grid);

const selectionBox = new THREE.BoxHelper();
const selectionBox = new OrientedBoxHelper(undefined, 0x1faaf2);
selectionBox.material.depthTest = false;
selectionBox.material.transparent = true;
selectionBox.material.color.set(0x1faaf2);
selectionBox.visible = false;
sceneHelpers.add(selectionBox);

// hoverBox BoxHelper version
const hoverBox = new THREE.BoxHelper();
const hoverBox = new OrientedBoxHelper(undefined, 0xff0000, true);
hoverBox.material.depthTest = false;
hoverBox.material.transparent = true;
hoverBox.material.color.set(0xff0000);
hoverBox.visible = true;
hoverBox.visible = false;
sceneHelpers.add(hoverBox);

// hoverBoxFill - Mesh with BoxGeometry and Semi-transparent Material
const hoverBoxFillGeometry = new THREE.BoxGeometry(1, 1, 1);
const hoverBoxFillMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
transparent: true,
opacity: 0.3,
depthTest: false
});
const hoverBoxFill = new THREE.Mesh(
hoverBoxFillGeometry,
hoverBoxFillMaterial
);
hoverBoxFill.visible = true;
sceneHelpers.add(hoverBoxFill);

// Create global instances of Box3 and Vector3
const tempBox3 = new THREE.Box3();
const tempVector3Size = new THREE.Vector3();
const tempVector3Center = new THREE.Vector3();

Events.on('raycastermouseenter', (el) => {
// update hoverBox to match el.object3D bounding box
hoverBox.visible = true;
hoverBox.setFromObject(el.object3D);
// update hoverBoxFill to match el.object3D bounding box
el.object3D.updateMatrixWorld();
tempBox3.setFromObject(el.object3D);
tempBox3.getSize(tempVector3Size);
tempBox3.getCenter(tempVector3Center);
hoverBoxFill.visible = true;
hoverBoxFill.position.copy(tempVector3Center);
hoverBoxFill.scale.copy(tempVector3Size);
hoverBoxFill.geometry.attributes.position.needsUpdate = true;
});

Events.on('raycastermouseleave', (el) => {
hoverBox.visible = false;
hoverBoxFill.visible = false;
});

function updateHelpers(object) {
Expand Down Expand Up @@ -149,7 +202,6 @@ export function Viewport(inspector) {
if (inspector.selectedEntity.object3DMap.mesh) {
selectionBox.setFromObject(inspector.selected);
hoverBox.visible = false;
hoverBoxFill.visible = false;
}
});

Expand Down Expand Up @@ -250,7 +302,6 @@ export function Viewport(inspector) {
) {
selectionBox.setFromObject(object);
hoverBox.visible = false;
hoverBoxFill.visible = false;
}
}

Expand Down

0 comments on commit 122f8c1

Please sign in to comment.