Skip to content

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gkjohnson committed Aug 26, 2023
1 parent 0d3c4ed commit d9e85e1
Show file tree
Hide file tree
Showing 11 changed files with 580 additions and 434 deletions.
155 changes: 81 additions & 74 deletions src/gpu/MeshBVHUniformStruct.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,87 @@ import {
SPLIT_AXIS,
} from '../core/utils/nodeBufferUtils.js';

export class MeshBVHUniformStruct {

constructor() {

this.index = new UIntVertexAttributeTexture();
this.position = new FloatVertexAttributeTexture();
this.bvhBounds = new DataTexture();
this.bvhContents = new DataTexture();
this._cachedIndexAttr = null;

this.index.overrideItemSize = 3;

}

updateFrom( bvh ) {

const { geometry } = bvh;
bvhToTextures( bvh, this.bvhBounds, this.bvhContents );

this.position.updateFrom( geometry.attributes.position );

// dereference a new index attribute if we're using indirect storage
if ( bvh.indirect ) {

const indirectBuffer = bvh._indirectBuffer;
if (
this._cachedIndexAttr === null ||
this._cachedIndexAttr.count !== indirectBuffer.length
) {

this._cachedIndexAttr = geometry.index ?
geometry.index.clone() :
new BufferAttribute( indirectBuffer.slice(), 1, false );

}

dereferenceIndex( geometry, indirectBuffer, this._cachedIndexAttr );
this.index.updateFrom( this._cachedIndexAttr );

console.log( 'NOT', this._cachedIndexAttr.count );

} else {

this.index.updateFrom( geometry.index );
console.log( 'RAW', geometry.index.count );

}

}

dispose() {

const { index, position, bvhBounds, bvhContents } = this;

if ( index ) index.dispose();
if ( position ) position.dispose();
if ( bvhBounds ) bvhBounds.dispose();
if ( bvhContents ) bvhContents.dispose();

}

}

function dereferenceIndex( geometry, indirectBuffer, target ) {

const unpacked = target.array;
const indexArray = geometry.index ? geometry.index.array : null;
for ( let i = 0, l = indirectBuffer.length; i < l; i ++ ) {

const i3 = 3 * i;
const v3 = 3 * indirectBuffer[ i ];
for ( let c = 0; c < 3; c ++ ) {

unpacked[ i3 + c ] = indexArray ? indexArray[ v3 + c ] : v3 + c;

}

}

}

