Three.js: Correct way to setIndex / indices for BufferGeometry?

梦想与她 提交于 2020-06-25 21:11:33

问题


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:


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

  • If you're looking to render each face with a different material, as the materialIndex corresponds to, then I would look into groups for BufferGeometry

  • If you want to actually generate custom UV coordinates for a BufferGeometry, I would look into BufferAttributes and the BufferGeometry.addAttribute function to add the new UV attribute.

Hope that helps!



来源:https://stackoverflow.com/questions/45123977/three-js-correct-way-to-setindex-indices-for-buffergeometry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!