Three.js вращая камеру в эллиптической форме - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь заставить мою камеру perspectiveCamera вращаться вокруг сцены, которая имеет эллиптическую или прямоугольную форму.Кажется, я не могу придумать, как заставить камеру автоматически уменьшать масштаб, когда она сталкивается с краем, чтобы сцена не обрезалась.

для целей визуализации Я хочу в значительной степени этот эффект

Я пробовал весь день, и мне не хватало жестких позиций (что не может быть правильным решением). Я терпел неудачу.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Копия @ тюрьмы849 с определенными проблемами исправлено для некоторого определения исправлено. Думал о том, чтобы просто отредактировать этот ответ, но думал, что я делаю слишком много изменений Рад снять это, если это неуместно

  1. Исправлена ​​ошибка с разрывом

  2. Удалить зависимость от размера окна

  3. Изменение размера дескриптора кода

  4. Ручка захвата мыши

    примечание: захват мыши не работает ни в iframe ни в Chrome, ни в v69, ни в Safari, как это реализовано здесь. Это работает в Firefox. Другими словами, нажмите на изображение, перетащите за пределы окна . Если вы фрейм-фрейм, вы прекратите получать события, как только вы перетащите за пределы кадра. Если вы фрейм верхнего уровня, вы продолжите получать события за пределами окна.

    У этого есть куча проблем.

    Если вы оставите код как есть, и вы в iframe, то если пользователь щелкает и перетаскивает в iframe, перемещает мышь из iframe, а затем отпускает кнопку мыши, перетаскивание будет застрял до мыши пользователь щелкает в кадре (событие mouseup никогда не приходит)

    Одним из решений этой проблемы является добавление слушателя к mouseout, чтобы удалить все слушатели. Проблема с этим решением, как только мышь касается края рамки или окна, от которого отключается мышь перетаскивание, которое ужасный UX.

    Еще одно возможное решение - отключить мышь только при наведении мыши. в iframe, но это все еще имеет проблему, которая, как только пользователь выходит из фрейма, мышь отключается, даже если они не отпускают мыши и в конечном итоге перетащить обратно в кадр

    проверяя другие сайты, большинство сайтов решают просто позволить мышке застрять в режиме перетаскивания (встроенные карты Google показывает это поведение как в качестве двух примеров выполняет управление камерой three.js).

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
var canvas = renderer.domElement
document.body.appendChild(canvas);

var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(10, 10, -10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));

scene.add(new THREE.GridHelper(20, 20, 0x404040, 0x404040));

// island
var boxGeo = new THREE.BoxBufferGeometry();
boxGeo.translate(0, 0.5, 0);
var boxMat = new THREE.MeshLambertMaterial({
  color: 0x909090
});
for (let x = -5; x < 6; x++) {
  for (let y = -3; y < 4; y++) {
    let box = new THREE.Mesh(boxGeo, boxMat);
    box.scale.y = THREE.Math.randInt(1, 3);
    box.position.set(x - 0.5, 0, y - 0.5);
    scene.add(box);
    let edgesGeo = new THREE.EdgesGeometry(boxGeo);
    let edges = new THREE.LineSegments(edgesGeo, new THREE.LineBasicMaterial({
      color: 0xaaaaaa
    }));
    box.add(edges);
  }
}

//path
var curve = new THREE.CatmullRomCurve3([
  new THREE.Vector3(0, 6, 6),
  new THREE.Vector3(12, 6, 0),
  new THREE.Vector3(0, 6, -6),
  new THREE.Vector3(-12, 6, 0)
])
curve.closed = true;

curve.getPoint(0, camera.position);
camera.lookAt(scene.position);

var mouseXOnMouseDown = 0;
var currPoint = 0;
var currPointOnMouseDown = 0;

canvas.addEventListener('mousedown', onCanvasMouseDown, true);

function onCanvasMouseDown(event) {
  event.preventDefault();
  event.stopPropagation();  
  window.addEventListener('mousemove', onDocumentMouseMove, true);
  window.addEventListener('mouseup', removeListeners, true);
  mouseXOnMouseDown = event.clientX;
  currPointOnMouseDown = currPoint;
}

function onDocumentMouseMove(event) {
  event.preventDefault();
  event.stopPropagation();
  var deltaMouseX = event.clientX - mouseXOnMouseDown;
  currPoint = THREE.Math.euclideanModulo(currPointOnMouseDown + deltaMouseX * 0.0005, 1);
}

function removeListeners() {
  window.removeEventListener('mousemove', onDocumentMouseMove, true);
  window.removeEventListener('mouseup', removeListeners, true);
}

render();

function resize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}

function render() {
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  
  curve.getPoint(currPoint, camera.position);
  camera.lookAt(scene.position);
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
html, body {
  height: 100%;
  margin: 0;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
0 голосов
/ 07 сентября 2018

Очень грубая концепция с кривой (код для событий мыши взят из здесь ):

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

var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(10, 10, -10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));

scene.add(new THREE.GridHelper(20, 20, 0x404040, 0x404040));

// island
var boxGeo = new THREE.BoxBufferGeometry();
boxGeo.translate(0, 0.5, 0);
var boxMat = new THREE.MeshLambertMaterial({
  color: 0x909090
});
for (let x = -5; x < 6; x++) {
  for (let y = -3; y < 4; y++) {
    let box = new THREE.Mesh(boxGeo, boxMat);
    box.scale.y = THREE.Math.randInt(1, 3);
    box.position.set(x - 0.5, 0, y - 0.5);
    scene.add(box);
    let edgesGeo = new THREE.EdgesGeometry(boxGeo);
    let edges = new THREE.LineSegments(edgesGeo, new THREE.LineBasicMaterial({
      color: 0xaaaaaa
    }));
    box.add(edges);
  }
}

//path
var curve = new THREE.CatmullRomCurve3([
  new THREE.Vector3(0, 6, 6),
  new THREE.Vector3(12, 6, 0),
  new THREE.Vector3(0, 6, -6),
  new THREE.Vector3(-12, 6, 0)
])
curve.closed = true;

curve.getPoint(0, camera.position);
camera.lookAt(scene.position);

var mouseX = 0;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var currentPoint = 0;
var currPoint = 0;

document.addEventListener('mousedown', onDocumentMouseDown, false);

function onDocumentMouseDown(event) {
  event.preventDefault();
  document.addEventListener('mousemove', onDocumentMouseMove, false);
  document.addEventListener('mouseup', onDocumentMouseUp, false);
  document.addEventListener('mouseout', onDocumentMouseOut, false);
  mouseXOnMouseDown = event.clientX - windowHalfX;
  targetRotationOnMouseDown = targetRotation;
}

function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
  currPoint = (targetRotation - targetRotationOnMouseDown) * 0.05;
}

function onDocumentMouseUp(event) {
  document.removeEventListener('mousemove', onDocumentMouseMove, false);
  document.removeEventListener('mouseup', onDocumentMouseUp, false);
  document.removeEventListener('mouseout', onDocumentMouseOut, false);
}

function onDocumentMouseOut(event) {
  document.removeEventListener('mousemove', onDocumentMouseMove, false);
  document.removeEventListener('mouseup', onDocumentMouseUp, false);
  document.removeEventListener('mouseout', onDocumentMouseOut, false);
}

render();

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