BufferGeometry.js 21.9 KB
Newer Older
1 2
/**
 * @author alteredq / http://alteredqualia.com/
3
 * @author mrdoob / http://mrdoob.com/
4 5 6 7
 */

THREE.BufferGeometry = function () {

M
Mr.doob 已提交
8 9
	Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );

10
	this.uuid = THREE.Math.generateUUID();
11

M
Mr.doob 已提交
12
	this.name = '';
13
	this.type = 'BufferGeometry';
M
Mr.doob 已提交
14

15
	this.attributes = {};
16

17
	this.morphAttributes = {};
18

19
	this.groups = [];
20

21 22 23 24 25 26 27
	this.boundingBox = null;
	this.boundingSphere = null;

};

THREE.BufferGeometry.prototype = {

28
	constructor: THREE.BufferGeometry,
29

M
Mr.doob 已提交
30
	addAttribute: function ( name, attribute ) {
31

M
Mr.doob 已提交
32
		if ( attribute instanceof THREE.BufferAttribute === false && attribute instanceof THREE.InterleavedBufferAttribute === false ) {
33

34
			console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
35 36 37 38 39 40 41

			this.attributes[ name ] = { array: arguments[ 1 ], itemSize: arguments[ 2 ] };

			return;

		}

M
Mr.doob 已提交
42 43 44 45 46 47 48
		if ( name === 'index' && attribute instanceof THREE.IndexBufferAttribute === false ) {

			console.warn( 'THREE.BufferGeometry.addAttribute: Use THREE.IndexBufferAttribute for index attribute.' );
			attribute = new THREE.IndexBufferAttribute( attribute.array, attribute.itemSize );

		}

M
Mr.doob 已提交
49
		this.attributes[ name ] = attribute;
50

M
Mr.doob 已提交
51 52 53 54
	},

	getAttribute: function ( name ) {

55 56
		return this.attributes[ name ];

57 58
	},

59 60 61 62 63 64
	removeAttribute: function ( name ) {

		delete this.attributes[ name ];

	},

65 66 67 68 69 70 71
	get drawcalls() {

		console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
		return this.groups;

	},

72
	get offsets() {
73

74 75
		console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
		return this.groups;
76 77 78

	},

M
Mr.doob 已提交
79 80
	addDrawCall: function ( start, count, indexOffset ) {

81 82 83 84 85 86
		if ( indexOffset !== undefined ) {

			console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );

		}

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
		console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
		this.addGroup( start, count );

	},

	clearDrawCalls: function () {

		console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
		this.clearGroups();

	},

	addGroup: function ( start, count, materialIndex ) {

		this.groups.push( {
M
Mr.doob 已提交
102 103

			start: start,
104 105
			count: count,
			materialIndex: materialIndex !== undefined ? materialIndex : 0
M
Mr.doob 已提交
106 107 108 109 110

		} );

	},

111
	clearGroups: function () {
D
dubejf 已提交
112

113
		this.groups = [];
D
dubejf 已提交
114 115 116

	},

