123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /**
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.BufferGeometry = function () {
- this.id = THREE.GeometryIdCount ++;
- this.uuid = THREE.Math.generateUUID();
- // attributes
- this.attributes = {};
- // attributes typed arrays are kept only if dynamic flag is set
- this.dynamic = false;
- // offsets for chunks when using indexed elements
- this.offsets = [];
- // boundings
- this.boundingBox = null;
- this.boundingSphere = null;
- this.hasTangents = false;
- // for compatibility
- this.morphTargets = [];
- };
- THREE.BufferGeometry.prototype = {
- constructor: THREE.BufferGeometry,
- addEventListener: THREE.EventDispatcher.prototype.addEventListener,
- hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
- removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
- dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,
- applyMatrix: function ( matrix ) {
- var positionArray;
- var normalArray;
- if ( this.attributes[ "position" ] ) positionArray = this.attributes[ "position" ].array;
- if ( this.attributes[ "normal" ] ) normalArray = this.attributes[ "normal" ].array;
- if ( positionArray !== undefined ) {
- matrix.multiplyVector3Array( positionArray );
- this.verticesNeedUpdate = true;
- }
- if ( normalArray !== undefined ) {
- var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
- normalMatrix.multiplyVector3Array( normalArray );
- this.normalizeNormals();
- this.normalsNeedUpdate = true;
- }
- },
- computeBoundingBox: function () {
- if ( this.boundingBox === null ) {
- this.boundingBox = new THREE.Box3();
- }
- var positions = this.attributes[ "position" ].array;
- if ( positions ) {
- var bb = this.boundingBox;
- var x, y, z;
- if( positions.length >= 3 ) {
- bb.min.x = bb.max.x = positions[ 0 ];
- bb.min.y = bb.max.y = positions[ 1 ];
- bb.min.z = bb.max.z = positions[ 2 ];
- }
- for ( var i = 3, il = positions.length; i < il; i += 3 ) {
- x = positions[ i ];
- y = positions[ i + 1 ];
- z = positions[ i + 2 ];
- // bounding box
- if ( x < bb.min.x ) {
- bb.min.x = x;
- } else if ( x > bb.max.x ) {
- bb.max.x = x;
- }
- if ( y < bb.min.y ) {
- bb.min.y = y;
- } else if ( y > bb.max.y ) {
- bb.max.y = y;
- }
- if ( z < bb.min.z ) {
- bb.min.z = z;
- } else if ( z > bb.max.z ) {
- bb.max.z = z;
- }
- }
- }
- if ( positions === undefined || positions.length === 0 ) {
- this.boundingBox.min.set( 0, 0, 0 );
- this.boundingBox.max.set( 0, 0, 0 );
- }
- },
- computeBoundingSphere: function () {
- if ( this.boundingSphere === null ) {
- this.boundingSphere = new THREE.Sphere();
- }
- var positions = this.attributes[ "position" ].array;
- if ( positions ) {
- var radiusSq, maxRadiusSq = 0;
- var x, y, z;
- for ( var i = 0, il = positions.length; i < il; i += 3 ) {
- x = positions[ i ];
- y = positions[ i + 1 ];
- z = positions[ i + 2 ];
- radiusSq = x * x + y * y + z * z;
- if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
- }
- this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
- }
- },
- computeVertexNormals: function () {
- if ( this.attributes[ "position" ] ) {
- var i, il;
- var j, jl;
- var nVertexElements = this.attributes[ "position" ].array.length;
- if ( this.attributes[ "normal" ] === undefined ) {
- this.attributes[ "normal" ] = {
- itemSize: 3,
- array: new Float32Array( nVertexElements )
- };
- } else {
- // reset existing normals to zero
- for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
- this.attributes[ "normal" ].array[ i ] = 0;
- }
- }
- var positions = this.attributes[ "position" ].array;
- var normals = this.attributes[ "normal" ].array;
- var vA, vB, vC, x, y, z,
- pA = new THREE.Vector3(),
- pB = new THREE.Vector3(),
- pC = new THREE.Vector3(),
- cb = new THREE.Vector3(),
- ab = new THREE.Vector3();
- // indexed elements
- if ( this.attributes[ "index" ] ) {
- var indices = this.attributes[ "index" ].array;
- var offsets = this.offsets;
- for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
- var start = offsets[ j ].start;
- var count = offsets[ j ].count;
- var index = offsets[ j ].index;
- for ( i = start, il = start + count; i < il; i += 3 ) {
- vA = index + indices[ i ];
- vB = index + indices[ i + 1 ];
- vC = index + indices[ i + 2 ];
- x = positions[ vA * 3 ];
- y = positions[ vA * 3 + 1 ];
- z = positions[ vA * 3 + 2 ];
- pA.set( x, y, z );
- x = positions[ vB * 3 ];
- y = positions[ vB * 3 + 1 ];
- z = positions[ vB * 3 + 2 ];
- pB.set( x, y, z );
- x = positions[ vC * 3 ];
- y = positions[ vC * 3 + 1 ];
- z = positions[ vC * 3 + 2 ];
- pC.set( x, y, z );
- cb.subVectors( pC, pB );
- ab.subVectors( pA, pB );
- cb.cross( ab );
- normals[ vA * 3 ] += cb.x;
- normals[ vA * 3 + 1 ] += cb.y;
- normals[ vA * 3 + 2 ] += cb.z;
- normals[ vB * 3 ] += cb.x;
- normals[ vB * 3 + 1 ] += cb.y;
- normals[ vB * 3 + 2 ] += cb.z;
- normals[ vC * 3 ] += cb.x;
- normals[ vC * 3 + 1 ] += cb.y;
- normals[ vC * 3 + 2 ] += cb.z;
- }
- }
- // non-indexed elements (unconnected triangle soup)
- } else {
- for ( i = 0, il = positions.length; i < il; i += 9 ) {
- x = positions[ i ];
- y = positions[ i + 1 ];
- z = positions[ i + 2 ];
- pA.set( x, y, z );
- x = positions[ i + 3 ];
- y = positions[ i + 4 ];
- z = positions[ i + 5 ];
- pB.set( x, y, z );
- x = positions[ i + 6 ];
- y = positions[ i + 7 ];
- z = positions[ i + 8 ];
- pC.set( x, y, z );
- cb.subVectors( pC, pB );
- ab.subVectors( pA, pB );
- cb.cross( ab );
- normals[ i ] = cb.x;
- normals[ i + 1 ] = cb.y;
- normals[ i + 2 ] = cb.z;
- normals[ i + 3 ] = cb.x;
- normals[ i + 4 ] = cb.y;
- normals[ i + 5 ] = cb.z;
- normals[ i + 6 ] = cb.x;
- normals[ i + 7 ] = cb.y;
- normals[ i + 8 ] = cb.z;
- }
- }
- this.normalizeNormals();
- this.normalsNeedUpdate = true;
- }
- },
- normalizeNormals: function () {
- var normals = this.attributes[ "normal" ].array;
- 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 );
- normals[ i ] *= n;
- normals[ i + 1 ] *= n;
- normals[ i + 2 ] *= n;
- }
- },
- computeTangents: function () {
- // based on http://www.terathon.com/code/tangent.html
- // (per vertex tangents)
- if ( this.attributes[ "index" ] === undefined ||
- this.attributes[ "position" ] === undefined ||
- this.attributes[ "normal" ] === undefined ||
- this.attributes[ "uv" ] === undefined ) {
- console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
- return;
- }
- var indices = this.attributes[ "index" ].array;
- var positions = this.attributes[ "position" ].array;
- var normals = this.attributes[ "normal" ].array;
- var uvs = this.attributes[ "uv" ].array;
- var nVertices = positions.length / 3;
- if ( this.attributes[ "tangent" ] === undefined ) {
- var nTangentElements = 4 * nVertices;
- this.attributes[ "tangent" ] = {
- itemSize: 4,
- array: new Float32Array( nTangentElements )
- };
- }
- var tangents = this.attributes[ "tangent" ].array;
- var tan1 = [], tan2 = [];
- for ( var k = 0; k < nVertices; k ++ ) {
- tan1[ k ] = new THREE.Vector3();
- tan2[ k ] = new THREE.Vector3();
- }
- var xA, yA, zA,
- xB, yB, zB,
- xC, yC, zC,
- uA, vA,
- uB, vB,
- uC, vC,
- 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 ) {
- xA = positions[ a * 3 ];
- yA = positions[ a * 3 + 1 ];
- zA = positions[ a * 3 + 2 ];
- xB = positions[ b * 3 ];
- yB = positions[ b * 3 + 1 ];
- zB = positions[ b * 3 + 2 ];
- xC = positions[ c * 3 ];
- yC = positions[ c * 3 + 1 ];
- zC = positions[ c * 3 + 2 ];
- uA = uvs[ a * 2 ];
- vA = uvs[ a * 2 + 1 ];
- uB = uvs[ b * 2 ];
- vB = uvs[ b * 2 + 1 ];
- uC = uvs[ c * 2 ];
- vC = uvs[ c * 2 + 1 ];
- x1 = xB - xA;
- x2 = xC - xA;
- y1 = yB - yA;
- y2 = yC - yA;
- z1 = zB - zA;
- z2 = zC - zA;
- s1 = uB - uA;
- s2 = uC - uA;
- t1 = vB - vA;
- t2 = vC - vA;
- r = 1.0 / ( s1 * t2 - s2 * t1 );
- 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
- );
- tan1[ a ].add( sdir );
- tan1[ b ].add( sdir );
- tan1[ c ].add( sdir );
- tan2[ a ].add( tdir );
- tan2[ b ].add( tdir );
- tan2[ c ].add( tdir );
- }
- var i, il;
- var j, jl;
- var iA, iB, iC;
- var offsets = this.offsets;
- for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
- var start = offsets[ j ].start;
- var count = offsets[ j ].count;
- var index = offsets[ j ].index;
- for ( i = start, il = start + count; i < il; i += 3 ) {
- iA = index + indices[ i ];
- iB = index + indices[ i + 1 ];
- iC = index + indices[ i + 2 ];
- 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 ) {
- n.x = normals[ v * 3 ];
- n.y = normals[ v * 3 + 1 ];
- n.z = normals[ v * 3 + 2 ];
- n2.copy( n );
- t = tan1[ v ];
- // Gram-Schmidt orthogonalize
- tmp.copy( t );
- tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
- // Calculate handedness
- tmp2.crossVectors( n2, t );
- test = tmp2.dot( tan2[ v ] );
- w = ( test < 0.0 ) ? -1.0 : 1.0;
- tangents[ v * 4 ] = tmp.x;
- tangents[ v * 4 + 1 ] = tmp.y;
- tangents[ v * 4 + 2 ] = tmp.z;
- tangents[ v * 4 + 3 ] = w;
- }
- for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
- var start = offsets[ j ].start;
- var count = offsets[ j ].count;
- var index = offsets[ j ].index;
- for ( i = start, il = start + count; i < il; i += 3 ) {
- iA = index + indices[ i ];
- iB = index + indices[ i + 1 ];
- iC = index + indices[ i + 2 ];
- handleVertex( iA );
- handleVertex( iB );
- handleVertex( iC );
- }
- }
- this.hasTangents = true;
- this.tangentsNeedUpdate = true;
- },
- dispose: function () {
- this.dispatchEvent( { type: 'dispose' } );
- }
- };
|