【问题标题】:THREE.js Random multidirectional orbits around point using trigTHREE.js 使用 trig 围绕点的随机多向轨道
【发布时间】:2017-07-12 15:54:23
【问题描述】:

我正在尝试围绕同一个 Vector3 点但在不同方向上旋转多个对象 - 因此它们有效地围绕该点“聚集”。

我使用 trig 方法,而不是简单地将每个对象包装在一个容器中并应用一些随机旋转,因为我将它们的 3D 矢量投影到 2D 位置以将标签 DIV 附加到画布上方,并且容器方法与项目混淆班级。

这是我当前的代码,它使所有对象沿同一轨道路径围绕该点旋转:

for(var i = 0; i<objectsArr.length; i++){
    var obj = objectsArr[i];
    var radius = obj.angle * (Math.PI / 180);
    obj.position.x = obj.radius * Math.cos(radius); 
    obj.position.y = obj.radius * Math.sin(radius);
    obj.angle += obj.orbitSpeed;
}

有谁知道我怎样才能让它们沿 X、Y、Z 轴在随机方向上运行?

【问题讨论】:

    标签: javascript 3d three.js trigonometry


    【解决方案1】:

    首先,请参阅this answer 关于围绕一个点旋转对象。

    从您的代码看来,您正在存储每个对象的轨道速度,以及它们当前的旋转角度(表示到该位置的向量)。与其存储 2D 角度,不如将其存储为 Vector3,它表示(垂直于)物体轨道平面的法线。 (当您可以定义不同的轨道平面时,这将让您真正获得“群”。)我还建议将轨道速度存储为每步的弧度,这样您就不必每次都执行转换。

    使用Vector3.applyAxisAngle 方法,剩下的问题实际上变得非常简单。

    一些伪代码:

    1. 从对象的位置减去旋转点位置。
    2. 使用物体的轨道速度和角度来更新温度位置。
    3. 将旋转点位置添加回对象的位置。

    要在您的代码中看到它:

    var obj;
    for(var i = 0; i< objectsArr.length; i++){
        obj = objectsArr[i];
        obj.position.sub(rotationPoint); // rotationPoint is a Vector3
        obj.position.applyAxisAngle(obj.angle, obj.orbitSpeed);
        obj.add(rotationPoint);
    }
    

    这里有几个物体在(10, 10, 10)的“核”周围随机运行的现场演示。

    var renderer, scene, camera, controls, stats, nucleus;
    
    var WIDTH = window.innerWidth,
      HEIGHT = window.innerHeight,
      FOV = 60,
      NEAR = 1,
      FAR = 1000;
    
    var electrons = [],
        numElectrons = 100; // more electrons = slower updating
    function populateScene() {
      var geo = new THREE.SphereBufferGeometry(10, 16, 16);
      var mat = new THREE.MeshPhongMaterial({color:"blue"});
      nucleus = new THREE.Mesh(geo, mat);
      nucleus.position.set(10, 10, 10); // you can change these values
      scene.add(nucleus);
      
      var electron = null,
        plane = new THREE.Plane(),
        point = new THREE.Vector3();
      geo = new THREE.SphereBufferGeometry(1, 16, 16);
      mat = new THREE.MeshPhongMaterial({color:"red"});
      for(var i = 0; i < numElectrons; ++i){
        electron = new THREE.Mesh(geo, mat);
        electrons.push(electron);
        electron.angle = new THREE.Vector3(
          Math.random(),
          Math.random(),
          Math.random()
        ).normalize();
        electron.orbitSpeed = (Math.random() * 0.05) + 0.05;
        if(Math.random() > 0.5) electron.orbitSpeed *= -1;
        plane.normal.copy(electron.angle);
        point.set(Math.random(), Math.random(), Math.random());
        plane.projectPoint(point, electron.position);
        electron.position.setLength(Math.floor(Math.random() * 20) + 15);
        electron.position.applyAxisAngle(electron.angle, Math.random() / 10);
        electron.position.add(nucleus.position);
        scene.add(electron);
      }  
    }
    
    function updateElectrons(){
      var obj = null;
      for(var i = 0; i < numElectrons; ++i){
          obj = electrons[i]
          obj.position.sub(nucleus.position);
          obj.position.applyAxisAngle(obj.angle, obj.orbitSpeed);
          obj.position.add(nucleus.position);
      }
    }
    
    function init() {
      document.body.style.backgroundColor = "slateGray";
    
      renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    
      document.body.appendChild(renderer.domElement);
      document.body.style.overflow = "hidden";
      document.body.style.margin = "0";
      document.body.style.padding = "0";
    
      scene = new THREE.Scene();
    
      camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
      camera.position.z = 100;
      scene.add(camera);
    
      controls = new THREE.TrackballControls(camera, renderer.domElement);
      controls.dynamicDampingFactor = 0.5;
      controls.rotateSpeed = 3;
    
      var light = new THREE.PointLight(0xffffff, 1, Infinity);
      camera.add(light);
    
      stats = new Stats();
      stats.domElement.style.position = 'absolute';
      stats.domElement.style.top = '0';
      document.body.appendChild(stats.domElement);
    
      resize();
      window.onresize = resize;
    
      populateScene();
    
      animate();
    }
    
    function resize() {
      WIDTH = window.innerWidth;
      HEIGHT = window.innerHeight;
      if (renderer && camera && controls) {
        renderer.setSize(WIDTH, HEIGHT);
        camera.aspect = WIDTH / HEIGHT;
        camera.updateProjectionMatrix();
        controls.handleResize();
      }
    }
    
    function render() {
      renderer.render(scene, camera);
    }
    
    function animate() {
      requestAnimationFrame(animate);
      updateElectrons();
      render();
      controls.update();
      stats.update();
    }
    
    function threeReady() {
      init();
    }
    
    (function() {
      function addScript(url, callback) {
        callback = callback || function() {};
        var script = document.createElement("script");
        script.addEventListener("load", callback);
        script.setAttribute("src", url);
        document.head.appendChild(script);
      }
    
      addScript("https://threejs.org/build/three.js", function() {
        addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
          addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
            threeReady();
          })
        })
      })
    })();

    三个.js r86

    【讨论】:

      猜你喜欢
      • 2013-03-16
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      相关资源
      最近更新 更多