117 118
	applyMatrix: function ( matrix ) {

M
Mr.doob 已提交
119
		var position = this.attributes.position;
120

M
Mr.doob 已提交
121
		if ( position !== undefined ) {
122

123
			matrix.applyToVector3Array( position.array );
M
Mr.doob 已提交
124
			position.needsUpdate = true;
125 126 127

		}

M
Mr.doob 已提交
128
		var normal = this.attributes.normal;
129

M
Mr.doob 已提交
130
		if ( normal !== undefined ) {
131

M
Mr.doob 已提交
132
			var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
133

134
			normalMatrix.applyToVector3Array( normal.array );
M
Mr.doob 已提交
135
			normal.needsUpdate = true;
136 137 138

		}

M
Mr.doob 已提交
139
		if ( this.boundingBox !== null ) {
140 141 142 143 144

			this.computeBoundingBox();

		}

M
Mr.doob 已提交
145
		if ( this.boundingSphere !== null ) {
146 147 148 149 150

			this.computeBoundingSphere();

		}

151 152
	},

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
	rotateX: function () {

		// rotate geometry around world x-axis

		var m1;

		return function rotateX( angle ) {

			if ( m1 === undefined ) m1 = new THREE.Matrix4();

			m1.makeRotationX( angle );

			this.applyMatrix( m1 );

			return this;

		};

	}(),

	rotateY: function () {

		// rotate geometry around world y-axis

		var m1;

		return function rotateY( angle ) {

			if ( m1 === undefined ) m1 = new THREE.Matrix4();

			m1.makeRotationY( angle );

			this.applyMatrix( m1 );

			return this;

		};

	}(),

	rotateZ: function () {

		// rotate geometry around world z-axis

		var m1;

		return function rotateZ( angle ) {

			if ( m1 === undefined ) m1 = new THREE.Matrix4();

			m1.makeRotationZ( angle );

			this.applyMatrix( m1 );

			return this;

		};

	}(),

	translate: function () {

		// translate geometry

		var m1;

		return function translate( x, y, z ) {

			if ( m1 === undefined ) m1 = new THREE.Matrix4();

			m1.makeTranslation( x, y, z );

			this.applyMatrix( m1 );

			return this;

		};

	}(),

	scale: function () {

		// scale geometry

		var m1;

		return function scale( x, y, z ) {

			if ( m1 === undefined ) m1 = new THREE.Matrix4();

			m1.makeScale( x, y, z );

			this.applyMatrix( m1 );

			return this;

		};

	}(),

	lookAt: function () {

		var obj;

		return function lookAt( vector ) {

			if ( obj === undefined ) obj = new THREE.Object3D();

			obj.lookAt( vector );

			obj.updateMatrix();

			this.applyMatrix( obj.matrix );

		};

	}(),

271 272
	center: function () {

M
Mr.doob 已提交
273 274 275 276
		this.computeBoundingBox();

		var offset = this.boundingBox.center().negate();

277
		this.translate( offset.x, offset.y, offset.z );
M
Mr.doob 已提交
278 279

		return offset;
280 281 282

	},

283
	setFromObject: function ( object ) {
284

285
		// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
286

287 288 289 290
		var geometry = object.geometry;

		if ( object instanceof THREE.PointCloud || object instanceof THREE.Line ) {

291 292
			var positions = new THREE.Float32Attribute( geometry.vertices.length * 3, 3 );
			var colors = new THREE.Float32Attribute( geometry.colors.length * 3, 3 );
293

294 295
			this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
			this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
296

C
Chen Pang 已提交
297 298 299 300 301 302 303 304
			if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {

				var lineDistances = new THREE.Float32Attribute( geometry.lineDistances.length, 1 );

				this.addAttribute( 'lineDistance',  lineDistances.copyArray( geometry.lineDistances ) );

			}

305 306 307 308 309 310 311 312 313 314 315
			if ( geometry.boundingSphere !== null ) {

				this.boundingSphere = geometry.boundingSphere.clone();

			}

			if ( geometry.boundingBox !== null ) {

				this.boundingBox = geometry.boundingBox.clone();

			}
316 317 318

		} else if ( object instanceof THREE.Mesh ) {

M
Mr.doob 已提交
319
			if ( geometry instanceof THREE.Geometry ) {
320 321

				this.fromGeometry( geometry );
322

M
Mr.doob 已提交
323
			}
324 325 326 327 328 329 330

		}

		return this;

	},

