Three.js - 推开然后恢复“鼠标移动”中的元素位置

时间:2016-03-14 13:24:16

标签: javascript three.js

Sample of what I want to achieve

大家好,我正在Three.js开发一个项目,用户可以hover一个镶嵌的面孔,每当网格相交和看不见的球体时,每个网格都应被推开,并回到原来的状态从它的区域外面的位置。我使用thisthis example作为参考,但由于我不知道如何在Three.js中使其工作,我陷入困境。

在我的代码中,我能够hover网格的每个面,使其变红并在鼠标消失后恢复其原始颜色。但我不能做与此类似的事情。这是代码中我认为问题的一部分:

if (intersects.length > 0) {

    // if the closest object intersected is not the currently stored intersection object
    if (intersects[0].object != INTERSECTED) {

        // Restore previous intersection objects (if they exist) to their original color
        if (INTERSECTED) {
            INTERSECTED.face.color.setHex(INTERSECTED.currentHex);
        }

        // Intersected elements
        INTERSECTED = intersects[0];
        var intGeometry = INTERSECTED.object.geometry;
        var intFace     = INTERSECTED.face;

        // Difference between intersected faces and geometry
        INTERSECTED.currentHex = intFace.color.getHex();
        intFace.color.setHex(0xc0392b);
        intGeometry.colorsNeedUpdate = true;

        // Identify the vertices of each face
        var intVertices = intGeometry.vertices;
        var v1 = intVertices[intFace.a],
            v2 = intVertices[intFace.a],
            v3 = intVertices[intFace.a];

        // Calculate the centroid of the selected face
        var intPosition = new THREE.Vector3();
        intPosition.x = (v1.x + v2.x + v3.x) / 3;
        intPosition.y = (v1.y + v2.y + v3.y) / 3;
        intPosition.z = (v1.z + v2.z + v3.z) / 3;
        console.log(intPosition);
    }

}

通过console.log()我可以看到人脸是正确识别的,还有他们的位置,但是球体没有正确跟踪鼠标,我需要帮助这个位置。这是一个带有完整代码的 JSFiddle

3 个答案:

答案 0 :(得分:4)

这是一个关于这个主题的小测试: https://jsfiddle.net/77xvepp7/

它无法正常工作,我将相机移动了一点以便可以看到这个想法。

基本思想是从曲面中选择一个顶点作为“基点”,它可以像在您的示例中那样是曲面的中心,并将该点保持为参考点以移动所有其他点相同数量的三角形。如果您不保存原始值,则下一轮可能包含无效值,三角形将随机移动。

然后计算鼠标到“基点”的距离,遍历所有顶点并将它们移动到基点的方向一定量。如果距离大于某个定义的量,则从顶点恢复原始值。

您可能尝试使用顶点着色器执行此操作,但问题是当鼠标位于曲面上时,每个顶点将朝相反方向移动,鼠标下方的三角形将缩放以填充空白。选择一个点作为“基点”可以消除此问题。

  // Modify the geometry
  var geometry = backgroundMesh.geometry;
    for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {

        var face = geometry.faces[ i ];

        if ( face instanceof THREE.Face3 ) {

            var a = geometry.vertices[face.a];
            var b = geometry.vertices[face.b];
            var c = geometry.vertices[face.c];
            var vList = [a,b,c];

            // The trick is to save the original face positions
            if(!a.origXSet) {
               a.origX = a.x;
               a.origY = a.y;
               a.origZ = a.z;
               a.origXSet = true;
            }

            var vect = a;
            var dx = (vect.origX - pos.x), 
                dy = (vect.origY - pos.y), 
                dz = (vect.origZ - pos.z);

            // distance to the mouse
            var dist = Math.sqrt( dx*dx + dy*dy);

            // magic constant, react if distance smaller than 4
            if(dist < 4) {
              vList.forEach(function(v) {
              if(!v.origXSet) {
                   v.origX = v.x;
                   v.origY = v.y;
                   v.origZ = v.z;
                   v.origXSet = true;
               }
               var len = Math.sqrt(dx*dx + dy*dy + dz*dz);
               if(len==0) return;
               var ndx = dx / len,
                   ndy = dy / len,
                   ndz = dz / len;
               v.x = v.origX + ndx * 2; // move 2 pixels
               v.y = v.origY + ndy * 2; 
               v.z = v.origZ + ndz * 2;
      });

      } else {
          // otherwise, reset coordinates
          vList.forEach(function(v) {
            if(v.origXSet) {
             v.x = v.origX;
             v.y = v.origY;   
             v.z = v.origZ;
             }
           });
      }

       geometry.verticesNeedUpdate = true;
       geometry.normalsNeedUpdate = true;    

    }
 }

主要问题是:未正确计算鼠标指针在世界坐标中的位置。现在我没有精力思考如何纠正这个问题,但我决定发布这个答案,以便你可以继续这样做。

答案 1 :(得分:1)

您没有将某些东西分配回几何体。有点效果:

intVertices[intFace.a].copy( intPosition );
intVertices[intFace.b].copy( intPosition );
intVertices[intFace.c].copy( intPosition );

intGeometry.verticesNeedUpdate = true;
intGeometry.normalsNeedUpdate = true;

答案 2 :(得分:0)

您遇到的问题是,您尝试targetList的{​​{1}} <{1}}实例。 因此,当您尝试访问ray.intersectObjects时,它会抛出错误