Hi!
Is there an easy way to remove a thin instance by index?
var matrix = BABYLON.Matrix.Translation(-2, 2, 0);
var idx = sphere.thinInstanceAdd(matrix);
sphere.thinInstanceRemove(idx) // this is the method I miss
I had a naive thought, that sphere.thinInstanceSetMatrixAt(idx, undefined); might work, but it throws an Error.
The goal of thin instances is to be fast and so you don’t have easy adding/removing. To do that, you must update the buffer of matrices yourself and pass it to the underlying function.
Maybe passing a matrix with all 0 would work to remove an instance, but that would be quite an edge case and I don’t know if it would work on all GPU…
There’s an easy way to do this - just go into the matrixData array, and overwrite the data for the instance you want to remove with the data of the last thin instance in your set, and then decrement thinInstanceCount.
I think if you did it that way with splicing then the indexes that you have cached would be incorrect, for all of the thin instances after the removed one instead of just the last one.
I’m doing this, but both the instance in question AND the last instance in the set are being removed.
Here is the code that’s performing that, the instanceIndex is coming from a picked event.
If I don’t deincriment thinInstanceCount the expected thin Instance is ‘removed’, if I do, both the instance and the last one in the set are removed.
Am I messing this up somewhere?
EDIT: Edited with working code for future readers
private static RemoveThinInstance(instanceIndex: number, buffer: Float32Array, prefab: BABYLON.Mesh) {
let indexToRemove = (instanceIndex * 16);
let indexToCopy = buffer.length - 1 - 15; // 16 items inclusive
// Copy the last instance in the array to the spot where the instance we want to remove is
// And then deincriment the instance count, cutting the end off
for(let i = 15; i >= 0; i--) {
indexToCopy = buffer.length - 1 - i;
buffer[indexToRemove] = buffer[indexToCopy];
indexToRemove++;
}
prefab.thinInstanceSetBuffer('matrix', buffer); // <--- do this instead
//prefab.thinInstanceBufferUpdated('matrix'); <--- don't do this instead
prefab.thinInstanceCount--;
}
@Blake You’re right, I didn’t quite get the concept till now.
I’m very sure that it is, if it wasn’t I would have some very weird effects happening. The behavior is consistent in that it works as expected until thinInstanceCount is deincrimented, at which point the last item is lost even though it was copied.
Setting the buffer instead of updating it is necessary for another reason as well, pick events still fire for thin instances that have been ‘removed’ when only calling thinInstanceBufferUpdated('matrix').
Here is the behavior of the scene using both methods, note how in the 2nd gif we lose both the picked instance and the last instance in the array? It’s pretty weird.
If need be I can see about trying to make a self-contained repro in another thread.