UNPKG

@threlte/extras

Version:

Utilities, abstractions and plugins for your Threlte apps

57 lines (56 loc) 2.32 kB
import { isInstanceOf } from '@threlte/core'; import { BufferGeometry, Color, FrontSide, Group, Matrix4, Mesh, MeshBasicMaterial, Raycaster } from 'three'; const _instanceLocalMatrix = new Matrix4(); const _instanceWorldMatrix = new Matrix4(); const _instanceIntersects = []; const _mesh = new Mesh(); export class PositionMesh extends Group { color; instancedMesh; instances; constructor(instancedMesh, instances) { super(); this.color = new Color('white'); this.instancedMesh = instancedMesh; this.instances = instances; } // This will allow the virtual instance have bounds get geometry() { return this.instancedMesh.current?.geometry; } // And this will allow the virtual instance to receive events raycast(raycaster, intersects) { const parent = this.instancedMesh.current; if (parent === undefined) return; if (parent.geometry === undefined || parent.material === undefined) return; _mesh.geometry = parent.geometry; const matrixWorld = parent.matrixWorld; const instanceId = this.instances.current.indexOf(this); // If the instance wasn't found or exceeds the parents draw range, bail out if (instanceId === -1 || instanceId > parent.count) return; // calculate the world matrix for each instance parent.getMatrixAt(instanceId, _instanceLocalMatrix); _instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix); // the mesh represents this single instance _mesh.matrixWorld = _instanceWorldMatrix; // raycast side according to instance material if (isInstanceOf(parent.material, 'Material')) { _mesh.material.side = parent.material.side; } else { _mesh.material.side = parent.material[0]?.side ?? FrontSide; } _mesh.raycast(raycaster, _instanceIntersects); // process the result of raycast for (let i = 0, l = _instanceIntersects.length; i < l; i++) { const intersect = _instanceIntersects[i]; intersect.instanceId = instanceId; intersect.object = this; intersects.push(intersect); } _instanceIntersects.length = 0; } }