javascript - 将物体放在房间里

标签 javascript three.js

我创建了一个 3D 房间,房间里有一个可以移动的架子。 我想让我的房间中的所有对象都留在我的房间中,用户不应该能够将任何东西拖出房间。

我尝试了多种方法让它发挥作用,但我所做的一切都不够好。 目前,架子有点超出了房间,一旦它超出了,我就无法再移动它了。单击鼠标时我应该仍然可以拖动它。 我希望有一个人可以帮助我。我在这个话题上花了很长时间,但我的大脑开始放弃:)

目前我的代码如下所示:

鼠标移动时:

 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);

鼠标按下时

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);

以下是我的场景的一些屏幕截图: 所以问题是架子停得太晚了,一旦停止我就不能再移动它了。箭头是我的光线转换器

我无法添加图片,所以我创建了一个 imgur 相册 /image/p2SCe.jpg

最佳答案

这只是一个从头开始制作的选项。

这个想法是使用 .clamp(min, max) THREE.Vector3() 的方法。

看起来可能很复杂,但这里的大部分内容都是为了可视化,重要部分都标有注释:

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>

关于javascript - 将物体放在房间里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50561020/

相关文章:

javascript - Javascript - 导出和导入

javascript - 我可以使用 jQuery 在 GWT 小部件上触发事件吗?

javascript - 处置对象并恢复它们

javascript - Spring 物理平衡总是向左移动

three.js - 在三个JS编辑器中使用场景的用户数据

javascript - ChartJS : how to make a bar chart with a horizontal guideline:

javascript - 构造 (x = x || y,z) 中的逗号是什么意思?

URL 中的 Javascript 单选按钮值

javascript - GUI 上 3 个顶点的方向

javascript - 如何使用 Three.js 在网站中创建圆形框架 webgl 窗口场景