浏览代码

Merge pull request #19528 from Mugen87/dev45

BufferGeometry: Retain interleaved data when using .toJSON().
Mr.doob 5 年之前
父节点
当前提交
ef33d40022

+ 2 - 2
src/core/BufferGeometry.js

@@ -1026,7 +1026,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 			const attribute = attributes[ key ];
 
-			const attributeData = attribute.toJSON();
+			const attributeData = attribute.toJSON( data.data, false );
 
 			if ( attribute.name !== '' ) attributeData.name = attribute.name;
 
@@ -1047,7 +1047,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 				const attribute = attributeArray[ i ];
 
-				const attributeData = attribute.toJSON();
+				const attributeData = attribute.toJSON( data.data, false );
 
 				if ( attribute.name !== '' ) attributeData.name = attribute.name;
 

+ 7 - 0
src/core/InterleavedBuffer.d.ts

@@ -16,6 +16,7 @@ export class InterleavedBuffer {
 	length: number;
 	count: number;
 	needsUpdate: boolean;
+	uuid: string;
 
 	setUsage( usage: Usage ): InterleavedBuffer;
 	clone(): this;
@@ -26,5 +27,11 @@ export class InterleavedBuffer {
 		index2: number
 	): InterleavedBuffer;
 	set( value: ArrayLike<number>, index: number ): InterleavedBuffer;
+	toJSON( data: object ): {
+		uuid: string,
+		buffer: string,
+		type: string,
+		stride: number
+	};
 
 }

+ 36 - 1
src/core/InterleavedBuffer.js

@@ -1,3 +1,4 @@
+import { MathUtils } from '../math/MathUtils.js';
 import { StaticDrawUsage } from '../constants.js';
 
 /**
@@ -15,6 +16,8 @@ function InterleavedBuffer( array, stride ) {
 
 	this.version = 0;
 
+	this.uuid = MathUtils.generateUUID();
+
 }
 
 Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
@@ -89,9 +92,41 @@ Object.assign( InterleavedBuffer.prototype, {
 
 		return this;
 
+	},
+
+	toJSON: function ( data ) {
+
+		if ( data.arrayBuffers === undefined ) {
+
+			data.arrayBuffers = {};
+
+		}
+
+		// generate UUID for array buffer if necessary
+
+		if ( this.array.buffer._uuid === undefined ) {
+
+			this.array.buffer._uuid = MathUtils.generateUUID();
+
+		}
+
+		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
+
+			data.arrayBuffers[ this.array.buffer._uuid ] = Array.prototype.slice.call( new Uint32Array( this.array.buffer ) );
+
+		}
+
+		//
+
+		return {
+			uuid: this.uuid,
+			buffer: this.array.buffer._uuid,
+			type: this.array.constructor.name,
+			stride: this.stride
+		};
+
 	}
 
 } );
 
-
 export { InterleavedBuffer };

+ 4 - 3
src/core/InterleavedBufferAttribute.d.ts

@@ -48,10 +48,11 @@ export class InterleavedBufferAttribute {
 		z: number,
 		w: number
 	): InterleavedBufferAttribute;
-	toJSON(): {
+	toJSON( data: object, deinterleave: boolean ): {
+		isInterleavedBufferAttribute: true,
 		itemSize: number,
-		type: string,
-		array: number[],
+		data: string,
+		offset: number,
 		normalized: boolean
 	};
 

+ 43 - 15
src/core/InterleavedBufferAttribute.js

@@ -179,32 +179,60 @@ Object.assign( InterleavedBufferAttribute.prototype, {
 
 	},
 
-	toJSON: function () {
+	toJSON: function ( data = null, deinterleave = true ) {
 
-		console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
+		if ( deinterleave === true ) {
 
-		const array = [];
+			console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.' );
 
-		for ( let i = 0; i < this.count; i ++ ) {
+			const array = [];
 
-			const index = i * this.data.stride + this.offset;
+			for ( let i = 0; i < this.count; i ++ ) {
 
-			for ( let j = 0; j < this.itemSize; j ++ ) {
+				const index = i * this.data.stride + this.offset;
 
-				array.push( this.data.array[ index + j ] );
+				for ( let j = 0; j < this.itemSize; j ++ ) {
+
+					array.push( this.data.array[ index + j ] );
+
+				}
 
 			}
 
-		}
+			// deinterleave data and save it as an ordinary buffer attribute for now
+
+			return {
+				itemSize: this.itemSize,
+				type: this.array.constructor.name,
+				array: array,
+				normalized: this.normalized
+			};
+
+		} else {
 
-		// deinterleave data and save it as an ordinary buffer attribute for now
+			// save as true interlaved attribtue
 
-		return {
-			itemSize: this.itemSize,
-			type: this.array.constructor.name,
-			array: array,
-			normalized: this.normalized
-		};
+			if ( data.interleavedBuffers === undefined ) {
+
+				data.interleavedBuffers = {};
+
+			}
+
+			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
+
+				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
+
+			}
+
+			return {
+				isInterleavedBufferAttribute: true,
+				itemSize: this.itemSize,
+				data: this.data.uuid,
+				offset: this.offset,
+				normalized: this.normalized
+			};
+
+		}
 
 	}
 

+ 67 - 5
src/loaders/BufferGeometryLoader.js

@@ -6,6 +6,8 @@ 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';
 
 /**
  * @author mrdoob / http://mrdoob.com/
@@ -55,6 +57,43 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 	parse: function ( 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 = new TYPED_ARRAYS[ 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;
@@ -71,9 +110,21 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype
 		for ( const key in attributes ) {
 
 			const attribute = attributes[ key ];
-			const typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
-			const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
-			const bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
+			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 = new TYPED_ARRAYS[ 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;
 			geometry.setAttribute( key, bufferAttribute );
 
@@ -92,9 +143,20 @@ BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype
 				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
 
 					const attribute = attributeArray[ i ];
-					const typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
+					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 = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
+						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
+
+					}
 
-					const bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
 					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
 					array.push( bufferAttribute );