您如何保持让相机平稳地移动到新位置,同时仍然注视目标?
How do you maintain make a camera move to a new position smoothy while still looking at a target?
在此 中,我询问了如何将相机移动到相对于目标的不同位置。一位非常善良的绅士@TheJim01 提供了一个非常好的答案。
但是,我遇到了这样的问题,即在我移动相机后,相机会旋转并奇怪地定位。
保持相机旋转并保持其对目标的平稳视野的策略是什么?
平滑移动相机的更好方法是创建关键帧并将它们放置在由 emphasys 曲线定义的某种形式的时间轴中。
您可以使用任何补间库(Tween.js、GSAP)将相机从当前位置平滑地移动到球体顶部的位置。
此外,使用 THREE.Spherical()
计算最终点。并且不要忘记使用 .makeSafe()
方法。
body {
overflow: hidden;
margin: 0;
}
button{
position: absolute;
font-weight: bold;
}
<button id="moveUp">MOVE UP</button>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.5.1/dist/gsap.min.js"></script>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
let scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 6, 15);
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
controls.maxDistance = 10;
controls.minDistance = 7;
let sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 36, 18), new THREE.MeshBasicMaterial({color: "aqua", wireframe: true}));
scene.add(sphere);
moveUp.addEventListener("click", onButtonClick);
let spherical = new THREE.Spherical();
let startPos = new THREE.Vector3();
let endPos = new THREE.Vector3();
let axis = new THREE.Vector3();
let tri = new THREE.Triangle();
function onButtonClick(event){
spherical.setFromVector3(camera.position);
spherical.phi = 0;
spherical.makeSafe(); // important thing, see the docs for what it does
endPos.setFromSpherical(spherical);
startPos.copy(camera.position);
tri.set(endPos, scene.position, startPos);
tri.getNormal(axis);
let angle = startPos.angleTo(endPos);
let value = {value: 0};
gsap.to(value, {value: 1,
duration: 2,
onUpdate: function(){
camera.position.copy(startPos).applyAxisAngle(axis, angle * value.value);
controls.update();
},
onStart: function(){
moveUp.disabled = true;
},
onComplete: function(){
moveUp.disabled = false;
}
})
.play();/**/
}
renderer.setAnimationLoop(()=>{
renderer.render(scene, camera);
});
</script>
在此
但是,我遇到了这样的问题,即在我移动相机后,相机会旋转并奇怪地定位。
保持相机旋转并保持其对目标的平稳视野的策略是什么?
平滑移动相机的更好方法是创建关键帧并将它们放置在由 emphasys 曲线定义的某种形式的时间轴中。
您可以使用任何补间库(Tween.js、GSAP)将相机从当前位置平滑地移动到球体顶部的位置。
此外,使用 THREE.Spherical()
计算最终点。并且不要忘记使用 .makeSafe()
方法。
body {
overflow: hidden;
margin: 0;
}
button{
position: absolute;
font-weight: bold;
}
<button id="moveUp">MOVE UP</button>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.5.1/dist/gsap.min.js"></script>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
let scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 6, 15);
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
controls.maxDistance = 10;
controls.minDistance = 7;
let sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 36, 18), new THREE.MeshBasicMaterial({color: "aqua", wireframe: true}));
scene.add(sphere);
moveUp.addEventListener("click", onButtonClick);
let spherical = new THREE.Spherical();
let startPos = new THREE.Vector3();
let endPos = new THREE.Vector3();
let axis = new THREE.Vector3();
let tri = new THREE.Triangle();
function onButtonClick(event){
spherical.setFromVector3(camera.position);
spherical.phi = 0;
spherical.makeSafe(); // important thing, see the docs for what it does
endPos.setFromSpherical(spherical);
startPos.copy(camera.position);
tri.set(endPos, scene.position, startPos);
tri.getNormal(axis);
let angle = startPos.angleTo(endPos);
let value = {value: 0};
gsap.to(value, {value: 1,
duration: 2,
onUpdate: function(){
camera.position.copy(startPos).applyAxisAngle(axis, angle * value.value);
controls.update();
},
onStart: function(){
moveUp.disabled = true;
},
onComplete: function(){
moveUp.disabled = false;
}
})
.play();/**/
}
renderer.setAnimationLoop(()=>{
renderer.render(scene, camera);
});
</script>