331 332
	updateFromObject: function ( object ) {

M
Mr.doob 已提交
333
		var geometry = object.geometry;
334

M
Mr.doob 已提交
335
		if ( object instanceof THREE.Mesh ) {
336

M
Mr.doob 已提交
337
			var direct = geometry.__directGeometry;
338

339 340 341 342 343 344
			if ( direct === undefined ) {

				return this.fromGeometry( geometry );

			}

M
Mr.doob 已提交
345 346 347 348
			direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
			direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
			direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
			direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
349
			direct.tangentsNeedUpdate = geometry.tangentsNeedUpdate;
M
Mr.doob 已提交
350 351 352 353 354

			geometry.verticesNeedUpdate = false;
			geometry.normalsNeedUpdate = false;
			geometry.colorsNeedUpdate = false;
			geometry.uvsNeedUpdate = false;
355
			geometry.tangentsNeedUpdate = false;
356

M
Mr.doob 已提交
357
			geometry = direct;
358 359

		}
360

M
Mr.doob 已提交
361
		if ( geometry.verticesNeedUpdate === true ) {
362

M
Mr.doob 已提交
363
			var attribute = this.attributes.position;
364

M
Mr.doob 已提交
365
			if ( attribute !== undefined ) {
366

M
Mr.doob 已提交
367 368
				attribute.copyVector3sArray( geometry.vertices );
				attribute.needsUpdate = true;
369 370 371

			}

M
Mr.doob 已提交
372
			geometry.verticesNeedUpdate = false;
373

M
Mr.doob 已提交
374
		}
375

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		if ( geometry.normalsNeedUpdate === true ) {

			var attribute = this.attributes.normal;

			if ( attribute !== undefined ) {

				attribute.copyVector3sArray( geometry.normals );
				attribute.needsUpdate = true;

			}

			geometry.normalsNeedUpdate = false;

		}

M
Mr.doob 已提交
391
		if ( geometry.colorsNeedUpdate === true ) {
392

M
Mr.doob 已提交
393
			var attribute = this.attributes.color;
394

M
Mr.doob 已提交
395
			if ( attribute !== undefined ) {
396

M
Mr.doob 已提交
397 398
				attribute.copyColorsArray( geometry.colors );
				attribute.needsUpdate = true;
399 400 401

			}

M
Mr.doob 已提交
402 403
			geometry.colorsNeedUpdate = false;

404
		}
405

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
		if ( geometry.tangentsNeedUpdate === true ) {

			var attribute = this.attributes.tangent;

			if ( attribute !== undefined ) {

				attribute.copyVector4sArray( geometry.tangents );
				attribute.needsUpdate = true;

			}

			geometry.tangentsNeedUpdate = false;

		}

C
Chen Pang 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
		if ( geometry.lineDistancesNeedUpdate ) {

			var attribute = this.attributes.lineDistance;

			if ( attribute !== undefined ) {

				attribute.copyArray( geometry.lineDistances );
				attribute.needsUpdate = true;

			}

			geometry.lineDistancesNeedUpdate = false;

		}

436
		return this;
437 438 439

	},

440
	fromGeometry: function ( geometry ) {
441

442
		geometry.__directGeometry = new THREE.DirectGeometry().fromGeometry( geometry );
443 444

		return this.fromDirectGeometry( geometry.__directGeometry );
445

446
	},
447

448
	fromDirectGeometry: function ( geometry ) {
449

450 451
		var positions = new Float32Array( geometry.vertices.length * 3 );
		this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
452

453 454 455 456 457 458 459 460
		if ( geometry.normals.length > 0 ) {

			var normals = new Float32Array( geometry.normals.length * 3 );
			this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );

		}

		if ( geometry.colors.length > 0 ) {
M
Mr.doob 已提交
461

462
			var colors = new Float32Array( geometry.colors.length * 3 );
463
			this.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
M
Mr.doob 已提交
464

465 466 467 468 469 470 471 472
		}

		if ( geometry.uvs.length > 0 ) {

			var uvs = new Float32Array( geometry.uvs.length * 2 );
			this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );

		}
M
Mr.doob 已提交
473

474 475 476 477 478 479 480 481 482 483 484 485 486 487
		if ( geometry.uvs2.length > 0 ) {

			var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
			this.addAttribute( 'uv2', new THREE.BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );

		}

		if ( geometry.tangents.length > 0 ) {

			var tangents = new Float32Array( geometry.tangents.length * 4 );
			this.addAttribute( 'tangent', new THREE.BufferAttribute( tangents, 4 ).copyVector4sArray( geometry.tangents ) );

		}

488 489
		if ( geometry.indices.length > 0 ) {

M
Mr.doob 已提交
490 491 492
			var TypeArray = geometry.vertices.length > 65535 ? Uint32Array : Uint16Array;
			var indices = new TypeArray( geometry.indices.length * 3 );
			this.addAttribute( 'index', new THREE.IndexBufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
493 494 495

		}

496 497 498 499
		// groups

		this.groups = geometry.groups;

500 501
		// morphs

502
		for ( var name in geometry.morphTargets ) {
503

504 505
			var array = [];
			var morphTargets = geometry.morphTargets[ name ];
506 507 508 509 510 511 512

			for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {

				var morphTarget = morphTargets[ i ];

				var attribute = new THREE.Float32Attribute( morphTarget.length * 3, 3 );

513
				array.push( attribute.copyVector3sArray( morphTarget ) );
514 515 516

			}

517
			this.morphAttributes[ name ] = array;
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538

		}

		// skinning

		if ( geometry.skinIndices.length > 0 ) {

			var skinIndices = new THREE.Float32Attribute( geometry.skinIndices.length * 4, 4 );
			this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );

		}

		if ( geometry.skinWeights.length > 0 ) {

			var skinWeights = new THREE.Float32Attribute( geometry.skinWeights.length * 4, 4 );
			this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );

		}

		//

