Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Ablesons
three.js
提交
786d570e
T
three.js
项目概览
Ablesons
/
three.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
three.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
786d570e
编写于
2月 18, 2014
作者:
M
Mr.doob
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Updated builds.
上级
8adc0489
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
1215 addition
and
1472 deletion
+1215
-1472
build/three.js
build/three.js
+887
-1138
build/three.min.js
build/three.min.js
+328
-334
未找到文件。
build/three.js
浏览文件 @
786d570e
...
...
@@ -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.
Buffer
Geometry = 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;
f
ace = this.faces[ f ];
f
or ( 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();
}
}
},
}
()
,
compute
Morph
Normals: function () {
compute
Vertex
Normals: 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 element
s
//
compute morph normal
s
if ( this.attributes[ "index" ] ) {
tmpGeo.computeFaceNormals();
tmpGeo.computeVertexNormals();
var indices = this.attributes[ "index" ].array;
// store morph normals
var offsets = this.offset
s;
var faceNormal, vertexNormal
s;
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
...
...
build/three.min.js
浏览文件 @
786d570e
因为 它太大了无法显示 source diff 。你可以改为
查看blob
。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录