4
votes

I'm trying to set per-face UV indices in a BufferGeometry.

I'm starting with a Geometry. Each face of my geometry has a face.materialIndex corresponding to a UV index. I'm trying to convert this to a BufferGeometry, and then map over the face.materialIndex to the BufferGeometry.

Here's what I have so far:

// Convert geometry > buffergeometry
const bufGeo = new BufferGeometry().fromGeometry( geometry );

// Get an array of all the original geometry's indices...
const faceIndices = geometry.faces.map( face => face.materialIndex );

// Build a new array with the indices...
const indices = new Uint16Array( faceIndices );

// Apply to the BufferGeometry
bufGeo.setIndex( new BufferAttribute( indices, 1 ) );

Right now this appears to clobber my mesh and make it not draw at all. What am I doing wrong?

By the way, under the hood, when a Geometry is converted to a BufferGeometry, Three.js puts it in an intermediary format first called a DirectGeometry. This used to copy over indices, but it was removed for reasons unknown in this commit by Mr Doob. Right now Three appears to discard indices entirely in a Geo > BufGeo conversion.

I have also tried using the code from that commit (modified to use setIndex):

const indices = new Uint16Array( faceIndices.length * 3 );
bufGeo.addAttribute( 'index', new BufferAttribute( indices, 1 ).copyIndicesArray( faceIndices ) );

But I have the same problem. The resulting mesh is clobbered.

1
please stop adding the webgl tag to this question. Nothing about this question has anything to do with WebGL. It is entirely a three.js questiongman
never!! (buffers are a pretty important part of webgl)Andy Ray
Did you ever find a solution? I'm having the exact same problem and not finding any documentation. One thing that seems to work is setting indices to a standard array and passing that right into setIndex (even though this is not in any of the documentation, it's what's done in the examples). However, then it does not appear to be possible to update the array.JSideris

1 Answers

1
votes

The setIndex function is used to specify triangle indices that reference the vertex attribute buffers on the BufferGeometry. In your example you're setting the the triangle index array to an array generated from the materialIndex of each face.

The materialIndex corresponds to a material to render that triangle with from an array of materials, not a UV index. From the Face3 documentation:

materialIndex — (optional) which index of an array of materials to associate with the face.

It's very possible that that materialIndex is zero for every face unless you've done something to change it, which would explain why your model stops drawing (the vertices on the faces are all the same one).

This line is your problem:

// Get an array of all the original geometry's indices... const faceIndices = geometry.faces.map( face => face.materialIndex );

It might also be important to note that you'll be getting 1/3 as many array elements as you need for an attribute by generating an array this way, because there are 3 vertices per face.

Possible Solutions

Hope that helps!