539 540 541 542 543 544 545 546 547 548 549
		if ( geometry.boundingSphere !== null ) {

			this.boundingSphere = geometry.boundingSphere.clone();

		}

		if ( geometry.boundingBox !== null ) {

			this.boundingBox = geometry.boundingBox.clone();

		}
M
Mr.doob 已提交
550 551 552 553 554

		return this;

	},

555 556
	computeBoundingBox: function () {

557
		var vector = new THREE.Vector3();
558

559
		return function () {
560

561
			if ( this.boundingBox === null ) {
562

563
				this.boundingBox = new THREE.Box3();
564

565 566
			}

567
			var positions = this.attributes.position.array;
568

569
			if ( positions ) {
570

571 572
				var bb = this.boundingBox;
				bb.makeEmpty();
573

574
				for ( var i = 0, il = positions.length; i < il; i += 3 ) {
575

576
					vector.fromArray( positions, i );
577
					bb.expandByPoint( vector );
578 579 580 581 582

				}

			}

583
			if ( positions === undefined || positions.length === 0 ) {
584

585 586
				this.boundingBox.min.set( 0, 0, 0 );
				this.boundingBox.max.set( 0, 0, 0 );
587

588
			}
589

590
			if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
591

592
				console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
593

594
			}
595

G
Greg French 已提交
596
		};
597

598
	}(),
599 600 601

	computeBoundingSphere: function () {

602 603
		var box = new THREE.Box3();
		var vector = new THREE.Vector3();
604

605
		return function () {
606

607
			if ( this.boundingSphere === null ) {
608

609
				this.boundingSphere = new THREE.Sphere();
610

611
			}
612

613
			var positions = this.attributes.position.array;
614

615
			if ( positions ) {
616

617 618
				box.makeEmpty();

619
				var center = this.boundingSphere.center;
620

621
				for ( var i = 0, il = positions.length; i < il; i += 3 ) {
622

623
					vector.fromArray( positions, i );
J
Jan Wrobel 已提交
624
					box.expandByPoint( vector );
625 626 627 628 629

				}

				box.center( center );

630
				// hoping to find a boundingSphere with a radius smaller than the
M
Mr.doob 已提交
631
				// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
632

633 634
				var maxRadiusSq = 0;

635
				for ( var i = 0, il = positions.length; i < il; i += 3 ) {
636

637
					vector.fromArray( positions, i );
638
					maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
639

640 641 642 643
				}

				this.boundingSphere.radius = Math.sqrt( maxRadiusSq );

644 645
				if ( isNaN( this.boundingSphere.radius ) ) {

646
					console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
647 648 649

				}

650
			}
651

G
Greg French 已提交
652
		};
653

654
	}(),
655

656 657 658 659 660 661
	computeFaceNormals: function () {

		// backwards compatibility

	},

662 663
	computeVertexNormals: function () {

664
		var attributes = this.attributes;
665
		var groups = this.groups;
666

667
		if ( attributes.position ) {
668

669
			var positions = attributes.position.array;
670

671
			if ( attributes.normal === undefined ) {
672

673
				this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( positions.length ), 3 ) );
674 675 676 677 678

			} else {

				// reset existing normals to zero

679 680 681
				var normals = attributes.normal.array;

				for ( var i = 0, il = normals.length; i < il; i ++ ) {
682

683
					normals[ i ] = 0;
684 685 686 687 688

				}

			}

689
			var normals = attributes.normal.array;
690

M
Mr.doob 已提交
691
			var vA, vB, vC,
692 693 694 695 696 697 698 699

			pA = new THREE.Vector3(),
			pB = new THREE.Vector3(),
			pC = new THREE.Vector3(),

			cb = new THREE.Vector3(),
			ab = new THREE.Vector3();

700 701
			// indexed elements

