Skip to content

BatchedMesh: setInstanceCount can't shrink available instances #31457

@andreas-hilti

Description

@andreas-hilti

Description

setInstanceCount doesn't correctly remove availableInstanceIds and thus, setInstanceCount can't be used to shrink the maxInstanceCount if more instances were used at some point.

For instance, create a BatchedMesh with 4 Instances, remove the last two instances, and then try to do setInstanceCount(2). This will fail with:
Instance ids outside the range 2 are being used. Cannot shrink instance count.

Root cause seems to be here:

while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length ) {

it should instead be:

while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length - 1) {

(the largest id is instanceInfo.length - 1)

Reproduction steps

  1. Add the unit test as provided below
  2. Run it

This results in

message: "Died on test #1: BatchedMesh: Instance ids outside the range 2 are being used. Cannot shrink instance count.
    at Object.<anonymous> (file:///[...]/three.js/test/unit/src/objects/BatchedMesh.tests.js

Code

/* global QUnit */

import { BatchedMesh } from '../../../../src/objects/BatchedMesh.js';
import { BoxGeometry } from '../../../../src/geometries/BoxGeometry.js';
import { MeshBasicMaterial } from '../../../../src/materials/MeshBasicMaterial.js';

export default QUnit.module( 'Objects', () => {

	QUnit.module( 'BatchedMesh', () => {

		// PUBLIC

		QUnit.test( 'setInstanceCount', ( assert ) => {

			const box = new BoxGeometry( 1, 1, 1 );
			const material = new MeshBasicMaterial( { color: 0x00ff00 } );
			
			// initialize and add geometries into the batched mesh
			const batchedMesh = new BatchedMesh( 4, 5000, 10000, material );
			const boxGeometryId = batchedMesh.addGeometry( box );
			
			// create instances of those geometries
			let boxInstanceIds = []
			for (let i = 0; i < 4; i++){
				boxInstanceIds.push( batchedMesh.addInstance( boxGeometryId ) );
			}
			
			batchedMesh.deleteInstance( boxInstanceIds[2] );
			batchedMesh.deleteInstance( boxInstanceIds[3] );

			// shrink the instance count
			batchedMesh.setInstanceCount(2);

			assert.ok( batchedMesh.instanceCount === 2, 'instance count unequal 2' );

		} );

	} );

} );

Live example

Screenshots

No response

Version

dev

Device

No response

Browser

No response

OS

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions