Hi,
I've been playing around with adding stuff to BufferGeometry dynamically and changing the material indices in geometry groups, and it seems like materials with wireframe=true are causing me trouble.
Say, we create a BufferGeometry and allocate the buffers (position/normal/color attributes and index) to allow adding (changing) values on the fly. Then we start adding those values and also creating new groups in geometry.groups. All this works fine (tested well!) until we decide to use a wireframe material for the newly added groups. At some point, new groups that are supposed to be rendered in wireframe, are not rendered at all.
I created a jsfiddle to illustrate this: https://jsfiddle.net/vakorol/5pm3r3e2/
The problem seems to originate in WebGLGeometries.getWireframeAttribute. There, a new index
buffer attribute (used to draw the lines in the wireframe) is constructed based on the given geometry's index. This new buffer attribute is then cached and is then served for all requests with the same geometry.id. This way, if we keep modifying the geometry's index array, and then we decide to change the material of new groups to wireframe, WebGLGeometries.getWireframeAttribute will still return the cached buffer which is missing the new values.
One possible solution could be to cache the buffer attributes by geometry.uuid instead of geometry.id, which is immutable. In this case, the user would be responsible for changing the uuid manually before rendering new groups.
What do you think of this?
PS: I am using THREE.js r87, but it seems like the affected code is the same in r88 and dev (as of Nov 28, 2017).
To restate the issue, the OP is allocating sufficiently-large geometry buffers, and modifying the content of the buffers after rendering once:
Simplified, working fiddle: https://jsfiddle.net/tehy7tsj/
However, with wireframe: true: https://jsfiddle.net/tehy7tsj/1/
@vakorol Be sure to set geometry.drawRange if the entire buffer does not have valid data. Also, there is no need to set needsUpdate unnecessarily.
UPD: this is still an issue in r97.
This is a work-around for this use case:
// Add another cube
addCube();
//geom.index.needsUpdate = true; // don't do this
//geom.attributes.position.needsUpdate = true; // or this
geom.dispose(); // do this instead
fiddle: https://jsfiddle.net/tehy7tsj/4/
@mrdoob It seems issue is that when the user updates the geometry index array values after the first render, the indices in wireframeAttributes[ geometry.id ] are not updated accordingly -- even if geometry.index.needsUpdate is set to true.
Updating the positions array does not seem to be a problem. I have not investigated the reason for the difference.
To summarize at least part of the issue, if mesh.material.wireframe is true, and the indexed-BufferGeometry indices are modified, setting mesh.geometry.index.needsUpdate = true has no effect.
It would be great if someone is interested in tracking this down.
It would be great if someone is interested in tracking this down.
I'm going to investigate this issue and report my findings in this thread 馃槉
Solved via #15198