Browse Source

Merge pull request #5969 from benaadams/DynamicBufferAttribute2

Dynamic buffer attribute
Mr.doob 10 years ago
parent
commit
b2d1e5d181
3 changed files with 181 additions and 9 deletions
  1. 4 3
      src/core/BufferAttribute.js
  2. 155 0
      src/core/DynamicBufferAttribute.js
  3. 22 6
      src/renderers/WebGLRenderer.js

+ 4 - 3
src/core/BufferAttribute.js

@@ -34,9 +34,10 @@ THREE.BufferAttribute.prototype = {
 
 	},
 
-	set: function ( value ) {
+	set: function ( value, offset ) {
 
-		this.array.set( value );
+		offset !== undefined ? offset : offset = 0;
+		this.array.set( value, offset );
 
 		return this;
 
@@ -101,7 +102,7 @@ THREE.BufferAttribute.prototype = {
 		return this;
 
 	},
-
+	
 	clone: function () {
 
 		return new THREE.BufferAttribute( new this.array.constructor( this.array ), this.itemSize );

+ 155 - 0
src/core/DynamicBufferAttribute.js

@@ -0,0 +1,155 @@
+/**
+ * @author benaadams / https://twitter.com/ben_a_adams
+ */
+
+THREE.DynamicBufferAttribute = function ( array, itemSize ) {
+
+	THREE.BufferAttribute.call( this, array, itemSize );
+
+	this.updateRange = { offset: 0, count: -1 };
+
+};
+
+THREE.DynamicBufferAttribute.prototype = {
+
+	constructor: THREE.DynamicBufferAttribute,
+
+	get length() {
+
+		return this.array.length;
+
+	},
+
+	copyAt: function ( index1, attribute, index2 ) {
+
+		index1 *= this.itemSize;
+		index2 *= attribute.itemSize;
+
+		for ( var i = 0, l = this.itemSize; i < l; i++ ) {
+
+			this.array[index1 + i] = attribute.array[index2 + i];
+
+		}
+
+		this.markForUpdate( index1, this.itemSize );
+
+	},
+
+	set: function ( value, offset ) {
+
+		offset !== undefined ? offset : offset = 0;
+
+		this.array.set( value, offset );
+
+		this.markForUpdate( offset, value.length );
+
+		return this;
+
+	},
+
+	setX: function ( index, x ) {
+
+		index *= this.itemSize;
+
+		this.array[index] = x;
+
+		this.markForUpdate( index, 1 );
+
+		return this;
+
+	},
+
+	setY: function ( index, y ) {
+
+		index = index * this.itemSize + 1;
+
+		this.array[index * this.itemSize + 1] = y;
+
+		this.markForUpdate( index, 1 );
+
+		return this;
+
+	},
+
+	setZ: function ( index, z ) {
+
+		index = index * this.itemSize + 2;
+
+		this.array[index * this.itemSize + 2] = z;
+
+		this.markForUpdate( index, 1 );
+
+		return this;
+
+	},
+
+	setXY: function ( index, x, y ) {
+
+		index *= this.itemSize;
+
+		this.array[index] = x;
+		this.array[index + 1] = y;
+
+		this.markForUpdate( index, 2 );
+
+		return this;
+
+	},
+
+	setXYZ: function ( index, x, y, z ) {
+
+		index *= this.itemSize;
+
+		this.array[index] = x;
+		this.array[index + 1] = y;
+		this.array[index + 2] = z;
+
+		this.markForUpdate( index, 3 );
+
+		return this;
+
+	},
+
+	setXYZW: function ( index, x, y, z, w ) {
+
+		index *= this.itemSize;
+
+		this.array[index] = x;
+		this.array[index + 1] = y;
+		this.array[index + 2] = z;
+		this.array[index + 3] = w;
+
+		this.markForUpdate( index, 4 );
+
+		return this;
+
+	},
+
+	markForUpdate: function ( offset, count ) {
+
+		if ( this.updateRange.count <= 0 ) {
+
+			this.updateRange.offset = offset;
+			this.updateRange.count = count;
+
+		} else {
+
+			var end0 = offset + count;
+			var end1 = this.updateRange.offset + this.updateRange.count;
+
+			this.updateRange.offset = ( offset <= this.updateRange.offset ) ? offset : this.updateRange.offset;
+			this.updateRange.count = ( ( end0 >= end1 ) ? end0 : end1 ) - this.updateRange.offset;
+
+		}
+
+		return this;
+
+	},
+
+	clone: function () {
+
+		return new THREE.DynamicBufferAttribute( new this.array.constructor( this.array ), this.itemSize );
+
+	}
+
+};

+ 22 - 6
src/renderers/WebGLRenderer.js

@@ -3939,20 +3939,36 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				var key = attributesKeys[ i ];
 				var attribute = attributes[ key ];
+				var bufferType = ( key === 'index' ) ? _gl.ELEMENT_ARRAY_BUFFER : _gl.ARRAY_BUFFER;
 
 				if ( attribute.buffer === undefined ) {
 
 					attribute.buffer = _gl.createBuffer();
-					attribute.needsUpdate = true;
-
-				}
+					_gl.bindBuffer( bufferType, attribute.buffer );
+					_gl.bufferData( bufferType, attribute.array, ( attribute instanceof THREE.DynamicBufferAttribute ) ? _gl.DYNAMIC_DRAW : _gl.STATIC_DRAW );
 
-				if ( attribute.needsUpdate === true ) {
+					attribute.needsUpdate = false;
 
-					var bufferType = ( key === 'index' ) ? _gl.ELEMENT_ARRAY_BUFFER : _gl.ARRAY_BUFFER;
+				} else if ( attribute.needsUpdate === true ) {
 
 					_gl.bindBuffer( bufferType, attribute.buffer );
-					_gl.bufferData( bufferType, attribute.array, _gl.STATIC_DRAW );
+
+					if ( attribute.updateRange === undefined || attribute.updateRange.count === -1 ) { // Not using update ranges
+
+						_gl.bufferSubData( bufferType, 0, attribute.array );
+
+					} else if ( attribute.updateRange.count === 0 ) {
+
+						console.error( 'THREE.WebGLRenderer.updateObject: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' );
+
+					} else {
+
+						_gl.bufferSubData( bufferType, attribute.updateRange.offset * attribute.array.BYTES_PER_ELEMENT,
+										   attribute.array.subarray( attribute.updateRange.offset, attribute.updateRange.offset + attribute.updateRange.count ) );
+
+						attribute.updateRange.count = 0; // reset range
+
+					}
 
 					attribute.needsUpdate = false;