Skip to content Skip to sidebar Skip to footer

Three.js - Push Away And Then Restore Elements Position On "mouse Move"

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

Solution 1:

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 geometryvar geometry = backgroundMesh.geometry;
    for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {

        var face = geometry.faces[ i ];

        if ( face instanceofTHREE.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 positionsif(!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 mousevar dist = Math.sqrt( dx*dx + dy*dy);

            // magic constant, react if distance smaller than 4if(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.

Solution 2:

You are not assigning something back to your geometry. Something to the effect:

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

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

Solution 3:

the problem you having it that the targetList that you try ray.intersectObjects is not a THREE.Mesh instance. because of that when you try to access to intersectedFace.acc it's throw an error

Post a Comment for "Three.js - Push Away And Then Restore Elements Position On "mouse Move""