PlaneBufferGeometry
345654
function ( width, height, widthSegments, heightSegments ) {

	BufferGeometry.call( this );

	this.type = '';

	this.parameters = {
		width: width,
		height: height,
		widthSegments: widthSegments,
		heightSegments: heightSegments
	};

	width = width || 1;
	height = height || 1;

	var width_half = width / 2;
	var height_half = height / 2;

	var gridX = Math.floor( widthSegments ) || 1;
	var gridY = Math.floor( heightSegments ) || 1;

	var gridX1 = gridX + 1;
	var gridY1 = gridY + 1;

	var segment_width = width / gridX;
	var segment_height = height / gridY;

	var ix, iy;

	// buffers

	var indices = [];
	var vertices = [];
	var normals = [];
	var uvs = [];

	// generate vertices, normals and uvs

	for ( iy = 0; iy < gridY1; iy ++ ) {

		var y = iy * segment_height - height_half;

		for ( ix = 0; ix < gridX1; ix ++ ) {

			var x = ix * segment_width - width_half;

			vertices.push( x, - y, 0 );

			normals.push( 0, 0, 1 );

			uvs.push( ix / gridX );
			uvs.push( 1 - ( iy / gridY ) );

		}

	}

	// indices

	for ( iy = 0; iy < gridY; iy ++ ) {

		for ( ix = 0; ix < gridX; ix ++ ) {

			var a = ix + gridX1 * iy;
			var b = ix + gridX1 * ( iy + 1 );
			var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
			var d = ( ix + 1 ) + gridX1 * iy;

			// faces

			indices.push( a, b, d );
			indices.push( b, c, d );

		}

	}

	// build geometry

	this.setIndex( indices );
	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );

}
920634
def plot_plane(where="back", texture=None):
    
    fig = gcf()
    xmin, xmax = fig.xlim
    ymin, ymax = fig.ylim
    zmin, zmax = fig.zlim
    if where == "back":
        x = [xmin, xmax, xmax, xmin]
        y = [ymin, ymin, ymax, ymax]
        z = [zmin, zmin, zmin, zmin]
    if where == "front":
        x = [xmin, xmax, xmax, xmin][::-1]
        y = [ymin, ymin, ymax, ymax]
        z = [zmax, zmax, zmax, zmax]
    if where == "left":
        x = [xmin, xmin, xmin, xmin]
        y = [ymin, ymin, ymax, ymax]
        z = [zmin, zmax, zmax, zmin]
    if where == "right":
        x = [xmax, xmax, xmax, xmax]
        y = [ymin, ymin, ymax, ymax]
        z = [zmin, zmax, zmax, zmin][::-1]
    if where == "top":
        x = [xmin, xmax, xmax, xmin]
        y = [ymax, ymax, ymax, ymax]
        z = [zmax, zmax, zmin, zmin]
    if where == "bottom":
        x = [xmax, xmin, xmin, xmax]
        y = [ymin, ymin, ymin, ymin]
        z = [zmin, zmin, zmax, zmax]
    triangles = [(0, 1, 2), (0, 2, 3)]
    u = v = None
    if texture is not None:
        u = [0.0, 1.0, 1.0, 0.0]
        v = [0.0, 0.0, 1.0, 1.0]
    mesh = plot_trisurf(x, y, z, triangles, texture=texture, u=u, v=v)
    return mesh
337122
function Plane3D( a , b , c , d ) {
	var self = Object.create( Plane3D.prototype ) ;

	self.normal = new Vector3D( a , b , c ) ;
	self.d = + d ;
	self.normalizeCheck() ;

	return self ;
}
108330
function () {
      var data = this.data;
      var material = this.material = new THREE.MeshBasicMaterial({color: data.color, opacity: data.opacity, transparent: data.transparent, wireframe: data.debug});
      var geometry = this.geometry = new THREE.PlaneBufferGeometry(data.width, data.height, 3, 3);

      var textureLoader = new THREE.TextureLoader();
      this.plane = new THREE.Mesh(geometry, material);
      this.el.setObject3D('mesh', this.plane);
      this.textureSrc = null;
    }
492487
def shape(self):
        
        if self.color_buffer is not None:
            return self.color_buffer.shape[:2]  # in case its a texture
        if self.depth_buffer is not None:
            return self.depth_buffer.shape[:2]
        if self.stencil_buffer is not None:
            return self.stencil_buffer.shape[:2]
        raise RuntimeError('FrameBuffer without buffers has undefined shape')
