更新相机位置以模拟对象旋转

时间:2016-06-17 06:59:44

标签: 3d three.js perspectivecamera

我有一个带有相机设置的3D场景,看起来总是在那个场景的中心。

如何通过更新相机的x,y,z来更改相机的坐标以旋转和缩放该中心?

旋转至少应包括滚动/偏航/缩放

我正在使用webGL / THREE,但我相信这应该适用于任何语言/引擎

3 个答案:

答案 0 :(得分:2)

我认为最简单的方法是使用矩阵层次结构。

在原点创建一个节点。在您想要相机的地方创建一个子节点。在原点处旋转节点。问孩子它在哪里,把相机放在那里。使用lookAt定位相机

这几乎总是比计算一个圆圈容易。你可以通过创造性地将节点放在场景中,移动它们并使用它们设置摄像机的位置和目标来实现各种效果。

var canvas = document.querySelector("#c");

var camera = new THREE.PerspectiveCamera(70, 1, 1, 1000);
var scene = new THREE.Scene();

// make some cubes
var geometry = new THREE.BoxBufferGeometry(20, 20, 20);
var material = new THREE.MeshLambertMaterial({ color: 0xFFEECC });

for (var z = -1; z <= 1; ++z) {
  for (var x = -1; x <= 1; ++x) { 
    var mesh = new THREE.Mesh(geometry, material);
    mesh.position.x = x * 30;
    mesh.position.z = z * 30;
    scene.add(mesh);    
  }
}

// add some lights
var light = new THREE.DirectionalLight(0xE0E0FF, 1);
light.position.set(200, 500, 200);
scene.add(light);
var light = new THREE.DirectionalLight(0xFFE0E0, 0.95);
light.position.set(-200, -500, -200);
scene.add(light);


// now make nodes for camera
var cameraCenterNode = new THREE.Object3D();
var cameraPositionNode = new THREE.Object3D();
scene.add(cameraCenterNode);
cameraCenterNode.add(cameraPositionNode);
cameraPositionNode.position.x = 100;
cameraPositionNode.position.y = 40;

var renderer = new THREE.WebGLRenderer({canvas: canvas});

function resizeIfChanged() {
  var width = canvas.clientWidth;
  var height = canvas.clientHeight;
  if (canvas.width != width || canvas.height != height) {
    camera.aspect = width / height;
    camera.updateProjectionMatrix();

    renderer.setSize(width, height, false);
 }
}

function render(time) {
  time *= 0.001; // make it seconds
  
  resizeIfChanged();
  
  // Rotate camera center
  cameraCenterNode.rotation.y = time;
  
  // get cameraPositionNode's world position and put it in camera
  cameraPositionNode.getWorldPosition(camera.position);
  
  // point camera at center
  camera.lookAt(cameraCenterNode.position);

  renderer.render(scene, camera);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
body { margin: 0 }
canvas { width: 100vw; height: 100vh; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r78/three.min.js"></script>
<canvas id="c"></canvas>

至于缩放,它实际上取决于你想要达到的目标。

例如,您可以计算cameraCenterNodecameraPositionNode之间的点。例如:

var out = cameraPositionNode.getWorldPosition();
var in  = cameraCenternode.getWorldPosition();
in.lerp(out, zoomAmount);  // where 0.0 = in and 1.0 = out

// now set the camera there
camera.position.copy(in);

或者可以随时沿着-zAxis

向前移动相机
var worldMatrix = camera.getWorldMatrix();

var zoomVector = new THREE.Vector3(
   wm.elememts[8], wm.elememts[9], wm.elememts[10]);

camera.position.sub(zoomVector.multiplyScalar(zoomAmount));

从您的问题中不清楚您真正希望相机如何工作。如果您希望它指向原点并始终围绕OR旋转,如果您希望它像典型的建模包一样更自由浮动。无论你必须选择一些旋转点。无论是固定点还是新点,取决于相机在哪里进行相同类型的计算都可以。

答案 1 :(得分:1)

如果我理解正确,你只需要&#34;旋转&#34;相机位置并将其设置为查看场景的原点:

camera.position.x = R * Math.cos(bearing) * Math.cos(pitch);
camera.position.y = R * Math.sin(bearing) * Math.cos(pitch);
camera.position.z = R * Math.sin(pitch);
camera.lookAt(new THREE.Vector3(0, 0, 0));

此处R是从相机到原点的距离,bearing是水平平面中的旋转pitch - 在垂直平面中。

答案 2 :(得分:0)

背后的数学有点复杂。

最好用http://threejs.org/examples/misc_controls_orbit.html

您也可以定义最大和最小角度并设置自动旋转。