EnginO
EnginO

Reputation: 206

Keep Object in Room

i have a 3D Room that i create and a shelf in my Room that i can move arround. I want to make all the objects i have in my Room to stay in my room, the user should not be able to drag anything out of it.

I have tried multiple ways to make it work but nothing i did worked well enough. At the moment the shelf goes a bit out of the room and as soon as it is out i cant move it anymore. I should still be able to drag it while the mouse is clicked. I hope someone can help me. i worked way to long on this topic and my brain just starts to give up :)

At the moment my code looks like this:

on Mouse Move:

 let bb = this.selectedHelper.geometry.boundingBox;

      let originPoint = this.selected.position.clone();
      originPoint.y = bb.getSize().y / 2;
      originPoint.z += bb.getSize().z / 2;

      this.raycasterLeft.set(originPoint, new THREE.Vector3(-1, 0, 0));
      this.raycasterRight.set(new THREE.Vector3(originPoint.x + bb.getSize().x, originPoint.y, originPoint.z), new THREE.Vector3(1, 0, 0));
      this.raycasterFront.set(new THREE.Vector3(originPoint.x + bb.getSize().x / 2, originPoint.y, originPoint.z + bb.getSize().z / 2), new THREE.Vector3(0, 0, 1));
      this.raycasterBack.set(new THREE.Vector3(originPoint.x + bb.getSize().x / 2, originPoint.y, originPoint.z - bb.getSize().z / 2), new THREE.Vector3(0, 0, -1));



      this.intersectionLeft = this.raycasterLeft.intersectObjects(this.walls, true);
      this.intersectionRight = this.raycasterRight.intersectObjects(this.walls, true);
      this.intersectionFront = this.raycasterFront.intersectObjects(this.walls, true);
      this.intersectionBack = this.raycasterBack.intersectObjects(this.walls, true);



      if (this.oktomove) {
        this.selected.position.x = this.intersection.sub(this.offsetControls).x;
        this.selected.position.z = this.intersection.z;
        if (this.selected.name != "door" && this.selected.name != "regal") this.selected.position.y = this.intersection.y;
        else { this.selected.position.y = 0; }
      }

      if (this.intersectionLeft.length > 0
        && this.intersectionRight.length > 0
        && this.intersectionFront.length > 0
        && this.intersectionBack.length > 0) {

        if (this.intersectionLeft[0].distance >= 10
          || this.intersectionRight[0].distance >= 10
          || this.intersectionFront[0].distance >= 10
          || this.intersectionBack[0].distance >= 10) {
          this.oktomove = true;
        }
      }
      else {
        console.log("drauflen")
        this.oktomove = false;
      }

      this.showCasters(this.raycasterLeft, this.raycasterRight, this.raycasterFront, this.raycasterBack);

and on mouse Down

this.oktomove = true;
    this.orbitControl.enabled = false;

    if (intersectRegal[intersectRegal.length - 1].object.parent.name == "regal") {
      this.selected = intersectRegal[intersectRegal.length - 1].object.parent;
    }
    else if (intersectRegal[intersectRegal.length - 1].object.parent.parent.name == "regal") {
      this.selected = intersectRegal[intersectRegal.length - 1].object.parent.parent;
    }
    else if (intersectRegal[intersectRegal.length - 1].object.parent.parent.parent.name == "regal") {
      this.selected = intersectRegal[intersectRegal.length - 1].object.parent.parent.parent;
    }

    this.selectedHelper = new THREE.BoxHelper(this.selected);
    this.selectedHelper.geometry.computeBoundingBox();

    let bb = this.selectedHelper.geometry.boundingBox;

    let originPoint = this.selected.position.clone();
    originPoint.y = bb.getSize().y / 2;
    originPoint.z += bb.getSize().z / 2;

    this.raycasterLeft = new THREE.Raycaster(originPoint, new THREE.Vector3(-1, 0, 0));
    this.raycasterRight = new THREE.Raycaster(new THREE.Vector3(originPoint.x + bb.getSize().x, originPoint.y, originPoint.z), new THREE.Vector3(1, 0, 0));
    this.raycasterFront = new THREE.Raycaster(new THREE.Vector3(originPoint.x + bb.getSize().x / 2, originPoint.y, originPoint.z + bb.getSize().z / 2), new THREE.Vector3(0, 0, 1));
    this.raycasterBack = new THREE.Raycaster(new THREE.Vector3(originPoint.x + bb.getSize().x / 2, originPoint.y, originPoint.z - bb.getSize().z / 2), new THREE.Vector3(0, 0, -1));

    this.intersectionLeft = this.raycasterLeft.intersectObjects(this.walls, true);
    this.intersectionRight = this.raycasterRight.intersectObjects(this.walls, true);
    this.intersectionFront = this.raycasterFront.intersectObjects(this.walls, true);
    this.intersectionBack = this.raycasterBack.intersectObjects(this.walls, true);
    this.showCasters( this.raycasterLeft , this.raycasterRight , this.raycasterFront , this.raycasterBack);

