Three.js - 在“鼠标移动"时推开然后恢复元素位置; [英] Three.js - Push away and then restore elements position on "mouse move"

查看:64
本文介绍了Three.js - 在“鼠标移动"时推开然后恢复元素位置;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我正在 Three.js 中开发一个项目,用户可以在其中 hover 一个细分的面,并且每个网格在它相交和不可见时都应该被推开球体,当它离开它的区域时回到它的原始位置.我正在使用 this这个例子 作为参考,但我卡住了,因为我不知道如何让它在 Three.js 中工作.

Hi all, I am developing a project in Three.js where the user can hover a tessellated face, and each mesh should be pushed away whenever it intersects and invisible sphere and, go back to its original position when its outside from its area. I am using this and this example as reference, but I got stuck since I don't know how to make it work in Three.js.

在我的代码中,我能够悬停网格的每个面,使其变为红色并在鼠标消失后恢复其原始颜色.但我不能对这个职位做类似的事情.这是我认为问题所在的代码部分:

In my code, I am able to hover each face of a mesh, make it red and restore its original colour after that the mouse is gone. But I can't do something similar with the position. This is the part of the code where I think the issue is:

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.

Via console.log() I can see that the faces are correctly recognised together with also their position, but the sphere is not tracking the mouse properly and I need help with the position. This is a JSFiddle with the full code.

推荐答案

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

Here is a small test about the subject: https://jsfiddle.net/77xvepp7/

它还不能正常工作,我将相机移得更远一些,以便可以看到这个想法.

It does not work properly yet, I moved the camera a bit further so the idea can be seen.

基本思想是从表面选取一个顶点作为基点",它可以是表面的中心,就像您在示例中所做的那样,并将该点作为参考点移动所有其他点等量的三角形.如果不保存原始值,那么下一轮可能会有无效值,三角形会随机移动一点.

The basic idea is to pick one vertex from the surface as the "base point", it could be the center of the surface as you did in your example, and keep that point as the reference point to move all other points in the triangle by same amount. If you do not save the original value, then the next round may have invalid values and the triangles will move a bit randomly.

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

Then you calculate the distance of the mouse to the "base point", go through all the vertices and move them to the direction of the base point some amount. If the distance is greater than some defined amount, restore the original value from the vertex.

您可能会尝试使用顶点着色器来做到这一点,但问题是当鼠标悬停在表面上时,每个顶点将转向相反的方向,鼠标下方的三角形将缩放以填充空白.选择一个点作为基点"可以解决这个问题.

You might try to do that using vertex shader, but the problem is that when the mouse is over the surface each vertex would go to opposite direction and the triangle which is under the mouse would scale to fill the void. Selecting one point as the "base point" removes this problem.

  // 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;    

    }
 }

主要问题是:鼠标指针在世界坐标中的位置计算不正确.现在我没有精力考虑如何更正,但决定发布此答案,以便您可以继续.

The main problems are: the position of the mouse pointer in the World Coordinates is not correctly calculated. Right now I don't have the energy to think about how to correct that, but decided to post this answer so that you can continue from that.

这篇关于Three.js - 在“鼠标移动"时推开然后恢复元素位置;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