diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bdcc20..5b2a5d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.0.2] - 2023.09.29 + +### Added +- SilhouetteGenerator: performance improvements by skipping unnecessary triangles that are determined to already be in the shape. +- SilhouetteGenerator: Perform simplification of edges. +- SilhouetteGenerator: Add ability to see outline and mesh edges. + ## [0.0.1] - 2023.09.18 ### Fixed diff --git a/README.md b/README.md index becc50e..b4b4ba0 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,22 @@ doubleSided = false : Boolean If `false` then only the triangles facing upwards are included in the silhouette. +### .sortTriangles + +```js +sortTriangles = false : Boolean +``` + +Whether to sort triangles and project them large-to-small. In some cases this can cause the performance to drop since the union operation is best performed with smooth, simple edge shapes. + +### .output + +```js +output = OUTPUT_MESH | OUTPUT_LINE_SEGMENTS | OUTPUT_BOTH +``` + +Whether to output mesh geometry, line segments geometry, or both in an array ( `[ mesh, line segments ]` ); + ### .generate ```js diff --git a/example/silhouetteProjection.js b/example/silhouetteProjection.js index 72bc724..871443a 100644 --- a/example/silhouetteProjection.js +++ b/example/silhouetteProjection.js @@ -17,7 +17,7 @@ import { import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js'; -import { SilhouetteGenerator } from '../src'; +import { OUTPUT_BOTH, SilhouetteGenerator } from '../src'; import { SilhouetteGeneratorWorker } from '../src/worker/SilhouetteGeneratorWorker.js'; const params = { @@ -185,7 +185,7 @@ function* updateEdges( runTime = 30 ) { const generator = new SilhouetteGenerator(); generator.iterationTime = runTime; - generator.output = 2; + generator.output = OUTPUT_BOTH; const task = generator.generate( mergedGeometry, { onProgress: ( p, info ) => { @@ -229,6 +229,7 @@ function* updateEdges( runTime = 30 ) { worker .generate( mergedGeometry, { + output: OUTPUT_BOTH, onProgress: p => { outputContainer.innerText = `processing: ${ parseFloat( ( p * 100 ).toFixed( 2 ) ) }%`; diff --git a/src/worker/SilhouetteGeneratorWorker.js b/src/worker/SilhouetteGeneratorWorker.js index ceb9cdc..895539c 100644 --- a/src/worker/SilhouetteGeneratorWorker.js +++ b/src/worker/SilhouetteGeneratorWorker.js @@ -1,4 +1,5 @@ import { BufferAttribute, BufferGeometry } from 'three'; +import { OUTPUT_BOTH } from '../SilhouetteGenerator'; const NAME = 'SilhouetteGeneratorWorker'; export class SilhouetteGeneratorWorker { @@ -61,10 +62,33 @@ export class SilhouetteGeneratorWorker { } else if ( data.result ) { - const geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new BufferAttribute( data.result.position, 3, false ) ); - geometry.setIndex( new BufferAttribute( data.result.index, 1, false ) ); - resolve( geometry ); + if ( options.output === OUTPUT_BOTH ) { + + const result = data.result.map( info => { + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new BufferAttribute( info.position, 3, false ) ); + if ( info.index ) { + + geometry.setIndex( new BufferAttribute( info.index, 1, false ) ); + + } + + return geometry; + + } ); + + resolve( result ); + + } else { + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new BufferAttribute( data.result.position, 3, false ) ); + geometry.setIndex( new BufferAttribute( data.result.index, 1, false ) ); + resolve( geometry ); + + } + worker.onmessage = null; } else if ( options.onProgress ) { diff --git a/src/worker/silhouetteAsync.worker.js b/src/worker/silhouetteAsync.worker.js index bee2b8d..475da35 100644 --- a/src/worker/silhouetteAsync.worker.js +++ b/src/worker/silhouetteAsync.worker.js @@ -1,5 +1,5 @@ import { BufferAttribute, BufferGeometry } from 'three'; -import { SilhouetteGenerator } from '../SilhouetteGenerator.js'; +import { OUTPUT_BOTH, SilhouetteGenerator } from '../SilhouetteGenerator.js'; onmessage = function ( { data } ) { @@ -30,6 +30,9 @@ onmessage = function ( { data } ) { const generator = new SilhouetteGenerator(); generator.doubleSided = options.doubleSided ?? generator.doubleSided; + generator.output = options.output ?? generator.output; + generator.intScalar = options.intScalar ?? generator.intScalar; + generator.sortTriangles = options.sortTriangles ?? generator.sortTriangles; const task = generator.generate( geometry, { onProgress: onProgressCallback, } ); @@ -41,18 +44,46 @@ onmessage = function ( { data } ) { } - const posArr = result.value.attributes.position.array; - const indexArr = result.value.index.array; - postMessage( { + let buffers, output; + if ( generator.output === OUTPUT_BOTH ) { + + buffers = []; + output = []; + result.value.forEach( g => { + + console.log( g ); + const posArr = g.attributes.position.array; + const indexArr = g.index?.array || null; + output.push( { + position: posArr, + index: indexArr, + } ); + buffers.push( + posArr.buffer, + indexArr?.buffer, + ); + + } ); - result: { + } else { + + const posArr = result.value.attributes.position.array; + const indexArr = result.value.index.array; + output = { position: posArr, index: indexArr, - }, + }; + buffers = [ posArr.buffer, indexArr.buffer ]; + + } + + postMessage( { + + result: output, error: null, progress: 1, - }, [ posArr.buffer, indexArr.buffer ] ); + }, buffers.filter( b => ! ! b ) ); } catch ( error ) {