here are some screenshots from my scene: so the problem is that the shelf stops to late and once it stops i cant move it anymore. The arrows are my raycasters

i could not add the pictures so i created a imgur album https://i.sstatic.net/p2SCe.jpg

Upvotes: 0

Views: 116

Answers (2)

manthrax
manthrax

Reputation: 5016

They implemented placement restrictions in here. Maybe you'll find it useful:

http://furnishup.github.io/blueprint3d/example/

Upvotes: 0

prisoner849
prisoner849

Reputation: 17586

Here is just an option, made from a scratch.

The idea is to use .clamp(min, max) method of THREE.Vector3().

It may look complicated, but most of the stuff here is made for visualization, important parts are marked with comments:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 5, 5);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var roomGeom = new THREE.BoxGeometry(7, 2, 7);
roomGeom.translate(0, 1, 0);
var room = new THREE.Mesh(roomGeom, [
  new THREE.MeshBasicMaterial({
    color: "red",
    side: THREE.BackSide
  }),
  new THREE.MeshBasicMaterial({
    color: "red",
    side: THREE.BackSide
  }),
  new THREE.MeshBasicMaterial({
    color: "green",
    side: THREE.BackSide
  }),
  new THREE.MeshBasicMaterial({
    color: "green",
    side: THREE.BackSide
  }),
  new THREE.MeshBasicMaterial({
    color: "blue",
    side: THREE.BackSide
  }),
  new THREE.MeshBasicMaterial({
    color: "blue",
    side: THREE.BackSide
  })
]);
scene.add(room);

var objGeom = new THREE.CylinderGeometry(1, 1, 2);
objGeom.translate(0, 1, 0);
var moveObj = new THREE.Mesh(objGeom, new THREE.MeshBasicMaterial({
  color: "aqua",
  wireframe: true
}));
moveObj.position.set(1, 0, 0);
scene.add(moveObj);

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects = [];
var isDragging = false;
var plane = new THREE.Plane();
var planePoint = new THREE.Vector3();
var planeNormal = new THREE.Vector3(0, 1, 0);
var movePoint = new THREE.Vector3();
var moveObjBox = new THREE.Box3();
var moveObjBoxSize = new THREE.Vector3();
moveObjBox.setFromObject(moveObj);
var boxHelper = new THREE.Box3Helper(moveObjBox, "yellow");
scene.add(boxHelper);
var moveObjShift = new THREE.Vector3();
var roomBox = new THREE.Box3().setFromObject(room);
var roomBoxMin = new THREE.Vector3();
var roomBoxMax = new THREE.Vector3();

renderer.domElement.addEventListener("mousedown", onMouseDown, false);
renderer.domElement.addEventListener("mousemove", onMouseMove, false);
renderer.domElement.addEventListener("mouseup", onMouseUp, false);

function onMouseDown(event) {
  setPlane(event);
}

function onMouseMove(event) {
  if (!isDragging) return;
  setMouse(event);
  raycaster.setFromCamera(mouse, camera);
  raycaster.ray.intersectPlane(plane, movePoint);
  
  moveObj.position.copy(movePoint).sub(moveObjShift).clamp(roomBoxMin, roomBoxMax); // clamp the position of an object

  moveObjBox.setFromObject(moveObj);
}

function onMouseUp() {
  isDragging = false;
}

function setPlane(event) {
  setMouse(event);
  raycaster.setFromCamera(mouse, camera);
  moveObjBox.setFromObject(moveObj);
  raycaster.ray.intersectBox(moveObjBox, planePoint)

  isDragging = true;
  plane.setFromNormalAndCoplanarPoint(planeNormal, planePoint);
  moveObjShift.copy(planePoint).sub(moveObj.position);
  roomBoxMin.copy(roomBox.min);
  roomBoxMax.copy(roomBox.max);
  moveObjBox.getSize(moveObjBoxSize);
  
  // adjust clamping vectors
  roomBoxMin.x += moveObjBoxSize.x * 0.5;
  roomBoxMin.z += moveObjBoxSize.z * 0.5;
  roomBoxMax.x -= moveObjBoxSize.x * 0.5;
  roomBoxMax.z -= moveObjBoxSize.z * 0.5;
}

function setMouse(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}

render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>

Upvotes: 2

Related Questions