786791
function ( radius, segments, thetaStart, thetaLength ) {

	BufferGeometry.call( this );

	this.type = '';

	this.parameters = {
		radius: radius,
		segments: segments,
		thetaStart: thetaStart,
		thetaLength: thetaLength
	};

	radius = radius || 1;
	segments = segments !== undefined ? Math.max( 3, segments ) : 8;

	thetaStart = thetaStart !== undefined ? thetaStart : 0;
	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;

	// buffers

	var indices = [];
	var vertices = [];
	var normals = [];
	var uvs = [];

	// helper variables

	var i, s;
	var vertex = new Vector3();
	var uv = new Vector2();

	// center point

	vertices.push( 0, 0, 0 );
	normals.push( 0, 0, 1 );
	uvs.push( 0.5, 0.5 );

	for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {

		var segment = thetaStart + s / segments * thetaLength;

		// vertex

		vertex.x = radius * Math.cos( segment );
		vertex.y = radius * Math.sin( segment );

		vertices.push( vertex.x, vertex.y, vertex.z );

		// normal

		normals.push( 0, 0, 1 );

		// uvs

		uv.x = ( vertices[ i ] / radius + 1 ) / 2;
		uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;

		uvs.push( uv.x, uv.y );

	}

	// indices

	for ( i = 1; i <= segments; i ++ ) {

		indices.push( i, i + 1, 0 );

	}

	// build geometry

	this.setIndex( indices );
	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );

}
897985
function Animation() {
  // the number of times the prefabGeometry will be repeated
  const prefabs = [
    new THREE.TorusBufferGeometry(4, 1),
    new THREE.TetrahedronGeometry(4),
    new THREE.IcosahedronGeometry(4),
  ];
  const repeatCount = 20000;

  const geometry = new BAS.MultiPrefabBufferGeometry(prefabs, repeatCount);

  const duration = 1.0;
  const maxPrefabDelay = 0.5;

  // used in the Animation.animate function below
  this.totalDuration = duration + maxPrefabDelay;

  geometry.createAttribute('aDelayDuration', 2, function(data) {
    data[0] = Math.random() * maxPrefabDelay;
    data[1] = duration;
  });

  const aStartPosition = geometry.createAttribute('aStartPosition', 3);
  const aEndPosition = geometry.createAttribute('aEndPosition', 3);

  const startPosition = new THREE.Vector3();
  const endPosition = new THREE.Vector3();
  const range = 100;
  const prefabData = [];

  for (let i = 0; i < repeatCount * prefabs.length; i++) {
    startPosition.x = THREE.Math.randFloatSpread(range) - range * 0.5;
    startPosition.y = THREE.Math.randFloatSpread(range);
    startPosition.z = THREE.Math.randFloatSpread(range);

    endPosition.x = THREE.Math.randFloatSpread(range) + range * 0.5;
    endPosition.y = THREE.Math.randFloatSpread(range);
    endPosition.z = THREE.Math.randFloatSpread(range);

    geometry.setPrefabData(aStartPosition, i, startPosition.toArray(prefabData));
    geometry.setPrefabData(aEndPosition, i, endPosition.toArray(prefabData));
  }

  const axis = new THREE.Vector3();

  geometry.createAttribute('aAxisAngle', 4, function(data) {
    axis.x = THREE.Math.randFloatSpread(2);
    axis.y = THREE.Math.randFloatSpread(2);
    axis.z = THREE.Math.randFloatSpread(2);
    axis.normalize();
    axis.toArray(data);

    data[3] = Math.PI * THREE.Math.randFloat(4.0, 8.0);
  });

  const material = new BAS.StandardAnimationMaterial({
    flatShading: true,
    side: THREE.DoubleSide,
    uniforms: {
      uTime: {value: 0}
    },
    uniformValues: {
      metalness: 0.5,
      roughness: 0.5,
      map: new THREE.TextureLoader().load('../_tex/UV_Grid.jpg')
    },
    vertexFunctions: [
      BAS.ShaderChunk['ease_cubic_in_out'],
      BAS.ShaderChunk['ease_quad_out'],
      BAS.ShaderChunk['quaternion_rotation']
    ],
    vertexParameters: [
      'uniform float uTime;',
      'attribute vec2 aDelayDuration;',
      'attribute vec3 aStartPosition;',
      'attribute vec3 aEndPosition;',
      'attribute vec4 aAxisAngle;'
    ],
    vertexInit: [
      'float tProgress = clamp(uTime - aDelayDuration.x, 0.0, aDelayDuration.y) / aDelayDuration.y;',
      'tProgress = easeCubicInOut(tProgress);',
      'vec4 tQuat = quatFromAxisAngle(aAxisAngle.xyz, aAxisAngle.w * tProgress);'
    ],
    vertexNormal: [
      //'objectNormal = rotateVector(tQuat, objectNormal);'
    ],
    vertexPosition: [
      'transformed = rotateVector(tQuat, transformed);',
      'transformed += mix(aStartPosition, aEndPosition, tProgress);',
    ]
  });

  //geometry.computeVertexNormals();

  geometry.bufferUvs();

  THREE.Mesh.call(this, geometry, material);

  this.frustumCulled = false;
}
84752
def Rectangle(p1=(0, 0, 0), p2=(2, 1, 0), c="k", bc="dg", lw=1, alpha=1, texture=None):
    """"""
    p1 = np.array(p1)
    p2 = np.array(p2)
    pos = (p1 + p2) / 2
    length = abs(p2[0] - p1[0])
    height = abs(p2[1] - p1[1])
    return Plane(pos, [0, 0, -1], length, height, c, bc, alpha, texture)
