【问题标题】:Three.js get particle in the center of viewable area三.js获取可视区域中心的粒子
【发布时间】:2013-10-31 15:08:51
【问题描述】:

我有一个粒子系统,其中有 1000 多个粒子散布在屏幕上。当我使用 OrbitControls 缩放和平移时,我想让粒子最接近可视区域的中心。

我认为这有两个部分。首先,我们需要找到可视区域的中心顶点。接下来,我们需要对所有粒子运行距离公式,以找到最接近中心顶点的粒子。希望有比这更有效的方法。第二部分使用蛮力相当简单。第一部分,我不确定。如何找到可视区域的中心顶点?

【问题讨论】:

  • 如果你使用OrbitControls,那么controls.target是相机旋转的点,也是相机注视的点,所以它在可视区域的中心。

标签: javascript three.js


【解决方案1】:

我不是 three.js 的人,但我确实有优化算法方面的经验。每次循环遍历所有粒子是错误的。

相反,粒子需要“排序”,然后当您确定相机位置时,您只需找到它在排序中的位置,您就会立即获得最近的点。它非常像数据库中的索引。或者想想图书馆。如果有人给你一本叫做“排序”的书,而整个图书馆都按照严格的字母顺序排列,你不必检查图书馆里的每一本书,你只需直接走到 S,然后 SO,然后 SOR,然后手动比较其余的部分。因此,您可以在几秒钟内找到与您的图书最近的图书,而无需查看所有图书。

这在二维情况下的工作方式是,您需要存储几个级别的“网格”,然后确定您所在的网格,并检查该网格中的粒子。例如,假设您有 100 万个粒子,并且在每个粒子上,您存储它是在中心的右侧还是左侧。现在通过一个快速的“if”,您可以检查您的相机是在右侧还是左侧,并且使用该 if,您已经切出了需要循环通过的 500,000 个粒子。所以在实践中,你可能会在每个粒子上存储 2 个级别的 1-9 网格,当它们被创建时,这将删除你必须检查的 99% 的粒子。一旦您确定了您的相机(精确中心)在哪个象限,您只需查看存储在该“网格位置”中的粒子阵列。所以你的粒子将存储在particle[1-9][1-9][1-100] 或类似的东西中。

现在如果你的粒子移动很多,你必须做一些简单的 mod (%) 类型的数学运算来确定它们在哪个网格位置,移动时等等。

可以通过设置阈值来进一步优化,即“足够接近”,所以即使你有 1000 个粒子几乎彼此重叠,如果你在 10 个像素内得到它,你会得到一个不错的结果更快。

【讨论】:

    【解决方案2】:

    你可能应该得到一个正前方 10 个单位的点,然后得到最接近的粒子。

    这篇文章帮助我告诉你这一点,顺便说一句,我已经完成了这一切。

    Three.js Projector and Ray objects

    它用于单击屏幕上的一个点,并从中获取一个矢量。

    projector = new THREE.Projector();
    
    // This is like clicking on the center of the screen, 0, 0 is center
    straight_ahead = new THREE.Vector3(0,0,.5);
    
    // Now we have straight_ahead relative to the camera
    projector.unprojectVector(straight_ahead, camera);
    
    // Now straight_ahead is just the direction of the camera, since we're taking away the camera's position from it
    straight_ahead.sub(camera.position)
    
    // It's a direction of where the camera is looking, so lets make it 10 units away( pick your own number)
    straight_ahead.normalize().multiplyScalar(10)
    
    // Now we we have a length of 10 units, we can get 10 units in front of the camera
    straight_ahead.add(camera.position)
    
    // At this point, straight ahead is a point in space 10 units in front of you, so lets find the closest point to that
    
    // here's where you put a simple loop in
    min_point = null
    min_distance = 999999999
    _.each( my_particles, function(particle) {
      distance = particle.position.distanceTo(straight_ahead)
      if (distance < min_distance) {
        min_point = particle
        min_distance = distance
      }
    });
    
    // now you have min_point, which should be the closest point to 10 feet in front of your face
    

    【讨论】:

      【解决方案3】:
      lookAt = camera.lookAt;
      pos = camera.position;
      
      min = MAX_FLOAT, min_index = -1;
      foreach(particle in particle_system) {
          d = distance(particle.position, lookAt, pos);
          if( min>d ) { min_index = particle.getIndex; min = d; }
      }
      

      distance函数在网上都可以找到,例如:http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line

      这是伪代码。它的作用是找到视线(lookAt 向量)并从中找到最近的粒子。

      编辑:

      var cam_position = camera.position,
          cam_eyeVec = getEyeVec(camera.projectionMatrix);
      
      var min_dist = 10000000,
          min_index = -1;
      
      for(var i=0; i<particle_count; i++) {
          var d = distance(particle[i].position, cam_eyeVec, cam_position);
          if(min_dist > d) {
               min_index = i;
               min_dist = d;
          }
      }
      
      function getEyeVec(projMat) {
          return new THREE.Vector3(projMat[8], projMat[9], projMat[10]);
      }
      
      function distance(p, n, a) {
          n = n.normalize();
          var diff = new THREE.Vector3(a.x-p.x, a.y-p.y, a.z-p.z);
          var diff_n = diff.multiply(n);
          var d = ((diff.selfSubstract(diff_n)).selfMultiply(n)).length();
          return d;
      }
      

      getEyeVec 的计算基于 - eye and up vectors from viewMatrixdistance 的计算基于 - Distance from a point to a line

      【讨论】:

      • 你能再解释一下吗?我意识到这是伪代码,但我不清楚您要传达的内容。距离公式比较两个点,而不是三个点。此外,lookAt 是一个函数。为什么要将它传递给距离函数?
      • 我通过相机的lookAt向量,相机的位置和每个粒子的位置。有一个公式可以计算点和线之间的距离,由它的原点和向量给出。这就是你用来获得距离的方法。还有更清楚的吗?
      • 我这几天一直在研究这个问题,但在计算可视区域中心最近的粒子时仍然遇到问题。我是 Three.js 的新手,正在计算点和线之间的距离。无论如何我们可以将距离伪代码更改为真实代码吗?
      • 已编辑。希望这是有道理的。
      • selfSubtract 和 selfMultiply 对于 Vector3 不存在。他们现在被称为“sub”和“multiply”吗?此外,看起来 diff_n 总是返回 Vector3 = (0, 0, 0)
      猜你喜欢
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      相关资源
      最近更新 更多