Change mesh rotation and position based on some other mesh

Hi discourse community!

I do have a concern regarding a feature that I want to implement in my app.

For context, this is an app built with react-three-fiber. This app has a type of mesh called ‘walls’ (they are the white lines shown in the screenshot) and ‘furniture’. I have a feature in my app which detects collision between objects based on OBB.

Whenever I drag a ‘furniture’ and this collision is triggered (I already have it set up), I want my ‘furniture’ to snap to where I’m indicating in this screenshot:

So basically, I want my ‘furniture’ to get turned with its back against the wall and snapped in the ‘wall’ edge.

The relevant info that I have from my furniture is:

  • Center position of the furniture (x,y)

The info that I have from my walls is:

  • Center position (x,y),
  • The coordinates of the start and end of the ‘wall’ (the place where the blue dots are located on both edges of the ‘wall’, the intersection of these points is actually where the ‘furniture’ should go),
  • Its rotation from the center, in radians
  • Its width, which is how long does the line extent from its center position on both vertical sides
  • Its thickness, which is how long does does the line extent from its center position on both horizontal sides

In case that the furniture detects a collision with the upper wall shown in the photo, I’d need the furniture to get aligned with the wall as well.

Ideally in the future, I’d need the furniture to get aligned to the wall to the axis where ‘it was coming from’, say:

Here I need the item to get placed aligned to the horizontal coordinate of the item the moment the collision is detected. Not to the center position of the wall. If I were dragging the item upwards, I need the item to be placed aligned with the vertical coordinate. I do not know how hard this would be so I’m leaving it as an aside for now.

This is how I create my wall OBB:

  useLayoutEffect(() => {
    if (!wallBBInfo || !meshRef?.current) return

    const obb = wallBBInfo.boundingBox
    // Update center of OBB according to the center coordinates of the 'wall'
    obb.center.set(x, y, z)
   // Adjust its half size
    obb.halfSize.set(width / 2, height / 2, thickness / 2)

    // Adjust its rotation (this is a bit messy, but I did not know any other way to pass 
    in the rotation as a Matrix3 to the OBB rotation property with just a radian value)
    const mat4 = new Matrix4().makeRotationFromEuler(
      new Euler(0, -rotation + 2 * Math.PI, 0, 'XYZ')
    )
    const rot = new Matrix3().setFromMatrix4(mat4)
    obb.rotation = rot
  }, [x, y, z, width, height, thickness, rotation])

This is how I currently have set up my item collisions:

    // This is executed when my item gets dragged
    // Previous OBB from Mesh
    const obb = meshBBInfo.boundingBox
    // Here I update the mesh OBB with a Box created from a R3F ref
    obb.fromBox3(new Box3().setFromObject(itemRef.current))

   // I iterate an array of all the OBB I have in the scene, filter them by type 'walls' 
    and check if any of them intersect
    for (const [wallID, bb] of sceneBoundingBoxes.entries()) {
      if (bb.type === 'walls') {
        if (obb.intersectsOBB(bb.boundingBox)) {
          // If that is the case, get the rotation and coordinates from the wall I 
          collisioned with (this data is saved on a Zustand store). Start and end are 
          unused for now.
          const { rotation, x, y, z, start, end } = items.get(wallID)

         // Execute Zustand actions that update the 'furniture' position and rotation
          editItemPosition(id, x, z)
          editItemRotation(id, rotation)
        }
      }
    }
  }

This is the result I get for now whenever this function triggers on collision detection.
image

Any indications or advice on how to get the desired result are greatly appreciated.