admin管理员组文章数量:1026956
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);
}
}
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.
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);
}
}
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.
- 1 For sphere to follow mouse, you need to convert screen coordinates to threejs world position. Check this link . And updated fiddle here, changed code starts at line 375. – uhura Commented Mar 16, 2016 at 21:29
- Thanks man! This was part of an issue of another question I have asked, if you want you can post the answer there and get rewarded. – d_z90 Commented Mar 17, 2016 at 8:10
3 Answers
Reset to default 4 +150Here is a small test about the subject: https://jsfiddle/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.
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;
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
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);
}
}
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.
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);
}
}
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.
- 1 For sphere to follow mouse, you need to convert screen coordinates to threejs world position. Check this link . And updated fiddle here, changed code starts at line 375. – uhura Commented Mar 16, 2016 at 21:29
- Thanks man! This was part of an issue of another question I have asked, if you want you can post the answer there and get rewarded. – d_z90 Commented Mar 17, 2016 at 8:10
3 Answers
Reset to default 4 +150Here is a small test about the subject: https://jsfiddle/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.
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;
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
本文标签: javascriptThreejsPush away and then restore elements position on quotmouse movequotStack Overflow
版权声明:本文标题:javascript - Three.js - Push away and then restore elements position on "mouse move" - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745654404a2161511.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论