Рассчитать положение камеры после поворота вокруг некоторой преднамеренной точки на сетке - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь реализовать текущий сценарий:

  1. при событии нажатия мыши на перспективной камере с фокусировкой сетки в точке, где пользователь щелкнул
  2. , позволяя пользователю вращатькамера через orbitControls;
  3. после завершения поворота при наведении мыши на изменение положения камеры и цели таким образом, что может показаться, что камера все еще смотрит на сетку под тем же углом, что и до фокусировки и вращения.

Таким образом, может показаться, что пользователь повернул камеру вокруг некоторой точки на сетке и после поворота может смотреть на нее с того же места, где он был до фокусировки и вращения.

Нет проблем с 1) и 2) И я довольно смущен 3)

Здесь я добавил несколько картинок, которые иллюстрируют основные шаги

1) Клики пользователейв некоторой точке сетки

2) Фокус камеры устанавливается на точку, где пользователь щелкнул

3) Пользователь поворачивает камеру вокругвыбранная точка поворота

4) При наведении мыши камера должна быть размещена таким образом, чтобы в глазах пользователя выбранная точка возвращалась туда, где она была, и камера смотритОт того же угла

Вопрос в том, как реализовать поведение, показанное на 4-м рисунке.

Важно то, что кажется, что камера смотрит из одной и той же позиции, и пирамида поворачивается вокруг точки, где щелкнул пользователь.

Буду признателенлюбая помощь.Спасибо!

1 Ответ

0 голосов
/ 04 июля 2019

Надеюсь, я вас правильно понял. Найдите разницу между начальной целью и целевой точкой на объекте, а при наведении курсора мыши - измените положение камеры на это значение.

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>
...