Three-mesh-bvh stop drag after collision

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 :sweat_smile:

1 Like