首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >three.js n体模拟

three.js n体模拟
EN

Stack Overflow用户
提问于 2015-08-18 18:51:57
回答 1查看 659关注 0票数 2

我试着做像这个http://mbostock.github.io/protovis/ex/nbody.html和同一个项目。但我的系统不起作用。你能帮我吗?这是我的http://mendow.github.io/projects/n-body/index.html,我在这里做错了,计算每一部分到每一部分

问题是,粒子有一个质心,围绕它旋转,反而有质心,从而改变了它的位置。

代码语言:javascript
运行
复制
<!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>

EN

回答 1

Stack Overflow用户

发布于 2016-02-18 01:02:16

马特维,你需要用旧值计算所有粒子位置和速度的变化,然后才能得到新的值。否则,你会根据改变的位置和速度计算一些变化,这是不准确的。

我编辑了您的呈现循环:

代码语言:javascript
运行
复制
<!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)所示。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32080466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档