将一个 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。
我在一个游戏引擎中有一个 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。