702
			if ( attributes.index ) {
703

704
				var indices = attributes.index.array;
705

706
				if ( groups.length === 0 ) {
D
dubejf 已提交
707

708
					this.addGroup( 0, indices.length );
709

D
dubejf 已提交
710 711
				}

712
				for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
713

714
					var group = groups[ j ];
715

716 717
					var start = group.start;
					var count = group.count;
718

719
					for ( var i = start, il = start + count; i < il; i += 3 ) {
720

721 722 723
						vA = indices[ i + 0 ] * 3;
						vB = indices[ i + 1 ] * 3;
						vC = indices[ i + 2 ] * 3;
724

M
Mr.doob 已提交
725 726 727
						pA.fromArray( positions, vA );
						pB.fromArray( positions, vB );
						pC.fromArray( positions, vC );
728

729 730 731
						cb.subVectors( pC, pB );
						ab.subVectors( pA, pB );
						cb.cross( ab );
732

G
gero3 已提交
733
						normals[ vA ] += cb.x;
M
Mr.doob 已提交
734 735
						normals[ vA + 1 ] += cb.y;
						normals[ vA + 2 ] += cb.z;
736

G
gero3 已提交
737
						normals[ vB ] += cb.x;
M
Mr.doob 已提交
738 739
						normals[ vB + 1 ] += cb.y;
						normals[ vB + 2 ] += cb.z;
740

G
gero3 已提交
741
						normals[ vC ] += cb.x;
M
Mr.doob 已提交
742 743
						normals[ vC + 1 ] += cb.y;
						normals[ vC + 2 ] += cb.z;
744 745 746 747 748 749

					}

				}

			} else {
750

751 752 753
				// non-indexed elements (unconnected triangle soup)

				for ( var i = 0, il = positions.length; i < il; i += 9 ) {
754

M
Mr.doob 已提交
755 756 757
					pA.fromArray( positions, i );
					pB.fromArray( positions, i + 3 );
					pC.fromArray( positions, i + 6 );
758

759 760 761
					cb.subVectors( pC, pB );
					ab.subVectors( pA, pB );
					cb.cross( ab );
762

G
gero3 已提交
763
					normals[ i ] = cb.x;
764 765
					normals[ i + 1 ] = cb.y;
					normals[ i + 2 ] = cb.z;
766

767 768 769
					normals[ i + 3 ] = cb.x;
					normals[ i + 4 ] = cb.y;
					normals[ i + 5 ] = cb.z;
770

771 772 773
					normals[ i + 6 ] = cb.x;
					normals[ i + 7 ] = cb.y;
					normals[ i + 8 ] = cb.z;
774 775 776 777 778

				}

			}

779
			this.normalizeNormals();
780

781
			attributes.normal.needsUpdate = true;
782

783
		}
784

785
	},
786

