sup*_*per 5 javascript physics vector
所以,我正在尝试用JavaScript创建一个N-Body Gravity模拟:
var Circle = function(c, r, cor, cof) { // Fix CoR & CoF // Had to add code for JSFiddle link :P
this.c = c
this.r = r
this.m = r * r * Math.PI
this.v = new Vector()
this.cor = cor
this.cof = cof
}
Run Code Online (Sandbox Code Playgroud)
问题在于,当你产生(点击)并将2个球(意外地重命名为"粒子")彼此相邻时,它们开始产生速度并且更快更快地推动彼此.我如何解决这个问题,顺便说一句,我的重力实现是否正确?
Dr.*_*ann 21
这很容易解释:您正在将Euler前向实现为ODE的求解器,而在机械系统中,Euler前向的系统误差会增加能量.欧拉向后减少能量,因此交替显式和隐式欧拉方法的组合将使能量更加恒定.
不过,你可以用相同或更少的努力实现第二阶辛方法,其节约能源和其他物理不变,无论是(隐含的)中点法或Verlet-(Stoermer - 克罗默-...-牛顿)方法.
甚至更高阶的Runge-Kutta,尽管不是辛,但它也能将能量保持在更高的阶数.
请参阅Stoermer-Verlet上的Hairer -...- Newton方法,postprint或preprint以及使用C++或Ruby的"Moving stars around" 教程文本.
关于物理学的一个注释:总而言之,这些实现非常简单且可读性很好.但引力是
g*m1*m2*(p2-p1)/norm(p2-p1)^3
Run Code Online (Sandbox Code Playgroud)
作为负梯度
g*m1*m2/norm(p2-p1)
Run Code Online (Sandbox Code Playgroud)
你只使用标准的平方,其中力将是重力势能的负梯度
g*m1*m2*ln(norm(p2-p1))
Run Code Online (Sandbox Code Playgroud)
这适用于平地物理,但不适用于3D空间的2D部分.
速度Verlet和能量保存:
将新字段a = Vector()添加到圆形对象,并使用以下专用函数集合替换作为update()函数的厨房接收器
function compute_forces() {
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
p.a.set(0);
for (var j = 0; j < i; j++) {
var p2 = particles[j];
var d = p.c.sub(p2.c);
var norm = Math.sqrt(100.0 + d.lengthSq());
var mag = gravity / (norm * norm * norm);
p.a.set(p.a.sub(d.mul(mag * p2.m)));
p2.a.set(p2.a.add(d.mul(mag * p.m)));
}
}
}
function do_collisions() {
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
for (var j = 0; j < i; j++) {
var p2 = particles[j];
if (checkCCCol(p, p2)) {
resCCCol(p, p2);
}
}
}
}
function do_physics(dt) {
// do velocity Verlet
// with consistent state at interval half points
// x += 0.5*v*dt
for (var i1 = 0; i1 < particles.length; i1++) {
var p1 = particles[i1];
p1.c.set(p1.c.add(p1.v.mul(0.5 * dt)));
}
// a = A(x)
compute_forces();
// v += a*dt
for (var i2 = 0; i2 < particles.length; i2++) {
var p2 = particles[i2];
p2.v.set(p2.v.add(p2.a.mul(dt)));
}
// x += 0.5*v*dt
for (var i3 = 0; i3 < particles.length; i3++) {
var p3 = particles[i3];
p3.c.set(p3.c.add(p3.v.mul(0.5 * dt)));
}
do_collisions();
}
function update() {
for (var k = 0; k < 4; k++) {
do_physics(1.0 / 4);
}
render();
RAF(update);
}
Run Code Online (Sandbox Code Playgroud)
更改了基于质量着色的粒子的示例(希望更好地显示它们的交互),修复了一个错误,以及一些其他注释:http://jsfiddle.net/24mg6ctg/12/