我试着做像这个http://mbostock.github.io/protovis/ex/nbody.html和同一个项目。但我的系统不起作用。你能帮我吗?这是我的http://mendow.github.io/projects/n-body/index.html,我在这里做错了,计算每一部分到每一部分
问题是,粒子有一个质心,围绕它旋转,反而有质心,从而改变了它的位置。
<!DOCTYPE html>
<html>
<head>
<title>n-body</title>
<script src="http://mendow.github.io/projects/n-body/libs/three.js"></script>
<script src="http://mendow.github.io/projects/n-body/libs/OrbitControls.js"></script>
<script src="http://mendow.github.io/projects/n-body/libs/OBJLoader.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<script>
//define global variable
{
var renderer;
var scene;
var camera;
var orbit;
var ps;
var G = 9.81;
var dt = 0.0001;
var count = 1000;
var cam = 30;
}
function init() {
{
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// position and point the camera to the center of the scene
camera.position.x = cam;
camera.position.y = cam;
camera.position.z = cam;
camera.lookAt(scene.position);
orbit = new THREE.OrbitControls(camera);
}
setupParticleSystem(count);
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// call the render function
render();
}
function setupParticleSystem(y) {
var geometry = new THREE.Geometry();
for (var j = 0; j < y; j++) {
var v = new THREE.Vector3();
var ran = 30;
v.x = intRand(ran, -ran);
v.y = intRand(ran, -ran);
v.z = intRand(ran, -ran);
v.vel = new THREE.Vector3(intRand(1, -1), intRand(1, -1), intRand(1, -1));
v.acc =new THREE.Vector3(intRand(1, -1), intRand(1, -1), intRand(1, -1));
v.mass = intRand(5, 0);
geometry.vertices.push(v);
}
console.log(geometry.vertices);
// use a material for some styling
var psMat = new THREE.PointCloudMaterial();
psMat.color = new THREE.Color(0x55ff55);
psMat.transparent = true;
psMat.size = 1;
psMat.blending = THREE.AdditiveBlending;
// Create a new particle system based on the provided geometry
ps = new THREE.PointCloud(geometry, psMat);
ps.sizeAttenuation = true;
ps.sortParticles = true;
ps.position.y = 100 / cam;
ps.position.x = 100 / cam;
ps.position.z = 100 / cam;
// add the particle system to the scene
scene.add(ps);
}
var step = 0;
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
var r,
mult;
var geometry = ps.geometry;
var temp = ps.geometry;
for (var i = 0; i < geometry.vertices.length; i++) {
for (var j = 0; j < geometry.vertices.length; j++) {
if (i != j) {
var particle = geometry.vertices[i];
var cntr = geometry.vertices[j];
r = particle.length(cntr);
mult = (-1) * G * (cntr.mass * particle.mass) / Math.pow(r, 3);
particle.acc.x = mult * particle.x;
particle.vel.x += particle.acc.x * dt;
particle.x += particle.vel.x * dt;
particle.acc.y = mult * particle.y;
particle.vel.y += particle.acc.y * dt;
particle.y += particle.vel.y * dt;
particle.acc.z = mult * particle.z;
particle.vel.z += particle.acc.z * dt;
particle.z += particle.vel.z * dt;
}
}
}
geometry.verticesNeedUpdate = true;
geometry.colorsNeedUpdate = true;
orbit.update();
}
// calls the init function when the window is done loading.
window.onload = init;
function mrand() {
return Math.random();
}
function intRand(min, max) {
return Math.random() * (max - min) + min;
}
</script>
<body>
</body>
</html>
发布于 2016-02-18 01:02:16
马特维,你需要用旧值计算所有粒子位置和速度的变化,然后才能得到新的值。否则,你会根据改变的位置和速度计算一些变化,这是不准确的。
我编辑了您的呈现循环:
<!DOCTYPE html>
<html>
<head>
<title>n-body</title>
<script src="http://mendow.github.io/projects/n-body/libs/three.js"></script>
<script src="http://mendow.github.io/projects/n-body/libs/OrbitControls.js"></script>
<script src="http://mendow.github.io/projects/n-body/libs/OBJLoader.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<script>
//define global variable
{
var renderer;
var scene;
var camera;
var orbit;
var ps;
var G = 9.81;
var dt = 0.0001;
var count = 1000;
var cam = 30;
}
function init() {
{
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// position and point the camera to the center of the scene
camera.position.x = cam;
camera.position.y = cam;
camera.position.z = cam;
camera.lookAt(scene.position);
orbit = new THREE.OrbitControls(camera);
}
setupParticleSystem(count);
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// call the render function
render();
}
function setupParticleSystem(y) {
var geometry = new THREE.Geometry();
for (var j = 0; j < y; j++) {
var v = new THREE.Vector3();
var ran = 30;
v.x = intRand(ran, -ran);
v.y = intRand(ran, -ran);
v.z = intRand(ran, -ran);
v.vel = new THREE.Vector3(intRand(1, -1), intRand(1, -1), intRand(1, -1));
v.acc =new THREE.Vector3(intRand(1, -1), intRand(1, -1), intRand(1, -1));
v.mass = intRand(5, 0);
geometry.vertices.push(v);
}
console.log(geometry.vertices);
// use a material for some styling
var psMat = new THREE.PointCloudMaterial();
psMat.color = new THREE.Color(0x55ff55);
psMat.transparent = true;
psMat.size = 1;
psMat.blending = THREE.AdditiveBlending;
// Create a new particle system based on the provided geometry
ps = new THREE.PointCloud(geometry, psMat);
ps.sizeAttenuation = true;
ps.sortParticles = true;
ps.position.y = 100 / cam;
ps.position.x = 100 / cam;
ps.position.z = 100 / cam;
// add the particle system to the scene
scene.add(ps);
}
var step = 0;
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
var r, mult;
var geometry = ps.geometry;
var temp = ps.geometry;
var dx = [];
var dv = [];
for (var i = 0; i < geometry.vertices.length; i++) {
var v = geometry.vertices[i].vel;
dx.push( new THREE.Vector3( v.x * dt, v.y * dt, v.z * dt ) );
var dvx = 0;
var dvy = 0;
var dvz = 0;
for (var j = 0; j < geometry.vertices.length; j++) {
if (i != j) {
mult = (-1) * G * geometry.vertices[i].mass * geometry.vertices[j].mass;
var vi = geometry.vertices[i];
var vj = geometry.vertices[j];
// http://www.scholarpedia.org/article/N-body_simulations_%28gravitational%29
epsilon = .1;
var r = Math.sqrt( ( vi.x - vj.x ) * ( vi.x - vj.x )
+ ( vi.y - vj.y ) * ( vi.y - vj.y )
+ ( vi.z - vj.z ) * ( vi.z - vj.z ) + epsilon )
dvx += mult * ( vi.x - vj.x ) / Math.pow( r, 3 );
dvy += mult * ( vi.y - vj.y ) / Math.pow( r, 3 );
dvz += mult * ( vi.z - vj.z ) / Math.pow( r, 3 );
}
}
dv.push( new THREE.Vector3( dvx * dt, dvy * dt, dvz * dt ) );
}
for ( var i=0 ; i < geometry.vertices.length ; i++ ) {
geometry.vertices[i].add( dx[i] );
geometry.vertices[i].vel.add( dv[i] );
}
geometry.verticesNeedUpdate = true;
geometry.colorsNeedUpdate = true;
orbit.update();
}
// calls the init function when the window is done loading.
window.onload = init;
function mrand() {
return Math.random();
}
function intRand(min, max) {
return Math.random() * (max - min) + min;
}
</script>
<body>
</body>
</html>
对力分母的修正有助于在粒子近距离碰撞时保持能量相对恒定,如(gravitational)所示。
https://stackoverflow.com/questions/32080466
复制相似问题