859460
function EaseSystem(ease) {
  this.ease = ease;

  var rangeX = 100;
  var rangeY = 100;
  var prefabCount = 1000;
  var size = rangeY / prefabCount;

  var prefabGeometry = new THREE.PlaneGeometry(size * 2, size);
  var geometry = new BAS.PrefabBufferGeometry(prefabGeometry, prefabCount);

  var i, j, offset;

  // Animation

  // x = animation delay, y = animation duration
  var aDelayDuration = geometry.createAttribute('aDelayDuration', 3);

  var duration = 2.0;
  var maxPrefabDelay = 1.0;
  var maxVertexDelay = 0.2;

  this.totalDuration = duration + maxPrefabDelay + maxVertexDelay * 2;

  for (i = 0, offset = 0; i < prefabCount; i++) {
    var prefabDelay = THREE.Math.mapLinear(i, 0, prefabCount, 0.0, maxPrefabDelay);

    for (j = 0; j < prefabGeometry.vertices.length; j++) {
      // give top right and bottom right corner of the plane a longer delay
      // this causes the plane to stretch
      aDelayDuration.array[offset    ] = prefabDelay + (2 - j % 2) * maxVertexDelay;
      aDelayDuration.array[offset + 1] = duration;

      offset += 3;
    }
  }

  // Position

  // planes will move from aStartPosition to aEndPosition
  var aStartPosition = geometry.createAttribute('aStartPosition', 3);
  var aEndPosition = geometry.createAttribute('aEndPosition', 3);

  // temp vars so we don't create redundant objects
  var startPosition = new THREE.Vector3();
  var endPosition = new THREE.Vector3();

  for (i = 0, offset = 0; i < prefabCount; i++) {
    // movement over the x axis, y and z are the same
    startPosition.x = -rangeX * 0.5;
    startPosition.y = THREE.Math.mapLinear(i, 0, prefabCount, -rangeY * 0.5, rangeY * 0.5);
    startPosition.z = 0;

    endPosition.x = rangeX * 0.5;
    endPosition.y = startPosition.y;
    endPosition.z = 0;

    // store the same values per prefab
    for (j = 0; j < prefabGeometry.vertices.length; j++) {
      aStartPosition.array[offset    ] = startPosition.x;
      aStartPosition.array[offset + 1] = startPosition.y;
      aStartPosition.array[offset + 2] = startPosition.z;

      aEndPosition.array[offset    ] = endPosition.x;
      aEndPosition.array[offset + 1] = endPosition.y;
      aEndPosition.array[offset + 2] = endPosition.z;

      offset += 3;
    }
  }

  // from names to to camel case (i.e. ease_back_in -> easeBackIn)
  function underscoreToCamelCase(str) {
    return str.replace(/_([a-z])/g, function (g) {return g[1].toUpperCase();});
  }

  var material = new BAS.BasicAnimationMaterial({
    side: THREE.DoubleSide,
    // uniforms for the material
    uniforms: {
      uTime: {type: 'f', value: 0}
    },
    // functions for the vertex shader
    vertexFunctions: [
      // get the easing function definition
      BAS.ShaderChunk[ease]
    ],
    // uniform names must correspond to material.uniforms keys
    // attribute names must correspond to geometry.attribute names
    vertexParameters: [
      'uniform float uTime;',
      'attribute vec2 aDelayDuration;',
      'attribute vec3 aStartPosition;',
      'attribute vec3 aEndPosition;'
    ],
    vertexInit: [
      // all ease functions have two signatures

      // one in the form of easeFunctionName(t, b, c, d)
      // t: time
      // b: begin value
      // c: change in value
      // d: duration
      // which looks like this:
      //'float tTime = clamp(uTime - aDelayDuration.x, 0.0, aDelayDuration.y);',
      //'float tProgress = ' + easeFunctionName + '(tTime, 0.0, 1.0, aDelayDuration.y);',

      // and another in the form of easeFunctionName(p);
      // here p is expected to be in range 0.0 to 1.0
      // which looks like this:
      'float tProgress = clamp(uTime - aDelayDuration.x, 0.0, aDelayDuration.y) / aDelayDuration.y;',
      'tProgress = ' + underscoreToCamelCase(ease) + '(tProgress);'

      // linear progress looks like this:
      //'float tProgress = tTime / aDelayDuration.y;'
    ],
    vertexPosition: [
      // simple linear interpolation between start and end positions
      'transformed += mix(aStartPosition, aEndPosition, tProgress);'
    ]
  });

  THREE.Mesh.call(this, geometry, material);

  this.frustumCulled = false;
}
17620
def conv3x3(in_planes, out_planes, fn, stride=1):
    """"""
    return fn(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=False)
