I’m using three-mesh-bvh to check collision between 2 object in Threejs.
The function intersectsGeometry
working for collision.
I edited the TransformControl.js
to check collision when dragging, like:
checkCollision(item1, item2) {
if (item1.isMesh && item2.isMesh) {
item1?.geometry?.computeBoundsTree()
item2?.geometry?.computeBoundsTree()
const transformMatrix = new THREE.Matrix4().copy( item1.matrixWorld ).invert().multiply( item2.matrixWorld );
const hit = item1.geometry.boundsTree.intersectsGeometry( item2.geometry, transformMatrix )
return hit;
}
return false
}
And, in the pointerMove
function, with translate
mode, I added below function to prevent drag after collision, like:
checkOverlap() {
const spheres = editor.scene.children.filter((item) => item.uuid !== object.uuid) // get object is not selecting
// let's say, i just get the first object to test
const hit = this.checkCollision(object, spheres[0]);
if (!hit) {
object.position.copy(this._offset).add(this._positionStart)
}
}
Of course, it stop after collision. But I can drag it again after collision, because it checked collision first.
Anyone have idea for this section?
Thank you~
You have to move the object before checking it, then undo the movement if the check fails.
It looks like you’re only testing it first… then moving it.
let savePos = new THREE.Vector3();
checkOverlap() {
savePos.copy( object.position)
object.position.copy(this._offset).add(this._positionStart)
const spheres = editor.scene.children.filter((item) => item.uuid !== object.uuid) // get object is not selecting
// let's say, i just get the first object to test
const hit = this.checkCollision(object, spheres[0]);
if ( hit ) {
object.position.copy( savePos )
}
}
Thank for your answer, but it seems not working.
After collision, I can’t move it again
Hmm ok I think perhaps you are moving the model somewhere in code that you didn’t show?
Generally… it will be very difficult to “correct” the position. You want to prevent it from ever getting into the colliding state in the first place… and if it IS in a colliding state at the start of an operation, then you may want to ignore collision for that object, to allow the object to be un-collided.
If you can share a jsfiddle or glitch of the thing running we can probably provide better help.
1 Like
Thank for your help. I try something another way to resolve it.
I realize that shouldn’t stop object in TransformControls.js
file.
Now, I check it in the Viewport.js
file of change
event.
When transformControls
has event change
, I added currentPosition to userData, if collision. I set position to previous position.
this.transformControls.addEventListener('change', () => {
const object: any = this.transformControls.object;
if (object !== undefined) {
if (!object.userData.currentPosition) {
object.userData.currentPosition = new THREE.Vector3();
}
this.box.setFromObject(object, true);
const mas = this.editor.scene.children.filter((item: any) => item.uuid !== object.uuid);
for ( var i = 0; i < mas.length; i ++ ) {
if ( object.uuid != mas[ i ].uuid ) {
var secondObject = mas[ i ];
var collision = this.checkCollision( object, mas[i] );
if ( collision ) {
object.position.copy( object.userData.currentPosition )
}
}
}
object.userData.currentPosition.copy( object.position );
// ... other logic
}
this.render();
});
Anyway, it’s working, although a bit difficult for use
1 Like