three-mesh-bvh
Advanced tools
Comparing version 0.5.19 to 0.5.20
{ | ||
"name": "three-mesh-bvh", | ||
"version": "0.5.19", | ||
"version": "0.5.20", | ||
"description": "A BVH implementation to speed up raycasting against three.js meshes.", | ||
@@ -5,0 +5,0 @@ "module": "src/index.js", |
# three-mesh-bvh | ||
[![npm version](https://img.shields.io/npm/v/three-mesh-bvh.svg?style=flat-square)](https://www.npmjs.com/package/three-mesh-bvh) | ||
[![lgtm code quality](https://img.shields.io/lgtm/grade/javascript/g/gkjohnson/three-mesh-bvh.svg?style=flat-square&label=code-quality)](https://lgtm.com/projects/g/gkjohnson/three-mesh-bvh/) | ||
[![build](https://img.shields.io/github/workflow/status/gkjohnson/three-mesh-bvh/Node.js%20CI?style=flat-square&label=build)](https://github.com/gkjohnson/three-mesh-bvh/actions) | ||
[![build](https://img.shields.io/github/actions/workflow/status/gkjohnson/three-mesh-bvh/node.js.yml?style=flat-square&label=build&branch=master)](https://github.com/gkjohnson/three-mesh-bvh/actions) | ||
[![github](https://flat.badgen.net/badge/icon/github?icon=github&label)](https://github.com/gkjohnson/three-mesh-bvh/) | ||
@@ -7,0 +6,0 @@ [![twitter](https://flat.badgen.net/twitter/follow/garrettkjohnson)](https://twitter.com/garrettkjohnson) |
@@ -480,3 +480,3 @@ import { BufferAttribute } from 'three'; | ||
// dont do anything with the bounds if the new bounds have no triangles | ||
// don't do anything with the bounds if the new bounds have no triangles | ||
if ( binCount !== 0 ) { | ||
@@ -483,0 +483,0 @@ |
@@ -36,3 +36,3 @@ export function arrayToBox( nodeIndex32, array, target ) { | ||
// copys bounds a into bounds b | ||
// copies bounds a into bounds b | ||
export function copyBounds( source, target ) { | ||
@@ -39,0 +39,0 @@ |
@@ -156,7 +156,7 @@ import { BufferAttribute, BufferGeometry, Vector3, Vector4, Matrix4, Matrix3 } from 'three'; | ||
// Modified version of BufferGeometryUtils.mergeBufferGeometries that ignores morph targets and updates a attributes in plac | ||
function mergeBufferGeometries( geometries, options = { useGroups: false, updateIndex: false }, targetGeometry = new BufferGeometry() ) { | ||
// Modified version of BufferGeometryUtils.mergeBufferGeometries that ignores morph targets and updates a attributes in place | ||
function mergeBufferGeometries( geometries, options = { useGroups: false, updateIndex: false, skipAttributes: [] }, targetGeometry = new BufferGeometry() ) { | ||
const isIndexed = geometries[ 0 ].index !== null; | ||
const { useGroups, updateIndex } = options; | ||
const { useGroups = false, updateIndex = false, skipAttributes = [] } = options; | ||
@@ -168,2 +168,3 @@ const attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) ); | ||
targetGeometry.clearGroups(); | ||
for ( let i = 0; i < geometries.length; ++ i ) { | ||
@@ -235,3 +236,3 @@ | ||
let forceUpateIndex = false; | ||
let forceUpdateIndex = false; | ||
if ( ! targetGeometry.index ) { | ||
@@ -247,7 +248,7 @@ | ||
targetGeometry.setIndex( new BufferAttribute( new Uint32Array( indexCount ), 1, false ) ); | ||
forceUpateIndex = true; | ||
forceUpdateIndex = true; | ||
} | ||
if ( updateIndex || forceUpateIndex ) { | ||
if ( updateIndex || forceUpdateIndex ) { | ||
@@ -261,7 +262,11 @@ const targetIndex = targetGeometry.index; | ||
const index = geometry.index; | ||
for ( let j = 0; j < index.count; ++ j ) { | ||
if ( skipAttributes[ i ] !== true ) { | ||
targetIndex.setX( targetOffset, index.getX( j ) + indexOffset ); | ||
targetOffset ++; | ||
for ( let j = 0; j < index.count; ++ j ) { | ||
targetIndex.setX( targetOffset, index.getX( j ) + indexOffset ); | ||
targetOffset ++; | ||
} | ||
} | ||
@@ -296,6 +301,11 @@ | ||
let offset = 0; | ||
for ( const key in attrList ) { | ||
for ( let i = 0, l = attrList.length; i < l; i ++ ) { | ||
const attr = attrList[ key ]; | ||
copyAttributeContents( attr, targetAttribute, offset ); | ||
const attr = attrList[ i ]; | ||
if ( skipAttributes[ i ] !== true ) { | ||
copyAttributeContents( attr, targetAttribute, offset ); | ||
} | ||
offset += attr.count; | ||
@@ -311,2 +321,103 @@ | ||
function checkTypedArrayEquality( a, b ) { | ||
if ( a === null || b === null ) { | ||
return a === b; | ||
} | ||
if ( a.length !== b.length ) { | ||
return false; | ||
} | ||
for ( let i = 0, l = a.length; i < l; i ++ ) { | ||
if ( a[ i ] !== b[ i ] ) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
// Checks whether the geometry changed between this and last evaluation | ||
class GeometryDiff { | ||
constructor( mesh ) { | ||
this.matrixWorld = new Matrix4(); | ||
this.geometryHash = null; | ||
this.boneMatrices = null; | ||
this.primitiveCount = - 1; | ||
this.mesh = mesh; | ||
this.update(); | ||
} | ||
update() { | ||
const mesh = this.mesh; | ||
const geometry = mesh.geometry; | ||
const skeleton = mesh.skeleton; | ||
const primitiveCount = ( geometry.index ? geometry.index.count : geometry.attributes.position.count ) / 3; | ||
this.matrixWorld.copy( mesh.matrixWorld ); | ||
this.geometryHash = geometry.attributes.position.version; | ||
this.primitiveCount = primitiveCount; | ||
if ( skeleton ) { | ||
// ensure the bone matrix array is updated to the appropriate length | ||
if ( ! skeleton.boneTexture ) { | ||
skeleton.computeBoneTexture(); | ||
} | ||
skeleton.update(); | ||
// copy data if possible otherwise clone it | ||
const boneMatrices = skeleton.boneMatrices; | ||
if ( ! this.boneMatrices || this.boneMatrices.length !== boneMatrices.length ) { | ||
this.boneMatrices = boneMatrices.slice(); | ||
} else { | ||
this.boneMatrices.set( boneMatrices ); | ||
} | ||
} else { | ||
this.boneMatrices = null; | ||
} | ||
} | ||
didChange() { | ||
const mesh = this.mesh; | ||
const geometry = mesh.geometry; | ||
const primitiveCount = ( geometry.index ? geometry.index.count : geometry.attributes.position.count ) / 3; | ||
const identical = | ||
this.matrixWorld.equals( mesh.matrixWorld ) && | ||
this.geometryHash === geometry.attributes.position.version && | ||
checkTypedArrayEquality( mesh.skeleton?.boneMatrices || null, this.boneMatrices ) && | ||
this.primitiveCount === primitiveCount; | ||
return ! identical; | ||
} | ||
} | ||
export class StaticGeometryGenerator { | ||
@@ -342,2 +453,3 @@ | ||
this._intermediateGeometry = new Array( finalMeshes.length ).fill().map( () => new BufferGeometry() ); | ||
this._diffMap = new WeakMap(); | ||
@@ -368,3 +480,5 @@ } | ||
const { meshes, useGroups, _intermediateGeometry } = this; | ||
// track which attributes have been updated and which to skip to avoid unnecessary attribute copies | ||
let skipAttributes = []; | ||
const { meshes, useGroups, _intermediateGeometry, _diffMap } = this; | ||
for ( let i = 0, l = meshes.length; i < l; i ++ ) { | ||
@@ -374,7 +488,28 @@ | ||
const geom = _intermediateGeometry[ i ]; | ||
this._convertToStaticGeometry( mesh, geom ); | ||
const diff = _diffMap.get( mesh ); | ||
if ( ! diff || diff.didChange( mesh ) ) { | ||
this._convertToStaticGeometry( mesh, geom ); | ||
skipAttributes.push( false ); | ||
if ( ! diff ) { | ||
_diffMap.set( mesh, new GeometryDiff( mesh ) ); | ||
} else { | ||
diff.update(); | ||
} | ||
} else { | ||
skipAttributes.push( true ); | ||
} | ||
} | ||
mergeBufferGeometries( _intermediateGeometry, { useGroups }, targetGeometry ); | ||
mergeBufferGeometries( _intermediateGeometry, { useGroups, skipAttributes }, targetGeometry ); | ||
for ( const key in targetGeometry.attributes ) { | ||
@@ -381,0 +516,0 @@ |
@@ -112,6 +112,6 @@ import { Box3, BufferAttribute } from 'three'; | ||
const transferrables = [ position ]; | ||
const transferable = [ position ]; | ||
if ( index ) { | ||
transferrables.push( index ); | ||
transferable.push( index ); | ||
@@ -131,3 +131,3 @@ } | ||
}, transferrables.map( arr => arr.buffer ) ); | ||
}, transferable.map( arr => arr.buffer ) ); | ||
@@ -134,0 +134,0 @@ } ); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1170127
13090
1089