我正在使用OrbitControls控制正交摄影机。该场景具有2d纹理图像。
到达图像边缘时,我想限制相机的摇摄。
例如,当摄像机向左平移,并且图像在查看窗口中向右移动时,当图像的左边缘在可见窗口的右侧时,停止向左平移(请参见附图) )
Here和here的平移限制是硬编码的,但是在我的情况下,该限制取决于缩放(并且我还假定图像的大小也取决于缩放)。例如,当图像一直向左移动时,
放大时,scope.target.x〜=〜100
缩小时,scope.target.x〜=〜800
当图像的左侧到达可见窗口的左侧边缘时,如何禁用向左平移?
谢谢, 阿夫纳
编辑:
@ Rabbid76感谢您的建议。通过对示例代码进行一些修改,我解决了问题,即图像始终覆盖视图窗口。 有关详情,请参见here
答案 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.Box3
和OrthographicCamera
:
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>