How to detect intersections of two faces of two bufferGeometryBox?

I am developing a 3d configurator. A cube appears on the scene. If you click on the side of this cube, a rectangle appears. The problem is that if I click on the same side of the cube, another one will be added over the existing rectangle. I would like to block the clicked side. My cubes and rectangles is buffer geometry. I can get raycasting face (a,b,c) and faceIndex. But how to get intersection of two different faces of two different objects? Sorry for my english

This is my project https://alovert.ru

enter image description here enter image description here

my code

if (intersect) {
            var index = Math.floor( intersect.faceIndex / 6 );
                if ( intersect.object.name == 'cube' ) {

                    switch ( index ) {
                        case 0: load( intersect.object.position.x + 6.58, intersect.object.position.y, intersect.object.position.z, 'beam', 0, 0, 0 ); break;
                        case 1: load( intersect.object.position.x - 6.58, intersect.object.position.y, intersect.object.position.z, 'beam', 0, 0, 0 ); break;
                        case 2: load( intersect.object.position.x, intersect.object.position.y + 6.58, intersect.object.position.z, 'beam', 0, 0, 90 ); break;
                        case 3: load( intersect.object.position.x, intersect.object.position.y - 6.58, intersect.object.position.z, 'beam', 0, 0, 90 ); break;
                        case 4: load( intersect.object.position.x, intersect.object.position.y, intersect.object.position.z + 6.58, 'beam', 0, 90, 0 ); break;
                        case 5: load( intersect.object.position.x, intersect.object.position.y, intersect.object.position.z - 6.58, 'beam', 0, 90, 0 ); break;
                    }

                }`



/cc

A very rough concept with additional “flags” for sides:
https://jsfiddle.net/prisoner849/oxujpaqy/
Click a side to add a square. If you click the same side again, you’ll get a message “Occupied!” and won’t be able to add another square to the side.

1 Like

Thank you! I thought about that, but what i should do in this case?

You can cast a ray from the intersected side, find intersection with an opposite box and do the same thing with flags on that box.

Its sounds very hard for me. I use three js just a couple of weeks…Can you please show me some example? Thank you very much

Only a small suggestion over what prisoner did, you might want to bind the OrbitControls rotation/pan button to right click. So you don’t interfere with all the mesh clicking. Having all the interactions on the same button is somewhat troublesome.

Yes, this is a temporary solution

You can read this topic How to find wall thickness of 3d models (STL) files?, it contains information about how to get a random point on a face.
When you know how to get those coordinates, you need to convert it to world coordinates (see this method), then you have to convert to world coordinates the normal of the face. Having point and normal in world coordinates (origin and direction) you can cast a ray.

2 Likes

Much thanks! I try to read this

Hi! I set ray from faces on my cube, but how i can check intersection between two faces?

i just copied code from your link

function rayCast(mesh) {
                    
                      var minDist = 0.6;
                    
                      var raycaster = new THREE.Raycaster();
                      var intersects = [];
                    
                      var pos = mesh.geometry.attributes.position;
                    
                      var ori = new THREE.Vector3();
                      var dir = new THREE.Vector3();
                      var trc = new THREE.Vector3();
                      var a = new THREE.Vector3(),
                        b = new THREE.Vector3(),
                        c = new THREE.Vector3(),
                        midPoint = new THREE.Vector3(),
                        tri = new THREE.Triangle();
                      var closest = new THREE.Vector3();
                      var geom = new THREE.Geometry();
                      console.log(mesh);
                       
                      var faces = pos.count / 3;
                      for (let i = 0; i < faces; i++) {
                        a.fromBufferAttribute(pos, i * 3 + 0);
                        b.fromBufferAttribute(pos, i * 3 + 1);
                        c.fromBufferAttribute(pos, i * 3 + 2);
                        tri.set(a, b, c);
                        tri.getMidpoint(ori);
                        tri.getNormal(dir)
                        raycaster.set(ori, dir);
                        intersects = raycaster.intersectObject(mesh);
                        scene.add(new THREE.ArrowHelper(raycaster.ray.direction, raycaster.ray.origin, 300, 0xff0000) );
                     /*  minDist = intersects[intersects.length > 1 ? 1 : 0].distance;
                         console.log(minDist);*/
                       
                    	//	minDist = Math.min(minDist, intersects[intersects.length > 1 ? 1 : 0].distance);
                      }

                    }

I used it for simplicity and to show the conception, but it’s not the ultimate solution. If you’ve read How to find wall thickness of 3d models (STL) files? carefully, then at the end of it you could find the link to the SO answer with the solution of how to get a random point on a face (triangle).

You say, that you just copied a piece of code. But it’s irrelevant. It’s just a concept of how to get origin and direction for a raycaster. And in your case, you have to convert them from local coordinates to world coordinates. After that you have to find intersection with the cube that is opposite to the current one and use that concept with flags for sides. Thus, each cube you add to the scene already has to have .userData.sides property.

Please, read about .intersectObjects method of raycaster.

sorry, I don’t quite understand why i need a random point if i can take the middle one? and do not quite understand why convert to world coordinates? I thought that if I just cast a ray from one object to another, I could check the face. I’m sorry I’m really noob in this question

And i’m not sure, that i shoul block only the opposite side

What do I have to think, looking at this? Which sides must be blocked? And sides of what?
To be honest, I’m lost :slight_smile:

Sorry, my bad. Every occupied side must be blocked

Hi again! I soppose i find a solutuion. I create a function, that will check intersections between objects. Raycaster will set from every face of objects and if ray intersects the face of nearest object it will disabled.
But how i can set ray from every object that appears on the scene? And how i can find intersection between them?

I use this code to set ray from faces of object

function rayCast( mesh ) {
                    
      
                        var raycaster = new THREE.Raycaster();
                        var intersects = [];
                        
                        var pos = mesh.geometry.attributes.position;  
                        
                        var ori = new THREE.Vector3();
                        var dir = new THREE.Vector3();
                        var trc = new THREE.Vector3();
                        var a = new THREE.Vector3(),
                        b = new THREE.Vector3(),
                        c = new THREE.Vector3(),
                        midPoint = new THREE.Vector3(),
                        tri = new THREE.Triangle();
                        var closest = new THREE.Vector3();
                        
               
                        
                        var faces = pos.count / 3;
                        for (let i = 0; i < faces; i++) {
                            a.fromBufferAttribute(pos, i * 3 + 0);
                            b.fromBufferAttribute(pos, i * 3 + 1);
                            c.fromBufferAttribute(pos, i * 3 + 2);
                            tri.set(a, b, c);
                            tri.getMidpoint(ori);
                            tri.getNormal(dir)
                            
                            raycaster.set(ori, dir);
                            intersects = raycaster.intersectObject(mesh, true);
                            if ( intersects.length > 0 ) {
                            console.log(Math.floor(intersects[0].faceIndex / 6));
                          
                        }
                    
                        }
                    
                    }

Ok. I push all my objects in a group. And in the function where my object is created, I insert this code

 var raycaster = new THREE.Raycaster();
                var intersects = [];
                
                var pos = box.geometry.attributes.position;  
                
                var ori = new THREE.Vector3();
                var dir = new THREE.Vector3();
                var trc = new THREE.Vector3();
                var a = new THREE.Vector3(),
                b = new THREE.Vector3(),
                c = new THREE.Vector3(),
                midPoint = new THREE.Vector3(),
                tri = new THREE.Triangle();
                var closest = new THREE.Vector3();
                
                //  console.log(mesh);
                
                var faces = pos.count / 3;
                for (let i = 0; i < faces; i++) {
                    a.fromBufferAttribute(pos, i * 3 + 0);
                    b.fromBufferAttribute(pos, i * 3 + 1);
                    c.fromBufferAttribute(pos, i * 3 + 2);
                    tri.set(a, b, c);
                    tri.getMidpoint(ori);
                    tri.getNormal(dir)
                    
                    raycaster.set(ori, dir);
                    intersects = raycaster.intersectObject(group, true);
                    if ( intersects.length > 0 ) {
                        console.log(Math.floor(intersects[0].faceIndex / 6));
                        console.log(intersects[0]);
                    }
              
                }

Intersections works fine, but faceIndex number and number of face (a,b,c) is too large. Its can be 30 or 1800. Is this code correct?

Just out of curiousity, why 6?