import { Sphere } from '../math/Sphere.js';
import { Vector3 } from '../math/Vector3.js';
import { BufferAttribute } from '../core/BufferAttribute.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { FileLoader } from './FileLoader.js';
import { Loader } from './Loader.js';
import { InstancedBufferGeometry } from '../core/InstancedBufferGeometry.js';
import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';
import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js';
import { InterleavedBuffer } from '../core/InterleavedBuffer.js';
import { getTypedArray } from '../utils.js';
class BufferGeometryLoader extends Loader {
constructor( manager ) {
super( manager );
}
load( url, onLoad, onProgress, onError ) {
const scope = this;
const loader = new FileLoader( scope.manager );
loader.setPath( scope.path );
loader.setRequestHeader( scope.requestHeader );
loader.setWithCredentials( scope.withCredentials );
loader.load( url, function ( text ) {
try {
onLoad( scope.parse( JSON.parse( text ) ) );
} catch ( e ) {
if ( onError ) {
onError( e );
} else {
console.error( e );
}
scope.manager.itemError( url );
}
}, onProgress, onError );
}
parse( json ) {
const interleavedBufferMap = {};
const arrayBufferMap = {};
function getInterleavedBuffer( json, uuid ) {
if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
const interleavedBuffers = json.interleavedBuffers;
const interleavedBuffer = interleavedBuffers[ uuid ];
const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
const array = getTypedArray( interleavedBuffer.type, buffer );
const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
ib.uuid = interleavedBuffer.uuid;
interleavedBufferMap[ uuid ] = ib;
return ib;
}
function getArrayBuffer( json, uuid ) {
if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
const arrayBuffers = json.arrayBuffers;
const arrayBuffer = arrayBuffers[ uuid ];
const ab = new Uint32Array( arrayBuffer ).buffer;
arrayBufferMap[ uuid ] = ab;
return ab;
}
const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
const index = json.data.index;
if ( index !== undefined ) {
const typedArray = getTypedArray( index.type, index.array );
geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
}
const attributes = json.data.attributes;
for ( const key in attributes ) {
const attribute = attributes[ key ];
let bufferAttribute;
if ( attribute.isInterleavedBufferAttribute ) {
const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
} else {
const typedArray = getTypedArray( attribute.type, attribute.array );
const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
}
if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
geometry.setAttribute( key, bufferAttribute );
}
const morphAttributes = json.data.morphAttributes;
if ( morphAttributes ) {
for ( const key in morphAttributes ) {
const attributeArray = morphAttributes[ key ];
const array = [];
for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
const attribute = attributeArray[ i ];
let bufferAttribute;
if ( attribute.isInterleavedBufferAttribute ) {
const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
} else {
const typedArray = getTypedArray( attribute.type, attribute.array );
bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
}
if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
array.push( bufferAttribute );
}
geometry.morphAttributes[ key ] = array;
}
}
const morphTargetsRelative = json.data.morphTargetsRelative;
if ( morphTargetsRelative ) {
geometry.morphTargetsRelative = true;
}
const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
if ( groups !== undefined ) {
for ( let i = 0, n = groups.length; i !== n; ++ i ) {
const group = groups[ i ];
geometry.addGroup( group.start, group.count, group.materialIndex );
}
}
const boundingSphere = json.data.boundingSphere;
if ( boundingSphere !== undefined ) {
const center = new Vector3();
if ( boundingSphere.center !== undefined ) {
center.fromArray( boundingSphere.center );
}
geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
}
if ( json.name ) geometry.name = json.name;
if ( json.userData ) geometry.userData = json.userData;
return geometry;
}
}
export { BufferGeometryLoader };