yuccai Posted December 1, 2016 Share Posted December 1, 2016 Hi, I would like to pick a mesh and moving it around a room which is a simple cube with backside orientation. Basically, it consists on 3 functions called on 3 distinct events onPointerDown : I select the mesh I want to move (main mesh) when I click on the mouse onPointerMove : I select a different mesh in order to move the main mesh when I drag the mouse onPointerUp : I deselect the main mesh when I release the click of the mouse The behavior I want to produce is to dragndrop the main mesh on visible faces only and keeping each face belonging to the same mesh (I don't want to create as many meshes as faces). For instance, when my camera is above the room, the ceiling is transparent and we can see the floor due to the backside orientation of the room. But on step 2, I can't figure out how to pick the face which corresponds to the floor. I only succeed to pick the ceiling. I tried to build a predicate (pickInfo = scene.pick(x,y,predicate)) based on faces normales but once a mesh has been evicted from the predicate, it is not recalled, even if more than one face which is intersected. So I would like to know if there is a way to do what I'm expecting to do. When a mesh has succeed the predicate, how the returned pickInfo is built ? The selected face (pickInfo.pickedPoint) is always the nearest from the camera ? Is is possible the return an array of valid meshes with an another array containing its corresponding faces intersected ? Here is a PG relating my issue : http://www.babylonjs-playground.com/#1V3CAT#185 Thanks Quote Link to comment Share on other sites More sharing options...
Wingnut Posted December 3, 2016 Share Posted December 3, 2016 Hiya @yuccai, good to see you again. Sorry it has taken so long to get a reply. http://www.babylonjs-playground.com/#1DE6PV#1 Above, I am just screwing around. Got some crappy box-dragging happening... without being blocked by room. Changed isPicked to pickedMesh... just some assorted testing crap. For accurate drag'n'drop, it might be wise to start with the Drag'n'Drop Playground Demo and make the ground (which is REQUIRED in that demo)... be invisible. (place its invisible ground behind/beneath your room). Dragging mesh in a 3D world... using a 2d pointer... is a challenge. As far as using picking (or using the new multi-pick)... to pick multiple faces (and possibly store all hit faces in an array)... using a backside box such as room... that might be impossible (so far). I have never heard of anyone doing it before. The picked face will always be the one closest to camera (unless the ray is fired from the far side of the room). I think most people would make the room... from 6 separate planes. But I DO see your hope. If room picking (floor, walls) would ALWAYS ignore the face that is closest to the camera (such as a room ceiling)... then you could get proper and correct face clicking (click upon inside walls and floor, and get the correct pickingInfo.faceID's). This is a cool challenge. Once upon a time, I was asked to remove the top... from a BJS box. http://www.babylonjs-playground.com/#1KH9RY#8 I just used my trusty "indices chainsaw", and hacked some indices. The top of the box disappeared. I don't think this method will work for you, but i thought I would show you. Fellow forum users... Yuccai is needing a picker... which IGNORES pickingInfo.faceID that are not rendered. In other words... if you can see-thru the face, don't allow picking of IT. Only pick the first RENDERED faceID that the ray hits. Pick PAST see-thru faces, and only hit the first (and maybe collect ALL...) faces that ARE rendered and can be seen. What a stalwart challenge! This might require coding a custom picker (a modification of the default BJS picking system). This custom picker would test HIT face-normals... checking if the face is see-thru (back-sided). If it IS a hit on a backfaced face, ignore this pickedPoint/faceID and continue the ray further... until it hits a non-backfaced face. (what a sentence!) I will keep thinking and perhaps try a custom picker (scary, I'm not a very good coder). Hopefully, others will comment and have more wisdom. Quote Link to comment Share on other sites More sharing options...
yuccai Posted December 5, 2016 Author Share Posted December 5, 2016 In fact it was not as difficult as I thought, I just added my predicate (which consists in checking the sign of the face normal with the intersecting ray) for each faces intersected. I had to patch the following function of Babylon.js : SubMesh.prototype.intersects = function (ray, positions, indices, fastCheck) { var intersectInfo = null; // LineMesh first as it's also a Mesh... if (this._mesh instanceof BABYLON.LinesMesh) { var lineMesh = this._mesh; // Line test for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 2) { var p0 = positions[indices[index]]; var p1 = positions[indices[index + 1]]; var length = ray.intersectionSegment(p0, p1, lineMesh.intersectionThreshold); if (length < 0) { continue; } if (fastCheck || !intersectInfo || length < intersectInfo.distance) { intersectInfo = new BABYLON.IntersectionInfo(null, null, length); if (fastCheck) { break; } } } } else { // Triangles test for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 3) { var p0 = positions[indices[index]]; var p1 = positions[indices[index + 1]]; var p2 = positions[indices[index + 2]]; var p0p1 = p0.subtract(p1); var p2p1 = p2.subtract(p1); var normal = BABYLON.Vector3.Cross(p0p1, p2p1); if(BABYLON.Vector3.Dot(ray.direction, normal) < 0 ) { var currentIntersectInfo = ray.intersectsTriangle(p0, p1, p2); if (currentIntersectInfo) { if (currentIntersectInfo.distance < 0) { continue; } if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) { intersectInfo = currentIntersectInfo; intersectInfo.faceId = index / 3; if (fastCheck) { break; } } } } } } return intersectInfo; }; The changes are effected on triangles test side. From the 3 vertices of the face, I calculate the normal and then I check the dot sign of this normal with the ray direction. If it is positive (the ray and the face are oriented in the same way), it means that the face is back to camera, thus invisible in a back face culling mesh. So I keep only negative dot product. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.