How to get the normal of a face/triangle? (BufferGeometry)

I am migrating my geometry to buffergeometry, but I have came to something preventing me to make progress. I can’t find a way to retrieve the normal of a triangle/face. I need to determine the direction a polygon is pointing… How can I accomplish this?

With geometry I was able to do

geometry.faces[f].normal

but I’m lost now with buffergeometry. How do I calculate the direction of a triangle?

			var posAttribute = this.face.geometry.attributes.position;
			var indexAttribute = this.face.geometry.index;
			
			for(var f=0; f<2; f++){	
                    var triangle = new THREE.Triangle(	new THREE.Vector3(posAttribute.getX(indexAttribute[0+(f*3)]),posAttribute.getY(indexAttribute[0+(f*3)]),posAttribute.getZ(indexAttribute[0+(f*3)])),
														new THREE.Vector3(posAttribute.getX(indexAttribute[1+(f*3)]),posAttribute.getY(indexAttribute[1+(f*3)]),posAttribute.getZ(indexAttribute[1+(f*3)])),
														new THREE.Vector3(posAttribute.getX(indexAttribute[2+(f*3)]),posAttribute.getY(indexAttribute[2+(f*3)]),posAttribute.getZ(indexAttribute[2+(f*3)])), );
					triangle.getNormal( copytoavector3 );
                    //otherstuff
		    }

I think I can do something like this… Let me know if there’s a better way.

Sometimes a geometry already has pre-computed normals, you can find them at: geometry.attributes.normal (they are per vertex, of course).

Or, if you create a custom geometry, you can make your life easier, calling .computeVertexNormals().

I need the face normal, not vertex normal.

Okay, there’s something, that can be simplified/optimized:

let pos = this.face.geometry.attributes.position;
let idx = this.face.geometry.index;

let tri = new THREE.Triangle(); // for re-use
let a = new THREE.Vector3(), 
    b = new THREE.Vector3(), 
    c = new THREE.Vector3(); // for re-use

for( let f = 0; f < 2; f++ ){
    let idxBase = f * 3;
    a.fromBufferAttribute( pos, idx.getX( idxBase + 0 ) );
    b.fromBufferAttribute( pos, idx.getX( idxBase + 1 ) );
    c.fromBufferAttribute( pos, idx.getX( idxBase + 2 ) );
    tri.set( a, b, c );
    tri.getNormal( copytoavector3 );
    //otherstuff
}

Thanks, that looks great! I didn’t know that you could set a vector from a buffer. Cool!

Hi guys, I was trying to re-write the threejs-slice-geometry - npm library to be able to slice with v125 and above of ThreeJs.

I was stack at this point:

geometry.faces.forEach(function(face, faceIndex) {
}

How I can translate that to the bufferGeometry? I have tried the next code, but i got undefined “idx”

let pos = this.sourceGeometry.geometry.attributes.position;

    let idx = this.sourceGeometry.geometry.index;

    let tri = new THREE.Triangle(); 

    let a = new THREE.Vector3(),

        b = new THREE.Vector3(),

        c = new THREE.Vector3();

    for (let f = 0; f < 2; f++) {

        let idxBase = f * 3;

        a.fromBufferAttribute(pos, idx.getX(idxBase + 0));

        b.fromBufferAttribute(pos, idx.getX(idxBase + 1));

        c.fromBufferAttribute(pos, idx.getX(idxBase + 2));

        tri.set(a, b, c);

    }

Really appreciate your help!

Thanks!

It means, that your model has a non-indexed buffer geometry, as it has no .index property. They call it “triangle soup”, when faces defined with triplets of consequential vertices. So, there’s no need to use .index, work with geometry.attributes.position;.

1 Like