Skip to content

Commit

Permalink
GLTFLoader: Add EXT_mesh_gpu_instancing built-in plugin (#24528)
Browse files Browse the repository at this point in the history
* GLTFLoader: Add EXT_mesh_gpu_instancing built-in plugin

* GLTFLoader: No Points or Lines + Instancing

Currenlty Three.js does not seem to support Points or Lines +
Instancing so GLTFLoader GPU instancing extension handler
ignores the extension if primitive draw mode is not triangle.

* GLTFLoader: Minor clean up

Co-authored-by: Don McCurdy <[email protected]>

* GLTFLoader: Minor clean up

Co-authored-by: Don McCurdy <[email protected]>

* Update examples/jsm/loaders/GLTFLoader.js

Co-authored-by: Don McCurdy <[email protected]>

* Update examples/jsm/loaders/GLTFLoader.js

Co-authored-by: Don McCurdy <[email protected]>

* GLTFLoader: Clean up

Co-authored-by: Don McCurdy <[email protected]>
  • Loading branch information
takahirox and donmccurdy authored Oct 13, 2022
1 parent 3a02d2f commit 0432e2f
Show file tree
Hide file tree
Showing 10 changed files with 570 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/examples/en/loaders/GLTFLoader.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ <h2>Extensions</h2>
<li>KHR_texture_transform<sup>2</sup></li>
<li>EXT_texture_webp</li>
<li>EXT_meshopt_compression</li>
<li>EXT_mesh_gpu_instancing</li>
</ul>

<p>
Expand Down
1 change: 1 addition & 0 deletions docs/examples/zh/loaders/GLTFLoader.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ <h2>扩展</h2>
<li>KHR_texture_transform<sup>2</sup></li>
<li>EXT_texture_webp</li>
<li>EXT_meshopt_compression</li>
<li>EXT_mesh_gpu_instancing</li>
</ul>

<p>
Expand Down
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"webgl_loader_gcode",
"webgl_loader_gltf",
"webgl_loader_gltf_compressed",
"webgl_loader_gltf_instancing",
"webgl_loader_gltf_iridescence",
"webgl_loader_gltf_sheen",
"webgl_loader_gltf_transmission",
Expand Down
163 changes: 162 additions & 1 deletion examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FrontSide,
Group,
ImageBitmapLoader,
InstancedMesh,
InterleavedBuffer,
InterleavedBufferAttribute,
Interpolant,
Expand Down Expand Up @@ -147,6 +148,12 @@ class GLTFLoader extends Loader {

} );

this.register( function ( parser ) {

return new GLTFMeshGpuInstancing( parser );

} );

}

load( url, onLoad, onProgress, onError ) {
Expand Down Expand Up @@ -468,7 +475,8 @@ const EXTENSIONS = {
KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
KHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',
EXT_TEXTURE_WEBP: 'EXT_texture_webp',
EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression'
EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
};

/**
Expand Down Expand Up @@ -1384,6 +1392,159 @@ class GLTFMeshoptCompression {

}

/**
* GPU Instancing Extension
*
* Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
*
*/
class GLTFMeshGpuInstancing {

constructor( parser ) {

this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;
this.parser = parser;

}

createNodeMesh( nodeIndex ) {

const json = this.parser.json;
const nodeDef = json.nodes[ nodeIndex ];

if ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||
nodeDef.mesh === undefined ) {

return null;

}

const meshDef = json.meshes[ nodeDef.mesh ];

// No Points or Lines + Instancing support yet

for ( const primitive of meshDef.primitives ) {

if ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&
primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&
primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&
primitive.mode !== undefined ) {

return null;

}

}

const extensionDef = nodeDef.extensions[ this.name ];
const attributesDef = extensionDef.attributes;

// @TODO: Can we support InstancedMesh + SkinnedMesh?

const pending = [];
const attributes = {};

for ( const key in attributesDef ) {

pending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {

attributes[ key ] = accessor;
return attributes[ key ];

}));

}

if ( pending.length < 1 ) {

return null;

}

pending.push( this.parser.createNodeMesh( nodeIndex ) );

return Promise.all( pending ).then( results => {

const nodeObject = results.pop();
const meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];
const count = results[ 0 ].count; // All attribute counts should be same
const instancedMeshes = [];

for ( const mesh of meshes ) {

// Temporal variables
const m = new Matrix4();
const p = new Vector3();
const q = new Quaternion();
const s = new Vector3( 1, 1, 1 );

const instancedMesh = new InstancedMesh( mesh.geometry, mesh.material, count );

for ( let i = 0; i < count; i ++ ) {

if ( attributes.TRANSLATION ) {

p.fromBufferAttribute( attributes.TRANSLATION, i );

}

if ( attributes.ROTATION ) {

q.fromBufferAttribute( attributes.ROTATION, i );

}

if ( attributes.SCALE ) {

s.fromBufferAttribute( attributes.SCALE, i );

}

instancedMesh.setMatrixAt( i, m.compose( p, q, s ) );

}

// Add instance attributes to the geometry, excluding TRS.
for ( const attributeName in attributes ) {

if ( attributeName !== 'TRANSLATION' &&
attributeName !== 'ROTATION' &&
attributeName !== 'SCALE' ) {

mesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );

}

}

// Just in case
Object3D.prototype.copy.call( instancedMesh, mesh );

// https://github.com/mrdoob/three.js/issues/18334
instancedMesh.frustumCulled = false;
this.parser.assignFinalMaterial( instancedMesh );

instancedMeshes.push( instancedMesh );

}

if ( nodeObject.isGroup ) {

nodeObject.clear();

nodeObject.add( ... instancedMeshes );

return nodeObject;
}

return instancedMeshes[ 0 ];

} );

}

}

/* BINARY EXTENSION */
const BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
const BINARY_EXTENSION_HEADER_LENGTH = 12;
Expand Down
Loading

0 comments on commit 0432e2f

Please sign in to comment.