将一个 3d 对象制作成 "orbit" 另一个,只需使用力

Make one 3d object to "orbit" another just using forces

我在一个游戏引擎中有一个 3d 对象 A 和 B。物体A是一颗行星,质量无穷大,不动。 我有一个定义固定轨道球体的半径常数(我希望 objectb 位于其边缘的球体)。 物体 B 受到来自其他物体碰撞的随机力的影响,因此已经有力作用在它上面。 如何仅使用力使对象 B 与对象 B 具有相同的距离(保持在球体的半径内)? 我知道雅可比方程有一些复杂的计算,但我试图避免这种情况。 目前我正在做:

gravity_vector = planetcentercoordinate - objectBposition

distance_number = size ( gravity_vector ) --> 只是两个物体的距离

IF distance_number>radius THEN gravity_vector = - gravity_vector --> 如果物体通过球体轨道进入行星核心,则反转力

力=gravity_vector

如果我这样做,物体会按预期进入轨道球体的方向,但它弹跳太多了...... 还有另一种简单的方法可以做到这一点,或者如果距离更小,可以修正力?

Javascript中的一个例子(为简洁起见省略了一些部分):我有一个CelestialBody函数(一个“class”),returns一个对象代表 space 中的物体(行星、恒星等...)

function CelestialBody(mass, velocity, mesh){
    
    this.forceBetween = function(body){
        var squareDistance = this.squareDistanceFrom(body);
        var force = Constants.G * (this.mass * body.mass) / squareDistance;
        return force;
    };
    
    this.addForceContribution = function(body){
        var forceMagnitude = this.forceBetween(body);
        var distance = this.distanceFrom(body);
        var xDiff = body.getPosition().x - this.getPosition().x;
        var yDiff = body.getPosition().y - this.getPosition().y;
        var zDiff = body.getPosition().z - this.getPosition().z;
        
        var xRatio = xDiff / distance;
        var yRatio = yDiff / distance;
        var zRatio = zDiff / distance;
        
        var fx = forceMagnitude * xRatio;
        var fy = forceMagnitude * yRatio;
        var fz = forceMagnitude * zRatio;
        
        var forceVector = new THREE.Vector3(fx, fy, fz);
        
        this.acceleration.add(forceVector.divideScalar(this.mass));
    };
    
    this.updatePosition = function(delta){
        if(!delta){
            delta = Constants.DEFAULT_TIME_DELTA; // just to make debugging possible
        }
        this.velocity = this.velocity.add(this.acceleration.multiplyScalar(delta));
        var tempVelocity = this.velocity.clone();
        var nextPosition = this.getPosition().clone(); 
        nextPosition.add( tempVelocity.multiplyScalar(delta) );
        
        this.mesh.position.x = nextPosition.x;
        this.mesh.position.y = nextPosition.y;
        this.mesh.position.z = nextPosition.z;
        
        this.acceleration = new THREE.Vector3(0, 0, 0);
    };
}

在主游戏循环中,在每一步,对于每个物体,我都会考虑任何其他物体的重力贡献并相应地更新位置:

for (var i = 0; i < celestialBodies.length; i++) {
        for (var j = 0; j < celestialBodies.length; j++) {
            if (celestialBodies[i] === celestialBodies[j]) {
                continue;
            }

            celestialBodies[i].addForceContribution(celestialBodies[j]);
        }
    }

    for (var i = 0; i < celestialBodies.length; i++) {
        celestialBodies[i].updatePosition();

        // check if the body is gone too far: if so, marks it for removal
        if (celestialBodies[i].getPosition().distanceTo(new THREE.Vector3(0, 0, 0)) > Constants.REMOVAL_DISTANCE_THRESHOLD) {
            celestialBodies[i].markedForRemoval = true;
        }
    }

完整代码为here