download
raw
5.02 kB
import {
DataTexture,
FloatType,
UnsignedIntType,
RGBAFormat,
RGIntegerFormat,
NearestFilter,
BufferAttribute,
} from 'three';
import {
FloatVertexAttributeTexture,
UIntVertexAttributeTexture,
} from './VertexAttributeTexture.js';
import { BYTES_PER_NODE } from '../core/Constants.js';
import {
BOUNDING_DATA_INDEX,
COUNT,
IS_LEAF,
RIGHT_NODE,
OFFSET,
SPLIT_AXIS,
} from '../core/utils/nodeBufferUtils.js';
import { getIndexArray, getVertexCount } from '../core/build/geometryUtils.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
) {
if ( geometry.index ) {
this._cachedIndexAttr = geometry.index.clone();
} else {
const array = getIndexArray( getVertexCount( geometry ) );
this._cachedIndexAttr = new BufferAttribute( array, 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 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;
if ( roots.length !== 1 ) {
throw new Error( 'MeshBVHUniformStruct: Multi-root BVHs not supported.' );
}
const root = roots[ 0 ];
const uint16Array = new Uint16Array( root );
const uint32Array = new Uint32Array( root );
const float32Array = new Float32Array( root );
// Both bounds need two elements per node so compute the height so it's twice as long as
// the width so we can expand the row by two and still have a square texture
const nodeCount = root.byteLength / BYTES_PER_NODE;
const boundsDimension = 2 * Math.ceil( Math.sqrt( nodeCount / 2 ) );
const boundsArray = new Float32Array( 4 * boundsDimension * boundsDimension );
const contentsDimension = Math.ceil( Math.sqrt( nodeCount ) );
const contentsArray = new Uint32Array( 2 * contentsDimension * contentsDimension );
for ( let i = 0; i < nodeCount; i ++ ) {
const nodeIndex32 = i * BYTES_PER_NODE / 4;
const nodeIndex16 = nodeIndex32 * 2;
const boundsIndex = BOUNDING_DATA_INDEX( nodeIndex32 );
for ( let b = 0; b < 3; b ++ ) {
boundsArray[ 8 * i + 0 + b ] = float32Array[ boundsIndex + 0 + b ];
boundsArray[ 8 * i + 4 + b ] = float32Array[ boundsIndex + 3 + b ];
}
if ( IS_LEAF( nodeIndex16, uint16Array ) ) {
const count = COUNT( nodeIndex16, uint16Array );
const offset = OFFSET( nodeIndex32, uint32Array );
const mergedLeafCount = 0xffff0000 | count;
contentsArray[ i * 2 + 0 ] = mergedLeafCount;
contentsArray[ i * 2 + 1 ] = offset;
} else {
const rightIndex = 4 * RIGHT_NODE( nodeIndex32, uint32Array ) / BYTES_PER_NODE;
const splitAxis = SPLIT_AXIS( nodeIndex32, uint32Array );
contentsArray[ i * 2 + 0 ] = splitAxis;
contentsArray[ i * 2 + 1 ] = rightIndex;
}
}
boundsTexture.image.data = boundsArray;
boundsTexture.image.width = boundsDimension;
boundsTexture.image.height = boundsDimension;
boundsTexture.format = RGBAFormat;
boundsTexture.type = FloatType;
boundsTexture.internalFormat = 'RGBA32F';
boundsTexture.minFilter = NearestFilter;
boundsTexture.magFilter = NearestFilter;
boundsTexture.generateMipmaps = false;
boundsTexture.needsUpdate = true;
boundsTexture.dispose();
contentsTexture.image.data = contentsArray;
contentsTexture.image.width = contentsDimension;
contentsTexture.image.height = contentsDimension;
contentsTexture.format = RGIntegerFormat;
contentsTexture.type = UnsignedIntType;
contentsTexture.internalFormat = 'RG32UI';
contentsTexture.minFilter = NearestFilter;
contentsTexture.magFilter = NearestFilter;
contentsTexture.generateMipmaps = false;
contentsTexture.needsUpdate = true;
contentsTexture.dispose();
}

Xet Storage Details

Size:
5.02 kB
·
Xet hash:
ff87d2616158f5cf72e0666d798413472820dcbd464f64d71bc8e4fc74a14c26

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.