Skip to content

Commit

Permalink
Merge pull request #140 from gkjohnson/set-type
Browse files Browse the repository at this point in the history
Add support for changing the attribute buffer type for TypedBackedArray
  • Loading branch information
gkjohnson authored Aug 29, 2023
2 parents a00a634 + 194e5e8 commit ef6c2ae
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 9 deletions.
51 changes: 43 additions & 8 deletions src/core/TypeBackedArray.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,70 @@
import { areSharedArrayBuffersSupported } from './utils.js';

function ceilToFourByteStride( byteLength ) {

byteLength = ~ ~ byteLength;
return byteLength + 4 - byteLength % 4;

}

// Make a new array wrapper class that more easily affords expansion when reaching it's max capacity
export class TypeBackedArray {

constructor( type, initialSize = 500 ) {

const bufferType = areSharedArrayBuffersSupported() ? SharedArrayBuffer : ArrayBuffer;

this.expansionFactor = 1.5;
this.type = type;
this.array = new type( new bufferType( initialSize * type.BYTES_PER_ELEMENT ) );
this.length = 0;
this.array = null;

this.setSize( initialSize );

}

expand( size = null ) {
setType( type ) {

const { type, array, expansionFactor } = this;
if ( this.length !== 0 ) {

if ( size === null ) {
throw new Error( 'TypeBackedArray: Cannot change the type while there is used data in the buffer.' );

}

const buffer = this.array.buffer;
this.array = new type( buffer );
this.type = type;

}

size = ~ ~ ( array.length * expansionFactor );
setSize( size ) {

if ( this.array && size === this.array.length ) {

return;

}

// ceil to the nearest 4 bytes so we can replace the array with any type using the same buffer
const type = this.type;
const bufferType = areSharedArrayBuffersSupported() ? SharedArrayBuffer : ArrayBuffer;
const newArray = new type( new bufferType( ceilToFourByteStride( size * type.BYTES_PER_ELEMENT ) ) );
if ( this.array ) {

newArray.set( this.array, 0 );

}

const newArray = new type( size );
newArray.set( array, 0 );
this.array = newArray;

}

expand() {

const { array, expansionFactor } = this;
this.setSize( array.length * expansionFactor );

}

push( ...args ) {

let { array, length } = this;
Expand Down
12 changes: 11 additions & 1 deletion src/core/TypedAttributeData.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,17 @@ export class TypedAttributeData {

if ( referenceAttr.type !== type ) {

throw new Error( `TypedAttributeData: Array ${ name } already initialized with a different type.` );
for ( let i = 0, l = groupAttributes.length; i < l; i ++ ) {

groupAttributes[ i ][ name ].setType( type );

}

// } else {

// throw new Error( `TypedAttributeData: Array ${ name } already initialized with a different type.` );

// }

}

Expand Down
30 changes: 30 additions & 0 deletions tests/BVH.Evaluator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Brush, Evaluator, SUBTRACTION } from '../src';
import { SphereGeometry, BufferAttribute } from 'three';

describe( 'Evaluator', () => {

it( 'it not fail if multiple operations with different buffer types.', () => {

const geo1 = new SphereGeometry();
const geo2 = new SphereGeometry();
geo2.setAttribute(
'uv',
new BufferAttribute( new Uint8Array( geo2.attributes.uv.array.length ), 2, true ),
);

const brush1A = new Brush( geo1 );
const brush1B = new Brush( geo1 );

const brush2A = new Brush( geo2 );
const brush2B = new Brush( geo2 );

const evaluator = new Evaluator();
const result1 = evaluator.evaluate( brush1A, brush1B, SUBTRACTION );
const result2 = evaluator.evaluate( brush2A, brush2B, SUBTRACTION );

expect( result1.geometry.attributes.uv.array.constructor ).toBe( Float32Array );
expect( result2.geometry.attributes.uv.array.constructor ).toBe( Uint8Array );

} );

} );
5 changes: 5 additions & 0 deletions tests/Utils.TypeBackedArray.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe( 'TypeBackedArray', () => {

it.todo( 'make tests' );

} );
5 changes: 5 additions & 0 deletions tests/Utils.TypedAttributeData.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe( 'TypedAttributeData', () => {

it.todo( 'make tests' );

} );

0 comments on commit ef6c2ae

Please sign in to comment.