围绕网格上的某个特定点旋转后计算相机的位置

时间:2019-07-03 16:01:20

标签: javascript three.js 3d camera rotation

我正在尝试实施当前方案:

  1. 在用户单击时在网状聚焦透视相机上发生的鼠标按下事件
  2. 允许用户通过orbitControls旋转相机;
  3. 在鼠标悬停事件上完成旋转之后,以这种方式更改相机的位置和目标,似乎相机仍在以与聚焦和旋转之前相同的角度注视着网格。

因此,用户似乎在围绕网格上的某个点旋转了相机,并且旋转之后可以从聚焦和旋转之前的同一位置观看它。

1)和2)没问题 我对3)感到很困惑

在这里我添加了一些图片,这些图片说明了主要步骤

1) User clicks on some point on the mesh

2) Camera focus is set on the point where the user clicked

3) User rotates the camera around the selected pivot point

4) On mouse up camera should be placed in such fashion so in user's eyes selected point is brought back to the place where it was and the camera is looking from the same angle

问题是如何实现第四张图中所示的行为。

重要的是,以为照相机似乎是从同一位置朝着同一目标注视,金字塔似乎围绕用户单击的点旋转。

我将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

希望我能正确理解你。 找到初始目标和目标上的目标点之间的差异,然后向上拖动鼠标-使用此值移动相机位置。

var w = window.innerWidth,
  h = window.innerHeight;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, w / h, 1, 1000);
camera.position.setScalar(5);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

scene.add(new THREE.GridHelper(10, 10));

var prismGeom = new THREE.ConeBufferGeometry(1, 2, 3);
prismGeom.translate(0, 1, 0);
var prismMat = new THREE.MeshBasicMaterial({
  color: "red",
  wireframe: true
});
var prism = new THREE.Mesh(prismGeom, prismMat);
prism.position.set(-1, 0, -2);
scene.add(prism);

var centralMarker = new THREE.Mesh(new THREE.SphereBufferGeometry(0.125, 4, 2), new THREE.MeshBasicMaterial({
  color: "aqua"
}));
scene.add(centralMarker);

var pointMarker = new THREE.Mesh(centralMarker.geometry, new THREE.MeshBasicMaterial({
  color: "magenta"
}));
pointMarker.visible = false;
scene.add(pointMarker);


var oldTarget = scene.position;
var targeted = false;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects = [];

window.addEventListener("mousedown", onMouseDown, false);
window.addEventListener("mouseup", onMouseUp, false);

function onMouseDown(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObject(prism);
  if (intersects.length > 0) {
    targeted = true;
    controls.target.copy(intersects[0].point);
    pointMarker.position.copy(intersects[0].point);
    pointMarker.visible = true;
    controls.update();
  }
}

function onMouseUp(event) {
  if (!targeted) return;
  let shift = new THREE.Vector3().copy(oldTarget).sub(controls.target);
  camera.position.add(shift);
  controls.target.copy(oldTarget);
  controls.update();
  targeted = false;
  pointMarker.visible = false;
}

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera)
})
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>