Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SceneUtils: Add sortInstancedMesh(mesh, fn) #24113

Merged
merged 3 commits into from
Oct 21, 2022

Conversation

donmccurdy
Copy link
Collaborator

@donmccurdy donmccurdy commented May 23, 2022

After implementing a function for sorting instances of a THREE.InstancedMesh, it turned out to be more code than expected and I thought we might want a helper function here. The new method takes an InstancedMesh and a comparator function:

import { sortInstancedMesh } from 'three/examples/jsm/utils/SceneUtils.js';

sortInstancedMesh( mesh, ( indexA, indexB ) => {

  let condition; 

  // ...

  return condition ? 1 : -1;

} );

This operation can be expensive for lots of instances, and shouldn't be done on every frame, but can certainly be useful as a bit of pre-processing to get transparency arranged correctly.


This contribution is funded by R&D, The New York Times.

@donmccurdy
Copy link
Collaborator Author

I'd missed #23348 and the removal of unit tests on examples/jsm/*, but for posterity here are tests on SceneUtils.sortInstancedMesh:

import { sortInstancedMesh } from '../../../../examples/jsm/utils/SceneUtils.js';

import { BufferAttribute } from '../../../../src/core/BufferAttribute.js';
import { BoxGeometry } from '../../../../src/geometries/BoxGeometry.js';
import { InstancedBufferAttribute } from '../../../../src/core/InstancedBufferAttribute.js';
import { InstancedMesh } from '../../../../src/objects/InstancedMesh.js';
import { Color } from '../../../../src/math/Color.js';
import { Matrix4 } from '../../../../src/math/Matrix4.js';

const color = new Color();
const matrix = new Matrix4();

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

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

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

			const valueA = new InstancedBufferAttribute( new Uint8Array( [ 2, 7, 1 ] ), 1 );
			const valueB = new InstancedBufferAttribute( new Float32Array( [ 1, 1, 1, 2, 2, 2, 3, 3, 3 ] ), 3 );

			const geometry = new BoxGeometry()
				.setAttribute( 'instanceValueA', valueA )
				.setAttribute( 'instanceValueB', valueB );

			const mesh = new InstancedMesh( geometry, undefined, 3 );

			mesh.setMatrixAt( 0, matrix.makeTranslation( 10, 0, 0 ) );
			mesh.setMatrixAt( 1, matrix.makeTranslation( 0, 10, 0 ) );
			mesh.setMatrixAt( 2, matrix.makeTranslation( 0, 0, 10 ) );

			mesh.setColorAt( 0, color.setRGB( 1, 0, 0 ) );
			mesh.setColorAt( 1, color.setRGB( 0, 1, 0 ) );
			mesh.setColorAt( 2, color.setRGB( 0, 0, 1 ) );

			sortInstancedMesh( mesh, ( a, b ) => valueA.getX( a ) - valueA.getX( b ) );

			//

			assert.smartEqual( Array.from( mesh.instanceMatrix.array ), [

				1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				0, 0, 10, 1,

				1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				10, 0, 0, 1,

				1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				0, 10, 0, 1,

			], 'sorted instanceMatrix' );

			assert.smartEqual( Array.from( mesh.instanceColor.array ), [

				0, 0, 1,
				1, 0, 0,
				0, 1, 0,

			], 'sorted instanceColor' );

			assert.smartEqual( Array.from( valueA.array ), [ 1, 2, 7 ], 'sorted instanceValueA' );
			assert.smartEqual( Array.from( valueB.array ), [ 3, 3, 3, 1, 1, 1, 2, 2, 2 ], 'sorted instanceValueB' );

		} );

	} );

} );

@takahirox
Copy link
Collaborator

takahirox commented May 25, 2022

Thanks for making a useful function.

This operation can be expensive for lots of instances, and shouldn't be done on every frame,

Nit: I think it would be useful for users to write this note in the code or documents.

@donmccurdy
Copy link
Collaborator Author

Agreed! I'll add documentation for sortInstancedMesh if the PR is accepted.

@Mugen87 Mugen87 added this to the r143 milestone Jul 14, 2022
@mrdoob mrdoob modified the milestones: r143, r144 Jul 28, 2022
@mrdoob mrdoob modified the milestones: r144, r145 Aug 31, 2022
@mrdoob mrdoob modified the milestones: r145, r146 Sep 29, 2022
@Mugen87 Mugen87 merged commit 381b54d into mrdoob:dev Oct 21, 2022
@donmccurdy donmccurdy deleted the feat/sort-instanced-mesh branch October 21, 2022 14:10
@donmccurdy
Copy link
Collaborator Author

@joshuaellis joshuaellis mentioned this pull request Oct 31, 2022
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants