Browse Source

GLTFExporter: WIP allow images to be stored in bufferViews.

Don McCurdy 7 years ago
parent
commit
e4063d8b91
1 changed files with 77 additions and 46 deletions
  1. 77 46
      examples/js/exporters/GLTFExporter.js

+ 77 - 46
examples/js/exporters/GLTFExporter.js

@@ -221,17 +221,17 @@ THREE.GLTFExporter.prototype = {
 		}
 
 		/**
-		 * Returns a buffer aligned to 4-byte boundary. 
-		 * 
+		 * Returns a buffer aligned to 4-byte boundary.
+		 *
 		 * @param {ArrayBuffer} arrayBuffer Buffer to pad
 		 * @returns {ArrayBuffer} The same buffer if it's already aligned to 4-byte boundary or a new buffer
 		 */
 		function getPaddedArrayBuffer( arrayBuffer ) {
-						
+
 			var paddedLength = getPaddedBufferSize( arrayBuffer.byteLength );
-			
+
 			if (paddedLength !== arrayBuffer.byteLength ) {
-			
+
 				var paddedBuffer = new ArrayBuffer( paddedLength );
 				new Uint8Array( paddedBuffer ).set(new Uint8Array(arrayBuffer));
 				return paddedBuffer;
@@ -244,11 +244,9 @@ THREE.GLTFExporter.prototype = {
 
 		/**
 		 * Process a buffer to append to the default one.
-		 * @param  {THREE.BufferAttribute} attribute     Attribute to store
-		 * @param  {Integer} componentType Component type (Unsigned short, unsigned int or float)
-		 * @return {Integer}               Index of the buffer created (Currently always 0)
+		 * @param {ArrayBuffer} buffer ArrayBuffer to store
 		 */
-		function processBuffer( attribute, componentType, start, count ) {
+		function processBuffer( buffer ) {
 
 			if ( ! outputJSON.buffers ) {
 
@@ -265,10 +263,34 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
-			var offset = 0;
-			var componentSize = componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ? 2 : 4;
+			// We just use one buffer
+			// TODO(donmccurdy): This isn't a DataView now.
+			dataViews.push( buffer );
+
+			// Always using just one buffer
+			return 0;
+
+		}
+
+		/**
+		 * Process and generate a BufferView
+		 * @param  {THREE.BufferAttribute} attribute
+		 * @param  {number} componentType
+		 * @param  {number} start
+		 * @param  {number} count
+		 * @param  {number} target (Optional) Target usage of the BufferView
+		 * @return {Object}
+		 */
+		function processBufferView( attribute, componentType, start, count, target ) {
+
+			if ( ! outputJSON.bufferViews ) {
+
+				outputJSON.bufferViews = [];
+
+			}
 
 			// Create a new dataview and dump the attribute's array into it
+			var componentSize = componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ? 2 : 4;
 			var byteLength = count * attribute.itemSize * componentSize;
 
 			// adjust required size of array buffer with padding
@@ -276,11 +298,14 @@ THREE.GLTFExporter.prototype = {
 			byteLength = getPaddedBufferSize( byteLength );
 
 			var dataView = new DataView( new ArrayBuffer( byteLength ) );
+			var offset = 0;
 
 			for ( var i = start; i < start + count; i ++ ) {
 
 				for ( var a = 0; a < attribute.itemSize; a ++ ) {
 
+					// TODO(donmccurdy): Fails on InterleavedBufferAttribute, and could
+					// probably be faster for normal BufferAttribute.
 					var value = attribute.array[ i * attribute.itemSize + a ];
 
 					if ( componentType === WEBGL_CONSTANTS.FLOAT ) {
@@ -303,39 +328,9 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
-			// We just use one buffer
-			dataViews.push( dataView );
-
-			// Always using just one buffer
-			return 0;
-
-		}
-
-		/**
-		 * Process and generate a BufferView
-		 * @param  {THREE.BufferAttribute} data
-		 * @param  {number} componentType
-		 * @param  {number} start
-		 * @param  {number} count
-		 * @param  {number} target (Optional) Target usage of the BufferView
-		 * @return {Object}
-		 */
-		function processBufferView( data, componentType, start, count, target ) {
-
-			if ( ! outputJSON.bufferViews ) {
-
-				outputJSON.bufferViews = [];
-
-			}
-
-			var componentSize = componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ? 2 : 4;
-
-			// Create a new dataview and dump the attribute's array into it
-			var byteLength = count * data.itemSize * componentSize;
-
 			var gltfBufferView = {
 
-				buffer: processBuffer( data, componentType, start, count ),
+				buffer: processBuffer( dataView.buffer ),
 				byteOffset: byteOffset,
 				byteLength: byteLength
 
@@ -346,7 +341,7 @@ THREE.GLTFExporter.prototype = {
 			if ( target === WEBGL_CONSTANTS.ARRAY_BUFFER ) {
 
 				// Only define byteStride for vertex attributes.
-				gltfBufferView.byteStride = data.itemSize * componentSize;
+				gltfBufferView.byteStride = attribute.itemSize * componentSize;
 
 			}
 
@@ -354,7 +349,7 @@ THREE.GLTFExporter.prototype = {
 
 			outputJSON.bufferViews.push( gltfBufferView );
 
-			// @TODO Ideally we'll have just two bufferviews: 0 is for vertex attributes, 1 for indices
+			// @TODO Merge bufferViews where possible.
 			var output = {
 
 				id: outputJSON.bufferViews.length - 1,
@@ -366,6 +361,35 @@ THREE.GLTFExporter.prototype = {
 
 		}
 
+		/**
+		 * Process and generate a BufferView from an image.
+		 * @param {ImageData} data
+		 * @return {number}
+		 */
+		function processBufferViewImage ( image ) {
+
+			if ( ! outputJSON.bufferViews ) {
+
+				outputJSON.bufferViews = [];
+
+			}
+
+			var byteLength = image.data.buffer.byteLength;
+
+			outputJSON.bufferViews.push( {
+
+				buffer: processBuffer( image.data.buffer ),
+				byteOffset: byteOffset,
+				byteLength: byteLength
+
+			} );
+
+			byteOffset += byteLength;
+
+			return outputJSON.bufferViews.length - 1;
+
+		}
+
 		/**
 		 * Process attribute to generate an accessor
 		 * @param  {THREE.BufferAttribute} attribute Attribute to process
@@ -500,9 +524,16 @@ THREE.GLTFExporter.prototype = {
 
 				ctx.drawImage( map.image, 0, 0, canvas.width, canvas.height );
 
-				// @TODO Embed in { bufferView } if options.binary set.
+				if ( options.binary === true ) {
 
-				gltfImage.uri = canvas.toDataURL( mimeType );
+					var imageData = ctx.getImageData( 0, 0, canvas.width, canvas.height );
+					gltfImage.bufferView = processBufferViewImage( imageData );
+
+				} else {
+
+					gltfImage.uri = canvas.toDataURL( mimeType );
+
+				}
 
 			} else {