提交 786d570e 编写于 作者: M Mr.doob

Updated builds.

上级 8adc0489
......@@ -8381,20 +8381,6 @@ THREE.Projector = function () {
}
} else if ( geometry instanceof THREE.Geometry2 ) {
vertices = geometry.vertices;
for ( var i = 0, j = 0, l = vertices.length; i < l; i += 9, j += 3 ) {
renderList.pushVertex( vertices[ i + 0 ], vertices[ i + 1 ], vertices[ i + 2 ] );
renderList.pushVertex( vertices[ i + 3 ], vertices[ i + 4 ], vertices[ i + 5 ] );
renderList.pushVertex( vertices[ i + 6 ], vertices[ i + 7 ], vertices[ i + 8 ] );
renderList.pushTriangle( j + 0, j + 1, j + 2 );
}
} else if ( geometry instanceof THREE.Geometry ) {
vertices = geometry.vertices;
......@@ -8914,329 +8900,353 @@ THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
};
/**
* @author mrdoob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author zz85 / http://www.lab4games.net/zz85/blog
* @author bhouston / http://exocortex.com
*/
THREE.Geometry = function () {
THREE.BufferGeometry = function () {
this.id = THREE.GeometryIdCount ++;
this.uuid = THREE.Math.generateUUID();
this.name = '';
this.vertices = [];
this.colors = []; // one-to-one vertex colors, used in ParticleSystem and Line
this.faces = [];
// attributes
this.faceVertexUvs = [[]];
this.attributes = {};
this.morphTargets = [];
this.morphColors = [];
this.morphNormals = [];
// offsets for chunks when using indexed elements
this.skinWeights = [];
this.skinIndices = [];
this.offsets = [];
this.lineDistances = [];
// boundings
this.boundingBox = null;
this.boundingSphere = null;
this.hasTangents = false;
};
this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
THREE.BufferGeometry.prototype = {
// update flags
constructor: THREE.BufferGeometry,
this.verticesNeedUpdate = false;
this.elementsNeedUpdate = false;
this.uvsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.tangentsNeedUpdate = false;
this.colorsNeedUpdate = false;
this.lineDistancesNeedUpdate = false;
addAttribute: function ( name, type, numItems, itemSize ) {
this.buffersNeedUpdate = false;
this.attributes[ name ] = {
};
array: new type( numItems * itemSize ),
itemSize: itemSize
THREE.Geometry.prototype = {
};
constructor: THREE.Geometry,
return this.attributes[ name ];
},
applyMatrix: function ( matrix ) {
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
var position = this.attributes.position;
for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
if ( position !== undefined ) {
var vertex = this.vertices[ i ];
vertex.applyMatrix4( matrix );
matrix.multiplyVector3Array( position.array );
position.needsUpdate = true;
}
for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
var normal = this.attributes.normal;
var face = this.faces[ i ];
face.normal.applyMatrix3( normalMatrix ).normalize();
if ( normal !== undefined ) {
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
normalMatrix.multiplyVector3Array( normal.array );
normal.needsUpdate = true;
}
}
face.centroid.applyMatrix4( matrix );
},
}
computeBoundingBox: function () {
if ( this.boundingBox instanceof THREE.Box3 ) {
if ( this.boundingBox === null ) {
this.computeBoundingBox();
this.boundingBox = new THREE.Box3();
}
if ( this.boundingSphere instanceof THREE.Sphere ) {
var positions = this.attributes[ "position" ].array;
this.computeBoundingSphere();
if ( positions ) {
}
var bb = this.boundingBox;
},
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 ];
}
computeCentroids: function () {
for ( var i = 3, il = positions.length; i < il; i += 3 ) {
var f, fl, face;
var x = positions[ i ];
var y = positions[ i + 1 ];
var z = positions[ i + 2 ];
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
// bounding box
face = this.faces[ f ];
face.centroid.set( 0, 0, 0 );
if ( x < bb.min.x ) {
face.centroid.add( this.vertices[ face.a ] );
face.centroid.add( this.vertices[ face.b ] );
face.centroid.add( this.vertices[ face.c ] );
face.centroid.divideScalar( 3 );
bb.min.x = x;
}
} else if ( x > bb.max.x ) {
},
bb.max.x = x;
computeFaceNormals: function () {
}
var cb = new THREE.Vector3(), ab = new THREE.Vector3();
if ( y < bb.min.y ) {
for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
bb.min.y = y;
var face = this.faces[ f ];
} else if ( y > bb.max.y ) {
var vA = this.vertices[ face.a ];
var vB = this.vertices[ face.b ];
var vC = this.vertices[ face.c ];
bb.max.y = y;
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
}
cb.normalize();
if ( z < bb.min.z ) {
face.normal.copy( cb );
bb.min.z = z;
}
} else if ( z > bb.max.z ) {
},
bb.max.z = z;
computeVertexNormals: function ( areaWeighted ) {
}
var v, vl, f, fl, face, vertices;
}
vertices = new Array( this.vertices.length );
}
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
if ( positions === undefined || positions.length === 0 ) {
vertices[ v ] = new THREE.Vector3();
this.boundingBox.min.set( 0, 0, 0 );
this.boundingBox.max.set( 0, 0, 0 );
}
if ( areaWeighted ) {
},
// vertex normals weighted by triangle areas
// http://www.iquilezles.org/www/articles/normals/normals.htm
computeBoundingSphere: function () {
var vA, vB, vC, vD;
var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
var box = new THREE.Box3();
var vector = new THREE.Vector3();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
return function () {
face = this.faces[ f ];
if ( this.boundingSphere === null ) {
vA = this.vertices[ face.a ];
vB = this.vertices[ face.b ];
vC = this.vertices[ face.c ];
this.boundingSphere = new THREE.Sphere();
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
}
vertices[ face.a ].add( cb );
vertices[ face.b ].add( cb );
vertices[ face.c ].add( cb );
var positions = this.attributes[ "position" ].array;
}
if ( positions ) {
} else {
box.makeEmpty();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
var center = this.boundingSphere.center;
face = this.faces[ f ];
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
vertices[ face.a ].add( face.normal );
vertices[ face.b ].add( face.normal );
vertices[ face.c ].add( face.normal );
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
box.addPoint( vector );
}
}
}
box.center( center );
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
var maxRadiusSq = 0;
vertices[ v ].normalize();
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
}
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
}
face = this.faces[ f ];
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
}
}
},
}(),
computeMorphNormals: function () {
computeVertexNormals: function () {
var i, il, f, fl, face;
if ( this.attributes[ "position" ] ) {
// save original normals
// - create temp variables on first access
// otherwise just copy (for faster repeated calls)
var i, il;
var j, jl;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
var nVertexElements = this.attributes[ "position" ].array.length;
face = this.faces[ f ];
if ( this.attributes[ "normal" ] === undefined ) {
if ( ! face.__originalFaceNormal ) {
this.attributes[ "normal" ] = {
face.__originalFaceNormal = face.normal.clone();
itemSize: 3,
array: new Float32Array( nVertexElements )
};
} else {
face.__originalFaceNormal.copy( face.normal );
// reset existing normals to zero
}
for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
this.attributes[ "normal" ].array[ i ] = 0;
for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
}
if ( ! face.__originalVertexNormals[ i ] ) {
}
face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
var positions = this.attributes[ "position" ].array;
var normals = this.attributes[ "normal" ].array;
} else {
var vA, vB, vC, x, y, z,
face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
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" ] ) {
// use temp geometry to compute face and vertex normals for each morph
var indices = this.attributes[ "index" ].array;
var tmpGeo = new THREE.Geometry();
tmpGeo.faces = this.faces;
var offsets = this.offsets;
for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
// create on first access
var start = offsets[ j ].start;
var count = offsets[ j ].count;
var index = offsets[ j ].index;
if ( ! this.morphNormals[ i ] ) {
for ( i = start, il = start + count; i < il; i += 3 ) {
this.morphNormals[ i ] = {};
this.morphNormals[ i ].faceNormals = [];
this.morphNormals[ i ].vertexNormals = [];
vA = index + indices[ i ];
vB = index + indices[ i + 1 ];
vC = index + indices[ i + 2 ];
var dstNormalsFace = this.morphNormals[ i ].faceNormals;
var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
x = positions[ vA * 3 ];
y = positions[ vA * 3 + 1 ];
z = positions[ vA * 3 + 2 ];
pA.set( x, y, z );
var faceNormal, vertexNormals;
x = positions[ vB * 3 ];
y = positions[ vB * 3 + 1 ];
z = positions[ vB * 3 + 2 ];
pB.set( x, y, z );
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
x = positions[ vC * 3 ];
y = positions[ vC * 3 + 1 ];
z = positions[ vC * 3 + 2 ];
pC.set( x, y, z );
face = this.faces[ f ];
cb.subVectors( pC, pB );
ab.subVectors( pA, pB );
cb.cross( ab );
faceNormal = new THREE.Vector3();
vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
normals[ vA * 3 ] += cb.x;
normals[ vA * 3 + 1 ] += cb.y;
normals[ vA * 3 + 2 ] += cb.z;
dstNormalsFace.push( faceNormal );
dstNormalsVertex.push( vertexNormals );
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;
}
}
var morphNormals = this.morphNormals[ i ];
}
// set vertices to morph target
// non-indexed elements (unconnected triangle soup)
tmpGeo.vertices = this.morphTargets[ i ].vertices;
} else {
// compute morph normals
for ( i = 0, il = positions.length; i < il; i += 9 ) {
tmpGeo.computeFaceNormals();
tmpGeo.computeVertexNormals();
x = positions[ i ];
y = positions[ i + 1 ];
z = positions[ i + 2 ];
pA.set( x, y, z );
// store morph normals
x = positions[ i + 3 ];
y = positions[ i + 4 ];
z = positions[ i + 5 ];
pB.set( x, y, z );
var faceNormal, vertexNormals;
x = positions[ i + 6 ];
y = positions[ i + 7 ];
z = positions[ i + 8 ];
pC.set( x, y, z );
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
cb.subVectors( pC, pB );
ab.subVectors( pA, pB );
cb.cross( ab );
face = this.faces[ f ];
normals[ i ] = cb.x;
normals[ i + 1 ] = cb.y;
normals[ i + 2 ] = cb.z;
faceNormal = morphNormals.faceNormals[ f ];
vertexNormals = morphNormals.vertexNormals[ f ];
normals[ i + 3 ] = cb.x;
normals[ i + 4 ] = cb.y;
normals[ i + 5 ] = cb.z;
faceNormal.copy( face.normal );
normals[ i + 6 ] = cb.x;
normals[ i + 7 ] = cb.y;
normals[ i + 8 ] = cb.z;
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
}
}
this.normalizeNormals();
this.normalsNeedUpdate = true;
}
// restore original normals
},
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
normalizeNormals: function () {
face = this.faces[ f ];
var normals = this.attributes[ "normal" ].array;
face.normal = face.__originalFaceNormal;
face.vertexNormals = face.__originalVertexNormals;
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;
}
......@@ -9245,1258 +9255,1091 @@ THREE.Geometry.prototype = {
computeTangents: function () {
// based on http://www.terathon.com/code/tangent.html
// tangents go to vertices
var f, fl, v, vl, i, il, vertexIndex,
face, uv, vA, vB, vC, uvA, uvB, uvC,
x1, x2, y1, y2, z1, z2,
s1, s2, t1, t2, r, t, test,
tan1 = [], tan2 = [],
sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
n = new THREE.Vector3(), w;
// (per vertex tangents)
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
if ( this.attributes[ "index" ] === undefined ||
this.attributes[ "position" ] === undefined ||
this.attributes[ "normal" ] === undefined ||
this.attributes[ "uv" ] === undefined ) {
tan1[ v ] = new THREE.Vector3();
tan2[ v ] = new THREE.Vector3();
console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
return;
}
function handleTriangle( context, a, b, c, ua, ub, uc ) {
vA = context.vertices[ a ];
vB = context.vertices[ b ];
vC = context.vertices[ c ];
var indices = this.attributes[ "index" ].array;
var positions = this.attributes[ "position" ].array;
var normals = this.attributes[ "normal" ].array;
var uvs = this.attributes[ "uv" ].array;
uvA = uv[ ua ];
uvB = uv[ ub ];
uvC = uv[ uc ];
var nVertices = positions.length / 3;
x1 = vB.x - vA.x;
x2 = vC.x - vA.x;
y1 = vB.y - vA.y;
y2 = vC.y - vA.y;
z1 = vB.z - vA.z;
z2 = vC.z - vA.z;
if ( this.attributes[ "tangent" ] === undefined ) {
s1 = uvB.x - uvA.x;
s2 = uvC.x - uvA.x;
t1 = uvB.y - uvA.y;
t2 = uvC.y - uvA.y;
var nTangentElements = 4 * nVertices;
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 );
this.attributes[ "tangent" ] = {
tan1[ a ].add( sdir );
tan1[ b ].add( sdir );
tan1[ c ].add( sdir );
itemSize: 4,
array: new Float32Array( nTangentElements )
tan2[ a ].add( tdir );
tan2[ b ].add( tdir );
tan2[ c ].add( tdir );
};
}
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
var tangents = this.attributes[ "tangent" ].array;
handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
var tan1 = [], tan2 = [];
}
for ( var k = 0; k < nVertices; k ++ ) {
var faceIndex = [ 'a', 'b', 'c', 'd' ];
tan1[ k ] = new THREE.Vector3();
tan2[ k ] = new THREE.Vector3();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
}
face = this.faces[ f ];
var xA, yA, zA,
xB, yB, zB,
xC, yC, zC,
for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
uA, vA,
uB, vB,
uC, vC,
n.copy( face.vertexNormals[ i ] );
x1, x2, y1, y2, z1, z2,
s1, s2, t1, t2, r;
vertexIndex = face[ faceIndex[ i ] ];
var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
t = tan1[ vertexIndex ];
function handleTriangle( a, b, c ) {
// Gram-Schmidt orthogonalize
xA = positions[ a * 3 ];
yA = positions[ a * 3 + 1 ];
zA = positions[ a * 3 + 2 ];
tmp.copy( t );
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
xB = positions[ b * 3 ];
yB = positions[ b * 3 + 1 ];
zB = positions[ b * 3 + 2 ];
// Calculate handedness
xC = positions[ c * 3 ];
yC = positions[ c * 3 + 1 ];
zC = positions[ c * 3 + 2 ];
tmp2.crossVectors( face.vertexNormals[ i ], t );
test = tmp2.dot( tan2[ vertexIndex ] );
w = (test < 0.0) ? -1.0 : 1.0;
uA = uvs[ a * 2 ];
vA = uvs[ a * 2 + 1 ];
face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
uB = uvs[ b * 2 ];
vB = uvs[ b * 2 + 1 ];
}
uC = uvs[ c * 2 ];
vC = uvs[ c * 2 + 1 ];
}
x1 = xB - xA;
x2 = xC - xA;
this.hasTangents = true;
y1 = yB - yA;
y2 = yC - yA;
},
z1 = zB - zA;
z2 = zC - zA;
computeLineDistances: function ( ) {
s1 = uB - uA;
s2 = uC - uA;
var d = 0;
var vertices = this.vertices;
t1 = vB - vA;
t2 = vC - vA;
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
r = 1.0 / ( s1 * t2 - s2 * t1 );
if ( i > 0 ) {
d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
}
this.lineDistances[ i ] = d;
}
},
computeBoundingBox: function () {
if ( this.boundingBox === null ) {
this.boundingBox = new THREE.Box3();
}
this.boundingBox.setFromPoints( this.vertices );
},
sdir.set(
( t2 * x1 - t1 * x2 ) * r,
( t2 * y1 - t1 * y2 ) * r,
( t2 * z1 - t1 * z2 ) * r
);
computeBoundingSphere: function () {
tdir.set(
( s1 * x2 - s2 * x1 ) * r,
( s1 * y2 - s2 * y1 ) * r,
( s1 * z2 - s2 * z1 ) * r
);
if ( this.boundingSphere === null ) {
tan1[ a ].add( sdir );
tan1[ b ].add( sdir );
tan1[ c ].add( sdir );
this.boundingSphere = new THREE.Sphere();
tan2[ a ].add( tdir );
tan2[ b ].add( tdir );
tan2[ c ].add( tdir );
}
this.boundingSphere.setFromPoints( this.vertices );
},
/*
* Checks for duplicate vertices with hashmap.
* Duplicated vertices are removed
* and faces' vertices are updated.
*/
mergeVertices: function () {
var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
var unique = [], changes = [];
var v, key;
var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
var precision = Math.pow( 10, precisionPoints );
var i,il, face;
var indices, k, j, jl, u;
var i, il;
var j, jl;
var iA, iB, iC;
for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
var offsets = this.offsets;
v = this.vertices[ i ];
key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
if ( verticesMap[ key ] === undefined ) {
var start = offsets[ j ].start;
var count = offsets[ j ].count;
var index = offsets[ j ].index;
verticesMap[ key ] = i;
unique.push( this.vertices[ i ] );
changes[ i ] = unique.length - 1;
for ( i = start, il = start + count; i < il; i += 3 ) {
} else {
iA = index + indices[ i ];
iB = index + indices[ i + 1 ];
iC = index + indices[ i + 2 ];
//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
changes[ i ] = changes[ verticesMap[ key ] ];
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;
// if faces are completely degenerate after merging vertices, we
// have to remove them from the geometry.
var faceIndicesToRemove = [];
function handleVertex( v ) {
for( i = 0, il = this.faces.length; i < il; i ++ ) {
n.x = normals[ v * 3 ];
n.y = normals[ v * 3 + 1 ];
n.z = normals[ v * 3 + 2 ];
face = this.faces[ i ];
n2.copy( n );
face.a = changes[ face.a ];
face.b = changes[ face.b ];
face.c = changes[ face.c ];
t = tan1[ v ];
indices = [ face.a, face.b, face.c ];
// Gram-Schmidt orthogonalize
var dupIndex = -1;
tmp.copy( t );
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
// if any duplicate vertices are found in a Face3
// we have to remove the face as nothing can be saved
for ( var n = 0; n < 3; n ++ ) {
if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
// Calculate handedness
dupIndex = n;
faceIndicesToRemove.push( i );
break;
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 ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
var idx = faceIndicesToRemove[ i ];
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
this.faces.splice( idx, 1 );
var start = offsets[ j ].start;
var count = offsets[ j ].count;
var index = offsets[ j ].index;
for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
for ( i = start, il = start + count; i < il; i += 3 ) {
this.faceVertexUvs[ j ].splice( idx, 1 );
iA = index + indices[ i ];
iB = index + indices[ i + 1 ];
iC = index + indices[ i + 2 ];
handleVertex( iA );
handleVertex( iB );
handleVertex( iC );
}
}
// Use unique set of vertices
var diff = this.vertices.length - unique.length;
this.vertices = unique;
return diff;
},
// Geometry splitting
makeGroups: ( function () {
var geometryGroupCounter = 0;
return function ( usesFaceMaterial ) {
var f, fl, face, materialIndex,
groupHash, hash_map = {};
var numMorphTargets = this.morphTargets.length;
var numMorphNormals = this.morphNormals.length;
/*
computeOffsets
Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
indexBufferSize - Defaults to 65535, but allows for larger or smaller chunks.
*/
computeOffsets: function(indexBufferSize) {
this.geometryGroups = {};
var size = indexBufferSize;
if(indexBufferSize === undefined)
size = 65535; //WebGL limits type of index buffer values to 16-bit.
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
var s = Date.now();
face = this.faces[ f ];
materialIndex = usesFaceMaterial ? face.materialIndex : 0;
var indices = this.attributes['index'].array;
var vertices = this.attributes['position'].array;
if ( ! ( materialIndex in hash_map ) ) {
var verticesCount = (vertices.length/3);
var facesCount = (indices.length/3);
hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
/*
console.log("Computing buffers in offsets of "+size+" -> indices:"+indices.length+" vertices:"+vertices.length);
console.log("Faces to process: "+(indices.length/3));
console.log("Reordering "+verticesCount+" vertices.");
*/
}
var sortedIndices = new Uint16Array( indices.length ); //16-bit buffers
var indexPtr = 0;
var vertexPtr = 0;
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
var offsets = [ { start:0, count:0, index:0 } ];
var offset = offsets[0];
if ( ! ( groupHash in this.geometryGroups ) ) {
var duplicatedVertices = 0;
var newVerticeMaps = 0;
var faceVertices = new Int32Array(6);
var vertexMap = new Int32Array( vertices.length );
var revVertexMap = new Int32Array( vertices.length );
for(var j = 0; j < vertices.length; j++) { vertexMap[j] = -1; revVertexMap[j] = -1; }
this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
/*
Traverse every face and reorder vertices in the proper offsets of 65k.
We can have more than 65k entries in the index buffer per offset, but only reference 65k values.
*/
for(var findex = 0; findex < facesCount; findex++) {
newVerticeMaps = 0;
for(var vo = 0; vo < 3; vo++) {
var vid = indices[ findex*3 + vo ];
if(vertexMap[vid] == -1) {
//Unmapped vertice
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = -1;
newVerticeMaps++;
} else if(vertexMap[vid] < offset.index) {
//Reused vertices from previous block (duplicate)
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = -1;
duplicatedVertices++;
} else {
//Reused vertice in the current block
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = vertexMap[vid];
}
}
if ( this.geometryGroups[ groupHash ].vertices + 3 > 65535 ) {
hash_map[ materialIndex ].counter += 1;
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
if ( ! ( groupHash in this.geometryGroups ) ) {
this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
}
var faceMax = vertexPtr + newVerticeMaps;
if(faceMax > (offset.index + size)) {
var new_offset = { start:indexPtr, count:0, index:vertexPtr };
offsets.push(new_offset);
offset = new_offset;
//Re-evaluate reused vertices in light of new offset.
for(var v = 0; v < 6; v+=2) {
var new_vid = faceVertices[v+1];
if(new_vid > -1 && new_vid < offset.index)
faceVertices[v+1] = -1;
}
this.geometryGroups[ groupHash ].faces3.push( f );
this.geometryGroups[ groupHash ].vertices += 3;
}
this.geometryGroupsList = [];
for ( var g in this.geometryGroups ) {
this.geometryGroups[ g ].id = geometryGroupCounter ++;
//Reindex the face.
for(var v = 0; v < 6; v+=2) {
var vid = faceVertices[v];
var new_vid = faceVertices[v+1];
this.geometryGroupsList.push( this.geometryGroups[ g ] );
if(new_vid === -1)
new_vid = vertexPtr++;
vertexMap[vid] = new_vid;
revVertexMap[new_vid] = vid;
sortedIndices[indexPtr++] = new_vid - offset.index; //XXX overflows at 16bit
offset.count++;
}
};
} )(),
clone: function () {
var geometry = new THREE.Geometry();
var vertices = this.vertices;
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
geometry.vertices.push( vertices[ i ].clone() );
}
var faces = this.faces;
for ( var i = 0, il = faces.length; i < il; i ++ ) {
geometry.faces.push( faces[ i ].clone() );
}
var uvs = this.faceVertexUvs[ 0 ];
for ( var i = 0, il = uvs.length; i < il; i ++ ) {
/* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */
this.reorderBuffers(sortedIndices, revVertexMap, vertexPtr);
this.offsets = offsets;
var uv = uvs[ i ], uvCopy = [];
/*
var orderTime = Date.now();
console.log("Reorder time: "+(orderTime-s)+"ms");
console.log("Duplicated "+duplicatedVertices+" vertices.");
console.log("Compute Buffers time: "+(Date.now()-s)+"ms");
console.log("Draw offsets: "+offsets.length);
*/
for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
return offsets;
},
uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
/*
reoderBuffers:
Reorder attributes based on a new indexBuffer and indexMap.
indexBuffer - Uint16Array of the new ordered indices.
indexMap - Int32Array where the position is the new vertex ID and the value the old vertex ID for each vertex.
vertexCount - Amount of total vertices considered in this reordering (in case you want to grow the vertice stack).
*/
reorderBuffers: function(indexBuffer, indexMap, vertexCount) {
/* Create a copy of all attributes for reordering. */
var sortedAttributes = {};
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
for( var attr in this.attributes ) {
if(attr == 'index')
continue;
var sourceArray = this.attributes[attr].array;
for ( var i = 0, il = types.length; i < il; i++ ) {
var type = types[i];
if (sourceArray instanceof type) {
sortedAttributes[attr] = new type( this.attributes[attr].itemSize * vertexCount );
break;
}
}
geometry.faceVertexUvs[ 0 ].push( uvCopy );
}
return geometry;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
}
};
THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
THREE.GeometryIdCount = 0;
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.Geometry2 = function ( size ) {
this.id = THREE.GeometryIdCount ++;
this.uuid = THREE.Math.generateUUID();
this.name = '';
this.vertices = size !== undefined ? new Float32Array( size * 3 ) : [];
this.normals = size !== undefined ? new Float32Array( size * 3 ) : [];
this.uvs = size !== undefined ? new Float32Array( size * 2 ) : [];
this.boundingBox = null;
this.boundingSphere = null;
};
THREE.Geometry2.prototype = {
constructor: THREE.Geometry2,
applyMatrix: function ( matrix ) {
matrix.multiplyVector3Array( this.vertices );
},
computeBoundingBox: function () {
if ( this.boundingBox === null ) {
this.boundingBox = new THREE.Box3();
/* Move attribute positions based on the new index map */
for(var new_vid = 0; new_vid < vertexCount; new_vid++) {
var vid = indexMap[new_vid];
for ( var attr in this.attributes ) {
if(attr == 'index')
continue;
var attrArray = this.attributes[attr].array;
var attrSize = this.attributes[attr].itemSize;
var sortedAttr = sortedAttributes[attr];
for(var k = 0; k < attrSize; k++)
sortedAttr[ new_vid * attrSize + k ] = attrArray[ vid * attrSize + k ];
}
}
var vertices = this.vertices;
var bb = this.boundingBox;
/* Carry the new sorted buffers locally */
this.attributes['index'].array = indexBuffer;
for ( var attr in this.attributes ) {
if(attr == 'index')
continue;
this.attributes[attr].array = sortedAttributes[attr];
this.attributes[attr].numItems = this.attributes[attr].itemSize * vertexCount;
}
},
if ( vertices.length >= 3 ) {
clone: function () {
bb.min.x = bb.max.x = vertices[ 0 ];
bb.min.y = bb.max.y = vertices[ 1 ];
bb.min.z = bb.max.z = vertices[ 2 ];
var geometry = new THREE.BufferGeometry();
}
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
for ( var i = 3, il = vertices.length; i < il; i += 3 ) {
for ( var attr in this.attributes ) {
var x = vertices[ i ];
var y = vertices[ i + 1 ];
var z = vertices[ i + 2 ];
var sourceAttr = this.attributes[ attr ];
var sourceArray = sourceAttr.array;
// bounding box
var attribute = {
if ( x < bb.min.x ) {
itemSize: sourceAttr.itemSize,
array: null
bb.min.x = x;
};
} else if ( x > bb.max.x ) {
for ( var i = 0, il = types.length; i < il; i ++ ) {
bb.max.x = x;
var type = types[ i ];
}
if ( sourceArray instanceof type ) {
if ( y < bb.min.y ) {
attribute.array = new type( sourceArray );
break;
bb.min.y = y;
}
} else if ( y > bb.max.y ) {
}
bb.max.y = y;
geometry.attributes[ attr ] = attribute;
}
}
if ( z < bb.min.z ) {
for ( var i = 0, il = this.offsets.length; i < il; i ++ ) {
bb.min.z = z;
var offset = this.offsets[ i ];
} else if ( z > bb.max.z ) {
geometry.offsets.push( {
bb.max.z = z;
start: offset.start,
index: offset.index,
count: offset.count
}
} );
}
},
return geometry;
computeBoundingSphere: function () {
},
var box = new THREE.Box3();
var vector = new THREE.Vector3();
dispose: function () {
return function () {
this.dispatchEvent( { type: 'dispose' } );
if ( this.boundingSphere === null ) {
}
this.boundingSphere = new THREE.Sphere();
};
}
THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
box.makeEmpty();
/**
* @author mrdoob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author zz85 / http://www.lab4games.net/zz85/blog
* @author bhouston / http://exocortex.com
*/
var vertices = this.vertices;
var center = this.boundingSphere.center;
THREE.Geometry = function () {
for ( var i = 0, il = vertices.length; i < il; i += 3 ) {
this.id = THREE.GeometryIdCount ++;
this.uuid = THREE.Math.generateUUID();
vector.set( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] );
box.addPoint( vector );
this.name = '';
}
this.vertices = [];
this.colors = []; // one-to-one vertex colors, used in ParticleSystem and Line
box.center( center );
this.faces = [];
var maxRadiusSq = 0;
this.faceVertexUvs = [[]];
for ( var i = 0, il = vertices.length; i < il; i += 3 ) {
this.morphTargets = [];
this.morphColors = [];
this.morphNormals = [];
vector.set( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] );
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
this.skinWeights = [];
this.skinIndices = [];
}
this.lineDistances = [];
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
this.boundingBox = null;
this.boundingSphere = null;
}
this.hasTangents = false;
}(),
this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
dispose: function () {
// update flags
this.dispatchEvent( { type: 'dispose' } );
this.verticesNeedUpdate = false;
this.elementsNeedUpdate = false;
this.uvsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.tangentsNeedUpdate = false;
this.colorsNeedUpdate = false;
this.lineDistancesNeedUpdate = false;
}
this.buffersNeedUpdate = false;
};
THREE.EventDispatcher.prototype.apply( THREE.Geometry2.prototype );
THREE.Geometry.prototype = {
/**
* @author alteredq / http://alteredqualia.com/
*/
constructor: THREE.Geometry,
THREE.BufferGeometry = function () {
applyMatrix: function ( matrix ) {
this.id = THREE.GeometryIdCount ++;
this.uuid = THREE.Math.generateUUID();
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
this.name = '';
for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
// attributes
var vertex = this.vertices[ i ];
vertex.applyMatrix4( matrix );
this.attributes = {};
}
// offsets for chunks when using indexed elements
for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
this.offsets = [];
var face = this.faces[ i ];
face.normal.applyMatrix3( normalMatrix ).normalize();
// boundings
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
this.boundingBox = null;
this.boundingSphere = null;
face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
};
}
THREE.BufferGeometry.prototype = {
face.centroid.applyMatrix4( matrix );
constructor: THREE.BufferGeometry,
}
addAttribute: function ( name, type, numItems, itemSize ) {
if ( this.boundingBox instanceof THREE.Box3 ) {
this.attributes[ name ] = {
this.computeBoundingBox();
itemSize: itemSize,
array: new type( numItems * itemSize )
}
};
if ( this.boundingSphere instanceof THREE.Sphere ) {
this.computeBoundingSphere();
}
},
applyMatrix: function ( matrix ) {
computeCentroids: function () {
var position = this.attributes.position;
var f, fl, face;
if ( position !== undefined ) {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
matrix.multiplyVector3Array( position.array );
position.needsUpdate = true;
face = this.faces[ f ];
face.centroid.set( 0, 0, 0 );
face.centroid.add( this.vertices[ face.a ] );
face.centroid.add( this.vertices[ face.b ] );
face.centroid.add( this.vertices[ face.c ] );
face.centroid.divideScalar( 3 );
}
var normal = this.attributes.normal;
},
if ( normal !== undefined ) {
computeFaceNormals: function () {
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
var cb = new THREE.Vector3(), ab = new THREE.Vector3();
normalMatrix.multiplyVector3Array( normal.array );
normal.needsUpdate = true;
for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
}
var face = this.faces[ f ];
},
var vA = this.vertices[ face.a ];
var vB = this.vertices[ face.b ];
var vC = this.vertices[ face.c ];
computeBoundingBox: function () {
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
if ( this.boundingBox === null ) {
cb.normalize();
this.boundingBox = new THREE.Box3();
face.normal.copy( cb );
}
var positions = this.attributes[ "position" ].array;
},
if ( positions ) {
computeVertexNormals: function ( areaWeighted ) {
var bb = this.boundingBox;
var v, vl, f, fl, face, vertices;
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 ];
}
vertices = new Array( this.vertices.length );
for ( var i = 3, il = positions.length; i < il; i += 3 ) {
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
var x = positions[ i ];
var y = positions[ i + 1 ];
var z = positions[ i + 2 ];
vertices[ v ] = new THREE.Vector3();
// bounding box
}
if ( x < bb.min.x ) {
if ( areaWeighted ) {
bb.min.x = x;
// vertex normals weighted by triangle areas
// http://www.iquilezles.org/www/articles/normals/normals.htm
} else if ( x > bb.max.x ) {
var vA, vB, vC, vD;
var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
bb.max.x = x;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
}
face = this.faces[ f ];
if ( y < bb.min.y ) {
vA = this.vertices[ face.a ];
vB = this.vertices[ face.b ];
vC = this.vertices[ face.c ];
bb.min.y = y;
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
} else if ( y > bb.max.y ) {
vertices[ face.a ].add( cb );
vertices[ face.b ].add( cb );
vertices[ face.c ].add( cb );
bb.max.y = y;
}
}
} else {
if ( z < bb.min.z ) {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
bb.min.z = z;
face = this.faces[ f ];
} else if ( z > bb.max.z ) {
vertices[ face.a ].add( face.normal );
vertices[ face.b ].add( face.normal );
vertices[ face.c ].add( face.normal );
bb.max.z = z;
}
}
}
}
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
vertices[ v ].normalize();
}
if ( positions === undefined || positions.length === 0 ) {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
this.boundingBox.min.set( 0, 0, 0 );
this.boundingBox.max.set( 0, 0, 0 );
face = this.faces[ f ];
face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
}
},
computeBoundingSphere: function () {
var box = new THREE.Box3();
var vector = new THREE.Vector3();
computeMorphNormals: function () {
return function () {
var i, il, f, fl, face;
if ( this.boundingSphere === null ) {
// save original normals
// - create temp variables on first access
// otherwise just copy (for faster repeated calls)
this.boundingSphere = new THREE.Sphere();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
}
face = this.faces[ f ];
var positions = this.attributes[ "position" ].array;
if ( ! face.__originalFaceNormal ) {
if ( positions ) {
face.__originalFaceNormal = face.normal.clone();
box.makeEmpty();
} else {
var center = this.boundingSphere.center;
face.__originalFaceNormal.copy( face.normal );
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
}
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
box.addPoint( vector );
if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
}
for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
box.center( center );
if ( ! face.__originalVertexNormals[ i ] ) {
var maxRadiusSq = 0;
face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
} else {
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
}
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
}
}
}(),
computeVertexNormals: function () {
// use temp geometry to compute face and vertex normals for each morph
if ( this.attributes[ "position" ] ) {
var tmpGeo = new THREE.Geometry();
tmpGeo.faces = this.faces;
var i, il;
var j, jl;
for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
var nVertexElements = this.attributes[ "position" ].array.length;
// create on first access
if ( this.attributes[ "normal" ] === undefined ) {
if ( ! this.morphNormals[ i ] ) {
this.attributes[ "normal" ] = {
this.morphNormals[ i ] = {};
this.morphNormals[ i ].faceNormals = [];
this.morphNormals[ i ].vertexNormals = [];
itemSize: 3,
array: new Float32Array( nVertexElements )
var dstNormalsFace = this.morphNormals[ i ].faceNormals;
var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
};
var faceNormal, vertexNormals;
} else {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
// reset existing normals to zero
face = this.faces[ f ];
for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
faceNormal = new THREE.Vector3();
vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
this.attributes[ "normal" ].array[ i ] = 0;
dstNormalsFace.push( faceNormal );
dstNormalsVertex.push( vertexNormals );
}
}
var positions = this.attributes[ "position" ].array;
var normals = this.attributes[ "normal" ].array;
var vA, vB, vC, x, y, z,
var morphNormals = this.morphNormals[ i ];
pA = new THREE.Vector3(),
pB = new THREE.Vector3(),
pC = new THREE.Vector3(),
// set vertices to morph target
cb = new THREE.Vector3(),
ab = new THREE.Vector3();
tmpGeo.vertices = this.morphTargets[ i ].vertices;
// indexed elements
// compute morph normals
if ( this.attributes[ "index" ] ) {
tmpGeo.computeFaceNormals();
tmpGeo.computeVertexNormals();
var indices = this.attributes[ "index" ].array;
// store morph normals
var offsets = this.offsets;
var faceNormal, vertexNormals;
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
var start = offsets[ j ].start;
var count = offsets[ j ].count;
var index = offsets[ j ].index;
face = this.faces[ f ];
for ( i = start, il = start + count; i < il; i += 3 ) {
faceNormal = morphNormals.faceNormals[ f ];
vertexNormals = morphNormals.vertexNormals[ f ];
vA = index + indices[ i ];
vB = index + indices[ i + 1 ];
vC = index + indices[ i + 2 ];
faceNormal.copy( face.normal );
x = positions[ vA * 3 ];
y = positions[ vA * 3 + 1 ];
z = positions[ vA * 3 + 2 ];
pA.set( x, y, z );
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
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 );
// restore original normals
normals[ vA * 3 ] += cb.x;
normals[ vA * 3 + 1 ] += cb.y;
normals[ vA * 3 + 2 ] += cb.z;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
normals[ vB * 3 ] += cb.x;
normals[ vB * 3 + 1 ] += cb.y;
normals[ vB * 3 + 2 ] += cb.z;
face = this.faces[ f ];
normals[ vC * 3 ] += cb.x;
normals[ vC * 3 + 1 ] += cb.y;
normals[ vC * 3 + 2 ] += cb.z;
face.normal = face.__originalFaceNormal;
face.vertexNormals = face.__originalVertexNormals;
}
}
}
},
// non-indexed elements (unconnected triangle soup)
computeTangents: function () {
} else {
// based on http://www.terathon.com/code/tangent.html
// tangents go to vertices
for ( i = 0, il = positions.length; i < il; i += 9 ) {
var f, fl, v, vl, i, il, vertexIndex,
face, uv, vA, vB, vC, uvA, uvB, uvC,
x1, x2, y1, y2, z1, z2,
s1, s2, t1, t2, r, t, test,
tan1 = [], tan2 = [],
sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
n = new THREE.Vector3(), w;
x = positions[ i ];
y = positions[ i + 1 ];
z = positions[ i + 2 ];
pA.set( x, y, z );
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
x = positions[ i + 3 ];
y = positions[ i + 4 ];
z = positions[ i + 5 ];
pB.set( x, y, z );
tan1[ v ] = new THREE.Vector3();
tan2[ v ] = new THREE.Vector3();
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 );
function handleTriangle( context, a, b, c, ua, ub, uc ) {
normals[ i ] = cb.x;
normals[ i + 1 ] = cb.y;
normals[ i + 2 ] = cb.z;
vA = context.vertices[ a ];
vB = context.vertices[ b ];
vC = context.vertices[ c ];
normals[ i + 3 ] = cb.x;
normals[ i + 4 ] = cb.y;
normals[ i + 5 ] = cb.z;
uvA = uv[ ua ];
uvB = uv[ ub ];
uvC = uv[ uc ];
normals[ i + 6 ] = cb.x;
normals[ i + 7 ] = cb.y;
normals[ i + 8 ] = cb.z;
x1 = vB.x - vA.x;
x2 = vC.x - vA.x;
y1 = vB.y - vA.y;
y2 = vC.y - vA.y;
z1 = vB.z - vA.z;
z2 = vC.z - vA.z;
}
s1 = uvB.x - uvA.x;
s2 = uvC.x - uvA.x;
t1 = uvB.y - uvA.y;
t2 = uvC.y - uvA.y;
}
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 );
this.normalizeNormals();
tan1[ a ].add( sdir );
tan1[ b ].add( sdir );
tan1[ c ].add( sdir );
this.normalsNeedUpdate = true;
tan2[ a ].add( tdir );
tan2[ b ].add( tdir );
tan2[ c ].add( tdir );
}
},
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 ];
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
n = 1.0 / Math.sqrt( x * x + y * y + z * z );
face = this.faces[ f ];
uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
normals[ i ] *= n;
normals[ i + 1 ] *= n;
normals[ i + 2 ] *= n;
handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
}
},
var faceIndex = [ 'a', 'b', 'c', 'd' ];
computeTangents: function () {
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
// based on http://www.terathon.com/code/tangent.html
// (per vertex tangents)
face = this.faces[ f ];
if ( this.attributes[ "index" ] === undefined ||
this.attributes[ "position" ] === undefined ||
this.attributes[ "normal" ] === undefined ||
this.attributes[ "uv" ] === undefined ) {
for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
return;
n.copy( face.vertexNormals[ i ] );
}
vertexIndex = face[ faceIndex[ i ] ];
var indices = this.attributes[ "index" ].array;
var positions = this.attributes[ "position" ].array;
var normals = this.attributes[ "normal" ].array;
var uvs = this.attributes[ "uv" ].array;
t = tan1[ vertexIndex ];
var nVertices = positions.length / 3;
// Gram-Schmidt orthogonalize
if ( this.attributes[ "tangent" ] === undefined ) {
tmp.copy( t );
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
var nTangentElements = 4 * nVertices;
// Calculate handedness
this.attributes[ "tangent" ] = {
tmp2.crossVectors( face.vertexNormals[ i ], t );
test = tmp2.dot( tan2[ vertexIndex ] );
w = (test < 0.0) ? -1.0 : 1.0;
itemSize: 4,
array: new Float32Array( nTangentElements )
face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
};
}
}
var tangents = this.attributes[ "tangent" ].array;
var tan1 = [], tan2 = [];
this.hasTangents = true;
for ( var k = 0; k < nVertices; k ++ ) {
},
tan1[ k ] = new THREE.Vector3();
tan2[ k ] = new THREE.Vector3();
computeLineDistances: function ( ) {
}
var d = 0;
var vertices = this.vertices;
var xA, yA, zA,
xB, yB, zB,
xC, yC, zC,
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
uA, vA,
uB, vB,
uC, vC,
if ( i > 0 ) {
x1, x2, y1, y2, z1, z2,
s1, s2, t1, t2, r;
d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
}
function handleTriangle( a, b, c ) {
this.lineDistances[ i ] = d;
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 ];
computeBoundingBox: function () {
uA = uvs[ a * 2 ];
vA = uvs[ a * 2 + 1 ];
if ( this.boundingBox === null ) {
uB = uvs[ b * 2 ];
vB = uvs[ b * 2 + 1 ];
this.boundingBox = new THREE.Box3();
uC = uvs[ c * 2 ];
vC = uvs[ c * 2 + 1 ];
}
x1 = xB - xA;
x2 = xC - xA;
this.boundingBox.setFromPoints( this.vertices );
y1 = yB - yA;
y2 = yC - yA;
},
z1 = zB - zA;
z2 = zC - zA;
computeBoundingSphere: function () {
s1 = uB - uA;
s2 = uC - uA;
if ( this.boundingSphere === null ) {
t1 = vB - vA;
t2 = vC - vA;
this.boundingSphere = new THREE.Sphere();
r = 1.0 / ( s1 * t2 - s2 * t1 );
}
sdir.set(
( t2 * x1 - t1 * x2 ) * r,
( t2 * y1 - t1 * y2 ) * r,
( t2 * z1 - t1 * z2 ) * r
);
this.boundingSphere.setFromPoints( this.vertices );
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 );
/*
* Checks for duplicate vertices with hashmap.
* Duplicated vertices are removed
* and faces' vertices are updated.
*/
tan2[ a ].add( tdir );
tan2[ b ].add( tdir );
tan2[ c ].add( tdir );
mergeVertices: function () {
}
var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
var unique = [], changes = [];
var i, il;
var j, jl;
var iA, iB, iC;
var v, key;
var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
var precision = Math.pow( 10, precisionPoints );
var i,il, face;
var indices, k, j, jl, u;
var offsets = this.offsets;
for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
v = this.vertices[ i ];
key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
var start = offsets[ j ].start;
var count = offsets[ j ].count;
var index = offsets[ j ].index;
if ( verticesMap[ key ] === undefined ) {
for ( i = start, il = start + count; i < il; i += 3 ) {
verticesMap[ key ] = i;
unique.push( this.vertices[ i ] );
changes[ i ] = unique.length - 1;
iA = index + indices[ i ];
iB = index + indices[ i + 1 ];
iC = index + indices[ i + 2 ];
} else {
handleTriangle( iA, iB, iC );
//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
changes[ i ] = changes[ verticesMap[ key ] ];
}
}
};
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 ) {
// if faces are completely degenerate after merging vertices, we
// have to remove them from the geometry.
var faceIndicesToRemove = [];
n.x = normals[ v * 3 ];
n.y = normals[ v * 3 + 1 ];
n.z = normals[ v * 3 + 2 ];
for( i = 0, il = this.faces.length; i < il; i ++ ) {
n2.copy( n );
face = this.faces[ i ];
t = tan1[ v ];
face.a = changes[ face.a ];
face.b = changes[ face.b ];
face.c = changes[ face.c ];
// Gram-Schmidt orthogonalize
indices = [ face.a, face.b, face.c ];
tmp.copy( t );
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
var dupIndex = -1;
// Calculate handedness
// if any duplicate vertices are found in a Face3
// we have to remove the face as nothing can be saved
for ( var n = 0; n < 3; n ++ ) {
if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
tmp2.crossVectors( n2, t );
test = tmp2.dot( tan2[ v ] );
w = ( test < 0.0 ) ? -1.0 : 1.0;
dupIndex = n;
faceIndicesToRemove.push( i );
break;
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 = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
var idx = faceIndicesToRemove[ i ];
for ( i = start, il = start + count; i < il; i += 3 ) {
this.faces.splice( idx, 1 );
iA = index + indices[ i ];
iB = index + indices[ i + 1 ];
iC = index + indices[ i + 2 ];
for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
handleVertex( iA );
handleVertex( iB );
handleVertex( iC );
this.faceVertexUvs[ j ].splice( idx, 1 );
}
}
},
// Use unique set of vertices
/*
computeOffsets
Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
indexBufferSize - Defaults to 65535, but allows for larger or smaller chunks.
*/
computeOffsets: function(indexBufferSize) {
var diff = this.vertices.length - unique.length;
this.vertices = unique;
return diff;
var size = indexBufferSize;
if(indexBufferSize === undefined)
size = 65535; //WebGL limits type of index buffer values to 16-bit.
},
var s = Date.now();
// Geometry splitting
var indices = this.attributes['index'].array;
var vertices = this.attributes['position'].array;
makeGroups: ( function () {
var verticesCount = (vertices.length/3);
var facesCount = (indices.length/3);
var geometryGroupCounter = 0;
return function ( usesFaceMaterial ) {
/*
console.log("Computing buffers in offsets of "+size+" -> indices:"+indices.length+" vertices:"+vertices.length);
console.log("Faces to process: "+(indices.length/3));
console.log("Reordering "+verticesCount+" vertices.");
*/
var f, fl, face, materialIndex,
groupHash, hash_map = {};
var sortedIndices = new Uint16Array( indices.length ); //16-bit buffers
var indexPtr = 0;
var vertexPtr = 0;
var numMorphTargets = this.morphTargets.length;
var numMorphNormals = this.morphNormals.length;
var offsets = [ { start:0, count:0, index:0 } ];
var offset = offsets[0];
this.geometryGroups = {};
var duplicatedVertices = 0;
var newVerticeMaps = 0;
var faceVertices = new Int32Array(6);
var vertexMap = new Int32Array( vertices.length );
var revVertexMap = new Int32Array( vertices.length );
for(var j = 0; j < vertices.length; j++) { vertexMap[j] = -1; revVertexMap[j] = -1; }
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
materialIndex = usesFaceMaterial ? face.materialIndex : 0;
/*
Traverse every face and reorder vertices in the proper offsets of 65k.
We can have more than 65k entries in the index buffer per offset, but only reference 65k values.
*/
for(var findex = 0; findex < facesCount; findex++) {
newVerticeMaps = 0;
if ( ! ( materialIndex in hash_map ) ) {
hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
for(var vo = 0; vo < 3; vo++) {
var vid = indices[ findex*3 + vo ];
if(vertexMap[vid] == -1) {
//Unmapped vertice
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = -1;
newVerticeMaps++;
} else if(vertexMap[vid] < offset.index) {
//Reused vertices from previous block (duplicate)
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = -1;
duplicatedVertices++;
} else {
//Reused vertice in the current block
faceVertices[vo*2] = vid;
faceVertices[vo*2+1] = vertexMap[vid];
}
}
var faceMax = vertexPtr + newVerticeMaps;
if(faceMax > (offset.index + size)) {
var new_offset = { start:indexPtr, count:0, index:vertexPtr };
offsets.push(new_offset);
offset = new_offset;
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
//Re-evaluate reused vertices in light of new offset.
for(var v = 0; v < 6; v+=2) {
var new_vid = faceVertices[v+1];
if(new_vid > -1 && new_vid < offset.index)
faceVertices[v+1] = -1;
}
}
if ( ! ( groupHash in this.geometryGroups ) ) {
//Reindex the face.
for(var v = 0; v < 6; v+=2) {
var vid = faceVertices[v];
var new_vid = faceVertices[v+1];
this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
if(new_vid === -1)
new_vid = vertexPtr++;
}
vertexMap[vid] = new_vid;
revVertexMap[new_vid] = vid;
sortedIndices[indexPtr++] = new_vid - offset.index; //XXX overflows at 16bit
offset.count++;
}
}
if ( this.geometryGroups[ groupHash ].vertices + 3 > 65535 ) {
/* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */
this.reorderBuffers(sortedIndices, revVertexMap, vertexPtr);
this.offsets = offsets;
hash_map[ materialIndex ].counter += 1;
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
/*
var orderTime = Date.now();
console.log("Reorder time: "+(orderTime-s)+"ms");
console.log("Duplicated "+duplicatedVertices+" vertices.");
console.log("Compute Buffers time: "+(Date.now()-s)+"ms");
console.log("Draw offsets: "+offsets.length);
*/
if ( ! ( groupHash in this.geometryGroups ) ) {
return offsets;
},
this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
/*
reoderBuffers:
Reorder attributes based on a new indexBuffer and indexMap.
indexBuffer - Uint16Array of the new ordered indices.
indexMap - Int32Array where the position is the new vertex ID and the value the old vertex ID for each vertex.
vertexCount - Amount of total vertices considered in this reordering (in case you want to grow the vertice stack).
*/
reorderBuffers: function(indexBuffer, indexMap, vertexCount) {
}
/* Create a copy of all attributes for reordering. */
var sortedAttributes = {};
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
for( var attr in this.attributes ) {
if(attr == 'index')
continue;
var sourceArray = this.attributes[attr].array;
for ( var i = 0, il = types.length; i < il; i++ ) {
var type = types[i];
if (sourceArray instanceof type) {
sortedAttributes[attr] = new type( this.attributes[attr].itemSize * vertexCount );
break;
}
}
}
/* Move attribute positions based on the new index map */
for(var new_vid = 0; new_vid < vertexCount; new_vid++) {
var vid = indexMap[new_vid];
for ( var attr in this.attributes ) {
if(attr == 'index')
continue;
var attrArray = this.attributes[attr].array;
var attrSize = this.attributes[attr].itemSize;
var sortedAttr = sortedAttributes[attr];
for(var k = 0; k < attrSize; k++)
sortedAttr[ new_vid * attrSize + k ] = attrArray[ vid * attrSize + k ];
}
}
this.geometryGroups[ groupHash ].faces3.push( f );
this.geometryGroups[ groupHash ].vertices += 3;
/* Carry the new sorted buffers locally */
this.attributes['index'].array = indexBuffer;
for ( var attr in this.attributes ) {
if(attr == 'index')
continue;
this.attributes[attr].array = sortedAttributes[attr];
this.attributes[attr].numItems = this.attributes[attr].itemSize * vertexCount;
}
},
}
clone: function () {
this.geometryGroupsList = [];
var geometry = new THREE.BufferGeometry();
for ( var g in this.geometryGroups ) {
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
this.geometryGroups[ g ].id = geometryGroupCounter ++;
for ( var attr in this.attributes ) {
this.geometryGroupsList.push( this.geometryGroups[ g ] );
var sourceAttr = this.attributes[ attr ];
var sourceArray = sourceAttr.array;
}
var attribute = {
};
} )(),
itemSize: sourceAttr.itemSize,
array: null
clone: function () {
};
var geometry = new THREE.Geometry();
for ( var i = 0, il = types.length; i < il; i ++ ) {
var vertices = this.vertices;
var type = types[ i ];
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
if ( sourceArray instanceof type ) {
geometry.vertices.push( vertices[ i ].clone() );
attribute.array = new type( sourceArray );
break;
}
}
var faces = this.faces;
}
for ( var i = 0, il = faces.length; i < il; i ++ ) {
geometry.attributes[ attr ] = attribute;
geometry.faces.push( faces[ i ].clone() );
}
for ( var i = 0, il = this.offsets.length; i < il; i ++ ) {
var uvs = this.faceVertexUvs[ 0 ];
var offset = this.offsets[ i ];
for ( var i = 0, il = uvs.length; i < il; i ++ ) {
geometry.offsets.push( {
var uv = uvs[ i ], uvCopy = [];
start: offset.start,
index: offset.index,
count: offset.count
for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
} );
uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
}
geometry.faceVertexUvs[ 0 ].push( uvCopy );
}
......@@ -10512,8 +10355,28 @@ THREE.BufferGeometry.prototype = {
};
THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
THREE.GeometryIdCount = 0;
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.Geometry2 = function ( size ) {
THREE.BufferGeometry.call( this );
this.vertices = this.addAttribute( 'position', Float32Array, size, 3 ).array;
this.normals = this.addAttribute( 'normal', Float32Array, size, 3 ).array;
this.uvs = this.addAttribute( 'uv', Float32Array, size, 2 ).array;
this.boundingBox = null;
this.boundingSphere = null;
};
THREE.Geometry2.prototype = Object.create( THREE.BufferGeometry.prototype );
/**
* @author mrdoob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
......@@ -21003,12 +20866,6 @@ THREE.WebGLRenderer = function ( parameters ) {
_this.info.memory.geometries --;
} if ( geometry instanceof THREE.Geometry2 ) {
delete _buffers[ geometry.id ];
_this.info.memory.geometries --;
} else {
if ( geometry.geometryGroups !== undefined ) {
......@@ -21485,27 +21342,6 @@ THREE.WebGLRenderer = function ( parameters ) {
};
function initGeometry2Buffers( geometry ) {
var buffers = {};
var attributes = [ 'vertices', 'normals', 'uvs' ];
for ( var key in attributes ) {
var array = geometry[ attributes[ key ] ];
var buffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
_gl.bufferData( _gl.ARRAY_BUFFER, array, _gl.STATIC_DRAW );
buffers[ attributes[ key ] ] = buffer;
}
_buffers[ geometry.id ] = buffers;
};
// Buffer setting
function setParticleBuffers ( geometry, hint, object ) {
......@@ -22876,27 +22712,6 @@ THREE.WebGLRenderer = function ( parameters ) {
}
function setGeometry2Buffers( geometry, hint ) {
if ( geometry.needsUpdate === false ) return;
var attributes = [ 'vertices', 'normals', 'uvs' ];
var buffers = _buffers[ geometry.id ];
for ( var key in attributes ) {
var array = geometry[ attributes[ key ] ];
var buffer = buffers[ attributes[ key ] ];
_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
_gl.bufferData( _gl.ARRAY_BUFFER, array, hint );
}
geometry.needsUpdate = false;
};
// Buffer rendering
this.renderBufferImmediate = function ( object, program, material ) {
......@@ -22992,56 +22807,6 @@ THREE.WebGLRenderer = function ( parameters ) {
};
this.renderBufferGeometry2 = function ( camera, lights, fog, material, geometry, object ) {
var program = setProgram( camera, lights, fog, material, object );
var programAttributes = program.attributes;
var attributes = { 'position': 'vertices', 'normal': 'normals', 'uv': 'uvs' };
var itemSizes = { 'position': 3, 'normal': 3, 'uv': 2 };
var buffers = _buffers[ geometry.id ];
disableAttributes();
for ( var name in programAttributes ) {
var attributePointer = programAttributes[ name ];
if ( attributePointer >= 0 ) {
var array = geometry[ attributes[ name ] ];
if ( array !== undefined && array.length > 0 ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers[ attributes[ name ] ] );
enableAttribute( attributePointer );
_gl.vertexAttribPointer( attributePointer, itemSizes[ name ], _gl.FLOAT, false, 0, 0 );
} else {
if ( itemSizes[ name ] === 3 ) {
_gl.vertexAttrib3fv( attributePointer, [ 0, 0, 0 ] );
} else if ( itemSizes[ name ] === 2 ) {
_gl.vertexAttrib2fv( attributePointer, [ 0, 0 ] );
}
}
}
}
_gl.drawArrays( _gl.TRIANGLES, 0, geometry.vertices.length / 3 );
};
this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
if ( material.visible === false ) return;
......@@ -24006,10 +23771,6 @@ THREE.WebGLRenderer = function ( parameters ) {
_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
} else if ( buffer instanceof THREE.Geometry2 ) {
_this.renderBufferGeometry2( camera, lights, fog, material, buffer, object );
} else {
_this.renderBuffer( camera, lights, fog, material, buffer, object );
......@@ -24229,10 +23990,6 @@ THREE.WebGLRenderer = function ( parameters ) {
initDirectBuffers( geometry );
} else if ( geometry instanceof THREE.Geometry2 ) {
initGeometry2Buffers( geometry );
} else if ( object instanceof THREE.Mesh ) {
material = object.material;
......@@ -24307,10 +24064,6 @@ THREE.WebGLRenderer = function ( parameters ) {
addBuffer( scene.__webglObjects, geometry, object );
} else if ( geometry instanceof THREE.Geometry2 ) {
addBuffer( scene.__webglObjects, geometry, object );
} else if ( geometry instanceof THREE.Geometry ) {
for ( g in geometry.geometryGroups ) {
......@@ -24389,10 +24142,6 @@ THREE.WebGLRenderer = function ( parameters ) {
setDirectBuffers( geometry, _gl.DYNAMIC_DRAW );
} else if ( geometry instanceof THREE.Geometry2 ) {
setGeometry2Buffers( geometry, _gl.DYNAMIC_DRAW );
} else if ( object instanceof THREE.Mesh ) {
// check all geometry groups
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册