787 788 789 790 791
	computeTangents: function () {

		// based on http://www.terathon.com/code/tangent.html
		// (per vertex tangents)

792 793 794 795
		if ( this.attributes.index === undefined ||
			 this.attributes.position === undefined ||
			 this.attributes.normal === undefined ||
			 this.attributes.uv === undefined ) {
796

797
			console.warn( 'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
798 799 800 801
			return;

		}

802 803 804 805
		var indices = this.attributes.index.array;
		var positions = this.attributes.position.array;
		var normals = this.attributes.normal.array;
		var uvs = this.attributes.uv.array;
806 807 808

		var nVertices = positions.length / 3;

809
		if ( this.attributes.tangent === undefined ) {
810

811
			this.addAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
812 813 814

		}

815
		var tangents = this.attributes.tangent.array;
816 817 818 819 820 821 822 823 824 825

		var tan1 = [], tan2 = [];

		for ( var k = 0; k < nVertices; k ++ ) {

			tan1[ k ] = new THREE.Vector3();
			tan2[ k ] = new THREE.Vector3();

		}

M
Mr.doob 已提交
826 827 828
		var vA = new THREE.Vector3(),
			vB = new THREE.Vector3(),
			vC = new THREE.Vector3(),
829

M
Mr.doob 已提交
830 831 832
			uvA = new THREE.Vector2(),
			uvB = new THREE.Vector2(),
			uvC = new THREE.Vector2(),
833 834 835 836 837 838 839 840

			x1, x2, y1, y2, z1, z2,
			s1, s2, t1, t2, r;

		var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();

		function handleTriangle( a, b, c ) {

M
Mr.doob 已提交
841 842 843
			vA.fromArray( positions, a * 3 );
			vB.fromArray( positions, b * 3 );
			vC.fromArray( positions, c * 3 );
844

M
Mr.doob 已提交
845 846 847
			uvA.fromArray( uvs, a * 2 );
			uvB.fromArray( uvs, b * 2 );
			uvC.fromArray( uvs, c * 2 );
848

M
Mr.doob 已提交
849 850
			x1 = vB.x - vA.x;
			x2 = vC.x - vA.x;
851

M
Mr.doob 已提交
852 853
			y1 = vB.y - vA.y;
			y2 = vC.y - vA.y;
854

M
Mr.doob 已提交
855 856
			z1 = vB.z - vA.z;
			z2 = vC.z - vA.z;
857

M
Mr.doob 已提交
858 859
			s1 = uvB.x - uvA.x;
			s2 = uvC.x - uvA.x;
860

M
Mr.doob 已提交
861 862
			t1 = uvB.y - uvA.y;
			t2 = uvC.y - uvA.y;
863 864 865

			r = 1.0 / ( s1 * t2 - s2 * t1 );

866 867 868 869 870 871 872 873 874 875 876
			sdir.set(
				( t2 * x1 - t1 * x2 ) * r,
				( t2 * y1 - t1 * y2 ) * r,
				( t2 * z1 - t1 * z2 ) * r
			);

			tdir.set(
				( s1 * x2 - s2 * x1 ) * r,
				( s1 * y2 - s2 * y1 ) * r,
				( s1 * z2 - s2 * z1 ) * r
			);
877

878 879 880
			tan1[ a ].add( sdir );
			tan1[ b ].add( sdir );
			tan1[ c ].add( sdir );
881

882 883 884
			tan2[ a ].add( tdir );
			tan2[ b ].add( tdir );
			tan2[ c ].add( tdir );
885 886 887 888 889 890 891

		}

		var i, il;
		var j, jl;
		var iA, iB, iC;

892
		if ( this.groups.length === 0 ) {
893

894
			this.addGroup( 0, indices.length );
895

896 897
		}

898
		var groups = this.groups;
899

900
		for ( j = 0, jl = groups.length; j < jl; ++ j ) {
901

902
			var group = groups[ j ];
903

904 905
			var start = group.start;
			var count = group.count;
906 907 908

			for ( i = start, il = start + count; i < il; i += 3 ) {

909 910 911
				iA = indices[ i + 0 ];
				iB = indices[ i + 1 ];
				iC = indices[ i + 2 ];
912 913 914 915 916 917 918 919 920 921 922 923 924

				handleTriangle( iA, iB, iC );

			}

		}

		var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
		var n = new THREE.Vector3(), n2 = new THREE.Vector3();
		var w, t, test;

		function handleVertex( v ) {

M
Mr.doob 已提交
925
			n.fromArray( normals, v * 3 );
926 927 928 929 930 931 932
			n2.copy( n );

			t = tan1[ v ];

			// Gram-Schmidt orthogonalize

			tmp.copy( t );
933
			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
934 935 936

			// Calculate handedness

937
			tmp2.crossVectors( n2, t );
938
			test = tmp2.dot( tan2[ v ] );
939
			w = ( test < 0.0 ) ? - 1.0 : 1.0;
940

G
gero3 已提交
941
			tangents[ v * 4 ] = tmp.x;
942 943 944 945 946 947
			tangents[ v * 4 + 1 ] = tmp.y;
			tangents[ v * 4 + 2 ] = tmp.z;
			tangents[ v * 4 + 3 ] = w;

		}

948
		for ( j = 0, jl = groups.length; j < jl; ++ j ) {
949

950
			var group = groups[ j ];
951

952 953
			var start = group.start;
			var count = group.count;
954 955 956

			for ( i = start, il = start + count; i < il; i += 3 ) {

957 958 959
				iA = indices[ i + 0 ];
				iB = indices[ i + 1 ];
				iC = indices[ i + 2 ];
960 961 962 963 964 965 966 967 968

				handleVertex( iA );
				handleVertex( iB );
				handleVertex( iC );

			}

		}

969 970
	},

M
Mr.doob 已提交
971
	computeOffsets: function ( size ) {
972

973
		console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.')
974 975 976

	},

977 978 979 980
	merge: function ( geometry, offset ) {

		if ( geometry instanceof THREE.BufferGeometry === false ) {

981
			console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
982 983 984 985 986 987 988 989 990 991 992
			return;

		}

		if ( offset === undefined ) offset = 0;

		var attributes = this.attributes;

		for ( var key in attributes ) {

			if ( geometry.attributes[ key ] === undefined ) continue;
993

994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
			var attribute1 = attributes[ key ];
			var attributeArray1 = attribute1.array;

			var attribute2 = geometry.attributes[ key ];
			var attributeArray2 = attribute2.array;

			var attributeSize = attribute2.itemSize;

			for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {

				attributeArray1[ j ] = attributeArray2[ i ];

			}

		}

		return this;
1011 1012 1013 1014 1015

	},

	normalizeNormals: function () {

1016
		var normals = this.attributes.normal.array;
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027

		var x, y, z, n;

		for ( var i = 0, il = normals.length; i < il; i += 3 ) {

			x = normals[ i ];
			y = normals[ i + 1 ];
			z = normals[ i + 2 ];

			n = 1.0 / Math.sqrt( x * x + y * y + z * z );

G
gero3 已提交
1028
			normals[ i ] *= n;
1029 1030 1031 1032 1033 1034 1035
			normals[ i + 1 ] *= n;
			normals[ i + 2 ] *= n;

		}

	},

1036
	toJSON: function () {
1037

1038 1039 1040 1041 1042 1043
		var data = {
			metadata: {
				version: 4.4,
				type: 'BufferGeometry',
				generator: 'BufferGeometry.toJSON'
			}
B
brason 已提交
1044
		};
1045

1046
		// standard BufferGeometry serialization
1047

1048
		data.uuid = this.uuid;
M
Mr.doob 已提交
1049
		data.type = this.type;
1050
		if ( this.name !== '' ) data.name = this.name;
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

		if ( this.parameters !== undefined ) {

			var parameters = this.parameters;

			for ( var key in parameters ) {

				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];

			}

			return data;

		}

		data.data = { attributes: {} };
1067

1068
		var attributes = this.attributes;
1069 1070
		var groups = this.groups;

1071 1072 1073 1074 1075 1076
		var boundingSphere = this.boundingSphere;

		for ( var key in attributes ) {

			var attribute = attributes[ key ];

M
makc 已提交
1077
			var array = Array.prototype.slice.call( attribute.array );
1078

1079
			data.data.attributes[ key ] = {
1080 1081 1082
				itemSize: attribute.itemSize,
				type: attribute.array.constructor.name,
				array: array
1083
			};
1084 1085 1086

		}

1087
		if ( groups.length > 0 ) {
1088

1089
			data.data.groups = JSON.parse( JSON.stringify( groups ) );
1090 1091 1092 1093 1094

		}

		if ( boundingSphere !== null ) {

1095
			data.data.boundingSphere = {
1096 1097
				center: boundingSphere.center.toArray(),
				radius: boundingSphere.radius
1098
			};
1099 1100 1101

		}

1102
		return data;
1103 1104 1105

	},