function bvhToTextures( bvh, boundsTexture, contentsTexture ) {

const roots = bvh._roots;
Expand Down Expand Up @@ -103,77 +184,3 @@ function bvhToTextures( bvh, boundsTexture, contentsTexture ) {
contentsTexture.dispose();

}

export class MeshBVHUniformStruct {

constructor() {

this.autoDispose = true;
this.index = new UIntVertexAttributeTexture();
this.position = new FloatVertexAttributeTexture();
this.bvhBounds = new DataTexture();
this.bvhContents = new DataTexture();
this._cachedIndexAttr = null;

this.index.overrideItemSize = 3;

}

updateFrom( bvh ) {

const { geometry } = bvh;
bvhToTextures( bvh, this.bvhBounds, this.bvhContents );

this.position.updateFrom( geometry.attributes.position );

// dereference a new index attribute if we're using indirect storage
const indirectBuffer = bvh._indirectBuffer;
if ( indirectBuffer ) {

if (
this._cachedIndexAttr === null ||
this._cachedIndexAttr.count !== indirectBuffer.length
) {

this._cachedIndexAttr = geometry.index ?
geometry.index.clone() :
new BufferAttribute( indirectBuffer.slice(), 1, false );

}

dereferenceIndex( geometry, indirectBuffer, this._cachedIndexAttr );
this.index.updateFrom( this._cachedIndexAttr );

} else {

this.index.updateFrom( geometry.index );

}

}

dispose() {

const { index, position, bvhBounds, bvhContents } = this;

if ( index ) index.dispose();
if ( position ) position.dispose();
if ( bvhBounds ) bvhBounds.dispose();
if ( bvhContents ) bvhContents.dispose();

}

}

function dereferenceIndex( geometry, indirectBuffer, target ) {

const index = geometry.index;
for ( let i = 0, l = indirectBuffer.length; i < l; i ++ ) {

const iv = indirectBuffer[ i ];
let nv = index ? index.getX( iv ) : iv;
target.setX( i, nv );

}

}
162 changes: 162 additions & 0 deletions test/Math.OBB.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { Vector3, Triangle, Plane } from 'three';
import { OrientedBox } from '../src/math/OrientedBox.js';
import { setRandomVector, getRandomOrientation } from './utils.js';

describe( 'OBB Intersections', () => {

let box, center;
beforeEach( () => {

box = new OrientedBox();
box.min.set( - 1, - 1, - 1 );
box.max.set( 1, 1, 1 );
getRandomOrientation( box.matrix, 10 );
box.needsUpdate = true;

center = new Vector3();
center.setFromMatrixPosition( box.matrix );

} );

it( 'should intersect triangles with a vertex inside', () => {

const triangle = new Triangle();
for ( let i = 0; i < 100; i ++ ) {

const fields = [ 'a', 'b', 'c' ];
const i0 = i % 3;
const i1 = ( i + 1 ) % 3;
const i2 = ( i + 2 ) % 3;

setRandomVector( triangle[ fields[ i0 ] ], Math.random() - 0.0001 )
.add( center );

setRandomVector( triangle[ fields[ i1 ] ], 3 + 0.0001 + Math.random() )
.add( center );

setRandomVector( triangle[ fields[ i2 ] ], 3 + 0.0001 + Math.random() )
.add( center );

expect( box.intersectsTriangle( triangle ) ).toBe( true );

}

} );

it( 'should intersect triangles with two vertices inside', () => {

const triangle = new Triangle();
for ( let i = 0; i < 100; i ++ ) {

const fields = [ 'a', 'b', 'c' ];
const i0 = i % 3;
const i1 = ( i + 1 ) % 3;
const i2 = ( i + 2 ) % 3;

setRandomVector( triangle[ fields[ i0 ] ], Math.random() - 0.0001 )
.add( center );

setRandomVector( triangle[ fields[ i1 ] ], Math.random() - 0.0001 )
.add( center );

setRandomVector( triangle[ fields[ i2 ] ], 3 + 0.0001 + Math.random() )
.add( center );

expect( box.intersectsTriangle( triangle ) ).toBe( true );

}

} );

it( 'should intersect triangles with all vertices inside', () => {

const triangle = new Triangle();
for ( let i = 0; i < 100; i ++ ) {

const fields = [ 'a', 'b', 'c' ];
const i0 = i % 3;
const i1 = ( i + 1 ) % 3;
const i2 = ( i + 2 ) % 3;

setRandomVector( triangle[ fields[ i0 ] ], Math.random() - 0.0001 )
.add( center );

setRandomVector( triangle[ fields[ i1 ] ], Math.random() - 0.0001 )
.add( center );

setRandomVector( triangle[ fields[ i2 ] ], Math.random() - 0.0001 )
.add( center );

expect( box.intersectsTriangle( triangle ) ).toBe( true );

}

} );


it( 'should intersect triangles that cut across', () => {

const triangle = new Triangle();
for ( let i = 0; i < 100; i ++ ) {

const fields = [ 'a', 'b', 'c' ];
const i0 = i % 3;
const i1 = ( i + 1 ) % 3;
const i2 = ( i + 2 ) % 3;

setRandomVector( triangle[ fields[ i0 ] ], 3 + 0.0001 + Math.random() );

triangle[ fields[ i1 ] ]
.copy( triangle[ fields[ i0 ] ] )
.multiplyScalar( - 1 )
.add( center );

triangle[ fields[ i0 ] ]
.add( center );

setRandomVector( triangle[ fields[ i2 ] ], 3 + 0.0001 + Math.random() )
.add( center );

expect( box.intersectsTriangle( triangle ) ).toBe( true );

}

} );

it( 'should not intersect triangles outside sphere', () => {

const plane = new Plane();
const vec = new Vector3();

const triangle = new Triangle();
for ( let i = 0; i < 100; i ++ ) {

// project the triangle out onto a plane
setRandomVector( plane.normal, 1 );
plane.setFromNormalAndCoplanarPoint( plane.normal, center );
plane.constant += ( Math.sign( Math.random() - 0.5 ) || 1 ) * 5.001;

const fields = [ 'a', 'b', 'c' ];
const i0 = i % 3;
const i1 = ( i + 1 ) % 3;
const i2 = ( i + 2 ) % 3;

setRandomVector( vec, 10 * Math.random() )
.add( center );
plane.projectPoint( vec, triangle[ fields[ i0 ] ] );

setRandomVector( vec, 10 * Math.random() )
.add( center );
plane.projectPoint( vec, triangle[ fields[ i1 ] ] );

setRandomVector( vec, 10 * Math.random() )
.add( center );
plane.projectPoint( vec, triangle[ fields[ i2 ] ] );

expect( box.intersectsTriangle( triangle ) ).toBe( false );

}

} );

} );
Loading

0 comments on commit d9e85e1

Please sign in to comment.