This works, but only half way. After the intersection occurs, the box gets stuck at that position and won’t move any more. I’m sure this happens because I’m checking the intersection after we already moved the box to a location where it intersects. I think I should instead make use of the target vector that’s passed to validateDrag() as a parameter. But I haven’t managed to figure out how.
For example, I tried to temporarily move the dragBox to target position, check for intersection, and then restore the position:
drag.validateDrag = (target) => {
// remember original position
const {x,y,z} = dragBox.position;
dragBox.position.x = target.x;
dragBox.position.y = target.y;
dragBox.position.z = target.z;
// check if new position intersects
const allowDrag = !dragBox.intersectsMesh(box2);
// restore original position
dragBox.position.x = x;
dragBox.position.y = y;
dragBox.position.z = z;
return allowDrag;
}
But the outcome is exactly the same
I’ve also tried cloning the mesh and setting its future position. Didn’t help
I’m probably doing something horribly wrong in here, but I have no clue.
What you could do is combining the use of a clone, with the moveWithCollision method, which allows to move a mesh toward a direction, until it collides.
That way non only you will prevent the collision, but also it will still allow a movement when collided (sliding along the edge)
NB: Line 30 I’m setting the visibility of the dragged mesh to 0.0, but you can set it to 0.5 in order to better understand what’s happening :
The dragged mesh in actually going through, and the moveWithCollision creates this “sticky” behavior
Thanks @Tricotou. This now works when the meshes that I drag are simple cubes. But of course in real life I’d like to have a bit more complex geometries. Like having some nested meshes.
As I understand, setting mesh visibility doesn’t effect the visibility of sub-meshes:
Which works, but is quite a nuisance. Perhaps there’s some better way to achieve the same?
Also, when I go this route of recursively setting visibility of all nested meshes to 0, this will mean I now have to reserve the use of visibility to this dragging behavior, otherwise I will run into conflicts when I have some nested mesh hidden with visibility=0.
Another problem with this whole solution is that now the actual mesh is hidden and we only see the clone. When in some other part of the program I want to change that mesh, while it happens to be dragged, those changes won’t be reflected in the clone that’s visible. (I actually already have this problem - in another part of the program I change the mesh to indicate that it’s in selected state, but that change is now invisible because it happens to occur right after dragging starts).
Yet another problem is that I’m monitoring the position of this mesh elsewhere in the application and doing stuff based on that location. But this logic now falls apart as the mesh appears to be in one place (where the clone is), but is actually in another place (just hidden).
Discovered that you can set PointerDragBehavior.moveAttached = false, which gives you full control over actually moving the mesh. The behavior can then be used to get the target position of where the mesh should be moved.
Basically one can do something like this:
let dragPosition = null;
dragBhv.moveAttached = false;
dragBhv.onDragStartObservable.add(() => {
dragPosition = mesh.position.clone();
});
dragBhv.onDragObservable.add(({delta}) => {
// keep track where PointerDragBehavior thinks the mesh should be dragged to
dragPosition.addInPlace(delta);
// perform the actual positioning of mesh in whatever way you need
if (isPositionValid(dragPosition)) {
mesh.position.copyFrom(dragPosition);
}
});