M
Mr.doob 已提交
1106
	clone: function () {
O
ohmed 已提交
1107

1108
		return new this.constructor().copy( this );
O
ohmed 已提交
1109

D
dubejf 已提交
1110 1111 1112
	},

	copy: function ( source ) {
O
ohmed 已提交
1113

M
Mr.doob 已提交
1114
		var attributes = source.attributes;
1115
		var groups = source.groups;
O
ohmed 已提交
1116

M
Mr.doob 已提交
1117
		for ( var name in attributes ) {
O
ohmed 已提交
1118

M
Mr.doob 已提交
1119 1120
			var attribute = attributes[ name ];
			this.addAttribute( name, attribute.clone() );
O
ohmed 已提交
1121

M
Mr.doob 已提交
1122
		}
O
ohmed 已提交
1123

1124 1125 1126
		for ( var i = 0, l = groups.length; i < l; i ++ ) {

			var group = groups[ i ];
O
ohmed 已提交
1127

1128
			this.addGorup( group.start, group.count );
O
ohmed 已提交
1129

O
ohmed 已提交
1130
		}
O
ohmed 已提交
1131

1132
		return this;
O
ohmed 已提交
1133 1134 1135

	},

1136
	dispose: function () {
1137

1138
		this.dispatchEvent( { type: 'dispose' } );
1139

1140
	}
1141 1142

};
M
Mr.doob 已提交
1143 1144

THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
1145

1146
THREE.BufferGeometry.MaxIndex = 65535;