You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js行星公转时位置不更新,点击缩放定位错误求助

问题:Three.js太阳系模型点击行星相机定位异常

我用Three.js开发太阳系模型,基础功能正常,但点击公转行星时,相机总是缩放至行星初始位置,点击太阳则正常。

当前实现逻辑:在太阳位置创建不可见父对象,通过animate()中调用parent.rotateY()模拟行星公转,行星自身position未更新,调用矩阵更新函数也无效。

我写了calculateCurrentPosition函数计算行星实时位置,怀疑函数逻辑或位置获取方式有误,用TWEEN实现相机移动动画,求修正函数或提供获取对象实时位置的方法。

相关代码

位置计算函数

function calculateCurrentPosition(initialPos, distance, angularSpeed, time) {
    console.log(initialPos, distance, angularSpeed, time);
    if (time === 0) {
        return initialPos;
    }
    var currentAngle = angularSpeed * time;
    var currentX = initialPos.x + distance * Math.cos(currentAngle);
    var currentZ = initialPos.z + distance * Math.sin(currentAngle);
    return { x: currentX, y: initialPos.y, z: currentZ };
}

运动沿X-Z平面进行,因此y值保持恒定

行星创建函数

function createPlanete(size, texture, position, ring) {
    const geo = new THREE.SphereGeometry(size, 30, 30);
    const mat = new THREE.MeshStandardMaterial({
        map: textureLoader.load(texture)
    });
    const mesh = new THREE.Mesh(geo, mat);
    const obj = new THREE.Object3D();
    obj.add(mesh);
    if(ring) {
        const ringGeo = new THREE.RingGeometry(
            ring.innerRadius,
            ring.outerRadius,
            32);
        const ringMat = new THREE.MeshBasicMaterial({
            map: textureLoader.load(ring.texture),
            side: THREE.DoubleSide
        });
        const ringMesh = new THREE.Mesh(ringGeo, ringMat);
        obj.add(ringMesh);
        ringMesh.position.x = position;
        ringMesh.rotation.x = -0.5 * Math.PI;
    }
    scene.add(obj);
    mesh.position.x = position;
    return {mesh, obj}
}
解决方案

不需要手动计算位置,直接利用Three.js内置方法获取行星的世界坐标即可:

  1. 获取行星实时世界坐标
    使用Vector3.setFromMatrixPosition方法,从行星的世界矩阵中提取真实位置:
function getPlanetWorldPosition(planetMesh) {
    const worldPos = new THREE.Vector3();
    // 确保矩阵是最新的
    planetMesh.updateMatrixWorld(true);
    worldPos.setFromMatrixPosition(planetMesh.matrixWorld);
    return worldPos;
}

调用该函数得到的坐标,可直接传给TWEEN作为相机移动的目标点。

  1. 原计算函数的问题
    你的手动计算逻辑错误:行星的初始position是相对于父对象的局部坐标,而非世界坐标。父对象旋转时,行星的世界坐标由父对象的旋转矩阵作用于局部坐标得到,手动用余弦/正弦叠加初始世界坐标的方式和实际变换逻辑不符,必然出错。

  2. 额外说明
    如果在animate函数中先执行了父对象旋转,再调用getPlanetWorldPosition,矩阵通常已经是最新的;若不确定,可手动调用updateMatrixWorld(true)强制更新整个场景的矩阵。

内容的提问来源于stack exchange,提问作者Safi ullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 06:35:29