1022235
function ( face, geometry, useCachedAreas ) {

		var vA, vB, vC, vD;

		if ( face instanceof THREE.Face3 ) {

			vA = geometry.vertices[ face.a ];
			vB = geometry.vertices[ face.b ];
			vC = geometry.vertices[ face.c ];

			return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );

		} else if ( face instanceof THREE.Face4 ) {

			vA = geometry.vertices[ face.a ];
			vB = geometry.vertices[ face.b ];
			vC = geometry.vertices[ face.c ];
			vD = geometry.vertices[ face.d ];

			var area1, area2;

			if ( useCachedAreas ) {

				if ( face._area1 && face._area2 ) {

					area1 = face._area1;
					area2 = face._area2;

				} else {

					area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
					area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );

					face._area1 = area1;
					face._area2 = area2;

				}

			} else {

				area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
				area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );

			}

			var r = THREE.GeometryUtils.random() * ( area1 + area2 );

			if ( r < area1 ) {

				return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );

			} else {

				return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );

			}

		}

	}
359119
function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {

	BufferGeometry.call( this );

	this.type = '';

	this.parameters = {
		width: width,
		height: height,
		depth: depth,
		widthSegments: widthSegments,
		heightSegments: heightSegments,
		depthSegments: depthSegments
	};

	var scope = this;

	width = width || 1;
	height = height || 1;
	depth = depth || 1;

	// segments

	widthSegments = Math.floor( widthSegments ) || 1;
	heightSegments = Math.floor( heightSegments ) || 1;
	depthSegments = Math.floor( depthSegments ) || 1;

	// buffers

	var indices = [];
	var vertices = [];
	var normals = [];
	var uvs = [];

	// helper variables

	var numberOfVertices = 0;
	var groupStart = 0;

	// build each side of the box geometry

	buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
	buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
	buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
	buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
	buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
	buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz

	// build geometry

	this.setIndex( indices );
	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );

	function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {

		var segmentWidth = width / gridX;
		var segmentHeight = height / gridY;

		var widthHalf = width / 2;
		var heightHalf = height / 2;
		var depthHalf = depth / 2;

		var gridX1 = gridX + 1;
		var gridY1 = gridY + 1;

		var vertexCounter = 0;
		var groupCount = 0;

		var ix, iy;

		var vector = new Vector3();

		// generate vertices, normals and uvs

		for ( iy = 0; iy < gridY1; iy ++ ) {

			var y = iy * segmentHeight - heightHalf;

			for ( ix = 0; ix < gridX1; ix ++ ) {

				var x = ix * segmentWidth - widthHalf;

				// set values to correct vector component

				vector[ u ] = x * udir;
				vector[ v ] = y * vdir;
				vector[ w ] = depthHalf;

				// now apply vector to vertex buffer

				vertices.push( vector.x, vector.y, vector.z );

				// set values to correct vector component

				vector[ u ] = 0;
				vector[ v ] = 0;
				vector[ w ] = depth > 0 ? 1 : - 1;

				// now apply vector to normal buffer

				normals.push( vector.x, vector.y, vector.z );

				// uvs

				uvs.push( ix / gridX );
				uvs.push( 1 - ( iy / gridY ) );

				// counters

				vertexCounter += 1;

			}

		}

		// indices

		// 1. you need three indices to draw a single face
		// 2. a single segment consists of two faces
		// 3. so we need to generate six (2*3) indices per segment

		for ( iy = 0; iy < gridY; iy ++ ) {

			for ( ix = 0; ix < gridX; ix ++ ) {

				var a = numberOfVertices + ix + gridX1 * iy;
				var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
				var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
				var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;

				// faces

				indices.push( a, b, d );
				indices.push( b, c, d );

				// increase counter

				groupCount += 6;

			}

		}

		// add a group to the geometry. this will ensure multi material support

		scope.addGroup( groupStart, groupCount, materialIndex );

		// calculate new start value for groups

		groupStart += groupCount;

		// update total number of vertices

		numberOfVertices += vertexCounter;

	}

}
1272470
function(gl, vertices, uv) {
  var verticesBuf = createBuffer(gl, new Float32Array(vertices))
  var uvBuf = createBuffer(gl, new Float32Array(uv))

  var mesh = createVAO(gl, [
      { buffer: verticesBuf,
        size: 3
      },
      {
        buffer: uvBuf,
        size: 2
      }
      ])
  mesh.length = vertices.length/3

  return mesh
}
701746
function createGeometry (data) {
  var geometryType = data.primitive;
  var GeometryClass = geometries[geometryType] && geometries[geometryType].Geometry;
  var geometryInstance = new GeometryClass();

  if (!GeometryClass) { throw new Error('Unknown geometry `' + geometryType + '`'); }

  geometryInstance.init(data);
  return toBufferGeometry(geometryInstance.geometry, data.buffer);
}
585536
function ( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {

	BufferGeometry.call( this );

	this.type = '';

	this.parameters = {
		innerRadius: innerRadius,
		outerRadius: outerRadius,
		thetaSegments: thetaSegments,
		phiSegments: phiSegments,
		thetaStart: thetaStart,
		thetaLength: thetaLength
	};

	innerRadius = innerRadius || 0.5;
	outerRadius = outerRadius || 1;

	thetaStart = thetaStart !== undefined ? thetaStart : 0;
	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;

	thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
	phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;

	// buffers

	var indices = [];
	var vertices = [];
	var normals = [];
	var uvs = [];

	// some helper variables

	var segment;
	var radius = innerRadius;
	var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
	var vertex = new Vector3();
	var uv = new Vector2();
	var j, i;

	// generate vertices, normals and uvs

	for ( j = 0; j <= phiSegments; j ++ ) {

		for ( i = 0; i <= thetaSegments; i ++ ) {

			// values are generate from the inside of the ring to the outside

			segment = thetaStart + i / thetaSegments * thetaLength;

			// vertex

			vertex.x = radius * Math.cos( segment );
			vertex.y = radius * Math.sin( segment );

			vertices.push( vertex.x, vertex.y, vertex.z );

			// normal

			normals.push( 0, 0, 1 );

			// uv

			uv.x = ( vertex.x / outerRadius + 1 ) / 2;
			uv.y = ( vertex.y / outerRadius + 1 ) / 2;

			uvs.push( uv.x, uv.y );

		}

		// increase the radius for next row of vertices

		radius += radiusStep;

	}

	// indices

	for ( j = 0; j < phiSegments; j ++ ) {

		var thetaSegmentLevel = j * ( thetaSegments + 1 );

		for ( i = 0; i < thetaSegments; i ++ ) {

			segment = i + thetaSegmentLevel;

			var a = segment;
			var b = segment + thetaSegments + 1;
			var c = segment + thetaSegments + 2;
			var d = segment + 1;

			// faces

			indices.push( a, b, d );
			indices.push( b, c, d );

		}

	}

	// build geometry

	this.setIndex( indices );
	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );

}
866630
def strain_in_plane(self, **kwargs):
        '''
        
        '''
        if self._strain_out_of_plane is not None:
            return ((self._strain_out_of_plane / -2.) *
                    (self.unstrained.c11(**kwargs) /
                     self.unstrained.c12(**kwargs)  )  )
        else:
            return 1 - self.unstrained.a(**kwargs) / self.substrate.a(**kwargs)
1144157
function toBufferGeometry (geometry, doBuffer) {
  var bufferGeometry;
  if (!doBuffer) { return geometry; }

  bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
  bufferGeometry.metadata = {type: geometry.type, parameters: geometry.parameters || {}};
  geometry.dispose();  // Dispose no longer needed non-buffer geometry.
  return bufferGeometry;
}