三个JS raycaster,当鼠标移动时找到交叉点

时间:2018-02-08 17:41:45

标签: javascript performance three.js

我觉得这种方法完全错误,因为我无法为我的网站获得适当的效果。

以下是我希望您看到的主要代码:

onDocumentMouseMove( event ) {
    if ( this.isUserInteracting === true ) {
      this.lon = ( this.onMouseDownMouseX - event.clientX ) * 0.1 + this.onMouseDownLon;
      this.lat = ( event.clientY - this.onMouseDownMouseY ) * 0.1 + this.onMouseDownLat;
    }
    this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

    if( !this.state.VR ){
      this.raycaster.setFromCamera( this.mouse, this.camera );
      var intersects = this.raycaster.intersectObjects( this.indicatorHotspotPlane );

      if( intersects.length > 0 ) {
        this.actualIntersect = intersects[0];

        $('html,body').css('cursor', 'pointer');
        if(!intersects[ 0 ].object.isAction){
          this.marker.material.opacity = 1;
          this.marker.lookAt( intersects[ 0 ].face.normal );
          this.marker.position.copy( intersects[ 0 ].point );
          this.marker.position.y = this.marker.position.y + 30;
          if( intersects[ 0 ].point.x >= 0 ){
            this.marker.position.x = this.marker.position.x - 30;
          }else{
            this.marker.position.x = this.marker.position.x + 30;
          } 
        }
      } else {
        this.actualIntersect = null;
        $('html,body').css('cursor', 'move');
        this.marker.material.opacity = 0;
      }
    }
  }

我相信raycaster.intersectObjects在这种事件处理程序中运行是一项非常昂贵的操作。

如果我评论这段代码,一切都运行良好。

当鼠标移动时没有任何其他方法可以找到交叉点而没有性能问题吗?

this.indicatorHotspotPlane是一个数组,可能包含5个这样的对象:

var hotspotPlane = new THREE.Mesh( new THREE.PlaneBufferGeometry( hotpot.width , hotpot.height ) );

我的场景包含这些物体和一个带有纹理的球体几何体。

1 个答案:

答案 0 :(得分:1)

看看this three.js example

请告诉我'发生在这里:

  1. 使用每个形状的唯一纯色将场景渲染到离屏渲染目标。
  2. 根据渲染目标X,Y坐标检查鼠标坐标,并获取鼠标下的颜色(如果有)。
  3. 根据颜色 - >网格
  4. 地图检查颜色
  5. 更新关联网格以反映其突出显示的"状态。
  6. 主场景重新渲染,部分现在突出显示。
  7. 执行此操作仍然需要付费:每次需要刷新渲染目标时,都会产生额外的渲染。此外,如果您的场景非常大(需要很长时间才能渲染),它的表现可能与光线投射一样糟糕。尽管如此,故事的寓意是,从缓冲区读取颜色值比执行光线投射更容易

    另一个警告是,这只适用于最近的形状(相当于intersects[0])。这是因为遮挡的形状不会暴露其颜色(它们的颜色完全被其他形状覆盖)。因此,如果您需要获得鼠标下的所有形状,那么光线投射仍然是最佳选择。

    其他信息:

    我忽略了部分代码并直接解决了光线追踪问题。经过深入审查后,这里有一些额外的信息:

    看起来你正在接受你所交叉的任何物体,并正在检查一个特定的财产:

    if(!intersects[ 0 ].object.isAction){
    

    使用上述方法,您可以检查从色彩图中获取的任何对象的属性。

    要获得交叉点,您需要执行光线投射,但现在只有当鼠标下的对象首先通过测试而不是每次鼠标移动时才会发生。

    当光标位于适当的对象上时,每次鼠标移动事件都会发生光线投射 ,因此您可能需要重新考虑更新标记的频率(可能每N帧),或者也许只在您第一次遇到特定形状时设置标记。我不知道你的用例,所以也许这是不可行的。