three.js - Three.js 将对象移动到相机前面
问题描述
您好我正在尝试将一个物体移动到相机前面,当它到达目标位置时,我希望它停止。但它不起作用。
function objectToCamera(mX, mY, object)
{
var vector = new THREE.Vector3(mX, mY, 1);
vector.unproject(camera);
vector.sub(object.position);
var dx = object.position.x - camera.position.x;
var dy = object.position.y - camera.position.y;
var dz = object.position.z - camera.position.z;
var distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
if(lastDistance < distance && lastDistance != -1)
keepOut = -1;
lastDistance = distance;
setTimeout(function(){
if( distance > 200 && keepOut == 1)
{
var amount = (1)*(indexForZoom/3);
amount = (amount>15) ? 15 : (1)*(indexForZoom/3);
if(distance - amount < 200)
amount = (distance-200)+1;
indexForZoom++;
object.translateZ(amount);
controls.target.addVectors(controls.target,vector.setLength(amount));
objectToCamera(mX, mY, object)
}
else
{
// stopForZoom = 1;
keepOut = -1;
objectClickHandler(object.name, object);
}
}, 10);
}
我正在检查相机和物体之间的距离,如果达到目标距离,我会让它停下来,但它不起作用。在坐标中,如果我在正 X 坐标中,则距离正在减小,否则,距离正在增加。
我认为,在我的代码中,距离应该一直在减少,但事实并非如此。
请帮忙。谢谢。
解决方案
您可以使用object.position.lerp(target, amount)
将对象移向目标。金额是一个从 0 到 1 的值,其中 1 = 100% 一直到目标,0.5 = 50% 到目标。
如果您想以固定速度移动,那么您可以获得到目标的距离
distance = object.position.distanceTo(target);
假设您希望每次交互最多 0.1 个单位。然后
moveSpeed = 0.1;
distance = object.position.distanceTo(target);
amount = Math.min(moveSpeed, distance) / distance;
object.position.lerp(target, amount)
剩下的就是让你选择一个目标。
摄像机前面的位置是
const distanceFromCamera = 3; // 3 units
const target = new THREE.Vector3(0, 0, -distanceToCamera);
target.applyMatrix4(camera.matrixWorld);
因此,例如,如果您移动相机(用鼠标拖动,使用滚轮)。注意:在代码中,速度被调整为与帧速率无关。
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 45;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
const scene = new THREE.Scene();
scene.background = new THREE.Color('lightblue');
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(0, 10, 0);
light.target.position.set(-5, 0, 0);
scene.add(light);
scene.add(light.target);
}
const gridHelper = new THREE.GridHelper(100, 10);
scene.add(gridHelper);
gridHelper.position.set(0, -5, 0);
const cube = new THREE.Mesh(
new THREE.BoxBufferGeometry(1, 1, 1),
new THREE.MeshPhongMaterial({color: 'red'}),
);
scene.add(cube);
function resizeRendererToDisplaySize(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;
}
let then = 0;
function render(now) {
now *= 0.001; // convert to seconds
const deltaTime = now - then;
then = now;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
cube.rotation.x = now;
cube.rotation.y = now * 1.1;
// move cube in front of camera
{
const distanceFromCamera = 3; // 3 units
const target = new THREE.Vector3(0, 0, -distanceFromCamera);
target.applyMatrix4(camera.matrixWorld);
const moveSpeed = 15; // units per second
const distance = cube.position.distanceTo(target);
if (distance > 0) {
const amount = Math.min(moveSpeed * deltaTime, distance) / distance;
cube.position.lerp(target, amount);
cube.material.color.set('green');
} else {
cube.material.color.set('red');
}
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r112/build/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r112/examples/js/controls/OrbitControls.js"></script>
<canvas id="c"></canvas>
请注意,您可能想camera.updateMatrixWorld()
在所有数学运算之前调用以确保目标不会迟到一帧。
如果对象在层次结构中,那么还有更多工作要做。您可以进行数学运算,也可以使用将对象附加到场景,然后将其附加回其在层次结构中的位置
const parent = object.parent;
// move object to scene without changing it's world orientation
scene.attach(object);
// do stuff above
// move object to parent without changing it's world orientation
parent.attach(object);
推荐阅读
- assembly - 8051微处理器中的累加器寄存器
- python - 用硒、美丽的汤、python 进行网页抓取 - 查找特定文本时遇到问题
- image-processing - 使用 Adobe Photoshop 只需单击即可绘制水平线
- pandas - Jupyter“TypeError:无效的类型比较”
- javascript - 从表格中获取以在模态表单上编辑记录
- android - 将数据从一个活动发送回另一个 ANDROID KOTLIN
- python - Python 中的 fsolve 函数因“函数调用的结果不是正确的浮点数组”而失败
- java - Room + ViewModel + LiveData + RecyclerView (MVVM) 第 7 部分 - 添加注意活动 - Android 教程崩溃
- php - 实际许可和所有者未打印
- python-3.x - 如何在 Python 中运行多个函数