第三是-如何限制OrbitographicCamera的OrbitControls中的平移,以使对象(纹理图像)始终在场景中

时间:2018-12-23 09:58:57

标签: three.js

我正在使用OrbitControls控制正交摄影机。该场景具有2d纹理图像。

到达图像边缘时,我想限制相机的摇摄。 例如,当摄像机向左平移,并且图像在查看窗口中向右移动时,当图像的左边缘在可见窗口的右侧时,停止向左平移(请参见附图) ) enter image description here

Herehere的平移限制是硬编码的,但是在我的情况下,该限制取决于缩放(并且我还假定图像的大小也取决于缩放)。例如,当图像一直向左移动时,

放大时,scope.target.x〜=〜100

缩小时,scope.target.x〜=〜800

当图像的左侧到达可见窗口的左侧边缘时,如何禁用向左平移?

谢谢, 阿夫纳


编辑:

@ Rabbid76感谢您的建议。通过对示例代码进行一些修改,我解决了问题,即图像始终覆盖视图窗口。 有关详情,请参见here

1 个答案:

答案 0 :(得分:1)

您可以手动限制平移。

考虑您有一个OrthographicCamera,它可以看到xy平面。

例如

camera = new THREE.OrthographicCamera(-5*aspect, 5*aspect, -5, 5, -100, 100);
camera.position.set(0, 0, -1);

您有一个网格(object),可以从中获得边界框({​​{3}}):

var bbox = new THREE.Box3().setFromObject(object);

使用此信息,可以计算出对象的最小和最大x和y坐标:

var min_x = camera.left  - bbox.min.x;
var max_x = camera.right - bbox.max.x;
var min_y = camera.top    - bbox.min.y;
var max_y = camera.bottom - bbox.max.y; 

当前摄像机位置和目标可以限制在限制范围内:

let pos_x =  Math.min(max_x, Math.max(min_x, camera.position.x));
let pos_y =  Math.min(max_y, Math.max(min_y, camera.position.y));

更新THREE.Box3OrthographicCamera

camera.position.set(pos_x, pos_y, camera.position.z);
camera.lookAt(pos_x, pos_y, orbitControls.target.z);

orbitControls.target.x = pos_x;
orbitControls.target.y = pos_y;
orbitControls.update();

请参见示例:

(function onLoad() {
  var container, loader, camera, scene, renderer, orbitControls, object, bbox;
  
  init();
  animate();

  function init() {
    container = document.getElementById('container');
    
    renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    container.appendChild(renderer.domElement);

    aspect = window.innerWidth / window.innerHeight;
    camera = new THREE.OrthographicCamera(-5*aspect, 5*aspect, -5, 5, -100, 100);
    camera.position.set(0, 0, -1);

    loader = new THREE.TextureLoader();
    loader.setCrossOrigin("");

    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);
    scene.add(camera);
    window.onresize = resize;
    
    orbitControls = new THREE.OrbitControls(camera);

    orbitControls.enabled = true;
    orbitControls.enableRotate = false;
    orbitControls.screenSpacePanning = true; 
    orbitControls.mouseButtons = {
	    LEFT: THREE.MOUSE.RIGHT,
	    MIDDLE: THREE.MOUSE.MIDDLE,
	    RIGHT: THREE.MOUSE.LEFT
    }

    
    addGridHelper();
    createModel();

  }

  function createModel() {

    var material = new THREE.MeshBasicMaterial({color:'#ff4040'});
    var geometry = new THREE.BoxGeometry( 1, 1, 1 );

    object = new THREE.Mesh(geometry, material);
    bbox = new THREE.Box3().setFromObject(object);

    scene.add(object);
  }

  function addGridHelper() {
    
    var helper = new THREE.GridHelper(100, 100);
    helper.rotation.x = Math.PI / 2;
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    scene.add(helper);

    var axis = new THREE.AxesHelper(1000);
    scene.add(axis);
  }

  function resize() {
    
    var aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.left = -5*aspect;
    camera.right = 5*aspect;
    camera.updateProjectionMatrix();
  }

  function animate() {
    requestAnimationFrame(animate);

    var min_x = camera.left  - bbox.min.x;
    var max_x = camera.right - bbox.max.x;
    var min_y = camera.top    - bbox.min.y;
    var max_y = camera.bottom - bbox.max.y;

    let pos_x =  Math.min(max_x, Math.max(min_x, camera.position.x));
    let pos_y =  Math.min(max_y, Math.max(min_y, camera.position.y));
    
    camera.position.set(pos_x, pos_y, camera.position.z);
    camera.lookAt(pos_x, pos_y, orbitControls.target.z);

    orbitControls.target.x = pos_x;
    orbitControls.target.y = pos_y;
    orbitControls.update();
    
    render();
  }

  function render() {
    renderer.render(scene, camera);
  }
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>