How to implement snapping effect and collision detection between two objects using Threejs?

472 views Asked by At

We are able to detect the collision but could not implement a snapping/magnetic effect like Snap edges of objects to each other and prevent overlap we need help with 3D objects here and we are using Vec3 for the active object's position.

With the following approach, collision detection is working perfectly for all cases, and magnetic effect is somehow working - not perfectly. It's working well when the object is moving along x or z-axis but when the object's movement is in diagonal direction (moving along x and z-axis simultaneously) that is where the problem comes.

Though am not satisfied with the following approach that's why am looking for new approach to implement both magnetic and collision detection features. It is not necessary to have the solution in Threejs, any general solution or algorithm of coordinates can be converted into Threejs.

        let collide = this.detectCollisionCubes(activeObject, collidingObject, vec3);
  
        let magneticEffect = new MagneticEffect(activeObject, vec3, collidingObject);
        vec3 = magneticEffect.setNewPosition(); 
        activeObject.position.copy(vec3); 
             

        detectCollisionCubes = function(a, d, vec3){
            // a is active object's positon
            // d is colliding object                        
   
            let aHeight = Math.abs(a.getHeight());
            let aWidth = Math.abs(a.getWidth());
            let aDepth = Math.abs(a.getDepth());

            let b1 = vec3.y - aHeight / 2;
            let t1 = vec3.y + aHeight / 2;

            let r1 = vec3.x + aWidth / 2;
            let l1 = vec3.x - aWidth / 2;

            let f1 = vec3.z - aDepth / 2;
            let B1 = vec3.z + aDepth / 2;

            let dHeight = Math.abs(d.getHeight());
            let dWidth = Math.abs(d.getWidth());
            let dDepth = Math.abs(d.getDepth());
            
            let b2 = d.position.y - dHeight / 2;
            let t2 = d.position.y + dHeight / 2;

            let r2 = d.position.x + dWidth / 2;
            let l2 = d.position.x - dWidth / 2;

            let f2 = d.position.z - dDepth / 2;
            let B2 = d.position.z + dDepth / 2;
            
            if (t1 < b2 || r1 < l2 || b1 > t2 || l1 > r2 || f1 > B2 || B1 < f2) {
              return false;
            }

            return true;
        }

Trying to create magnetic effect via

    this.currentObject = currentObject;
    this.collisionObject = collisionObject;
    this.collisionType = null;
    this.objectType = null;
    this.currentPosition = currentPosition; 

    this.currentObjectHeight = Math.abs(currentObject.getHeight());
    this.currentObjectWidth = Math.abs(currentObject.getWidth());

    this.collisionObjectHeight = Math.abs(collisionObject.getHeight());
    this.collisionObjectWidth = Math.abs(collisionObject.getWidth());
    this.collisionObjectDepth = Math.abs(collisionObject.getDepth());

    this.objectTop = currentObject.position.y + (this.currentObjectHeight/2);
    this.objectBottom = currentObject.position.y - (this.currentObjectHeight/2);

    this.collideTop = collisionObject.position.y + (this.collisionObjectHeight/2);
    this.collideBottom = collisionObject.position.y - (this.collisionObjectHeight/2);

    this.zAxisDifference = Math.abs(Math.abs(currentPosition.z) - Math.abs(collisionObject.position.z));
    this.xAxisDifference = Math.abs(Math.abs(currentPosition.x) - Math.abs(collisionObject.position.x));
     
     // Extra code here   
     
    if (
        this.objectTop < this.collideBottom
    ) { 
        this.collisionType = collisionTypes.verticalBottom;
    } else if (
        this.objectBottom > this.collideTop
    ) { 
        this.collisionType = collisionTypes.verticalTop;
    } else if (
        this.currentPosition.x > this.collisionObject.position.x &&
        this.zAxisDifference < 2
    ) {
        this.collisionType = collisionTypes.horizentalXLeft;
    } else if (
        this.currentPosition.x < this.collisionObject.position.x &&
        this.zAxisDifference < 2
    ) {
        this.collisionType = collisionTypes.horizentalXRight;
    } else if (
        this.currentPosition.z > this.collisionObject.position.z &&
        this.xAxisDifference < 2
    ) {
        this.collisionType = collisionTypes.horizentalZLeft;
    } else if (
        this.currentPosition.z < this.collisionObject.position.z &&
        this.xAxisDifference < 2
    ) {
        this.collisionType = collisionTypes.horizentalZRight;
    }

 MagneticEffect.prototype.setNewPosition = function () {
    
    if (this.collisionType === collisionTypes.verticalBottom) {
        this.currentPosition.y = this.collideBottom + 0.5;
    } else if (this.collisionType === collisionTypes.verticalTop) {
        this.currentPosition.y = this.collideTop - 0.5;
    } else if (this.collisionType === collisionTypes.horizentalXRight) {
        this.currentPosition.x = this.collisionObject.position.x - this.collisionObjectWidth - 0.5;
    } else if (this.collisionType === collisionTypes.horizentalXLeft) {
        this.currentPosition.x = this.collisionObject.position.x + this.collisionObjectWidth + 0.5;
    } else if (this.collisionType === collisionTypes.horizentalZRight) {
        this.currentPosition.z = this.collisionObject.position.z - this.collisionObjectWidth - 0.5;
    } else if (this.collisionType === collisionTypes.horizentalZLeft) {
        this.currentPosition.z = this.collisionObject.position.z + this.collisionObjectWidth + 0.5;
    }

    return this.currentPosition;
};
0

There are 0 answers